diff options
author | dimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7> | 2005-01-29 11:51:21 (GMT) |
---|---|---|
committer | dimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7> | 2005-01-29 11:51:21 (GMT) |
commit | c635cffd1d8bcf5bcbe90ce2c3c5fc3371e01a1c (patch) | |
tree | 5d48c44b9a2f19b38592c2cb51a919ebd456c8fb /src | |
parent | 13feb604f3aa783f927ed47df8e4c561a8d8032a (diff) | |
download | Doxygen-c635cffd1d8bcf5bcbe90ce2c3c5fc3371e01a1c.zip Doxygen-c635cffd1d8bcf5bcbe90ce2c3c5fc3371e01a1c.tar.gz Doxygen-c635cffd1d8bcf5bcbe90ce2c3c5fc3371e01a1c.tar.bz2 |
Release-1.4.1-20050129
Diffstat (limited to 'src')
-rw-r--r-- | src/code.l | 9 | ||||
-rw-r--r-- | src/commentscan.h | 31 | ||||
-rw-r--r-- | src/commentscan.l | 1915 | ||||
-rw-r--r-- | src/doctokenizer.l | 6 | ||||
-rw-r--r-- | src/dot.cpp | 9 | ||||
-rw-r--r-- | src/doxygen.cpp | 4 | ||||
-rw-r--r-- | src/htmldocvisitor.cpp | 2 | ||||
-rw-r--r-- | src/index.xsd | 4 | ||||
-rw-r--r-- | src/index_xsd.h | 4 | ||||
-rw-r--r-- | src/language.cpp | 4 | ||||
-rw-r--r-- | src/libdoxygen.pro.in | 5 | ||||
-rw-r--r-- | src/pre.l | 6 | ||||
-rw-r--r-- | src/scanner.h | 10 | ||||
-rw-r--r-- | src/scanner.l | 302 |
14 files changed, 2289 insertions, 22 deletions
@@ -2395,7 +2395,14 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} g_code->codify(yytext); if (--g_bracketCount<=0) { - BEGIN( CallEnd ); + if (g_name.isEmpty()) + { + BEGIN( Body ); + } + else + { + BEGIN( CallEnd ); + } } } <CallEnd>[ \t\n]* { codifyLines(yytext); } diff --git a/src/commentscan.h b/src/commentscan.h new file mode 100644 index 0000000..d954a93 --- /dev/null +++ b/src/commentscan.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2005 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. + * + */ + +#ifndef COMMENTSCAN_H +#define COMMENTSCAN_H + +#include "qtbc.h" +#include "entry.h" + +bool parseCommentBlock(/* in,out */ Entry *curEntry, + /* in */ const QCString &comment, + /* in */ const QCString &fileName, + /* in */ int lineNr, + /* in */ bool isBrief, + /* in */ bool isJavaDocStyle, + /* in,out */ Protection &prot + ); + +#endif diff --git a/src/commentscan.l b/src/commentscan.l new file mode 100644 index 0000000..e31eda3 --- /dev/null +++ b/src/commentscan.l @@ -0,0 +1,1915 @@ +/***************************************************************************** + * + * Copyright (C) 1997-2005 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 <stdlib.h> +#include <assert.h> +#include <ctype.h> + +#include "qtbc.h" +#include <qarray.h> +#include <qstack.h> +#include <qregexp.h> +#include <unistd.h> +#include <qfile.h> + +#include "scanner.h" +#include "entry.h" +#include "doxygen.h" +#include "message.h" +#include "config.h" +#include "util.h" +#include "index.h" +#include "defargs.h" +#include "language.h" +#include "outputlist.h" +#include "membergroup.h" +#include "reflist.h" +#include "code.h" + +// forward declarations +static void handleBrief(const QCString &); +static void handleFn(const QCString &); +static void handleDef(const QCString &); +static void handleOverload(const QCString &); +static void handleEnum(const QCString &); +static void handleDefGroup(const QCString &); +static void handleAddToGroup(const QCString &); +static void handleWeakGroup(const QCString &); +static void handleNamespace(const QCString &); +static void handlePackage(const QCString &); +static void handleClass(const QCString &); +static void handleProtocol(const QCString &); +static void handleCategory(const QCString &); +static void handleUnion(const QCString &); +static void handleStruct(const QCString &); +static void handleInterface(const QCString &); +static void handleIdlException(const QCString &); +static void handlePage(const QCString &); +static void handleMainpage(const QCString &); +static void handleFile(const QCString &); +static void handleDir(const QCString &); +static void handleExample(const QCString &); +static void handleDetails(const QCString &); +static void handleName(const QCString &); +static void handleTodo(const QCString &); +static void handleTest(const QCString &); +static void handleBug(const QCString &); +static void handleDeprecated(const QCString &); +static void handleXRefItem(const QCString &); +static void handleRelated(const QCString &); +static void handleRelatedAlso(const QCString &); +static void handleRefItem(const QCString &); +static void handleSection(const QCString &); +static void handleAnchor(const QCString &); +static void handleFormatBlock(const QCString &); +static void handleAddIndex(const QCString &); +static void handleIf(const QCString &); +static void handleIfNot(const QCString &); +static void handleElseIf(const QCString &); +static void handleElse(const QCString &); +static void handleEndIf(const QCString &); +static void handleIngroup(const QCString &); +static void handleNoSubGrouping(const QCString &); +static void handleShowInitializer(const QCString &); +static void handleHideInitializer(const QCString &); +static void handleCallgraph(const QCString &); +static void handleInternal(const QCString &); +static void handleLineBr(const QCString &); +static void handleStatic(const QCString &); +static void handlePure(const QCString &); +static void handlePrivate(const QCString &); +static void handlePrivateSection(const QCString &); +static void handleProtected(const QCString &); +static void handleProtectedSection(const QCString &); +static void handlePublic(const QCString &s); +static void handlePublicSection(const QCString &s); +static void handleInherit(const QCString &); + + +typedef void (*DocCmdFunc)(const QCString &name); + +struct DocCmdMap +{ + const char *cmdName; + DocCmdFunc handler; +}; + +static DocCmdMap docCmdMap[] = +{ + { "brief", &handleBrief }, + { "short", &handleBrief }, + { "fn", &handleFn }, + { "var", &handleFn }, + { "typedef", &handleFn }, + { "property", &handleFn }, + { "def", &handleDef }, + { "overload", &handleOverload }, + { "enum", &handleEnum }, + { "defgroup", &handleDefGroup }, + { "addtogroup", &handleAddToGroup }, + { "weakgroup", &handleWeakGroup }, + { "namespace", &handleNamespace }, + { "package", &handlePackage }, + { "class", &handleClass }, + { "protocol", &handleProtocol }, + { "category", &handleCategory }, + { "union", &handleUnion }, + { "struct", &handleStruct }, + { "interface", &handleInterface }, + { "idlexcept", &handleIdlException }, + { "page", &handlePage }, + { "mainpage", &handleMainpage }, + { "file", &handleFile }, + { "dir", &handleDir }, + { "example", &handleExample }, + { "details", &handleDetails }, + { "name", &handleName }, + { "todo", &handleTodo }, + { "test", &handleTest }, + { "bug", &handleBug }, + { "deprecated", &handleDeprecated }, + { "xrefitem", &handleXRefItem }, + { "related", &handleRelated }, + { "relates", &handleRelated }, + { "relatedalso", &handleRelatedAlso }, + { "relatesalso", &handleRelatedAlso }, + { "refitem", &handleRefItem }, + { "section", &handleSection }, + { "subsection", &handleSection }, + { "subsubsection", &handleSection }, + { "paragraph", &handleSection }, + { "anchor", &handleAnchor }, + { "verbatim", &handleFormatBlock }, + { "latexonly", &handleFormatBlock }, + { "htmlonly", &handleFormatBlock }, + { "rtfonly", &handleFormatBlock }, + { "dot", &handleFormatBlock }, + { "code", &handleFormatBlock }, + { "addindex", &handleAddIndex }, + { "if", &handleIf }, + { "ifnot", &handleIfNot }, + { "elseif", &handleElseIf }, + { "else", &handleElse }, + { "endif", &handleEndIf }, + { "ingroup", &handleIngroup }, + { "nosubgrouping", &handleNoSubGrouping }, + { "showinitializer", &handleShowInitializer }, + { "hideinitializer", &handleHideInitializer }, + { "callgraph", &handleCallgraph }, + { "internal", &handleInternal }, + { "_linebr", &handleLineBr }, + { "static", &handleStatic }, + { "pure", &handlePure }, + { "private", &handlePrivate}, + { "privatesection", &handlePrivateSection }, + { "protected", &handleProtected }, + { "protectedsection",&handleProtectedSection }, + { "public", &handlePublic }, + { "publicsection", &handlePublicSection }, + { "inherit", &handleInherit }, + { 0, 0 } +}; + + + +/** @brief Command mapper. + * + * Maps a command name (as found in a comment block) onto a + * specific handler function. + */ +class DocCmdMapper +{ + public: + /** maps a command name to a handler function */ + static DocCmdFunc *map(const char *name) + { + return instance()->find(name); + } + + /** release the singleton */ + static void freeInstance() + { + delete s_instance; s_instance=0; + } + + private: + static DocCmdMapper *instance() + { + if (s_instance==0) s_instance = new DocCmdMapper; + return s_instance; + } + + DocCmdMapper() : m_map(89) + { + DocCmdMap *p = docCmdMap; + while (p->cmdName) + { + m_map.insert(p->cmdName,&p->handler); + p++; + } + } + + DocCmdFunc *find(const char *name) + { + return m_map.find(name); + } + QDict<DocCmdFunc> m_map; + static DocCmdMapper *s_instance; +}; + +DocCmdMapper *DocCmdMapper::s_instance=0; + + +#define YY_NEVER_INTERACTIVE 1 + +enum XRefKind +{ + XRef_Item, + XRef_Todo, + XRef_Test, + XRef_Bug, + XRef_Deprecated +}; + +enum OutputContext +{ + OutputDoc, + OutputBrief, + OutputXRef +}; + +enum GuardType +{ + Guard_If, + Guard_IfNot +}; + +class GuardedSection +{ + public: + GuardedSection(bool enabled,bool parentVisible) + : m_enabled(enabled),m_parentVisible(parentVisible) {} + bool isEnabled() const { return m_enabled; } + bool parentVisible() const { return m_parentVisible; } + + private: + bool m_enabled; + bool m_parentVisible; +}; + + +/* ----------------------------------------------------------------- + * + * statics + */ + +static const char * inputString; // input string +static int inputPosition; // read pointer +static QCString yyFileName; // file name that is read from +static int yyLineNr; // line number in the input +//static bool inBody; // was the comment found inside the body of a function? +static OutputContext inContext; // are we inside the brief, details or xref part +static bool briefEndsAtDot; // does the brief description stop at a dot? +static QCString formulaText; // Running text of a formula +static QCString formulaEnv; // environment name +static QCString *pOutputString; // pointer to string to which the output is appended. +static QCString outputXRef; // temp argument of todo/test/../xrefitem commands +static QCString blockName; // preformatted block name (e.g. verbatim, latexonly,...) +static XRefKind xrefKind; // kind of cross-reference command +static GuardType guardType; // kind of guard for conditional section +static QCString nameHeader; // heading of the @name command +static QCString functionProto; // function prototype +static QStack<GuardedSection> guards; // tracks nested conditional sections (if,ifnot,..) +static Entry* current = 0 ; // working entry +//static Entry* current_root = 0 ; // parent of working entry + + +//static Entry* previous = 0 ; // TODO: remove need for this +static bool needNewEntry; + +static QCString sectionLabel; +static QCString sectionTitle; +static QCString xrefItemKey; +static QCString xrefItemTitle; +static QCString xrefListTitle; +static Protection protection; + +//----------------------------------------------------------------------------- + +static void initParser() +{ + sectionLabel.resize(0); + sectionTitle.resize(0); + nameHeader.resize(0); +} + +//----------------------------------------------------------------------------- + +static void makeStructuralIndicator(Entry::Sections s) +{ + needNewEntry = TRUE; + current->section = s; + current->fileName = yyFileName; + current->startLine = yyLineNr; +} + +static void lineCount() +{ + for( const char* c = yytext ; *c ; ++c ) + yyLineNr += (*c == '\n') ; +} + + +static QCString stripQuotes(const char *s) +{ + QCString name; + if (s==0 || *s==0) return name; + name=s; + if (name.at(0)=='"' && name.at(name.length()-1)=='"') + { + name=name.mid(1,name.length()-2); + } + return name; +} + +//----------------------------------------------------------------- + +static void addXRefItem(const char *listName,const char *itemTitle,const char *listTitle) +{ + Entry *docEntry = current; // inBody && previous ? previous : current; + //printf("docEntry=%p\n",docEntry); + if (listName==0) return; + + //printf("addXRefItem(%s,%s,%s)\n",listName,itemTitle,listTitle); + ListItemInfo *lii=0; + RefList *refList = Doxygen::xrefLists->find(listName); + if (refList==0) // new list + { + refList = new RefList(listName,listTitle,itemTitle); + Doxygen::xrefLists->insert(listName,refList); + //printf("new list!\n"); + } + if (docEntry->sli) + { + QListIterator<ListItemInfo> slii(*docEntry->sli); + for (slii.toFirst();(lii=slii.current());++slii) + { + if (strcmp(lii->type,listName)==0) + { + //printf("found %s lii->type=%s\n",listName,lii->type); + break; + } + } + } +#if 0 // with this code multiple @todo items can be put under the same + // heading, I removed it because it changes the text flow. + if (lii) // already found item of same type before + { + //printf("listName=%s item id = %d existing\n",listName,lii->itemId); + RefItem *item = refList->getRefItem(lii->itemId); + ASSERT(item!=0); + item->text += " <p>"; + item->text += outputXRef; + //printf("%s: text +=%s\n",listName,item->text.data()); + } + else // new item +#endif + { + int itemId = refList->addRefItem(); + //printf("listName=%s item id = %d new current=%p\n",listName,itemId,current); + + // if we have already an item from the same list type (e.g. a second @todo) + // in the same Entry (i.e. lii!=0) then we reuse its link anchor. + char anchorLabel[1024]; + sprintf(anchorLabel,"_%s%06d",listName,lii ? lii->itemId : itemId); + RefItem *item = refList->getRefItem(itemId); + ASSERT(item!=0); + item->text = outputXRef; + item->listAnchor = anchorLabel; + docEntry->addSpecialListItem(listName,itemId); + QCString cmdString; + cmdString.sprintf("\\xrefitem %s %d\n",listName,itemId); + docEntry->doc += cmdString; + SectionInfo *si=new SectionInfo(listName,anchorLabel, + sectionTitle,SectionInfo::Anchor); + Doxygen::sectionDict.insert(anchorLabel,si); + docEntry->anchors->append(si); + } + //current->brief = slString; // restore orginial brief desc. +} + +//----------------------------------------------------------------------------- + +// Adds a formula text to the list/dictionary of formulas if it was +// not already added. Returns the label of the formula. +static QCString addFormula() +{ + QCString formLabel; + QCString fText=formulaText.simplifyWhiteSpace(); + Formula *f=0; + if ((f=Doxygen::formulaDict[fText])==0) + { + f = new Formula(fText); + Doxygen::formulaList.append(f); + Doxygen::formulaDict.insert(fText,f); + formLabel.sprintf("\\form#%d",f->getId()); + Doxygen::formulaNameDict.insert(formLabel,f); + } + else + { + formLabel.sprintf("\\form#%d",f->getId()); + } + return formLabel; +} + +//----------------------------------------------------------------------------- + +static void checkFormula(); +//----------------------------------------------------------------------------- + +static void prependScope() +{ + Entry *current_root = current->parent; + if (current_root && current_root->section & Entry::SCOPE_MASK) + { + //printf("--- prependScope %s to %s\n",current_root->name.data(),current->name.data()); + current->name.prepend(current_root->name+"::"); + if (current_root->tArgLists) + { + if (current->tArgLists==0) + { + current->tArgLists = new QList<ArgumentList>; + current->tArgLists->setAutoDelete(TRUE); + } + //printf("prependScope #=%d #current=%d\n",current_root->tArgLists->count(),current->tArgLists->count()); + QListIterator<ArgumentList> talsi(*current_root->tArgLists); + ArgumentList *srcAl=0; + for (talsi.toLast();(srcAl=talsi.current());--talsi) + { + ArgumentList *dstAl = new ArgumentList; + dstAl->setAutoDelete(TRUE); + QListIterator<Argument> tali(*srcAl); + Argument *a; + for (;(a=tali.current());++tali) + { + dstAl->append(new Argument(*a)); + //printf("appending argument %s %s\n",a->type.data(),a->name.data()); + } + current->tArgLists->insert(0,dstAl); + } + } + } +} + +static void addSection() +{ + sectionTitle+=yytext; + sectionTitle=sectionTitle.stripWhiteSpace(); + //printf("Adding new section file=%s label=%s title=%s\n",yyFileName,sectionLabel.data(),sectionTitle.data()); + SectionInfo *si = new SectionInfo(yyFileName,sectionLabel,sectionTitle,SectionInfo::Anchor); + current->anchors->append(si); + Doxygen::sectionDict.insert(yytext,si); +} + +//----------------------------------------------------------------------------- + +// determines the string to write to +static inline void setOutput(OutputContext ctx) +{ + if (inContext==OutputXRef) // end of XRef section => add the item + { + switch(xrefKind) + { + case XRef_Todo: + addXRefItem("todo",theTranslator->trTodo(),theTranslator->trTodoList()); + break; + case XRef_Test: + addXRefItem("test",theTranslator->trTest(),theTranslator->trTestList()); + break; + case XRef_Bug: + addXRefItem("bug",theTranslator->trBug(),theTranslator->trBugList()); + break; + case XRef_Deprecated: + addXRefItem("deprecated",theTranslator->trDeprecated(),theTranslator->trDeprecatedList()); + break; + case XRef_Item: + addXRefItem(xrefItemKey,xrefItemTitle,xrefListTitle); + break; + } + } + inContext = ctx; + switch(inContext) + { + case OutputDoc: + pOutputString = ¤t->doc; + break; + case OutputBrief: + pOutputString = ¤t->brief; + break; + case OutputXRef: + pOutputString = &outputXRef; + break; + } +} + +// add a string to the output +static inline void addOutput(const char *s) +{ + *pOutputString+=s; +} + +// add a character to the output +static inline void addOutput(char c) +{ + *pOutputString+=c; +} + +/* ----------------------------------------------------------------- */ +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); + +static int yyread(char *buf,int max_size) +{ + int c=0; + while( c < max_size && inputString[inputPosition] ) + { + *buf = inputString[inputPosition++] ; + //printf("%d (%c)\n",*buf,*buf); + c++; buf++; + } + return c; +} + +%} + + /* start command character */ +CMD ("\\"|"@") +DETAILEDCMD {CMD}("arg"|"attention"|"author"|"bug"|"code"|"date"|"deprecated"|"dot"|"dotfile"|"example"|"htmlinclude"|"htmlonly"|"image"|"include"|"includelineno"|"internal"|"invariant"|"latexonly"|"li"|"line"|manonly"|"name"|"note"|"par"|"paragraph"|"param"|"post"|"pre"|"remarks"|"relate"[sd]"("also")?|"remarks"|"return"[s]?|"retval"|"sa"|"section"|"see"|"since"|"subsection"|"subsubsection"|"test"|"throw"|"todo"|"until"|"verbatim"|"verbinclude"|"version"|"warning"|"xmlonly"|"xrefitem") + /* ("image"|"author"|"internal"|"version"|"date"|"deprecated"|"param"|"exception"|"return"[s]?|"retval"|"bug"|"warning"|"par"|"sa"|"see"|"pre"|"post"|"invariant"|"note"|"remark"[s]?|"todo"|"test"|"xrefitem"|"ingroup"|"callgraph"|"latexonly"|"htmlonly"|"xmlonly"|"{"|"verbatim"|"dotfile"|"dot"|"defgroup"|"addtogroup"|"weakgroup"|"class"|"namespace"|"union"|"struct"|"fn"|"var"|"details"|"typedef"|"def"|"overload")|("<"{PRE}">") */ +PRE [pP][rR][eE] +TABLE [tT][aA][bB][lL][eE] +P [pP] +UL [uU][lL] +OL [oO][lL] +DL [dD][lL] +IMG [iI][mM][gG] +HR [hH][rR] +CODE [cC][oO][dD][eE] +DETAILEDHTML {PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}|{CODE} +BN [ \t\n\r] +BL [ \t\r]*"\n" +B [ \t] +BS ^(({B}*"//")?)(({B}*"*"+)?){B}* +ATTR ({B}+[^>\n]*)? +DOCNL "\n"|"\\_linebr" +LC "\\"{B}*"\n" +NW [^a-z_A-Z0-9] +FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+] +FILEECHAR [a-z_A-Z0-9\-\+] +FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]+"\"") +ID "$"?[a-z_A-Z][a-z_A-Z0-9]* +LABELID [a-z_A-Z][a-z_A-Z0-9\-]* +SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?) +SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)((~{BN}*)?{ID}) + +%option nounput +%option noyywrap + + /* comment parsing states. */ +%x Comment +%x PageDocArg1 +%x PageDocArg2 +%x RelatesParam1 +%x ClassDocArg1 +%x ClassDocArg2 +%x ClassDocArg3 +%x CategoryDocArg1 +%x XRefItemParam1 +%x XRefItemParam2 +%x XRefItemParam3 +%x FileDocArg1 +%x EnumDocArg1 +%x NameSpaceDocArg1 +%x PackageDocArg1 +%x GroupDocArg1 +%x GroupDocArg2 +%x SectionLabel +%x SectionTitle +%x FormatBlock +%x LineParam +%x GuardParam +%x SkipGuardedSection +%x SkipInternal +%x NameParam +%x InGroupParam +%x FnParam +%x OverloadParam +%x InheritParam +%x ReadFormulaShort +%x ReadFormulaLong +%x AnchorLabel +%x HtmlComment + +%% + + /* What can happen in while parsing a comment block: + * commands (e.g. @page, or \page) + * escaped commands (e.g. @@page or \\page). + * formulas (e.g. \f$ \f[ \f{..) + * directories (e.g. \doxygen\src\) + * autolist end. (e.g. a dot on an otherwise empty line) + * newlines. + * end of brief due to blank line. + * end of brief due to some command (@command, or <command>). + * words and whitespace and other characters (#,?!, etc). + * grouping commands (e.g. @{ and @}) + */ + +<Comment>{CMD}{CMD}[a-z_A-Z]*{B}* { // escaped command + addOutput(yytext); + } +<Comment>("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!) + addOutput(yytext); + } +<Comment>{DETAILEDCMD}/[^a-z_A-Z] { // command that can end a brief description + setOutput(OutputDoc); + // continue with the same input + REJECT; + } +<Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description + setOutput(OutputDoc); + // continue with the same input + REJECT; + } +<Comment>"<!--" { + BEGIN(HtmlComment); + } +<Comment>{CMD}[a-z_A-Z]+{B}* { // potentially interesting command + QCString cmdName = QCString(&yytext[1]).stripWhiteSpace(); + DocCmdFunc *funcPtr = DocCmdMapper::map(cmdName); + if (funcPtr) // special action is required + { + //printf("Special command %s\n",yytext); + (*funcPtr)(cmdName); + } + else // command not relevant + { + addOutput(yytext); + } + } +<Comment>("\\\\"|"@@")"f"[$\[{] { // escaped formula command + addOutput(yytext); + } +<Comment>{CMD}"f{"[^}\n]+"}" { // start of a formula with custom environment + formulaText="\\begin"; + formulaEnv=&yytext[2]; + formulaText+=formulaEnv; + BEGIN(ReadFormulaLong); + } +<Comment>{CMD}"f$" { // start of a inline formula + formulaText="$"; + BEGIN(ReadFormulaShort); + } +<Comment>{CMD}"f[" { // start of a block formula + formulaText="\\["; + BEGIN(ReadFormulaLong); + } +<Comment>{CMD}"{" { // begin of a group + handleGroupStartCommand(nameHeader); + } +<Comment>{CMD}"}" { // end of a group + handleGroupEndCommand(); + } +<Comment>{CMD}[$@\\&~<>#%] { // escaped character + addOutput(yytext); + } +<Comment>[a-z_A-Z]+ { // normal word + addOutput(yytext); + } +<Comment>^{B}*"."{B}*/\n { // explicit end autolist: e.g " ." + addOutput(yytext); + } +<Comment>"."[a-z_A-Z0-9] { // . at start or in the middle of a word + addOutput(yytext); + } +<Comment>".\\"[ \t] { // . with escaped space. + addOutput(yytext[0]); + addOutput(yytext[2]); + } +<Comment>\n({B}*\n)+ { // at least one blank line + if (inContext) + { + setOutput(OutputDoc); + } + else + { + addOutput(yytext); + } + lineCount(); + } +<Comment>"." { // potential end of a JavaDoc style comment + addOutput(*yytext); + if (briefEndsAtDot) + { + setOutput(OutputDoc); + } + } +<Comment>\n { // newline + addOutput(*yytext); + yyLineNr++; + } +<Comment>. { // catch-all for anything else + addOutput(*yytext); + } + + + /* -------------- Rules for handling HTML comments ----------- */ + +<HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); } +<HtmlComment>{DOCNL} { + if (*yytext=='\n') yyLineNr++; + } +<HtmlComment>[^\\\n\-]+ { // ignore unimportant characters + } +<HtmlComment>. { // ignore every else + } + + /* -------------- Rules for handling formulas ---------------- */ + +<ReadFormulaShort>{CMD}"f$" { // end of inline formula + formulaText+="$"; + addOutput(addFormula()); + addOutput(' '); + BEGIN(Comment); + } +<ReadFormulaLong>{CMD}"f]" { // end of block formula + formulaText+="\\]"; + addOutput(addFormula()); + addOutput(' '); + BEGIN(Comment); + } +<ReadFormulaLong>{CMD}"f}" { // end of custom env formula + formulaText+="\\end"; + formulaText+=formulaEnv; + addOutput(addFormula()); + addOutput(' '); + BEGIN(Comment); + } +<ReadFormulaLong,ReadFormulaShort>[^\\@\n]+ { // any non-special character + formulaText+=yytext; + } +<ReadFormulaLong,ReadFormulaShort>\n { // new line + formulaText+=*yytext; + yyLineNr++; + } +<ReadFormulaLong,ReadFormulaShort>. { // any othe character + formulaText+=*yytext; + } + + /* ------------ handle argument of enum command --------------- */ + +<EnumDocArg1>{SCOPEID} { // handle argument + current->name = yytext; + prependScope(); + BEGIN( Comment ); + } +<EnumDocArg1>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<EnumDocArg1>{DOCNL} { // missing argument + warn(yyFileName,yyLineNr, + "Warning: missing argument after \\enum." + ); + addOutput('\n'); + if (*yytext=='\n') yyLineNr++; + BEGIN( Comment ); + } +<EnumDocArg1>. { // ignore other stuff + } + + /* ------------ handle argument of namespace command --------------- */ + +<NameSpaceDocArg1>{SCOPENAME} { // handle argument + current->name = yytext; + BEGIN( Comment ); + } +<NameSpaceDocArg1>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<NameSpaceDocArg1>{DOCNL} { // missing argument + warn(yyFileName,yyLineNr, + "Warning: missing argument after " + "\\namespace." + ); + addOutput('\n'); + if (*yytext=='\n') yyLineNr++; + BEGIN( Comment ); + } +<NameSpaceDocArg1>. { // ignore other stuff + } + + /* ------------ handle argument of package command --------------- */ + +<PackageDocArg1>{ID}("."{ID})* { // handle argument + current->name = yytext; + BEGIN( Comment ); + } +<PackageDocArg1>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<PackageDocArg1>{DOCNL} { // missing argument + warn(yyFileName,yyLineNr, + "Warning: missing argument after " + "\\package." + ); + addOutput('\n'); + if (*yytext=='\n') yyLineNr++; + BEGIN( Comment ); + } +<PackageDocArg1>. { // ignore other stuff + } + + /* ------ handle argument of class/struct/union command --------------- */ + +<ClassDocArg1>{SCOPENAME} { // first argument + current->name = yytext; + if (current->section==Entry::PROTOCOLDOC_SEC) + { + current->name+="-p"; + } + // prepend outer scope name + prependScope(); + BEGIN( ClassDocArg2 ); + } +<CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" { + current->name = yytext; + prependScope(); + BEGIN( ClassDocArg2 ); + } +<ClassDocArg1,CategoryDocArg1>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<ClassDocArg1,CategoryDocArg1>{DOCNL} { + warn(yyFileName,yyLineNr, + "Warning: missing argument after " + "\\%s.",YY_START==ClassDocArg1?"class":"category" + ); + addOutput('\n'); + if (*yytext=='\n') yyLineNr++; + BEGIN( Comment ); + } +<ClassDocArg1,CategoryDocArg1>. { // ignore other stuff + } + +<ClassDocArg2>{FILE} { // second argument; include file + current->includeFile = stripQuotes(yytext); + BEGIN( ClassDocArg3 ); + } +<ClassDocArg2>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<ClassDocArg2>{DOCNL} { + addOutput('\n'); + if (*yytext=='\n') yyLineNr++; + BEGIN( Comment ); + } +<ClassDocArg2>. { // ignore other stuff + } + +<ClassDocArg3>[<]?{FILE}[>]? { // third argument; include file name + current->includeName = yytext; + BEGIN( Comment ); + } +<ClassDocArg3>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<ClassDocArg3>{DOCNL} { + if (*yytext=='\n') yyLineNr++; + BEGIN( Comment ); + } +<ClassDocArg3>. { // ignore other stuff + } + + /* --------- handle arguments of {def,add,weak}group commands --------- */ + +<GroupDocArg1>{ID}(".html"?) { // group name + current->name = yytext; + //lastDefGroup.groupname = yytext; + //lastDefGroup.pri = current->groupingPri(); + // the .html stuff is for Qt compatibility + if (current->name.right(5)==".html") + { + current->name=current->name.left(current->name.length()-5); + } + BEGIN(GroupDocArg2); + } +<GroupDocArg1>"\\"{B}*"\n" { // line continuation + yyLineNr++; + addOutput('\n'); + } +<GroupDocArg1>{DOCNL} { // missing argument! + warn(yyFileName,yyLineNr, + "Warning: missing group name after %s", + current->groupDocCmd() + ); + addOutput('\n'); + if (*yytext=='\n') yyLineNr++; + BEGIN( Comment ); + } +<GroupDocArg2>"\\"{B}*"\n" { // line continuation + yyLineNr++; + addOutput('\n'); + } +<GroupDocArg2>[^\n\\\*]+ { // title (stored in type) + current->type += yytext; + current->type = current->type.stripWhiteSpace(); + } +<GroupDocArg2>{DOCNL} { + if ( current->groupDocType==Entry::GROUPDOC_NORMAL && + current->type.isEmpty() + ) // defgroup requires second argument + { + warn(yyFileName,yyLineNr, + "Warning: missing title after " + "\\defgroup %s", current->name.data() + ); + } + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } + + /* --------- handle arguments of page/mainpage command ------------------- */ + +<PageDocArg1>{FILE} { // first argument; page name + current->name = stripQuotes(yytext); + BEGIN( PageDocArg2 ); + } +<PageDocArg1>{LC} { yyLineNr++; + addOutput('\n'); + } +<PageDocArg1>{DOCNL} { + warn(yyFileName,yyLineNr, + "Warning: missing argument after " + "\\page." + ); + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<PageDocArg1>. { // ignore other stuff + } +<PageDocArg2>.*"\n" { // second argument; page title + yyLineNr++; + current->args = yytext; + addOutput('\n'); + BEGIN( Comment ); + } + + /* --------- handle arguments of the file/dir/example command ------------ */ + +<FileDocArg1>{FILE} { // first argument; name + current->name = stripQuotes(yytext); + BEGIN( Comment ); + } +<FileDocArg1>{LC} { yyLineNr++; + addOutput('\n'); + } +<FileDocArg1>{DOCNL} { // no file name specfied + current->name = yyFileName; + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<FileDocArg1>. { // ignore other stuff + } + + /* --------- handle arguments of the xrefitem command ------------ */ + +<XRefItemParam1>{ID} { // first argument + xrefItemKey=yytext; + BEGIN(XRefItemParam2); + } +<XRefItemParam1>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<XRefItemParam1>{DOCNL} { // missing arguments + warn(yyFileName,yyLineNr, + "Warning: Missing first argument of \\xrefitem" + ); + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + inContext = OutputDoc; + BEGIN( Comment ); + } +<XRefItemParam1>. { // ignore other stuff + } + +<XRefItemParam2>"\""[^\n\"]*"\"" { // second argument + xrefItemTitle = stripQuotes(yytext); + BEGIN(XRefItemParam3); + } +<XRefItemParam2>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<XRefItemParam2>{DOCNL} { // missing argument + warn(yyFileName,yyLineNr, + "Warning: Missing second argument of \\xrefitem" + ); + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + inContext = OutputDoc; + BEGIN( Comment ); + } +<XRefItemParam2>. { // ignore other stuff + } + +<XRefItemParam3>"\""[^\n\"]*"\"" { // third argument + xrefListTitle = stripQuotes(yytext); + BEGIN( Comment ); + } +<XRefItemParam2>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<XRefItemParam3>{DOCNL} { // missing argument + warn(yyFileName,yyLineNr, + "Warning: Missing third argument of \\xrefitem" + ); + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + inContext = OutputDoc; + BEGIN( Comment ); + } +<XRefItemParam3>. { // ignore other stuff + } + + + /* --------- handle arguments of the relates(also) command ------------ */ + +<RelatesParam1>({ID}("::"|"."))*{ID} { // argument + current->relates = yytext; + //if (current->mGrpId!=DOX_NOGROUP) + //{ + // memberGroupRelates = yytext; + //} + BEGIN( Comment ); + } +<RelatesParam1>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<RelatesParam1>{DOCNL} { // missing argument + warn(yyFileName,yyLineNr, + "Warning: Missing argument of \\relates command" + ); + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<RelatesParam1>. { // ignore other stuff + } + + + /* ----- handle arguments of the relates(also)/addindex commands ----- */ + +<LineParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<LineParam>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<LineParam>. { // ignore other stuff + addOutput(*yytext); + } + + /* ----- handle arguments of the section/subsection/.. commands ------- */ + +<SectionLabel>{LABELID} { // first argyment + sectionLabel=yytext; + sectionTitle.resize(0); + current->doc+=yytext; + BEGIN(SectionTitle); + } +<SectionLabel>{DOCNL} { // missing argument + warn(yyFileName,yyLineNr, + "Warning: \\section command has no label" + ); + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<SectionLabel>. { // invalid character for section label + warn(yyFileName,yyLineNr, + "Warning: Invalid or missing section label" + ); + BEGIN(Comment); + } + +<SectionTitle>[^\n@\\*]*/"\n" { // end of section title + addSection(); + addOutput(yytext); + BEGIN( Comment ); + } +<SectionTitle>[^\n@\\]*/"\\_linebr" { // end of section title + addSection(); + addOutput(yytext); + BEGIN( Comment ); + } +<SectionTitle>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<SectionTitle>[^\n@\\]* { // any character without special meaning + sectionTitle+=yytext; + current->doc+=yytext; + } +<SectionTitle>("\\\\"|"@@") { // unescape escaped command + sectionTitle+=*yytext; + current->doc+=*yytext; + } +<SectionTitle>. { // anything else + sectionTitle+=yytext; + current->doc+=yytext; + } + + /* ----- handle arguments of the anchor command ------- */ + +<AnchorLabel>{LABELID} { // found argument + SectionInfo *si = new SectionInfo(yyFileName,yytext,0,SectionInfo::Anchor); + Doxygen::sectionDict.insert(yytext,si); + current->anchors->append(si); + addOutput(yytext); + BEGIN( Comment ); + } +<AnchorLabel>{DOCNL} { // missing argument + warn(yyFileName,yyLineNr, + "Warning: \\anchor command has no label" + ); + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<AnchorLabel>. { // invalid character for anchor label + warn(yyFileName,yyLineNr, + "Warning: Invalid or missing anchor label" + ); + BEGIN(Comment); + } + + + /* ----- handle arguments of the preformatted block commands ------- */ + +<FormatBlock>{CMD}("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddot"|"endcode")/{NW} { // possible ends + addOutput(yytext); + if (&yytext[4]==blockName) // found end of the block + { + BEGIN(Comment); + } + } +<FormatBlock>[^ \@\\\n]* { // some word + addOutput(yytext); + } +<FormatBlock>{DOCNL} { // new line + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + } +<FormatBlock>. { + addOutput(*yytext); + } +<FormatBlock><<EOF>> { + warn(yyFileName,yyLineNr, + "Warning: reached end of comment while inside a @%s block; check for missing @end%s tag!", + blockName.data(),blockName.data() + ); + yyterminate(); + } + + /* ----- handle arguments of if/ifnot commands ------- */ + +<GuardParam>{LABELID} { // parameter of if/ifnot guard + bool sectionEnabled = Config_getList("ENABLED_SECTIONS").find(yytext)!=-1; + bool parentEnabled = TRUE; + if (!guards.isEmpty()) parentEnabled = guards.top()->isEnabled(); + if (parentEnabled) + { + if ( + (sectionEnabled && guardType==Guard_If) || + (!sectionEnabled && guardType==Guard_IfNot) + ) // section is visible + { + guards.push(new GuardedSection(TRUE,TRUE)); + BEGIN( Comment ); + } + else // section is invisible + { + guards.push(new GuardedSection(FALSE,TRUE)); + BEGIN( SkipGuardedSection ); + } + } + else // invisible because of parent + { + guards.push(new GuardedSection(FALSE,FALSE)); + BEGIN( SkipGuardedSection ); + } + } +<GuardParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<GuardParam>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<GuardParam>. { // ignore other stuff + addOutput(*yytext); + } + + /* ----- handle skipping of conditional sections ------- */ + +<SkipGuardedSection>{CMD}"ifnot"/{NW} { + guardType = Guard_IfNot; + BEGIN( GuardParam ); + } +<SkipGuardedSection>{CMD}"if"/{NW} { + guardType = Guard_If; + BEGIN( GuardParam ); + } +<SkipGuardedSection>{CMD}"endif"/{NW} { + if (guards.isEmpty()) + { + warn(yyFileName,yyLineNr, + "Warning: found @endif without matching start command"); + } + else + { + delete guards.pop(); + BEGIN( Comment ); + } + } +<SkipGuardedSection>{CMD}"else"/{NW}] { + if (guards.isEmpty()) + { + warn(yyFileName,yyLineNr, + "Warning: found @else without matching start command"); + } + else + { + if (guards.top()->parentVisible()) + { + delete guards.pop(); + guards.push(new GuardedSection(TRUE,TRUE)); + BEGIN( Comment ); + } + } + } +<SkipGuardedSection>{CMD}"elseif"/{NW} { + if (guards.isEmpty()) + { + warn(yyFileName,yyLineNr, + "Warning: found @elseif without matching start command"); + } + else + { + if (guards.top()->parentVisible()) + { + delete guards.pop(); + BEGIN( GuardParam ); + } + } + } +<SkipGuardedSection>{DOCNL} { // skip line + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + } +<SkipGuardedSection>[^ \\@\n]+ { // skip non-special characters + } +<SkipGuardedSection>. { // any other character + } + + + /* ----- handle skipping of internal section ------- */ + +<SkipInternal>{DOCNL} { // skip line + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + } +<SkipInternal>[^ \\@\n]+ { // skip non-special characters + } +<SkipInternal>. { // any other character + } + + + /* ----- handle argument of name command ------- */ + +<NameParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<NameParam>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + nameHeader+=' '; + } +<NameParam>. { // ignore other stuff + nameHeader+=*yytext; + } + + /* ----- handle argument of ingroup command ------- */ + +<InGroupParam>{ID} { // group id + current->groups->append( + new Grouping(yytext, Grouping::GROUPING_INGROUP) + ); + BEGIN( Comment ); + } +<InGroupParam>{DOCNL} { // missing argument + warn(yyFileName,yyLineNr, + "Warning: Missing group name for \\ingroup command" + ); + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<InGroupParam>{LC} { // line continuation + yyLineNr++; + addOutput('\n'); + } +<InGroupParam>. { // ignore other stuff + addOutput(*yytext); + } + + /* ----- handle argument of fn command ------- */ + +<FnParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + parsePrototype(functionProto); + BEGIN( Comment ); + } +<FnParam>{LC} { // line continuation + yyLineNr++; + functionProto+=' '; + } +<FnParam>[^@\\\n]+ { // non-special characters + functionProto+=yytext; + } +<FnParam>. { // add other stuff + functionProto+=*yytext; + } + + + /* ----- handle argument of overload command ------- */ + + +<OverloadParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + if (functionProto.stripWhiteSpace().isEmpty()) + { // plain overload command + addOutput(getOverloadDocs()); + } + else // overload declaration + { + makeStructuralIndicator(Entry::OVERLOADDOC_SEC); + parsePrototype(functionProto); + } + BEGIN( Comment ); + } +<OverloadParam>{LC} { // line continuation + yyLineNr++; + functionProto+=' '; + } +<OverloadParam>. { // add other stuff + functionProto+=*yytext; + } + + /* ----- handle argument of inherit command ------- */ + +<InheritParam>({ID}("::"|"."))*{ID} { // found argument + current->extends->append( + new BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal) + ); + BEGIN( Comment ); + } +<InheritParam>{DOCNL} { // missing argument + warn(yyFileName,yyLineNr, + "Warning: \\inherit command has no argument" + ); + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<InheritParam>. { // invalid character for anchor label + warn(yyFileName,yyLineNr, + "Warning: Invalid or missing name for \\inherit command" + ); + BEGIN(Comment); + } + +%% + +//---------------------------------------------------------------------------- + +static void handleBrief(const QCString &) +{ + //printf("handleBrief\n"); + setOutput(OutputBrief); +} + +static void handleFn(const QCString &) +{ + makeStructuralIndicator(Entry::MEMBERDOC_SEC); + functionProto.resize(0); + BEGIN(FnParam); +} + +static void handleDef(const QCString &) +{ + makeStructuralIndicator(Entry::DEFINEDOC_SEC); + functionProto.resize(0); + BEGIN(FnParam); +} + +static void handleOverload(const QCString &) +{ + functionProto.resize(0); + BEGIN(OverloadParam); +} + +static void handleEnum(const QCString &) +{ + makeStructuralIndicator(Entry::ENUMDOC_SEC); + BEGIN(EnumDocArg1); +} + +static void handleDefGroup(const QCString &) +{ + makeStructuralIndicator(Entry::GROUPDOC_SEC); + current->groupDocType = Entry::GROUPDOC_NORMAL; + BEGIN( GroupDocArg1 ); +} + +static void handleAddToGroup(const QCString &) +{ + makeStructuralIndicator(Entry::GROUPDOC_SEC); + current->groupDocType = Entry::GROUPDOC_ADD; + BEGIN( GroupDocArg1 ); +} + +static void handleWeakGroup(const QCString &) +{ + makeStructuralIndicator(Entry::GROUPDOC_SEC); + current->groupDocType = Entry::GROUPDOC_WEAK; + BEGIN( GroupDocArg1 ); +} + +static void handleNamespace(const QCString &) +{ + makeStructuralIndicator(Entry::NAMESPACEDOC_SEC); + BEGIN( NameSpaceDocArg1 ); +} + +static void handlePackage(const QCString &) +{ + makeStructuralIndicator(Entry::PACKAGEDOC_SEC); + BEGIN( PackageDocArg1 ); +} + +static void handleClass(const QCString &) +{ + makeStructuralIndicator(Entry::CLASSDOC_SEC); + BEGIN( ClassDocArg1 ); +} + +static void handleProtocol(const QCString &) +{ // Obj-C protocol + makeStructuralIndicator(Entry::PROTOCOLDOC_SEC); + BEGIN( ClassDocArg1 ); +} + +static void handleCategory(const QCString &) +{ // Obj-C category + makeStructuralIndicator(Entry::CATEGORYDOC_SEC); + BEGIN( CategoryDocArg1 ); +} + +static void handleUnion(const QCString &) +{ + makeStructuralIndicator(Entry::UNIONDOC_SEC); + BEGIN( ClassDocArg1 ); +} + +static void handleStruct(const QCString &) +{ + makeStructuralIndicator(Entry::STRUCTDOC_SEC); + BEGIN( ClassDocArg1 ); +} + +static void handleInterface(const QCString &) +{ + makeStructuralIndicator(Entry::INTERFACEDOC_SEC); + BEGIN( ClassDocArg1 ); +} + +static void handleIdlException(const QCString &) +{ + makeStructuralIndicator(Entry::EXCEPTIONDOC_SEC); + BEGIN( ClassDocArg1 ); +} + +static void handlePage(const QCString &) +{ + makeStructuralIndicator(Entry::PAGEDOC_SEC); + BEGIN( PageDocArg1 ); +} + +static void handleMainpage(const QCString &) +{ + makeStructuralIndicator(Entry::MAINPAGEDOC_SEC); + current->name = "mainpage"; + BEGIN( PageDocArg2 ); +} + +static void handleFile(const QCString &) +{ + makeStructuralIndicator(Entry::FILEDOC_SEC); + BEGIN( FileDocArg1 ); +} + +static void handleDir(const QCString &) +{ + makeStructuralIndicator(Entry::DIRDOC_SEC); + BEGIN( FileDocArg1 ); +} + +static void handleExample(const QCString &) +{ + makeStructuralIndicator(Entry::EXAMPLE_SEC); + BEGIN( FileDocArg1 ); +} + +static void handleDetails(const QCString &) +{ + setOutput(OutputDoc); +} + +static void handleName(const QCString &) +{ + makeStructuralIndicator(Entry::MEMBERGRP_SEC); + nameHeader.resize(0); + BEGIN( NameParam ); +} + +static void handleTodo(const QCString &) +{ + xrefKind = XRef_Todo; + setOutput(OutputXRef); +} + +static void handleTest(const QCString &) +{ + xrefKind = XRef_Test; + setOutput(OutputXRef); +} + +static void handleBug(const QCString &) +{ + xrefKind = XRef_Bug; + setOutput(OutputXRef); +} + +static void handleDeprecated(const QCString &) +{ + xrefKind = XRef_Deprecated; + setOutput(OutputXRef); +} + +static void handleXRefItem(const QCString &) +{ + xrefKind = XRef_Item; + setOutput(OutputXRef); + BEGIN(XRefItemParam1); +} + +static void handleRelated(const QCString &) +{ + BEGIN(RelatesParam1); +} + +static void handleRelatedAlso(const QCString &) +{ + current->relatesDup = TRUE; + BEGIN(RelatesParam1); +} + +static void handleRefItem(const QCString &) +{ + addOutput("@refitem "); + BEGIN(LineParam); +} + +static void handleSection(const QCString &s) +{ + addOutput("@"+s+" "); + BEGIN(SectionLabel); +} + +static void handleAnchor(const QCString &) +{ + BEGIN(AnchorLabel); +} + +static void handleFormatBlock(const QCString &s) +{ + addOutput("@"+s+" "); + //printf("handleFormatBlock(%s)\n",s.data()); + blockName=s; + BEGIN(FormatBlock); +} + +static void handleAddIndex(const QCString &) +{ + addOutput("@addindex "); + BEGIN(LineParam); +} + +static void handleIf(const QCString &) +{ + guardType = Guard_If; + BEGIN(GuardParam); +} + +static void handleIfNot(const QCString &) +{ + guardType = Guard_IfNot; + BEGIN(GuardParam); +} + +static void handleElseIf(const QCString &) +{ + if (guards.isEmpty()) + { + warn(yyFileName,yyLineNr, + "Warning: found @else without matching start command"); + } + else + { + guardType = Guard_If; + BEGIN(GuardParam); + } +} + +static void handleElse(const QCString &) +{ + if (guards.isEmpty()) + { + warn(yyFileName,yyLineNr, + "Warning: found @else without matching start command"); + } + else + { + BEGIN( SkipGuardedSection ); + } +} + +static void handleEndIf(const QCString &) +{ + if (guards.isEmpty()) + { + warn(yyFileName,yyLineNr, + "Warning: found @endif without matching start command"); + } + else + { + delete guards.pop(); + } +} + +static void handleIngroup(const QCString &) +{ + BEGIN( InGroupParam ); +} + +static void handleNoSubGrouping(const QCString &) +{ + current->subGrouping = FALSE; +} + +static void handleShowInitializer(const QCString &) +{ + current->initLines = 100000; // ON +} + +static void handleHideInitializer(const QCString &) +{ + current->initLines = 0; // OFF +} + +static void handleCallgraph(const QCString &) +{ + current->callGraph = TRUE; // ON +} + +static void handleInternal(const QCString &) +{ + if (!Config_getBool("INTERNAL_DOCS")) + { + BEGIN( SkipInternal ); + } + else + { + addOutput("\\internal "); + } +} + +static void handleLineBr(const QCString &) +{ + addOutput('\n'); +} + +static void handleStatic(const QCString &) +{ + current->stat = TRUE; +} + +static void handlePure(const QCString &) +{ + current->virt = Pure; +} + +static void handlePrivate(const QCString &) +{ + current->protection = Private; +} + +static void handlePrivateSection(const QCString &) +{ + current->protection = protection = Private; +} + +static void handleProtected(const QCString &) +{ + current->protection = Protected; +} + +static void handleProtectedSection(const QCString &) +{ + current->protection = protection = Protected ; +} + +static void handlePublic(const QCString &) +{ + current->protection = Public; +} + +static void handlePublicSection(const QCString &) +{ + current->protection = protection = Public; +} + +static void handleInherit(const QCString &) +{ + BEGIN(InheritParam); +} + +//---------------------------------------------------------------------------- + +static void checkFormula() +{ + if (YY_START==ReadFormulaShort || YY_START==ReadFormulaLong) + { + warn(yyFileName,yyLineNr,"Warning: End of comment block while inside formula."); + } +} + +//---------------------------------------------------------------------------- + +bool parseCommentBlock(/* in,out */ Entry *curEntry, + /* in */ const QCString &comment, + /* in */ const QCString &fileName, + /* in */ int lineNr, + /* in */ bool isBrief, + /* in */ bool isJavaDocStyle, + /* in,out */ Protection &prot + ) +{ + //fprintf(stderr,"isBrief=%d isJavaDocStyle=%d\n", + // isBrief,isJavaDocStyle); + initParser(); + guards.setAutoDelete(TRUE); + guards.clear(); + //current_root = rootEntry; + current = curEntry; + //previous = prevEntry; + inputString = comment; + inputPosition = 0; + yyLineNr = lineNr; + yyFileName = fileName; + //inBody = foundInBody; + protection = prot; + needNewEntry = FALSE; + setOutput( isBrief || isJavaDocStyle ? OutputBrief : OutputDoc ); + briefEndsAtDot = isJavaDocStyle; + commentScanYYrestart( commentScanYYin ); + BEGIN( Comment ); + commentScanYYlex(); + setOutput( OutputDoc ); + + if (!guards.isEmpty()) + { + warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!"); + } + + if (current->section==Entry::FILEDOC_SEC && current->doc.isEmpty()) + { + // to allow a comment block with just a @file command. + current->doc="\n\n"; + } + + checkFormula(); + prot = protection; + + return needNewEntry; +} + +#if 0 +//---------------------------------------------------------------------------- +void commentScanTest() +{ + Entry *ce = new Entry; + Entry *pe = new Entry; + Entry *re = new Entry; + Protection prot=Public; + + ce->doc.resize(0);ce->brief.resize(0); + parseCommentBlock(ce,pe,re,"@brief A brief description.\n\n" + "This is a @e simple test!\n","test.dox", + 1,FALSE,FALSE,FALSE,prot); + printf("---------\nbrief test: result: brief=[%s] doc=[%s]\n",ce->brief.data(),ce->doc.data()); + + ce->doc.resize(0);ce->brief.resize(0); + parseCommentBlock(ce,pe,re,"@defgroup grp A group\n" + "This is a @c group definition.","test.dox", + 1,FALSE,FALSE,FALSE,prot); + printf("---------\ndefgroup test: result: brief=[%s] doc=[%s]\n",ce->brief.data(),ce->doc.data()); + + ce->doc.resize(0);ce->brief.resize(0); + parseCommentBlock(ce,pe,re,"A code example:\n" + "@code\n" + "void main()\n" + "{\n" + " printf(\"Hello world\");\n" + "}\n" + "@endcode\n" + "More text follows.","test.dox", + 1,FALSE,FALSE,FALSE,prot); + printf("---------\ncode test: result: brief=[%s] doc=[%s]\n",ce->brief.data(),ce->doc.data()); + + ce->doc.resize(0);ce->brief.resize(0); + parseCommentBlock(ce,pe,re,"Some text <!-- A comment --> and more.\n" + ,"test.dox", + 1,FALSE,FALSE,FALSE,prot); + printf("---------\nhtml comment test: result: brief=[%s] doc=[%s]\n",ce->brief.data(),ce->doc.data()); + +} +#endif + +#if !defined(YY_FLEX_SUBMINOR_VERSION) +//---------------------------------------------------------------------------- +extern "C" { // some bogus code to keep the compiler happy + void commentScanYYdummy() { yy_flex_realloc(0,0); } +} +#endif + diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 5b14d35..e77f1b2 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -308,9 +308,11 @@ OPMASK ({BLANK}*{OPNORM}{FUNCARG})|({OPCAST}{FUNCARG}) LNKWORD1 ("::"|"#")?{SCOPEMASK} CVSPEC {BLANK}*("const"|"volatile") LNKWORD2 {SCOPEPRE}*"operator"{OPMASK} -WORD1 [^ \t\n\r\\@<>()\[\]:;\?{}&$#,.]+|"{"|"}"|("\""[^"\n]*"\"") +CHARWORD [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,.] +CHARWORDQ [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,."] +WORD1 "%"?{CHARWORD}+|"{"|"}"|("\""[^"\n]*"\"") WORD2 "."|","|"("|")"|"["|"]"|":"|";"|"\?" -WORD1NQ [^ \t\n\r\\@<>()\[\]:;\?{}&$#,."]+ +WORD1NQ "%"?{CHARWORDQ}+ WORD2NQ "."|","|"("|")"|"["|"]"|":"|";"|"\?" HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*">" HTMLKEYL "strong"|"center"|"table"|"caption"|"small"|"code"|"dfn"|"var"|"img"|"pre"|"sub"|"sup"|"tr"|"td"|"th"|"ol"|"ul"|"li"|"tt"|"kbd"|"em"|"hr"|"dl"|"dt"|"dd"|"br"|"i"|"a"|"b"|"p" diff --git a/src/dot.cpp b/src/dot.cpp index c2eb310..d13a7ff 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -566,10 +566,11 @@ static QCString convertLabel(const QCString &l) switch(c) { case '\\': result+="\\\\"; break; - case '<': result+="\\<"; break; - case '>': result+="\\>"; break; - case '|': result+="\\|"; break; - default: result+=c; break; + case '<': result+="\\<"; break; + case '>': result+="\\>"; break; + case '|': result+="\\|"; break; + case '"': result+="\\\""; break; + default: result+=c; break; } } return result; diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 03fdbfe..44c7796 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -7839,7 +7839,7 @@ static const char *getArg(int argc,char **argv,int &optind) //---------------------------------------------------------------------------- -//extern void commentScanTest(); +extern void commentScanTest(); void initDoxygen() { @@ -7868,8 +7868,6 @@ void initDoxygen() Doxygen::lookupCache.setAutoDelete(TRUE); Doxygen::directories.setAutoDelete(TRUE); Doxygen::dirRelations.setAutoDelete(TRUE); - - // commentScanTest(); } void cleanUpDoxygen() diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index 542745d..33de0e3 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -722,7 +722,7 @@ void HtmlDocVisitor::visitPre(DocImage *img) } m_t << "<div align=\"center\">" << endl; m_t << "<img src=\"" << img->relPath() << img->name() << "\" alt=\"" - << baseName << "\"" << htmlAttribsToString(img->attribs()) << ">" << endl; + << baseName << "\"" << ">" << endl; if (img->hasCaption()) { m_t << "<p><strong>"; diff --git a/src/index.xsd b/src/index.xsd index 0e145c1..d7ab2a9 100644 --- a/src/index.xsd +++ b/src/index.xsd @@ -14,7 +14,7 @@ <xsd:element name="name" type="xsd:string"/> <xsd:element name="member" type="MemberType" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> - <xsd:attribute name="refid" type="xsd:Name" use="required"/> + <xsd:attribute name="refid" type="xsd:string" use="required"/> <xsd:attribute name="kind" type="CompoundKind" use="required"/> </xsd:complexType> @@ -22,7 +22,7 @@ <xsd:sequence> <xsd:element name="name" type="xsd:string"/> </xsd:sequence> - <xsd:attribute name="refid" type="xsd:Name" use="required"/> + <xsd:attribute name="refid" type="xsd:string" use="required"/> <xsd:attribute name="kind" type="MemberKind" use="required"/> </xsd:complexType> diff --git a/src/index_xsd.h b/src/index_xsd.h index 6a3b3da..2f5d0c5 100644 --- a/src/index_xsd.h +++ b/src/index_xsd.h @@ -14,7 +14,7 @@ " <xsd:element name=\"name\" type=\"xsd:string\"/>\n" " <xsd:element name=\"member\" type=\"MemberType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n" " </xsd:sequence>\n" -" <xsd:attribute name=\"refid\" type=\"xsd:Name\" use=\"required\"/>\n" +" <xsd:attribute name=\"refid\" type=\"xsd:string\" use=\"required\"/>\n" " <xsd:attribute name=\"kind\" type=\"CompoundKind\" use=\"required\"/>\n" " </xsd:complexType>\n" "\n" @@ -22,7 +22,7 @@ " <xsd:sequence>\n" " <xsd:element name=\"name\" type=\"xsd:string\"/>\n" " </xsd:sequence>\n" -" <xsd:attribute name=\"refid\" type=\"xsd:Name\" use=\"required\"/>\n" +" <xsd:attribute name=\"refid\" type=\"xsd:string\" use=\"required\"/>\n" " <xsd:attribute name=\"kind\" type=\"MemberKind\" use=\"required\"/>\n" " </xsd:complexType>\n" " \n" diff --git a/src/language.cpp b/src/language.cpp index 8bb6b88..8b8f426 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -182,6 +182,8 @@ bool setTranslator(const char *langName) { theTranslator=new TranslatorJapanese; } +#endif +#ifdef LANG_JE else if (L_EQUAL("japanese-en")) { theTranslator=new TranslatorJapaneseEn; @@ -236,6 +238,8 @@ bool setTranslator(const char *langName) { theTranslator=new TranslatorKorean; } +#endif +#ifdef LANG_KE else if (L_EQUAL("korean-en")) { theTranslator=new TranslatorKoreanEn; diff --git a/src/libdoxygen.pro.in b/src/libdoxygen.pro.in index 4a1b5cd..55b97ab 100644 --- a/src/libdoxygen.pro.in +++ b/src/libdoxygen.pro.in @@ -22,6 +22,7 @@ HEADERS = bufstr.h \ cmdmapper.h \ code.h \ commentcnv.h \ + commentscan.h \ compound_xsd.h \ config.h \ constexp.h \ @@ -183,8 +184,8 @@ SOURCES = ce_lex.cpp \ util.cpp \ version.cpp \ xmldocvisitor.cpp \ - xmlgen.cpp -# commentscan.cpp + xmlgen.cpp \ + commentscan.cpp win32:TMAKE_CXXFLAGS += -DQT_NODLL win32-msvc:TMAKE_CXXFLAGS += -Zm200 @@ -402,12 +402,12 @@ static void returnCharToStream(char c) static inline void addTillEndOfString(const QCString &expr,QCString *rest, uint &pos,char term,QCString &arg) { - char cc; + int cc; while ((cc=getNextChar(expr,rest,pos))!=EOF) { - if (cc=='\\') arg+=cc,cc=getNextChar(expr,rest,pos); + if (cc=='\\') arg+=(char)cc,cc=getNextChar(expr,rest,pos); else if (cc==term) return; - arg+=cc; + arg+=(char)cc; } } diff --git a/src/scanner.h b/src/scanner.h index 1fc6416..36abd4d 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -23,7 +23,13 @@ class OutputList; class Entry; -extern void parseMain(Entry *); -extern void parseMain(Entry *,const char *fileName); +// Public interface provided by the language scanner +void parseMain(Entry *); +void parseMain(Entry *,const char *fileName); + +// Internal callback interface for comment block scanner +void parsePrototype(const QCString &text); +void handleGroupStartCommand(const char *header); +void handleGroupEndCommand(); #endif diff --git a/src/scanner.l b/src/scanner.l index a42e86d..0c04c87 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -45,7 +45,9 @@ #include "membergroup.h" #include "reflist.h" #include "code.h" +#include "commentscan.h" +#define COMMENTSCAN #define YY_NEVER_INTERACTIVE 1 @@ -176,6 +178,12 @@ static QCString docBackup; static QCString briefBackup; static bool g_inputFromFile; +static int docBlockContext; +static QCString docBlock; +static QCString docBlockName; +static bool docBlockInBody; +static bool docBlockJavaStyle; + //----------------------------------------------------------------------------- @@ -257,7 +265,9 @@ static int newMemberGroupId() } // forward declarations +#ifndef COMMENTSCAN static void startGroup(); +#endif static void startGroupInDoc(); static void endGroup(); @@ -305,6 +315,74 @@ static void newDocState(); //----------------------------------------------------------------- +static void addMemberGroupDocs() +{ + memberGroupDocs=current->brief.stripWhiteSpace(); + current->doc = current->doc.stripWhiteSpace(); + if (!memberGroupDocs.isEmpty() && !current->doc.isEmpty()) + { + memberGroupDocs+="\n\n"; + } + memberGroupDocs+=current->doc; + MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(memberGroupId); + if (info) + { + info->doc = memberGroupDocs; + info->docFile = yyFileName; + } + current->doc.resize(0); + current->brief.resize(0); +} + +//----------------------------------------------------------------- + +static void handleCommentBlock(const QCString &doc,bool brief) +{ + if (brief) + { + current->briefFile = yyFileName; + current->briefLine = yyLineNr; + } + else + { + current->docFile = yyFileName; + current->docLine = yyLineNr; + } + if (docBlockInBody) + { + if (previous==0) + { + ASSERT(previous!=0); // shouldn't happen + return; + } + if (!previous->doc.isEmpty()) + { // start a new paragraph for the next piece of text found in the body + previous->doc=previous->doc.stripWhiteSpace()+"\n\n"; + } + } + if (parseCommentBlock( + docBlockInBody ? previous : current, + doc, // text + yyFileName, // file + yyLineNr, // line + docBlockInBody ? FALSE : brief, + docBlockInBody ? FALSE : docBlockJavaStyle, + protection) + ) // need to start a new entry + { + if (current->section==Entry::MEMBERGRP_SEC) + { + addMemberGroupDocs(); + } + current_root->addSubEntry(current); + previous = current; + current = new Entry ; + initEntry(); + } +} + +//----------------------------------------------------------------- + static void addXRefItem(bool inBody,const char *listName,const char *itemTitle,const char *listTitle) { Entry *docEntry = inBody && previous ? previous : current; @@ -617,6 +695,7 @@ static void addKnRArgInfo(const QCString &type,const QCString &name, } } +//----------------------------------------------------------------------------- /* ----------------------------------------------------------------- */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); @@ -849,6 +928,12 @@ IDLATTR ("["[^\]]*"]"){BN}* %x ReadFormulaLong %x AnchorLabel + /** new comment parsing states */ + +%x DocLine +%x DocBlock +%x DocCopyBlock + %% <*>\x06[^\x06]*\x06 { // new file @@ -2036,7 +2121,11 @@ IDLATTR ("["[^\]]*"]"){BN}* BEGIN(AfterDoc); } } + <FindMembers,FindFields>("//"([!/]?){B}*{CMD}"{")|("/*"([!*]?){B}*{CMD}"{") { +#ifdef COMMENTSCAN + REJECT; +#else startGroup(); tmpDocType=-1; if (current_root->section & Entry::SCOPE_MASK) @@ -2064,8 +2153,12 @@ IDLATTR ("["[^\]]*"]"){BN}* removeSlashes=FALSE; BEGIN( Doc ); } +#endif } <FindMembers,FindFields,ReadInitializer>"//"([!/]?){B}*{CMD}"}".*|"/*"([!*]?){B}*{CMD}"}".*"*/" { +#ifdef COMMENTSCAN + REJECT; +#else if (memberGroupId==DOX_NOGROUP && autoGroupStack.isEmpty()) { warn(yyFileName,yyLineNr, @@ -2074,6 +2167,7 @@ IDLATTR ("["[^\]]*"]"){BN}* //printf("end of member group marker ends group %d\n",memberGroupId); endGroup(); memberGroupHeader.resize(0); +#endif } <FindMembers>"=" { current->bodyLine = yyLineNr; @@ -4043,7 +4137,15 @@ IDLATTR ("["[^\]]*"]"){BN}* memberGroupInside = current->inside.copy(); } } +#ifdef COMMENTSCAN + docBlockContext = YY_START; + docBlockInBody = YY_START==SkipCurly; + docBlockJavaStyle = FALSE; + docBlock.resize(0); + BEGIN( DocBlock ); +#else BEGIN( Doc ); +#endif } <FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/**"/[^/*] { removeSlashes=(yytext[1]=='/'); @@ -4057,6 +4159,28 @@ IDLATTR ("["[^\]]*"]"){BN}* memberGroupInside = current->inside.copy(); } } +#ifdef COMMENTSCAN + current->docLine = yyLineNr; + current->docFile = yyFileName; + docBlockContext = YY_START; + docBlockInBody = YY_START==SkipCurly; + docBlockJavaStyle = Config_getBool("JAVADOC_AUTOBRIEF"); + docBlock.resize(0); + if (docBlockJavaStyle) + { + current->briefLine = yyLineNr; + current->briefFile = yyFileName; + } + if (!docBlockInBody) + { + current->doc.resize(0); + if (docBlockJavaStyle) + { + current->brief.resize(0); + } + } + BEGIN( DocBlock ); +#else if (!Config_getBool("JAVADOC_AUTOBRIEF")) // use the Qt style { current->docLine = yyLineNr; @@ -4095,6 +4219,7 @@ IDLATTR ("["[^\]]*"]"){BN}* BEGIN( JavaDoc ); } } +#endif } <FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"//!" { if (YY_START!=SkipCurly) @@ -4113,7 +4238,15 @@ IDLATTR ("["[^\]]*"]"){BN}* memberGroupInside = current->inside.copy(); } } +#ifdef COMMENTSCAN + docBlockContext = YY_START; + docBlockInBody = YY_START==SkipCurly; + docBlockJavaStyle = FALSE; + docBlock.resize(0); + BEGIN( DocLine ); +#else BEGIN( LineDoc ); +#endif } <FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"///"/[^/] { if (YY_START!=SkipCurly) @@ -4132,7 +4265,15 @@ IDLATTR ("["[^\]]*"]"){BN}* memberGroupInside = current->inside.copy(); } } +#ifdef COMMENTSCAN + docBlockContext = YY_START; + docBlockInBody = YY_START==SkipCurly; + docBlockJavaStyle = FALSE; + docBlock.resize(0); + BEGIN( DocLine ); +#else BEGIN( LineDoc ); +#endif } <FindMembers>"extern"{BN}*"\"C"("++")?"\""{BN}*("{")? { lineCount(); @@ -4200,6 +4341,91 @@ IDLATTR ("["[^\]]*"]"){BN}* <CSAccessorDecl>"get" { if (curlyCount==0) current->memSpec |= Entry::Gettable; } <CSAccessorDecl>. {} <CSAccessorDecl>\n { yyLineNr++; } + + + + + /**********************************************************************************/ + /******************** Documentation block related rules ***************************/ + /**********************************************************************************/ + + /* ---- Single line comments ------ */ + +<DocLine>[^\n]*"\n" { // whole line + yyLineNr++; + handleCommentBlock(yytext,TRUE); + BEGIN( docBlockContext ); + } + + /* ---- Comments blocks ------ */ + +<DocBlock>"*/" { // end of comment block + handleCommentBlock(docBlock,FALSE); + BEGIN(docBlockContext); + } +<DocBlock>^{B}*"*"+/{BN}+ { // start of a comment line + } +<DocBlock>("@@"|"\\\\"){ID} { // escaped command + docBlock+=yytext; + } +<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"dot"|"code")/[^a-z_A-Z0-9] { // verbatim command (which could contain nested comments!) + docBlock+=yytext; + docBlockName=&yytext[1]; + BEGIN(DocCopyBlock); + } +<DocBlock>[^@*\\\n]+ { // any character that isn't special + docBlock+=yytext; + } +<DocBlock>\n { // newline + yyLineNr++; + docBlock+=*yytext; + } +<DocBlock>. { // command block + docBlock+=*yytext; + } + + /* ---- Copy verbatim sections ------ */ + +<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddot"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block + docBlock+=yytext; + if (&yytext[4]==docBlockName) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line + if (docBlockName=="verbatim") + { + REJECT; + } + } +<DocCopyBlock>[^@\*\\\n]+ { // any character that is not special + docBlock+=yytext; + } +<DocCopyBlock>\n { // newline + docBlock+=*yytext; + yyLineNr++; + } +<DocCopyBlock>. { // any other character + docBlock+=*yytext; + } +<DocCopyBlock><<EOF>> { + warn(yyFileName,yyLineNr, + "Warning: reached end of file while inside a %s block!\n", + docBlockName.data()); + yyterminate(); + } + + + + + + /*************************************************************************/ + /*** The next part is obsolete and will be removed */ + + + + <JavaDoc>{CMD}("brief"|"short"){B}+ { lastBriefContext=tmpDocType; BEGIN( ClassDocBrief ); @@ -4211,6 +4437,8 @@ IDLATTR ("["[^\]]*"]"){BN}* BEGIN( tmpDocType ); } } + + /* <JavaDoc>"@" { unput(*yytext); @@ -5863,6 +6091,12 @@ IDLATTR ("["[^\]]*"]"){BN}* current->brief+=yytext; } <DefLineDoc,LineDoc,ClassDoc,PageDoc,Doc>"/*"|"//" { current->doc += yytext; } + + + /**** End of obsolete part */ + /***********************************************************************/ + + <SkipCxxComment>.*/\n { BEGIN( lastCContext ) ; } @@ -5908,6 +6142,7 @@ IDLATTR ("["[^\]]*"]"){BN}* //---------------------------------------------------------------------------- +#ifndef COMMENTSCAN static void startGroup() { if (!lastDefGroup.groupname.isEmpty()) @@ -5944,6 +6179,7 @@ static void startGroup() lastMemberGroupLine = yyLineNr; } } +#endif static void startGroupInDoc() { @@ -6221,6 +6457,72 @@ void parseMain(Entry *rt) #endif +void parsePrototype(const QCString &text) +{ + //printf("**** parsePrototype(%s) begin\n",text.data()); + + const char *orgInputString; + int orgInputPosition; + YY_BUFFER_STATE orgState; + bool orgInputFromFile; + + // save scanner state + orgState = YY_CURRENT_BUFFER; + yy_switch_to_buffer(yy_create_buffer(scanYYin, YY_BUF_SIZE)); + orgInputString = inputString; + orgInputPosition = inputPosition; + orgInputFromFile = g_inputFromFile; + + // set new string + inputString = text; + inputPosition = 0; + g_inputFromFile = FALSE; + scanYYrestart( scanYYin ); + BEGIN(ClassDocFunc); + scanYYlex(); + + // restore original scanner state + yy_switch_to_buffer(orgState); + inputString = orgInputString; + inputPosition = orgInputPosition; + g_inputFromFile = orgInputFromFile; + + //printf("**** parsePrototype end\n"); +} + +Entry *startNewEntry() +{ + // make copy of documentation up till now + QCString doc = current->doc; + QCString brief = current->brief; + current->doc.resize(0); + current->brief.resize(0); + + // create new entry + current_root->addSubEntry(current); + previous = current; + current = new Entry ; + initEntry(); + + // move documentation to this entry + current->doc = doc; + current->brief = brief; + + return current; +} + +void handleGroupStartCommand(const char *header) +{ + memberGroupHeader=header; + startGroupInDoc(); +} + +void handleGroupEndCommand() +{ + endGroup(); +} + + //---------------------------------------------------------------------------- #if !defined(YY_FLEX_SUBMINOR_VERSION) |