Skip to main content

The commentcnv.l File Reference

Included Headers

#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <stack> #include <algorithm> #include <deque> #include <string_view> #include "debug.h" #include "message.h" #include "config.h" #include "doxygen.h" #include "util.h" #include "aliases.h" #include "condparser.h" #include "fileinfo.h" #include "stringutil.h" #include "regex.h" #include "section.h" #include <assert.h> #include "doxygen_lex.h" #include "commentcnv.l.h"

Classes Index

structcommentcnvYY_CondCtx
structCommentCtx
structcommentcnv_FileState
structcommentcnvYY_state

Typedefs Index

typedefyyguts_t * yyscan_t

Functions Index

static const char *stateToString (int state)
static intcomputeIndent (const char *s)
static voidreplaceCommentMarker (yyscan_t yyscanner, std::string_view s)
static voidcopyToOutput (yyscan_t yyscanner, std::string_view s)
static voidcopyToOutput (yyscan_t yyscanner, const char *s, int len)
static voidstartCondSection (yyscan_t yyscanner, const QCString &sectId)
static voidendCondSection (yyscan_t yyscanner)
static voidhandleCondSectionId (yyscan_t yyscanner, const char *expression)
static voidreplaceAliases (yyscan_t yyscanner, std::string_view s, bool replaceComment)

copies string s with length len to the output, while replacing any alias commands found in the string. More...

static intyyread (yyscan_t yyscanner, char *buf, int max_size)
static voidreplaceComment (yyscan_t yyscanner, int offset)
static voidclearCommentStack (yyscan_t yyscanner)
static boolreadIncludeFile (yyscan_t yyscanner, const QCString &inc, const QCString &blockId)
static voidinsertCommentStart (yyscan_t yyscanner)
static boolparseIncludeOptions (yyscan_t yyscanner, std::string_view s)
static const char *getLexerFILE ()
intyylex (yyscan_t yyscanner)
static QCStringextractBlock (const QCString &text, const QCString &marker, int &blockPos)

Returns the section of text, in between a pair of markers. More...

voidconvertCppComments (const std::string &inBuf, std::string &outBuf, const std::string &fn)

Converts the comments in a file. More...

Macro Definitions Index

#defineYY_BUF_SIZE   10*1024*1024
#defineYY_TYPEDEF_YY_SCANNER_T
#defineYY_NO_INPUT   1
#defineYY_NO_UNISTD_H   1
#defineYY_INPUT(buf, result, max_size)   result=yyread(yyscanner,buf,max_size);

Typedefs

yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 31 of file commentcnv.l.

31typedef yyguts_t *yyscan_t;

Functions

clearCommentStack()

void clearCommentStack (yyscan_t yyscanner)
static

Definition at line 1575 of file commentcnv.l.

1575static void clearCommentStack(yyscan_t yyscanner)
1576{
1577 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1578 while (!yyextra->commentStack.empty()) yyextra->commentStack.pop();
1579}

Referenced by convertCppComments.

computeIndent()

int computeIndent (const char * s)
inline static

Definition at line 1513 of file commentcnv.l.

1513static inline int computeIndent(const char *s)
1514{
1515 int col=0;
1516 int tabSize=Config_getInt(TAB_SIZE);
1517 const char *p=s;
1518 char c = 0;
1519 while ((c=*p++))
1520 {
1521 if (c==' ') col++;
1522 else if (c=='\t') col+=tabSize-(col%tabSize);
1523 else break;
1524 }
1525 return col;
1526}

Reference Config_getInt.

Referenced by replaceComment.

convertCppComments()

void convertCppComments (const std::string & inBuf, std::string & outBuf, const std::string & fn)

Converts the comments in a file.

This function does three things:

  1. It converts multi-line C++ style comment blocks (that are aligned) to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO).
  2. It replaces aliases with their definition (see ALIASES)
  3. It handles conditional sections (cond...endcond blocks)

Definition at line 1964 of file commentcnv.l.

1964void convertCppComments(const std::string &inBuf,std::string &outBuf,const std::string &fn)
1965{
1966 QCString fileName { fn };
1967 yyscan_t yyscanner;
1968 commentcnvYY_state extra(&inBuf,outBuf);
1969 commentcnvYYlex_init_extra(&extra,&yyscanner);
1970#ifdef FLEX_DEBUG
1971 commentcnvYYset_debug(Debug::isFlagSet(Debug::Lex_commentcnv)?1:0,yyscanner);
1972#endif
1973 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1974 //printf("convertCppComments(%s)\n",qPrint(fileName));
1975 yyextra->inBufPos = 0;
1976 yyextra->col = 0;
1977 yyextra->mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
1978 yyextra->skip = FALSE;
1979 yyextra->fileName = fileName;
1980 yyextra->lang = getLanguageFromFileName(fileName);
1981 yyextra->pythonDocString = FALSE;
1982 yyextra->lineNr = 1;
1983 yyextra->raiseLevel = 0;
1984 yyextra->raiseLabel = "";
1985 yyextra->raiseIncrement = 0;
1986 yyextra->raisePrefix = "";
1987 yyextra->insertCppCommentMarker=false;
1988 yyextra->expandedAliases.clear();
1989 while (!yyextra->condStack.empty()) yyextra->condStack.pop();
1990 clearCommentStack(yyscanner);
1991 yyextra->vhdl = FALSE;
1992
1993 DebugLex debugLex(Debug::Lex_commentcnv,__FILE__, qPrint(fileName));
1994 yyextra->isFixedForm = FALSE;
1995 if (yyextra->lang==SrcLangExt::Fortran)
1996 {
1998 yyextra->isFixedForm = recognizeFixedForm(QCString(inBuf),fmt);
1999 }
2000
2001 if (yyextra->lang==SrcLangExt::Markdown)
2002 {
2003 yyextra->nestingCount=0;
2004 BEGIN(CComment);
2005 yyextra->commentStack.push(yyextra->lineNr);
2006 }
2007 else
2008 {
2009 BEGIN(Scan);
2010 }
2011 yylex(yyscanner);
2012 while (!yyextra->condStack.empty())
2013 {
2014 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
2015 QCString sectionInfo(" ");
2016 if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data());
2017 warn(yyextra->fileName,ctx.lineNr,"Conditional section{}does not have "
2018 "a corresponding \\endcond command within this file.",sectionInfo.data());
2019 yyextra->condStack.pop();
2020 }
2021 if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt::Markdown && yyextra->lang!=SrcLangExt::Fortran)
2022 {
2023 QCString lines;
2024 bool first = true;
2025 while (!yyextra->commentStack.empty())
2026 {
2027 int lineNr = yyextra->commentStack.top();
2028 if (!first) lines += ", ";
2029 lines += QCString().setNum(lineNr);
2030 first = false;
2031 yyextra->commentStack.pop();
2032 }
2033 warn(yyextra->fileName,yyextra->lineNr,"Reached end of file while still inside a (nested) comment. "
2034 "Nesting level {} (possible line reference(s): {})",yyextra->nestingCount,lines);
2035 }
2036 yyextra->nestingCount = 0;
2038 {
2039 Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: {}\n"
2040 "output=[\n{}]\n-----------\n",fileName,yyextra->outBuf
2041 );
2042 }
2043 commentcnvYYlex_destroy(yyscanner);
2044}

References clearCommentStack, Debug::CommentCnv, Config_getBool, convertFileNameFortranParserCode, QCString::data, FALSE, getLanguageFromFileName, Debug::isFlagSet, Debug::Lex_commentcnv, commentcnvYY_CondCtx::lineNr, Debug::print, qPrint, recognizeFixedForm, commentcnvYY_CondCtx::sectionId, QCString::setNum, QCString::sprintf, QCString::stripWhiteSpace, warn and yylex.

Referenced by generateHtmlForComment and parseFile.

copyToOutput()

void copyToOutput (yyscan_t yyscanner, std::string_view s)
inline static

Definition at line 1528 of file commentcnv.l.

1528static inline void copyToOutput(yyscan_t yyscanner,std::string_view s)
1529{
1530 int tabSize=Config_getInt(TAB_SIZE);
1531 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1532 size_t len = s.length();
1533 if (yyextra->skip) // only add newlines.
1534 {
1535 for (size_t i=0;i<len;i++)
1536 {
1537 switch(s[i])
1538 {
1539 case '\n':
1540 yyextra->outBuf+='\n';
1541 yyextra->lineNr++;
1542 yyextra->col=0;
1543 break;
1544 case '\t':
1545 yyextra->col+=tabSize-(yyextra->col%tabSize);
1546 break;
1547 default:
1548 yyextra->col++;
1549 break;
1550 }
1551 }
1552 }
1553 else if (len>0)
1554 {
1555 yyextra->outBuf+=s;
1556 for (size_t i=0;i<len;i++)
1557 {
1558 switch (s[i])
1559 {
1560 case '\n': yyextra->col=0;
1561 //fprintf(stderr,"---> copy %d\n",g_lineNr);
1562 yyextra->lineNr++; break;
1563 case '\t': yyextra->col+=tabSize-(yyextra->col%tabSize); break;
1564 default: yyextra->col++; break;
1565 }
1566 }
1567 }
1568}

Reference Config_getInt.

Referenced by copyToOutput, insertCommentStart, readIncludeFile, replaceAliases and replaceComment.

copyToOutput()

void copyToOutput (yyscan_t yyscanner, const char * s, int len)
inline static

Definition at line 1570 of file commentcnv.l.

1570static inline void copyToOutput(yyscan_t yyscanner,const char *s,int len)
1571{
1572 copyToOutput(yyscanner,std::string_view{s,(size_t)len});
1573}

Reference copyToOutput.

endCondSection()

void endCondSection (yyscan_t yyscanner)
static

Definition at line 1594 of file commentcnv.l.

1594static void endCondSection(yyscan_t yyscanner)
1595{
1596 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1597 if (yyextra->condStack.empty())
1598 {
1599 warn(yyextra->fileName,yyextra->lineNr,"Found \\endcond command without matching \\cond");
1600 yyextra->skip=FALSE;
1601 }
1602 else
1603 {
1604 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
1605 yyextra->skip=ctx.skip;
1606 yyextra->condStack.pop();
1607 }
1608 //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1609}

References FALSE, commentcnvYY_CondCtx::skip and warn.

extractBlock()

QCString extractBlock (const QCString & text, const QCString & marker, int & blockPos)
static

Returns the section of text, in between a pair of markers.

Full lines are returned, excluding the lines on which the markers appear.

See Also

routine lineBlock

Definition at line 1643 of file commentcnv.l.

1643static QCString extractBlock(const QCString &text,const QCString &marker,int &blockPos)
1644{
1645 QCString result;
1646 int p=0,i=-1;
1647 bool found=FALSE;
1648
1649 // find the character positions of the markers
1650 int m1 = text.find(marker);
1651 if (m1==-1) return result;
1652 int m2 = text.find(marker,m1+static_cast<int>(marker.length()));
1653 if (m2==-1) return result;
1654
1655 // find start and end line positions for the markers
1656 int l1=-1,l2=-1;
1657 while (!found && (i=text.find('\n',p))!=-1)
1658 {
1659 found = (p<=m1 && m1<i); // found the line with the start marker
1660 p=i+1;
1661 }
1662 l1=p;
1663 blockPos=p;
1664 int lp=i;
1665 if (found)
1666 {
1667 while ((i=text.find('\n',p))!=-1)
1668 {
1669 if (p<=m2 && m2<i) // found the line with the end marker
1670 {
1671 l2=p;
1672 break;
1673 }
1674 p=i+1;
1675 lp=i;
1676 }
1677 }
1678 if (l2==-1) // marker at last line without newline (see bug706874)
1679 {
1680 l2=lp;
1681 }
1682 return l2>l1 ? text.mid(l1,l2-l1) : QCString();
1683}

References FALSE, QCString::find, QCString::length and QCString::mid.

Referenced by readIncludeFile.

getLexerFILE()

const char * getLexerFILE ()
inline static

Definition at line 166 of file commentcnv.l.

166static inline const char *getLexerFILE() {return __FILE__;}

handleCondSectionId()

void handleCondSectionId (yyscan_t yyscanner, const char * expression)
static

Definition at line 1611 of file commentcnv.l.

1611static void handleCondSectionId(yyscan_t yyscanner,const char *expression)
1612{
1613 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1614 bool oldSkip=yyextra->skip;
1615 startCondSection(yyscanner,QCString(expression));
1616 if ((yyextra->condCtx==CComment || yyextra->readLineCtx==SComment) &&
1617 !oldSkip && yyextra->skip)
1618 {
1619 if (yyextra->lang!=SrcLangExt::Python &&
1620 yyextra->lang!=SrcLangExt::VHDL &&
1621 yyextra->lang!=SrcLangExt::Markdown &&
1622 yyextra->lang!=SrcLangExt::Fortran)
1623 {
1624 yyextra->outBuf+='*';
1625 yyextra->outBuf+='/';
1626 yyextra->col+=2;
1627 }
1628 }
1629 if (yyextra->readLineCtx==SComment)
1630 {
1631 BEGIN(SComment);
1632 }
1633 else
1634 {
1635 BEGIN(yyextra->condCtx);
1636 }
1637}

Reference startCondSection.

insertCommentStart()

void insertCommentStart (yyscan_t yyscanner)
static

Definition at line 1685 of file commentcnv.l.

1685static void insertCommentStart(yyscan_t yyscanner)
1686{
1687 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1688 int startCol=yyextra->blockHeadCol;
1689 int contentCol=yyextra->insertCommentCol;
1690 int markerSpace=contentCol-startCol;
1691 //printf("insertCommentStart startCol=%d contentCol=%d mlBrief=%d insertCppCommentMarker=%d\n",
1692 // yyextra->blockHeadCol,yyextra->insertCommentCol,yyextra->mlBrief,yyextra->insertCppCommentMarker);
1693 std::string marker;
1694 if (yyextra->lang==SrcLangExt::Python) // need to insert # or space
1695 {
1696 if (yyextra->pythonDocString) // """! style comment
1697 {
1698 marker=" ";
1699 }
1700 else
1701 {
1702 marker="# ";
1703 }
1704 }
1705 else if (yyextra->lang==SrcLangExt::Fortran) // need to insert !!
1706 {
1707 marker="!! ";
1708 }
1709 else if (yyextra->lang==SrcLangExt::Markdown)
1710 {
1711 marker=" ";
1712 }
1713 else if (yyextra->insertCppCommentMarker) // need to insert ///
1714 {
1715 marker="/// ";
1716 if (startCol>0)
1717 {
1718 // insert `///` instead of '* '
1719 startCol--;
1720 markerSpace++;
1721 }
1722 }
1723 else // need to insert *
1724 {
1725 marker="* ";
1726 }
1727 int i=0;
1728 for (;i<startCol;i++)
1729 {
1730 copyToOutput(yyscanner," ");
1731 }
1732 if (static_cast<int>(marker.length())<=markerSpace && !yyextra->firstIncludeLine)
1733 {
1734 copyToOutput(yyscanner,marker);
1735 i+=marker.length();
1736 }
1737 for (;i<contentCol;i++)
1738 {
1739 copyToOutput(yyscanner," ");
1740 }
1741 yyextra->firstIncludeLine = false;
1742}

Reference copyToOutput.

Referenced by readIncludeFile.

parseIncludeOptions()

bool parseIncludeOptions (yyscan_t yyscanner, std::string_view s)
static

Definition at line 1401 of file commentcnv.l.

1401static bool parseIncludeOptions(yyscan_t yyscanner,std::string_view s)
1402{
1403 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1404
1405 //printf("parseIncludeOptions=%s\n",qPrint(QCString(s)));
1406 size_t optIdxStart = s.find('{');
1407 size_t optIdxEnd = optIdxStart!=std::string::npos ? s.find("}",optIdxStart+1) : std::string::npos;
1408 std::string cmdName;
1409 StringVector optList;
1410 if (optIdxStart == std::string::npos) // no options
1411 {
1412 cmdName = stripWhiteSpace(s.substr(1)); // to remove {CMD}
1413 }
1414 else // options present
1415 {
1416 cmdName = stripWhiteSpace(s.substr(1,optIdxStart-1)); // to remove {CMD}
1417 optList = split(std::string{s.substr(optIdxStart+1,optIdxEnd-optIdxStart-1)},",");
1418 }
1419 bool isDoc = cmdName=="includedoc" || cmdName=="snippetdoc";
1420 for (const auto &opt : optList)
1421 {
1422 if (stripWhiteSpace(opt)==std::string_view{"doc"})
1423 {
1424 isDoc=true;
1425 break;
1426 }
1427 }
1428
1429 if (isDoc)
1430 {
1431 for (const auto &opt : optList)
1432 {
1433 std::string_view locOpt = stripWhiteSpace(opt);
1434 size_t posEqual = locOpt.find('=');
1435 std::string_view option = posEqual!=std::string::npos ? stripWhiteSpace(locOpt.substr(0,posEqual)) : locOpt;
1436 std::string_view value = posEqual!=std::string::npos ? stripWhiteSpace(locOpt.substr(posEqual+1)) : std::string_view();
1437
1438 if (option==std::string_view{"doc"} && value.empty())
1439 {
1440 }
1441 else if (option==std::string_view{"raise"} && !value.empty())
1442 {
1443 yyextra->raiseIncrement = atoi(value.data());
1444 if (yyextra->raiseLevel+yyextra->raiseIncrement>=SectionType::MaxLevel) // check range
1445 {
1446 warn(yyextra->fileName,yyextra->lineNr,"Raising section level from {} to {}, exceeds allowed range [0-{}], adjusting",
1447 yyextra->raiseLevel,yyextra->raiseLevel+yyextra->raiseIncrement,SectionType::MaxLevel-1);
1448 yyextra->raiseIncrement = std::max(0,SectionType::MaxLevel-1-yyextra->raiseLevel);
1449 }
1450 }
1451 else if (option==std::string_view{"prefix"} && !value.empty())
1452 {
1453 yyextra->raisePrefix = value;
1454 }
1455 else
1456 {
1457 warn(yyextra->fileName,yyextra->lineNr,"Unsupported option '{}' for {} command",option, cmdName);
1458 }
1459 }
1460 }
1461
1462 return isDoc;
1463}

References SectionType::MaxLevel, split, stripWhiteSpace and warn.

readIncludeFile()

bool readIncludeFile (yyscan_t yyscanner, const QCString & inc, const QCString & blockId)
static

Definition at line 1744 of file commentcnv.l.

1744static bool readIncludeFile(yyscan_t yyscanner,const QCString &inc,const QCString &blockId)
1745{
1746 //printf("readIncludeFile(inc=%s,blockId=%s)\n",qPrint(inc),qPrint(blockId));
1747 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1748 bool ambig = false;
1749 QCString absFileName = findFilePath(inc,ambig);
1750 FileInfo fi(absFileName.str());
1751 if (!absFileName.isEmpty() && fi.exists() && fi.isFile())
1752 {
1753 if (ambig)
1754 {
1755 warn_doc_error(yyextra->fileName,yyextra->lineNr,"included file name '{}' is ambiguous"
1756 "Possible candidates:\n{}",inc, showFileDefMatches(Doxygen::exampleNameLinkedMap,inc));
1757 }
1758 bool alreadyProcessed = std::any_of(
1759 yyextra->includeStack.begin(),
1760 yyextra->includeStack.end(),
1761 [&absFileName,&blockId](const auto &lfs)
1762 { return lfs->fileName==absFileName && lfs->blockId==blockId; }
1763 );
1764
1765 if (alreadyProcessed)
1766 {
1767 if (!blockId.isEmpty())
1768 {
1769 warn_doc_error(yyextra->fileName,yyextra->lineNr,"recursive usage of '\\snippet{{doc}}' block with name '{}' and file name '{}', skipping",
1770 blockId,absFileName);
1771 }
1772 else
1773 {
1774 warn_doc_error(yyextra->fileName,yyextra->lineNr,"recursive usage of '\\include{{doc}}' with file name '{}', skipping", absFileName);
1775 }
1776 return false;
1777 }
1778
1779 auto fs = std::make_unique<commentcnv_FileState>();
1780 if (!readInputFile(absFileName,fs->fileBuf,false))
1781 {
1782 warn_doc_error(yyextra->fileName,yyextra->lineNr,"\\{}{{doc}} file '{}' could not be read",blockId.isEmpty()?"include":"snippet",absFileName);
1783 fs.reset();
1784 return false;
1785 }
1786 int lineNr=1;
1787 if (!blockId.isEmpty())
1788 {
1789 QCString incText { fs->fileBuf };
1790 int count = incText.contains(blockId.data());
1791 if (count!=2)
1792 {
1793 warn_doc_error(yyextra->fileName,yyextra->lineNr,"block marked with {} for \\snippet{{doc}} should appear twice in file {}, found it {:d} times, skipping",
1794 blockId,absFileName,count);
1795 return false;
1796 }
1797 lineNr = lineBlock(incText, blockId);
1798 int blockPos = 0;
1799 incText = extractBlock(incText, blockId, blockPos);
1800 fs->fileBuf.clear();
1801 if (!incText.isEmpty())
1802 {
1803 fs->fileBuf.append(incText.str());
1804 }
1805 }
1806 int oldRaiseLevel = yyextra->raiseLevel;
1807 QCString oldRaiseLabel = yyextra->raiseLabel;
1808 yyextra->raiseLevel+=yyextra->raiseIncrement;
1809 yyextra->raiseLabel+=yyextra->raisePrefix;
1810 QCString lineStr=" \\ifile \""+absFileName+"\" \\iline " + std::to_string(lineNr)+" ";
1811 if (yyextra->raiseLevel>0)
1812 {
1813 lineStr+="\\iraise " + std::to_string(yyextra->raiseLevel)+" ";
1814 }
1815 if (!yyextra->raiseLabel.isEmpty())
1816 {
1817 lineStr+="\\iprefix \"" + yyextra->raiseLabel + "\" ";
1818 }
1819 lineStr+="\\ilinebr ";
1820 copyToOutput(yyscanner,lineStr.view());
1821
1822 fs->fileName = absFileName;
1823 fs->bufState = YY_CURRENT_BUFFER;
1824 fs->oldLineNr = yyextra->lineNr;
1825 fs->oldFileName = yyextra->fileName;
1826 fs->oldState = yyextra->includeCtx;
1827 fs->oldFileBuf = yyextra->inBuf;
1828 fs->oldFileBufPos = yyextra->inBufPos;
1829 fs->oldIncludeCtx = yyextra->includeCtx;
1830 fs->oldRaiseLvl = oldRaiseLevel;
1831 fs->oldRaiseLbl = oldRaiseLabel;
1832 fs->blockId = blockId;
1833 yy_switch_to_buffer(yy_create_buffer(nullptr, YY_BUF_SIZE, yyscanner),yyscanner);
1834 yyextra->fileName = absFileName;
1835 yyextra->lineNr = lineNr;
1836 yyextra->inBuf = &fs->fileBuf;
1837 yyextra->inBufPos = 0;
1838 yyextra->includeStack.push_back(std::move(fs));
1839 insertCommentStart(yyscanner);
1840 //printf("switched to %s\n",qPrint(fileName));
1841 }
1842 else
1843 {
1844 warn_doc_error(yyextra->fileName,yyextra->lineNr,"\\{}{{doc}} file '{}' not found",blockId.isEmpty()?"include":"snippet",inc);
1845 return false;
1846 }
1847 return true;
1848}

References QCString::contains, copyToOutput, QCString::data, Doxygen::exampleNameLinkedMap, FileInfo::exists, extractBlock, findFilePath, insertCommentStart, QCString::isEmpty, FileInfo::isFile, lineBlock, readInputFile, showFileDefMatches, QCString::str, QCString::view, warn_doc_error and YY_BUF_SIZE.

replaceAliases()

void replaceAliases (yyscan_t yyscanner, std::string_view s, bool replaceComment=false)
static

copies string s with length len to the output, while replacing any alias commands found in the string.

Definition at line 1853 of file commentcnv.l.

1853static void replaceAliases(yyscan_t yyscanner,std::string_view s,bool replaceComment)
1854{
1855 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1856 if (s.empty()) return;
1857 size_t pos = s.find('{');
1858 std::string cmd { s.substr(1, pos!=std::string::npos ? pos-1 : s.length()-1) };
1859 auto &expAlias = yyextra->expandedAliases;
1860 if (std::find(expAlias.begin(),expAlias.end(),cmd)!=std::end(expAlias))
1861 {
1862 copyToOutput(yyscanner,s);
1863 return; // prevent recursive expansion
1864 }
1865 else if (cmd=="ialias")
1866 {
1867 if (s.length()>cmd.length()+3) // \cmd{value}
1868 {
1869 std::string value { s.substr(cmd.length()+2,s.length()-cmd.length()-3) };
1870 //printf("removing value '%s'\n",qPrint(value));
1871 expAlias.erase(std::remove(expAlias.begin(),expAlias.end(),value),expAlias.end());
1872 }
1873 return;
1874 }
1875 std::string result = resolveAliasCmd(s);
1876 if (yyextra->inVerbatim) // inside verbatim blocks (like @code...@endcode) only expand aliases if
1877 // their expansion contains the matching end block marker.
1878 {
1879 std::string blk = yyextra->blockName.str();
1880 assert(!blk.empty());
1881 bool isNamedCommand=isId(blk[0]); // true for e.g. @endcode, false for e.g. ~~~
1882 size_t i=0,p=0;
1883 bool found=false;
1884 while ((i=result.find(blk,p))!=std::string::npos && !found) // for each match of blk in result
1885 {
1886 found = !isNamedCommand || // e.g. '~~~' or '-->'
1887 (i>0 && (result[i-1]=='\\' || result[i-1]=='@') && !isId(result[i+blk.length()])); // e.g. '@endcode' but not ~endcode or @endcodex
1888 p = i+yyextra->blockName.length();
1889 }
1890 //printf("blk=%s result=%s found=%d\n",qPrint(blk),qPrint(result),found);
1891 if (!found) // treat alias as part of the verbatim block
1892 {
1893 copyToOutput(yyscanner,s);
1894 return;
1895 }
1896 }
1897 //printf("replaceAliases(%s)->'%s' replaceComment=%d\n",qPrint(s),qPrint(result),replaceComment);
1898 if (result!=s)
1899 {
1900 if (replaceComment) // In case we are replacing a multiline /// comment by a C style comment
1901 // and we have new lines in the alias argument, we need to place back a /// for each new line
1902 // to prevent breaking the multiline comment into multiple C style comments
1903 {
1904 result = substituteStringView(result,"\n","\n///");
1905 }
1906 expAlias.push_back(cmd);
1907 // add a ialias command to allow expansion of cmd again
1908 result += " \\ilinebr \\ialias{";
1909 result += cmd;
1910 result += "}";
1911 for (int i=(int)result.length()-1; i>=0; i--)
1912 {
1913 unput(result[i]);
1914 }
1915 }
1916 else
1917 {
1918 copyToOutput(yyscanner,result);
1919 }
1920}

References copyToOutput, isId, replaceComment, resolveAliasCmd and substituteStringView.

replaceComment()

void replaceComment (yyscan_t yyscanner, int offset)
static

Definition at line 1933 of file commentcnv.l.

1933static void replaceComment(yyscan_t yyscanner,int offset)
1934{
1935 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1936 if (yyextra->mlBrief || yyextra->skip)
1937 {
1938 copyToOutput(yyscanner,yytext,yyleng);
1939 }
1940 else
1941 {
1942 int i=computeIndent(&yytext[offset]);
1943 //printf("i=%d blockHeadCol=%d\n",i,yyextra->blockHeadCol);
1944 if (i==yyextra->blockHeadCol || i+1==yyextra->blockHeadCol)
1945 {
1946 replaceCommentMarker(yyscanner,std::string_view(yytext,yyleng));
1947 }
1948 else
1949 {
1950 copyToOutput(yyscanner," */");
1951 for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
1952 yyextra->inSpecialComment=FALSE;
1953 BEGIN(Scan);
1954 }
1955 }
1956}

References computeIndent, copyToOutput, FALSE and replaceCommentMarker.

Referenced by replaceAliases and stateToString.

replaceCommentMarker()

void replaceCommentMarker (yyscan_t yyscanner, std::string_view s)
static

Definition at line 1466 of file commentcnv.l.

1466static void replaceCommentMarker(yyscan_t yyscanner,std::string_view s)
1467{
1468 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1469 if (s.empty()) return;
1470 size_t p = 0;
1471 size_t len = s.length();
1472 char c = 0;
1473 // copy leading blanks
1474 while (p<len && (c=s[p]) && (c==' ' || c=='\t' || c=='\n'))
1475 {
1476 yyextra->outBuf+=c;
1477 if (c=='\n') { yyextra->lineNr++; yyextra->col=0; } else { yyextra->col++; }
1478 p++;
1479 }
1480 // replace start of comment marker by blanks and the last character by a *
1481 int blanks=0;
1482 while (p<len && (c=s[p]) && (c=='/' || c=='!' || c=='#'))
1483 {
1484 blanks++;
1485 p++;
1486 if (p<len && s[p]=='<') // comment-after-item marker
1487 {
1488 blanks++;
1489 p++;
1490 }
1491 if (c=='!') // end after first !
1492 {
1493 break;
1494 }
1495 }
1496 if (blanks>0)
1497 {
1498 while (blanks>2)
1499 {
1500 yyextra->outBuf+=' ';
1501 yyextra->col++;
1502 blanks--;
1503 }
1504 if (blanks>1) { yyextra->outBuf+='*'; yyextra->col++; }
1505 yyextra->outBuf+=' ';
1506 yyextra->col++;
1507 }
1508 // copy comment line to output
1509 yyextra->outBuf+=s.substr(p);
1510 yyextra->col+=s.substr(p).length();
1511}

Referenced by replaceComment.

startCondSection()

void startCondSection (yyscan_t yyscanner, const QCString & sectId)
static

Definition at line 1581 of file commentcnv.l.

1581static void startCondSection(yyscan_t yyscanner,const QCString &sectId)
1582{
1583 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1584 //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1585 CondParser prs;
1586 bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
1587 yyextra->condStack.emplace(yyextra->lineNr,sectId,yyextra->skip);
1588 if (!expResult) // not enabled
1589 {
1590 yyextra->skip=TRUE;
1591 }
1592}

References CondParser::parse and TRUE.

Referenced by handleCondSectionId.

stateToString()

const char * stateToString (int state)
static

Definition at line 145 of file commentcnv.l.

Reference replaceComment.

yylex()

int yylex (yyscan_t yyscanner)

Definition at line 252 of file commentcnv.l.

252%%
253
254<Scan>{NUMBER} { //Note similar code in code.l
255 if (yyextra->lang!=SrcLangExt::Cpp) REJECT;
256 copyToOutput(yyscanner,yytext,yyleng);
257 }
258<Scan>[^"'!\/\n\\#,\-=; \t@$]* { /* eat anything that is not " / , or \n */
259 copyToOutput(yyscanner,yytext,yyleng);
260 }
261<Scan>[,= ;\t] { /* eat , so we have a nice separator in long initialization lines */
262 copyToOutput(yyscanner,yytext,yyleng);
263 }
264<Scan>"'''"! |
265<Scan>"\"\"\""! { /* start of python long comment */
266 if (yyextra->lang!=SrcLangExt::Python)
267 {
268 REJECT;
269 }
270 else
271 {
272 yyextra->pythonDocString = TRUE;
273 yyextra->pythonDocStringChar = yytext[0];
274 yyextra->nestingCount=1;
275 clearCommentStack(yyscanner); /* to be on the save side */
276 copyToOutput(yyscanner,yytext,yyleng);
277 BEGIN(CComment);
278 yyextra->commentStack.push(yyextra->lineNr);
279 }
280 }
281<Scan>"'''" |
282<Scan>"\"\"\"" { /* start of python long comment */
283 if (yyextra->lang!=SrcLangExt::Python)
284 {
285 REJECT;
286 }
287 else if (Config_getBool(PYTHON_DOCSTRING))
288 {
289 REJECT;
290 }
291 else
292 { /* handle as if """! */
293 yyextra->pythonDocString = TRUE;
294 yyextra->pythonDocStringChar = yytext[0];
295 yyextra->nestingCount=1;
296 clearCommentStack(yyscanner); /* to be on the save side */
297 copyToOutput(yyscanner,yytext,yyleng);
298 BEGIN(CComment);
299 yyextra->commentStack.push(yyextra->lineNr);
300 }
301 }
302<Scan>{B}*![><!]/.*\n {
303 if (yyextra->lang!=SrcLangExt::Fortran)
304 {
305 REJECT;
306 }
307 else
308 {
309 yyextra->nestingCount=0; // Fortran doesn't have an end comment
310 clearCommentStack(yyscanner); /* to be on the save side */
311 yyextra->specialComment=true;
312 copyToOutput(yyscanner,yytext,yyleng);
313 yyextra->blockHeadCol=yyextra->col-2;
314 BEGIN(CComment);
315 yyextra->commentStack.push(yyextra->lineNr);
316 }
317 }
318<Scan>[Cc\*][><!]/.*\n {
319 if (yyextra->lang!=SrcLangExt::Fortran)
320 {
321 REJECT;
322 }
323 else
324 {
325 /* check for fixed format; we might have some conditional as part of multiline if like C<5 .and. & */
326 if (yyextra->isFixedForm && (yyextra->col == 0))
327 {
328 yyextra->nestingCount=0; // Fortran doesn't have an end comment
329 clearCommentStack(yyscanner); /* to be on the save side */
330 yyextra->specialComment=true;
331 copyToOutput(yyscanner,yytext,yyleng);
332 yyextra->blockHeadCol=yyextra->col-1;
333 BEGIN(CComment);
334 yyextra->commentStack.push(yyextra->lineNr);
335 }
336 else
337 {
338 REJECT;
339 }
340 }
341 }
342<Scan>!.*\n {
343 if (yyextra->lang!=SrcLangExt::Fortran)
344 {
345 REJECT;
346 }
347 else
348 {
349 copyToOutput(yyscanner,yytext,yyleng);
350 }
351 }
352<Scan>[Cc\*].*\n {
353 if (yyextra->lang!=SrcLangExt::Fortran)
354 {
355 REJECT;
356 }
357 else
358 {
359 if (yyextra->col == 0)
360 {
361 copyToOutput(yyscanner,yytext,yyleng);
362 }
363 else
364 {
365 REJECT;
366 }
367 }
368 }
369<Scan>[$]?"@\"" { /* start of an interpolated verbatim C# string */
370 if (yyextra->lang!=SrcLangExt::CSharp) REJECT
371 copyToOutput(yyscanner,yytext,yyleng);
372 yyextra->stringContext = YY_START;
373 BEGIN(SkipVerbString);
374 }
375<Scan>"\"" { /* start of a string */
376 copyToOutput(yyscanner,yytext,yyleng);
377 yyextra->stringContext = YY_START;
378 BEGIN(SkipString);
379 }
380<Scan>' {
381 copyToOutput(yyscanner,yytext,yyleng);
382 yyextra->charContext = YY_START;
383 if (yyextra->lang!=SrcLangExt::VHDL)
384 {
385 BEGIN(SkipChar);
386 }
387 }
388<Scan>\n { /* new line */
389 copyToOutput(yyscanner,yytext,yyleng);
390 }
391<Scan>{CPPC}[!/]/.*\n[ \t]*{CPPC}[!/][ \t]*{CMD}"}" { // see bug #8731, don't treat multiline C++ comment as detailed description
392 // if the next line is an end of group marker.
393 yyextra->inSpecialComment=true;
394 yyextra->blockHeadCol=yyextra->col+1;
395 yyextra->insertCppCommentMarker=true;
396 copyToOutput(yyscanner,yytext,yyleng);
397 yyextra->readLineCtx=YY_START;
398 BEGIN(ReadLine);
399 }
400<Scan>{CPPC}"!"/.*\n[ \t]*{CPPC}[\/!][^\/] | /* start C++ style special comment block */
401<Scan>({CPPC}"/"[/]*)/[^/].*\n[ \t]*{CPPC}[\/!][^\/] { /* start C++ style special comment block */
402 if (yyextra->mlBrief)
403 {
404 REJECT; // bail out if we do not need to convert
405 }
406 else
407 {
408 int i=3;
409 if (yytext[2]=='/')
410 {
411 while (i<(int)yyleng && yytext[i]=='/') i++;
412 }
413 yyextra->blockHeadCol=yyextra->col+1;
414 if (yytext[2] == '!')
415 {
416 copyToOutput(yyscanner,"/*!");
417 }
418 else
419 {
420 copyToOutput(yyscanner,"/**");
421 }
422 if (i<yyleng) replaceAliases(yyscanner,yytext+i);
423 yyextra->inSpecialComment=TRUE;
424 //BEGIN(SComment);
425 yyextra->readLineCtx=SComment;
426 BEGIN(ReadLine);
427 }
428 }
429<Scan>{CPPC}"##Documentation"{ANYopt}/\n { /* Start of Rational Rose ANSI C++ comment block */
430 if (yyextra->mlBrief) REJECT;
431 int i=17; //=strlen("//##Documentation");
432 yyextra->blockHeadCol=yyextra->col+1;
433 copyToOutput(yyscanner,"/**");
434 if (i<yyleng) replaceAliases(yyscanner,yytext+i);
435 yyextra->inRoseComment=TRUE;
436 BEGIN(SComment);
437 }
438<Scan>{CPPC}[!\/]/.*\n[ \t]*{CPPC}[|\/][ \t]*[@\\]"}" { // next line contains an end marker, see bug 752712
439 yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
440 if (yyextra->inSpecialComment)
441 {
442 yyextra->blockHeadCol=yyextra->col+1;
443 }
444 copyToOutput(yyscanner,yytext,yyleng);
445 yyextra->readLineCtx=YY_START;
446 BEGIN(ReadLine);
447 }
448<Scan>{CPPC}[!/]/.*\n { /* one line special C++ comment */
449 yyextra->inSpecialComment=true;
450 yyextra->blockHeadCol=yyextra->col+1;
451 yyextra->insertCppCommentMarker=true;
452 copyToOutput(yyscanner,yytext,yyleng);
453 yyextra->readLineCtx=YY_START;
454 BEGIN(ReadLine);
455 }
456<Scan>{CPPC}/.*\n { /* one line normal C++ comment */
457 yyextra->inSpecialComment=false;
458 copyToOutput(yyscanner,yytext,yyleng);
459 yyextra->readLineCtx=YY_START;
460 BEGIN(CopyLine);
461 }
462<Scan>{CCS}{CCE} { /* avoid matching next rule for empty C comment, see bug 711723 */
463 copyToOutput(yyscanner,yytext,yyleng);
464 }
465<Scan>{CCS}[*!]? { /* start of a C comment */
466 if (yyextra->lang==SrcLangExt::Python)
467 {
468 REJECT;
469 }
470 yyextra->specialComment=(int)yyleng==3;
471 yyextra->nestingCount=1;
472 clearCommentStack(yyscanner); /* to be on the save side */
473 copyToOutput(yyscanner,yytext,yyleng);
474 if (yyextra->specialComment)
475 {
476 yyextra->blockHeadCol=0;
477 BEGIN(CComment);
478 }
479 else
480 {
481 BEGIN(CNComment);
482 }
483 yyextra->commentStack.push(yyextra->lineNr);
484 }
485<Scan>"#"[^\n]*\n {
486 if (yyextra->lang!=SrcLangExt::PHP)
487 {
488 REJECT;
489 }
490 copyToOutput(yyscanner,yytext,yyleng);
491 }
492<Scan>"#"("#")? {
493 if (yyextra->lang!=SrcLangExt::Python)
494 {
495 REJECT;
496 }
497 else
498 {
499 yyextra->nestingCount=0; // Python doesn't have an end comment for #
500 clearCommentStack(yyscanner); /* to be on the save side */
501 yyextra->specialComment=(int)yyleng==2;
502 if (yyextra->specialComment)
503 {
504 yyextra->blockHeadCol=yyextra->col;
505 }
506 yyextra->commentStack.push(yyextra->lineNr);
507 copyToOutput(yyscanner,yytext,yyleng);
508 BEGIN(CComment);
509 }
510 }
511<Scan>"--"[^!][^\n]* {
512 if (yyextra->lang!=SrcLangExt::VHDL)
513 {
514 REJECT;
515 }
516 else
517 {
518 copyToOutput(yyscanner,yytext,yyleng);
519 }
520 }
521<Scan>"--!" {
522 if (yyextra->lang!=SrcLangExt::VHDL)
523 {
524 REJECT;
525 }
526 else
527 {
528 yyextra->specialComment=true;
529 yyextra->blockHeadCol=yyextra->col;
530 yyextra->vhdl = TRUE;
531 yyextra->nestingCount=0; // VHDL doesn't have an end comment
532 clearCommentStack(yyscanner); /* to be on the save side */
533 yyextra->commentStack.push(yyextra->lineNr);
534 copyToOutput(yyscanner,yytext,yyleng);
535 BEGIN(CComment);
536 }
537 }
538<Scan>{B}*![><!] {
539 if (yyextra->lang!=SrcLangExt::Fortran)
540 {
541 REJECT;
542 }
543 else
544 {
545 yyextra->nestingCount=0; // Fortran doesn't have an end comment
546 clearCommentStack(yyscanner); /* to be on the save side */
547 yyextra->specialComment=true;
548 yyextra->blockHeadCol=yyextra->col;
549 yyextra->commentStack.push(yyextra->lineNr);
550 copyToOutput(yyscanner,yytext,yyleng);
551 BEGIN(CComment);
552 }
553 }
554<CComment,CNComment,ReadLine,IncludeFile>{MAILADDR} |
555<CComment,CNComment,ReadLine,IncludeFile>"<"{MAILADDR}">" { // Mail address, to prevent seeing e.g x@code-factory.org as start of a code block
556 copyToOutput(yyscanner,yytext,yyleng);
557 }
558<CComment,IncludeFile>"{"[ \t]*"@code"/[ \t\n] {
559 copyToOutput(yyscanner,"@iliteral{code}");
560 yyextra->lastCommentContext = YY_START;
561 yyextra->javaBlock=1;
562 yyextra->blockName=QCString("end")+&yytext[1];
563 yyextra->inVerbatim=true;
564 BEGIN(VerbatimCode);
565 }
566<CComment,IncludeFile>"{"[ \t]*"@literal"/[ \t\n] {
567 copyToOutput(yyscanner,"@iliteral");
568 yyextra->lastCommentContext = YY_START;
569 yyextra->javaBlock=1;
570 yyextra->blockName=QCString("end")+&yytext[1];
571 yyextra->inVerbatim=true;
572 BEGIN(VerbatimCode);
573 }
574<CComment,ReadLine,IncludeFile>{CMD}"ilinebr"[ \t]+("```"[`]*|"~~~"[~]*) { /* start of markdown code block */
575 if (!Config_getBool(MARKDOWN_SUPPORT))
576 {
577 REJECT;
578 }
579 copyToOutput(yyscanner,yytext,yyleng);
580 yyextra->lastCommentContext = YY_START;
581 yyextra->javaBlock=0;
582 yyextra->blockName=QCString(yytext).stripWhiteSpace().right(3); // take the ``` or ~~~ part
583 yyextra->inVerbatim=true;
584 BEGIN(VerbatimCode);
585 }
586<CComment,ReadLine,IncludeFile>^[ \t]*("```"[`]*|"~~~"[~]*) { /* start of markdown code block */
587 if (!Config_getBool(MARKDOWN_SUPPORT))
588 {
589 REJECT;
590 }
591 copyToOutput(yyscanner,yytext,yyleng);
592 yyextra->lastCommentContext = YY_START;
593 yyextra->javaBlock=0;
594 yyextra->blockName=QCString(yytext).stripWhiteSpace().left(3); // take the ``` or ~~~ part
595 yyextra->inVerbatim=true;
596 BEGIN(VerbatimCode);
597 }
598<CComment,ReadLine,IncludeFile>[\\@]("dot"|"code"|"msc"|"startuml")/[^a-z_A-Z0-9] { /* start of a verbatim block */
599 copyToOutput(yyscanner,yytext,yyleng);
600 yyextra->lastCommentContext = YY_START;
601 yyextra->javaBlock=0;
602 if (qstrcmp(&yytext[1],"startuml")==0)
603 {
604 yyextra->blockName="enduml";
605 }
606 else
607 {
608 yyextra->blockName=QCString("end")+&yytext[1];
609 }
610 yyextra->inVerbatim=true;
611 BEGIN(VerbatimCode);
612 }
613<CComment,ReadLine,IncludeFile>[\\@]("f$"|"f["|"f{"|"f(") {
614 copyToOutput(yyscanner,yytext,yyleng);
615 yyextra->blockName=&yytext[1];
616 if (yyextra->blockName.at(1)=='[')
617 {
618 yyextra->blockName.at(1)=']';
619 }
620 else if (yyextra->blockName.at(1)=='{')
621 {
622 yyextra->blockName.at(1)='}';
623 }
624 else if (yyextra->blockName.at(1)=='(')
625 {
626 yyextra->blockName.at(1)=')';
627 }
628 yyextra->lastCommentContext = YY_START;
629 yyextra->inVerbatim=true;
630 BEGIN(Verbatim);
631 }
632<CComment,ReadLine,IncludeFile>"<!--!" { /* HTML comment doxygen command*/
633 if (yyextra->inVerbatim) REJECT;
634 //copyToOutput(yyscanner," ",5);
635 yyextra->inHtmlDoxygenCommand=true;
636 }
637<CComment,ReadLine,IncludeFile>"-->" { /* potential end HTML comment doxygen command*/
638 if (yyextra->inHtmlDoxygenCommand)
639 {
640 yyextra->inHtmlDoxygenCommand=false;
641 }
642 else
643 {
644 copyToOutput(yyscanner,yytext,yyleng);
645 }
646 }
647<CComment,ReadLine,IncludeFile>"<!--" { /* HTML comment */
648 copyToOutput(yyscanner,yytext,yyleng);
649 yyextra->blockName="-->";
650 yyextra->lastCommentContext = YY_START;
651 yyextra->inVerbatim=true;
652 BEGIN(Verbatim);
653 }
654<CComment,ReadLine,IncludeFile>[\\@]("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
655 copyToOutput(yyscanner,yytext,yyleng);
656 yyextra->blockName=QCString("end")+&yytext[1];
657 yyextra->lastCommentContext = YY_START;
658 yyextra->inVerbatim=true;
659 BEGIN(Verbatim);
660 }
661<Scan>"\\\"" { /* escaped double quote */
662 copyToOutput(yyscanner,yytext,yyleng);
663 }
664<Scan>"\\\\" { /* escaped backslash */
665 copyToOutput(yyscanner,yytext,yyleng);
666 }
667<Scan>. { /* any other character */
668 copyToOutput(yyscanner,yytext,yyleng);
669 }
670<Verbatim>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */
671 copyToOutput(yyscanner,yytext,yyleng);
672 if (&yytext[1]==yyextra->blockName) // end of command or formula
673 {
674 yyextra->inVerbatim=false;
675 BEGIN(yyextra->lastCommentContext);
676 }
677 }
678<Verbatim>"-->" {
679 copyToOutput(yyscanner,yytext,yyleng);
680 if (yytext==yyextra->blockName)
681 {
682 yyextra->inVerbatim=false;
683 BEGIN(yyextra->lastCommentContext);
684 }
685 }
686<VerbatimCode>"{" {
687 if (yyextra->javaBlock==0)
688 {
689 REJECT;
690 }
691 else
692 {
693 yyextra->javaBlock++;
694 copyToOutput(yyscanner,yytext,yyleng);
695 }
696 }
697<VerbatimCode>"}" {
698 if (yyextra->javaBlock==0)
699 {
700 REJECT;
701 }
702 else
703 {
704 yyextra->javaBlock--;
705 if (yyextra->javaBlock==0)
706 {
707 copyToOutput(yyscanner," @endiliteral ");
708 yyextra->inVerbatim=false;
709 BEGIN(yyextra->lastCommentContext);
710 }
711 else
712 {
713 copyToOutput(yyscanner,yytext,yyleng);
714 }
715 }
716 }
717<VerbatimCode>("```"[`]*|"~~~"[~]*) { /* end of markdown code block */
718 copyToOutput(yyscanner,yytext,yyleng);
719 if (yytext[0]==yyextra->blockName[0])
720 {
721 yyextra->inVerbatim=false;
722 BEGIN(yyextra->lastCommentContext);
723 }
724 }
725<VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc"|"enduml")/("{")? { /* end of verbatim block */
726 copyToOutput(yyscanner,yytext,yyleng);
727 if (&yytext[1]==yyextra->blockName)
728 {
729 yyextra->inVerbatim=false;
730 BEGIN(yyextra->lastCommentContext);
731 }
732 }
733<VerbatimCode>^[ \t]*{CPPC}[\!\/]? { /* skip leading comments */
734 if (!yyextra->inSpecialComment || yyextra->mlBrief)
735 {
736 copyToOutput(yyscanner,yytext,yyleng);
737 }
738 else
739 {
740 int l=0;
741 while (yytext[l]==' ' || yytext[l]=='\t')
742 {
743 l++;
744 }
745 copyToOutput(yyscanner,yytext,l);
746 if (yyleng-l==3) // ends with //! or ///
747 {
748 copyToOutput(yyscanner," * ");
749 }
750 else // ends with //
751 {
752 copyToOutput(yyscanner,"//");
753 }
754 }
755 }
756<Verbatim,VerbatimCode>[^`~@\/\-\\\n{}]* { /* any character not a backslash or new line or } */
757 copyToOutput(yyscanner,yytext,yyleng);
758 }
759<Verbatim,VerbatimCode>\n { /* new line in verbatim block */
760 copyToOutput(yyscanner,yytext,yyleng);
761 if (yyextra->lastCommentContext == IncludeFile)
762 {
763 insertCommentStart(yyscanner);
764 }
765 }
766<Verbatim>^[ \t]*{CPPC}[/!] {
767 if (yyextra->blockName=="enddot" || yyextra->blockName=="endmsc" || yyextra->blockName=="enduml" || yyextra->blockName.at(0)=='f')
768 {
769 // see bug 487871, strip /// from dot images and formulas.
770 int l=0;
771 while (yytext[l]==' ' || yytext[l]=='\t')
772 {
773 l++;
774 }
775 copyToOutput(yyscanner,yytext,l);
776 copyToOutput(yyscanner," ");
777 }
778 else // even slashes are verbatim (e.g. \verbatim, \code)
779 {
780 REJECT;
781 }
782 }
783<Verbatim,VerbatimCode>. { /* any other character */
784 copyToOutput(yyscanner,yytext,yyleng);
785 }
786<SkipString>\\. { /* escaped character in string */
787 if (yyextra->lang==SrcLangExt::Fortran || yyextra->lang==SrcLangExt::VHDL)
788 {
789 unput(yytext[1]);
790 copyToOutput(yyscanner,yytext,1);
791 }
792 else
793 {
794 copyToOutput(yyscanner,yytext,yyleng);
795 }
796 }
797<SkipString>"\"" { /* end of string */
798 copyToOutput(yyscanner,yytext,yyleng);
799 BEGIN(yyextra->stringContext);
800 }
801<SkipString>. { /* any other string character */
802 copyToOutput(yyscanner,yytext,yyleng);
803 }
804<SkipString>\n { /* new line inside string (illegal for some compilers) */
805 copyToOutput(yyscanner,yytext,yyleng);
806 }
807<SkipVerbString>[^"\n]+ {
808 copyToOutput(yyscanner,yytext,yyleng);
809 }
810<SkipVerbString>\"\" { // escaped quote
811 copyToOutput(yyscanner,yytext,yyleng);
812 }
813<SkipVerbString>"\"" { /* end of string */
814 copyToOutput(yyscanner,yytext,yyleng);
815 BEGIN(yyextra->stringContext);
816 }
817<SkipVerbString>. {
818 copyToOutput(yyscanner,yytext,yyleng);
819 }
820<SkipVerbString>\n {
821 copyToOutput(yyscanner,yytext,yyleng);
822 }
823<SkipChar>\\. { /* escaped character */
824 if (yyextra->lang==SrcLangExt::Fortran || yyextra->lang==SrcLangExt::VHDL)
825 {
826 unput(yytext[1]);
827 copyToOutput(yyscanner,yytext,1);
828 }
829 else
830 {
831 copyToOutput(yyscanner,yytext,yyleng);
832 }
833 }
834<SkipChar>' { /* end of character literal */
835 copyToOutput(yyscanner,yytext,yyleng);
836 BEGIN(yyextra->charContext);
837 }
838<SkipChar>. { /* any other string character */
839 copyToOutput(yyscanner,yytext,yyleng);
840 }
841<SkipChar>\n { /* new line character */
842 copyToOutput(yyscanner,yytext,yyleng);
843 }
844
845<CComment,CNComment>[^ `~<\\!@*\n{\"'\/-]* { /* anything that is not a '*' or command */
846 copyToOutput(yyscanner,yytext,yyleng);
847 }
848<CComment,CNComment>^{B}*"*"+[^*\/<\\@\n{\"]* { /* stars without slashes */
849 if (yyextra->lang==SrcLangExt::Markdown) REJECT;
850 yyextra->col = computeIndent(yytext);
851 if (yyextra->col>yyextra->blockHeadCol)
852 {
853 //printf("new blockHeadCol=%d\n",yyextra->blockHeadCol);
854 yyextra->blockHeadCol=yyextra->col;
855 }
856 copyToOutput(yyscanner,yytext,yyleng);
857 }
858<CComment>"'''" |
859<CComment>"\"\"\"" { /* end of Python docstring */
860 if (yyextra->lang!=SrcLangExt::Python)
861 {
862 REJECT;
863 }
864 else if (yyextra->pythonDocStringChar != yytext[0])
865 {
866 copyToOutput(yyscanner,yytext,yyleng);
867 }
868 else
869 {
870 yyextra->nestingCount--;
871 yyextra->pythonDocString = FALSE;
872 yyextra->pythonDocStringChar = '\0';
873 copyToOutput(yyscanner,yytext,yyleng);
874 BEGIN(Scan);
875 }
876 }
877<CComment,CNComment>\n { /* new line in comment */
878 copyToOutput(yyscanner,yytext,yyleng);
879 /* in case of Fortran always end of comment */
880 if (yyextra->lang==SrcLangExt::Fortran)
881 {
882 BEGIN(Scan);
883 }
884 }
885<CComment,CNComment>"/""/"+/"*/" { /* we are already in C-comment so not a start of a nested comment but
886 * just the end of the comment (the end part is handled later). */
887 copyToOutput(yyscanner,yytext,yyleng);
888 }
889<CComment,CNComment>"/"+"*" { /* nested C comment */
890 if (yyextra->lang==SrcLangExt::Python ||
891 yyextra->lang==SrcLangExt::Markdown)
892 {
893 REJECT;
894 }
895 yyextra->nestingCount++;
896 yyextra->commentStack.push(yyextra->lineNr);
897 copyToOutput(yyscanner,yytext,yyleng);
898 }
899<CComment,CNComment>^{B}*"*"+"/" |
900<CComment,CNComment>"*"+"/" { /* end of C comment */
901 if (yyextra->lang==SrcLangExt::Python ||
902 yyextra->lang==SrcLangExt::Markdown)
903 {
904 REJECT;
905 }
906 else
907 {
908 copyToOutput(yyscanner,yytext,yyleng);
909 yyextra->nestingCount--;
910 if (yyextra->nestingCount<=0)
911 {
912 BEGIN(Scan);
913 }
914 else
915 {
916 //yyextra->nestingCount--;
917 yyextra->commentStack.pop();
918 }
919 }
920 }
921 /* Python an VHDL share CComment,CNComment, so special attention for ending comments is required */
922<CComment,CNComment>"\n"/[ \t]*"#" {
923 if (yyextra->lang!=SrcLangExt::VHDL)
924 {
925 REJECT;
926 }
927 else
928 {
929 if (yyextra->vhdl) // inside --! comment
930 {
931 yyextra->vhdl = FALSE;
932 copyToOutput(yyscanner,yytext,yyleng);
933 BEGIN(Scan);
934 }
935 else // C-type comment
936 {
937 REJECT;
938 }
939 }
940 }
941<CComment,CNComment>"\n"/[ \t]*"-" {
942 if (yyextra->lang!=SrcLangExt::Python || yyextra->pythonDocString)
943 {
944 REJECT;
945 }
946 else
947 {
948 copyToOutput(yyscanner,yytext,yyleng);
949 BEGIN(Scan);
950 }
951 }
952<CComment,CNComment>"\n"/[ \t]*[^ \t#\-] {
953 if (yyextra->lang==SrcLangExt::Python)
954 {
955 if (yyextra->pythonDocString)
956 {
957 REJECT;
958 }
959 else
960 {
961 copyToOutput(yyscanner,yytext,yyleng);
962 BEGIN(Scan);
963 }
964 }
965 else if (yyextra->lang==SrcLangExt::VHDL)
966 {
967 if (yyextra->vhdl) // inside --! comment
968 {
969 yyextra->vhdl = FALSE;
970 copyToOutput(yyscanner,yytext,yyleng);
971 BEGIN(Scan);
972 }
973 else // C-type comment
974 {
975 REJECT;
976 }
977 }
978 else
979 {
980 REJECT;
981 }
982 }
983 /* removed for bug 674842 (bug was introduced in rev 768)
984<CComment,CNComment>"'" {
985 yyextra->charContext = YY_START;
986 copyToOutput(yyscanner,yytext,yyleng);
987 BEGIN(SkipChar);
988 }
989<CComment,CNComment>"\"" {
990 yyextra->stringContext = YY_START;
991 copyToOutput(yyscanner,yytext,yyleng);
992 BEGIN(SkipString);
993 }
994 */
995<CComment,CNComment>{CMD}"~"[a-z_A-Z-]* { // language switch command
996 if (yyextra->lang!=SrcLangExt::Markdown) REJECT;
997 QCString langId = QCString(yytext).mid(2);
998 if (!langId.isEmpty() &&
999 qstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE),langId)!=0)
1000 { // enable language specific section
1001 if (!Config_isAvailableEnum(OUTPUT_LANGUAGE,langId))
1002 {
1003 warn(yyextra->fileName,yyextra->lineNr,
1004 "non supported language '{}' specified in '{}'",langId,QCString(yytext).stripWhiteSpace());
1005 }
1006 BEGIN(SkipLang);
1007 }
1008 }
1009<CComment,CNComment>{CMD}{CMD} |
1010<CComment,CNComment>. {
1011 copyToOutput(yyscanner,yytext,yyleng);
1012 }
1013<SkipLang>{CMD}"~"[a-zA-Z-]* { /* language switch */
1014 QCString langId(&yytext[2]);
1015 if (!langId.isEmpty() && !Config_isAvailableEnum(OUTPUT_LANGUAGE,langId))
1016 {
1017 warn(yyextra->fileName,yyextra->lineNr,
1018 "non supported language '{}' specified in '{}'",langId,QCString(yytext).stripWhiteSpace());
1019 }
1020 else if (langId.isEmpty() ||
1021 qstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE),langId)==0)
1022 { // enable language specific section
1023 BEGIN(CComment);
1024 }
1025 }
1026<SkipLang>[^*@\\\n]* { /* any character not a *, @, backslash or new line */
1027 }
1028<SkipLang>\n { /* new line in language block, needed for keeping track of line numbers */
1029 copyToOutput(yyscanner,yytext,yyleng);
1030 }
1031<SkipLang>. { /* any other character */
1032 }
1033<SComment>^[ \t]*{CPPC}"/"{SLASHopt}/\n {
1034 replaceComment(yyscanner,0);
1035 }
1036<SComment>\n[ \t]*{CPPC}"/"{SLASHopt}/\n {
1037 replaceComment(yyscanner,1);
1038 }
1039<SComment>^[ \t]*{CPPC}"/"[^\/\n]/.*\n {
1040 replaceComment(yyscanner,0);
1041 yyextra->readLineCtx=YY_START;
1042 BEGIN(ReadLine);
1043 }
1044<SComment>\n[ \t]*{CPPC}[\/!]("<")?[ \t]*[\\@]"}".*\n {
1045 /* See Bug 752712: end the multiline comment when finding a @} or \} command */
1046 copyToOutput(yyscanner," */");
1047 copyToOutput(yyscanner,yytext,yyleng);
1048 yyextra->inSpecialComment=false;
1049 yyextra->inRoseComment=false;
1050 BEGIN(Scan);
1051 }
1052<SComment>\n[ \t]*{CPPC}"/"[^\\@\/\n]/.*\n {
1053 replaceComment(yyscanner,1);
1054 yyextra->readLineCtx=YY_START;
1055 BEGIN(ReadLine);
1056 }
1057<SComment>^[ \t]*{CPPC}"!" | // just //!
1058<SComment>^[ \t]*{CPPC}"!<"/.*\n | // or //!< something
1059<SComment>^[ \t]*{CPPC}"!"[^<]/.*\n { // or //!something
1060 replaceComment(yyscanner,0);
1061 yyextra->readLineCtx=YY_START;
1062 BEGIN(ReadLine);
1063 }
1064<SComment>\n[ \t]*{CPPC}"!" |
1065<SComment>\n[ \t]*{CPPC}"!<"/.*\n |
1066<SComment>\n[ \t]*{CPPC}"!"[^<\n]/.*\n {
1067 replaceComment(yyscanner,1);
1068 yyextra->readLineCtx=YY_START;
1069 BEGIN(ReadLine);
1070 }
1071<SComment>^[ \t]*{CPPC}"##"/.*\n {
1072 if (!yyextra->inRoseComment)
1073 {
1074 REJECT;
1075 }
1076 else
1077 {
1078 replaceComment(yyscanner,0);
1079 yyextra->readLineCtx=YY_START;
1080 BEGIN(ReadLine);
1081 }
1082 }
1083<SComment>\n[ \t]*{CPPC}"##"/.*\n {
1084 if (!yyextra->inRoseComment)
1085 {
1086 REJECT;
1087 }
1088 else
1089 {
1090 replaceComment(yyscanner,1);
1091 yyextra->readLineCtx=YY_START;
1092 BEGIN(ReadLine);
1093 }
1094 }
1095<SComment>\n { /* end of special comment */
1096 copyToOutput(yyscanner," */");
1097 copyToOutput(yyscanner,yytext,yyleng);
1098 yyextra->inSpecialComment=FALSE;
1099 yyextra->inRoseComment=FALSE;
1100 yyextra->insertCppCommentMarker=false;
1101 yyextra->readLineCtx = Scan; // reset, otherwise there will be problems with:
1102 // static void handleCondSectionId
1103 BEGIN(Scan);
1104 }
1105<ReadLine>{CCS}"*" {
1106 copyToOutput(yyscanner,"/&zwj;**");
1107 }
1108<ReadLine>{CCE} {
1109 copyToOutput(yyscanner,"*&zwj;/");
1110 }
1111<ReadLine,CopyLine>"*" {
1112 copyToOutput(yyscanner,yytext,yyleng);
1113 }
1114<ReadLine,CopyLine>{RL} {
1115 copyToOutput(yyscanner,yytext,yyleng);
1116 }
1117<ReadLine,CopyLine>{RL}/{B}{CMD}"ilinebr"{B} {
1118 copyToOutput(yyscanner,yytext,yyleng);
1119 }
1120<ReadLine,CopyLine>{RLopt}/\n {
1121 copyToOutput(yyscanner,yytext,yyleng);
1122 yyextra->insertCppCommentMarker=false;
1123 BEGIN(yyextra->readLineCtx);
1124 }
1125<CComment,CNComment,ReadLine>"\\<" { /* escaped html comment */
1126 copyToOutput(yyscanner,yytext,yyleng);
1127 }
1128<CComment,CNComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
1129 copyToOutput(yyscanner,yytext,yyleng);
1130 }
1131
1132<CComment,ReadLine,IncludeFile>[\\@]("include"{OPTS}|"includedoc"{OPTS}*) {
1133 if (!parseIncludeOptions(yyscanner,std::string_view{yytext,static_cast<size_t>(yyleng)})) REJECT;
1134 yyextra->includeCtx = YY_START;
1135 yyextra->firstIncludeLine = true;
1136 yyextra->insertCommentCol = yyextra->col;
1137 if (!yyextra->insertCppCommentMarker && (yyextra->includeCtx==ReadLine || yyextra->includeCtx==IncludeFile))
1138 {
1139 yyextra->insertCppCommentMarker = yyextra->mlBrief;
1140 }
1141 //printf("blockHeadCol=%d insertCommentCol=%d\n",yyextra->blockHeadCol, yyextra->insertCommentCol);
1142 BEGIN(IncludeDoc);
1143 }
1144<CComment,ReadLine,IncludeFile>[\\@]("snippet"{OPTS}|"snippetdoc"{OPTS}*) {
1145 if (!parseIncludeOptions(yyscanner,std::string_view{yytext,static_cast<size_t>(yyleng)})) REJECT;
1146 yyextra->includeCtx = YY_START;
1147 yyextra->firstIncludeLine = true;
1148 yyextra->insertCommentCol = yyextra->col;
1149 if (!yyextra->insertCppCommentMarker && (yyextra->includeCtx==ReadLine || yyextra->includeCtx==IncludeFile))
1150 {
1151 yyextra->insertCppCommentMarker = yyextra->mlBrief;
1152 }
1153 //printf("blockHeadCol=%d insertCommentCol=%d\n",yyextra->blockHeadCol, yyextra->insertCommentCol);
1154 BEGIN(SnippetDoc);
1155 }
1156<IncludeDoc,SnippetDoc>{B}*
1157<IncludeDoc>{FILEMASK}|"\""[^\n\"]+"\"" {
1158 QCString fileName=yytext;
1159 if (yytext[0]=='"')
1160 {
1161 fileName=fileName.mid(1,fileName.length()-2); // strip quotes
1162 }
1163 if (readIncludeFile(yyscanner,fileName,""))
1164 {
1165 BEGIN(IncludeFile);
1166 }
1167 else
1168 {
1169 BEGIN(yyextra->includeCtx);
1170 }
1171 }
1172<SnippetDoc>({FILEMASK}|"\""[^\n\"]+"\""){B}+ {
1173 yyextra->snippetFileName=yytext;
1174 yyextra->snippetFileName=yyextra->snippetFileName.stripWhiteSpace();
1175 if (yyextra->snippetFileName == "this") yyextra->snippetFileName=yyextra->fileName;
1176 yyextra->snippetName = "";
1177 BEGIN(SnippetDocTag);
1178 }
1179<SnippetDocTag>[^\\@\n]+ {
1180 yyextra->snippetName += yytext;
1181 }
1182<SnippetDocTag>{CMD} {
1183 yyextra->snippetName += yytext;
1184 }
1185<SnippetDocTag>(\n|{CMD}"ilinebr") {
1186 for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
1187 yyextra->snippetName = yyextra->snippetName.stripWhiteSpace();
1188 QCString blockId = "["+yyextra->snippetName+"]";
1189 if (readIncludeFile(yyscanner,yyextra->snippetFileName,blockId))
1190 {
1191 BEGIN(IncludeFile);
1192 }
1193 else
1194 {
1195 BEGIN(yyextra->includeCtx);
1196 }
1197 }
1198
1199<IncludeDoc,SnippetDoc>\n {
1200 copyToOutput(yyscanner,yytext,yyleng);
1201 insertCommentStart(yyscanner);
1202 // missing file name
1203 //warn(yyextra->fileName,yyextra->lineNr,"Found \\include{{doc}} command without valid file name argument");
1204 BEGIN(yyextra->includeCtx);
1205 }
1206<IncludeDoc,SnippetDoc>. { // invalid character
1207 copyToOutput(yyscanner,yytext,yyleng);
1208 BEGIN(yyextra->includeCtx);
1209 }
1210<CComment,ReadLine,IncludeFile>[\\@]"cond"/[^a-z_A-Z0-9] { // conditional section
1211 yyextra->condCtx = YY_START;
1212 BEGIN(CondLine);
1213 }
1214<CComment,ReadLine,IncludeFile>[\\@]"endcond"/[^a-z_A-Z0-9] { // end of conditional section
1215 bool oldSkip=yyextra->skip;
1216 endCondSection(yyscanner);
1217 if (YY_START==CComment && oldSkip && !yyextra->skip)
1218 {
1219 //printf("** Adding start of comment!\n");
1220 if (yyextra->lang!=SrcLangExt::Python &&
1221 yyextra->lang!=SrcLangExt::VHDL &&
1222 yyextra->lang!=SrcLangExt::Markdown &&
1223 yyextra->lang!=SrcLangExt::Fortran)
1224 {
1225 yyextra->outBuf+='/';
1226 yyextra->outBuf+='*';
1227 yyextra->col+=2;
1228 if (yyextra->specialComment)
1229 {
1230 yyextra->outBuf+='*';
1231 yyextra->col++;
1232 }
1233 }
1234 }
1235 }
1236<CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
1237 handleCondSectionId(yyscanner,yytext);
1238 }
1239<CComment,ReadLine,IncludeFile>[\\@]"cond"{WSopt}/\n {
1240 yyextra->condCtx=YY_START;
1241 handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
1242 }
1243<CondLine>\n |
1244<CondLine>. { // forgot section id?
1245 handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
1246 if (*yytext=='\n') { copyToOutput(yyscanner,"\n");}
1247 }
1248<CComment,ReadLine,IncludeFile,Verbatim,VerbatimCode>[\\@][a-z_A-Z][a-z_A-Z0-9-]* { // expand alias without arguments
1249 replaceAliases(yyscanner,yytext,YY_START==ReadLine && yyextra->readLineCtx==SComment);
1250 }
1251<CComment,ReadLine,IncludeFile,Verbatim,VerbatimCode>{B}?{CMD}"ilinebr"{B}[\\@]"ialias{" { // expand alias with arguments
1252 yyextra->lastBlockContext=YY_START;
1253 yyextra->blockCount=1;
1254 int extraSpace = (yytext[0]==' '? 1:0);
1255 yyextra->aliasString=yytext+9+extraSpace;
1256 yyextra->aliasCmd=yytext+9+extraSpace;
1257 yyextra->lastEscaped=0;
1258 BEGIN( ReadAliasArgs );
1259 }
1260<CComment,ReadLine,IncludeFile,Verbatim,VerbatimCode>[\\@][a-z_A-Z][a-z_A-Z0-9-]*"{" { // expand alias with arguments
1261 yyextra->lastBlockContext=YY_START;
1262 yyextra->blockCount=1;
1263 yyextra->aliasString=yytext;
1264 yyextra->aliasCmd=yytext;
1265 yyextra->lastEscaped=0;
1266 BEGIN( ReadAliasArgs );
1267 }
1268<ReadAliasArgs>^[ \t]*"*" { // skip leading *
1269 }
1270<ReadAliasArgs>^[ \t]*{CPPC}[/!]/[^\n]* { // skip leading special comments (see bug 618079)
1271 }
1272<ReadAliasArgs>[^{}\n\\\*]+ {
1273 yyextra->aliasString+=yytext;
1274 yyextra->lastEscaped=FALSE;
1275 }
1276<ReadAliasArgs>"\\" {
1277 if (yyextra->lastEscaped) yyextra->lastEscaped=FALSE;
1278 else yyextra->lastEscaped=TRUE;
1279 yyextra->aliasString+=yytext;
1280 }
1281<ReadAliasArgs>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */
1282 yyextra->aliasString+=yytext;
1283 if (yyextra->inVerbatim && &yytext[1]==yyextra->blockName)
1284 // For verbatim sections we do not support matching end block markers inside
1285 // alias arguments. Instead this will end the verbatim block.
1286 // This is needed to support an alias definition
1287 // like startalign=" \latexonly\noalign{\endlatexonly" were otherwise
1288 // the scanner would try to find a matching closing brace for noalign and then
1289 // skip over the \endlatexonly command.
1290 {
1291 copyToOutput(yyscanner,yyextra->aliasString.view());
1292 yyextra->inVerbatim=false;
1293 BEGIN(yyextra->lastCommentContext);
1294 }
1295 }
1296<ReadAliasArgs>\n {
1297 yyextra->aliasString+=yytext;
1298 yyextra->lastEscaped=FALSE;
1299 if (yyextra->inVerbatim) // for verbatim sections we do not support multi-line
1300 // alias arguments.
1301 {
1302 copyToOutput(yyscanner,yyextra->aliasString.view());
1303 BEGIN( yyextra->lastBlockContext );
1304 }
1305 }
1306<ReadAliasArgs>"{" {
1307 yyextra->aliasString+=yytext;
1308 if (!yyextra->lastEscaped) yyextra->blockCount++;
1309 yyextra->lastEscaped=FALSE;
1310 }
1311<ReadAliasArgs>"}" {
1312 yyextra->aliasString+=yytext;
1313 if (!yyextra->lastEscaped) yyextra->blockCount--;
1314 if (yyextra->blockCount==0)
1315 {
1316 replaceAliases(yyscanner,yyextra->aliasString.view(),
1317 yyextra->lastBlockContext==ReadLine && yyextra->readLineCtx==SComment);
1318 BEGIN( yyextra->lastBlockContext );
1319 }
1320 yyextra->lastEscaped=FALSE;
1321 }
1322<ReadAliasArgs>. {
1323 yyextra->aliasString+=yytext;
1324 yyextra->lastEscaped=FALSE;
1325 }
1326<CopyLine>. {
1327 copyToOutput(yyscanner,yytext,yyleng);
1328 }
1329<CopyLine>\n {
1330 copyToOutput(yyscanner,yytext,yyleng);
1331 yyextra->insertCppCommentMarker=false;
1332 BEGIN(yyextra->readLineCtx);
1333 }
1334<ReadLine>``` {
1335 copyToOutput(yyscanner,yytext,yyleng);
1336 }
1337<ReadLine>`[^`]+` {
1338 copyToOutput(yyscanner,yytext,yyleng);
1339 }
1340<ReadLine>{CMD}{CMD} |
1341<ReadLine>. {
1342 copyToOutput(yyscanner,yytext,yyleng);
1343 }
1344<IncludeFile>. {
1345 copyToOutput(yyscanner,yytext,yyleng);
1346 }
1347<IncludeFile>\n {
1348 copyToOutput(yyscanner,yytext,yyleng);
1349 insertCommentStart(yyscanner);
1350 }
1351<*>. {
1352 copyToOutput(yyscanner,yytext,yyleng);
1353 }
1354<<EOF>> {
1355 if (YY_START == ReadAliasArgs)
1356 {
1357 warn(yyextra->fileName,yyextra->lineNr,
1358 "Reached end of file while still searching closing '}}' of an alias argument (probable start: '{}')",
1359 yyextra->aliasCmd);
1360 }
1361 if (yyextra->includeStack.empty())
1362 {
1363 yyextra->insertCppCommentMarker=false;
1364 yyterminate();
1365 }
1366 else // switch back to parent file
1367 {
1368 std::unique_ptr<commentcnv_FileState> &fs = yyextra->includeStack.back();
1369 YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER;
1370 yy_switch_to_buffer(fs->bufState, yyscanner);
1371 yy_delete_buffer(oldBuf, yyscanner);
1372 BEGIN(fs->oldState);
1373 yyextra->fileName = fs->oldFileName;
1374 yyextra->lineNr = fs->oldLineNr;
1375 yyextra->inBuf = fs->oldFileBuf;
1376 yyextra->inBufPos = fs->oldFileBufPos;
1377 yyextra->includeCtx = fs->oldIncludeCtx;
1378 QCString lineStr= " \\ifile \""+yyextra->fileName+"\" \\iline "+QCString().setNum(yyextra->lineNr)+" ";
1379 if (fs->oldRaiseLvl!=yyextra->raiseLevel)
1380 {
1381 lineStr+="\\iraise " + std::to_string(fs->oldRaiseLvl)+ " ";
1382 }
1383 if (fs->oldRaiseLbl!=yyextra->raiseLabel)
1384 {
1385 lineStr+="\\iprefix \"" + fs->oldRaiseLbl + "\" ";
1386 }
1387 lineStr+="\\ilinebr ";
1388 yyextra->raiseLevel = fs->oldRaiseLvl;
1389 yyextra->raiseLabel = fs->oldRaiseLbl;
1390 copyToOutput(yyscanner,lineStr.view());
1391 yyextra->includeStack.pop_back();
1392 //printf("<<EOF>> switch back to %s line %d inbufPos=%d outbufPos=%d\n",
1393 // qPrint(yyextra->fileName),yyextra->lineNr,yyextra->inBufPos,yyextra->outBuf.curPos());
1394 }
1395 }
1396 /*
1397<*>\n { fprintf(stderr,"Lex scanner %s (%s) default rule newline for state %s.\n", __FILE__, qPrint(yyextra->fileName),stateToString(YY_START));}
1398 */
1399%%

yyread()

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

Definition at line 1923 of file commentcnv.l.

1923static int yyread(yyscan_t yyscanner,char *buf,int max_size)
1924{
1925 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1926 int bytesInBuf = static_cast<int>(yyextra->inBuf->size())-yyextra->inBufPos;
1927 int bytesToCopy = std::min(max_size,bytesInBuf);
1928 memcpy(buf,yyextra->inBuf->data()+yyextra->inBufPos,bytesToCopy);
1929 yyextra->inBufPos+=bytesToCopy;
1930 return bytesToCopy;
1931}

Macro Definitions

YY_BUF_SIZE

#define YY_BUF_SIZE   10*1024*1024

Definition at line 19 of file commentcnv.l.

19 #define YY_BUF_SIZE 10*1024*1024 // 10Mb should be sufficient for a source file

Referenced by parsePrototype, parsePrototype, DocTokenizer::pushContext, readIncludeFile, readIncludeFile and readIncludeFile.

YY_INPUT

#define YY_INPUT(buf, result, max_size)   result=yyread(yyscanner,buf,max_size);

Definition at line 163 of file commentcnv.l.

163#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);

YY_NO_INPUT

#define YY_NO_INPUT   1

Definition at line 58 of file commentcnv.l.

58#define YY_NO_INPUT 1

YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 59 of file commentcnv.l.

59#define YY_NO_UNISTD_H 1

YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 29 of file commentcnv.l.

29#define YY_TYPEDEF_YY_SCANNER_T

Generated via doxygen2docusaurus by Doxygen 1.14.0.