Doxygen
Loading...
Searching...
No Matches
commentcnv.l File Reference
#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"
Include dependency graph for commentcnv.l:

Go to the source code of this file.

Classes

struct  commentcnvYY_CondCtx
struct  CommentCtx
struct  commentcnv_FileState
struct  commentcnvYY_state

Macros

#define YY_BUF_SIZE   10*1024*1024
#define YY_TYPEDEF_YY_SCANNER_T
#define YY_NO_INPUT   1
#define YY_NO_UNISTD_H   1
#define YY_INPUT(buf, result, max_size)

Typedefs

typedef yyguts_t * yyscan_t

Functions

static const char * stateToString (int state)
static int computeIndent (const char *s)
static void replaceCommentMarker (yyscan_t yyscanner, std::string_view s)
static void copyToOutput (yyscan_t yyscanner, std::string_view s)
static void copyToOutput (yyscan_t yyscanner, const char *s, int len)
static void startCondSection (yyscan_t yyscanner, const QCString &sectId)
static void endCondSection (yyscan_t yyscanner)
static void handleCondSectionId (yyscan_t yyscanner, const char *expression)
static void replaceAliases (yyscan_t yyscanner, std::string_view s, bool replaceCppComment, bool replaceCComment)
 copies string s with length len to the output, while replacing any alias commands found in the string.
static int yyread (yyscan_t yyscanner, char *buf, int max_size)
static void replaceComment (yyscan_t yyscanner, int offset)
static void clearCommentStack (yyscan_t yyscanner)
static bool readIncludeFile (yyscan_t yyscanner, const QCString &inc, const QCString &blockId)
static void insertCommentStart (yyscan_t yyscanner)
static bool parseIncludeOptions (yyscan_t yyscanner, std::string_view s)
static const char * getLexerFILE ()
int yylex (yyscan_t yyscanner)
static QCString extractBlock (const QCString &text, const QCString &marker, int &blockPos)
 Returns the section of text, in between a pair of markers.
void convertCppComments (const std::string &inBuf, std::string &outBuf, const std::string &fn)
 Converts the comments in a file.

Macro Definition Documentation

◆ YY_BUF_SIZE

#define YY_BUF_SIZE   10*1024*1024

◆ YY_INPUT

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

Definition at line 165 of file commentcnv.l.

◆ YY_NO_INPUT

#define YY_NO_INPUT   1

Definition at line 58 of file commentcnv.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 59 of file commentcnv.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 29 of file commentcnv.l.

Typedef Documentation

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 31 of file commentcnv.l.

Function Documentation

◆ clearCommentStack()

void clearCommentStack ( yyscan_t yyscanner)
static

Definition at line 1692 of file commentcnv.l.

1693{
1694 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1695 while (!yyextra->commentStack.empty()) yyextra->commentStack.pop();
1696}

Referenced by convertCppComments().

◆ computeIndent()

int computeIndent ( const char * s)
inlinestatic

Definition at line 1630 of file commentcnv.l.

1631{
1632 int col=0;
1633 int tabSize=Config_getInt(TAB_SIZE);
1634 const char *p=s;
1635 char c = 0;
1636 while ((c=*p++))
1637 {
1638 if (c==' ') col++;
1639 else if (c=='\t') col+=tabSize-(col%tabSize);
1640 else break;
1641 }
1642 return col;
#define Config_getInt(name)
Definition config.h:34
1643}

References 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 2089 of file commentcnv.l.

2090{
2091 QCString fileName { fn };
2092 yyscan_t yyscanner;
2093 commentcnvYY_state extra(&inBuf,outBuf);
2094 commentcnvYYlex_init_extra(&extra,&yyscanner);
This is an alternative implementation of QCString.
Definition qcstring.h:101
yyguts_t * yyscan_t
Definition code.l:24
2095#ifdef FLEX_DEBUG
2096 commentcnvYYset_debug(Debug::isFlagSet(Debug::Lex_commentcnv)?1:0,yyscanner);
@ Lex_commentcnv
Definition debug.h:53
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:132
2097#endif
2098 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2099 //printf("convertCppComments(%s)\n",qPrint(fileName));
2100 yyextra->inBufPos = 0;
2101 yyextra->col = 0;
2102 yyextra->mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
2103 yyextra->skip = FALSE;
2104 yyextra->fileName = fileName;
2105 yyextra->lang = getLanguageFromFileName(fileName);
2106 yyextra->pythonDocString = FALSE;
2107 yyextra->lineNr = 1;
2108 yyextra->raiseLevel = 0;
2109 yyextra->raiseLabel = "";
2110 yyextra->raiseIncrement = 0;
2111 yyextra->raisePrefix = "";
2112 yyextra->insertCppCommentMarker=false;
2113 yyextra->expandedAliases.clear();
2114 while (!yyextra->condStack.empty()) yyextra->condStack.pop();
2115 clearCommentStack(yyscanner);
2116 yyextra->vhdl = FALSE;
static void clearCommentStack(yyscan_t yyscanner)
#define Config_getBool(name)
Definition config.h:33
#define FALSE
Definition qcstring.h:34
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5724
2117
2118 DebugLex debugLex(Debug::Lex_commentcnv,__FILE__, qPrint(fileName));
2119 yyextra->isFixedForm = FALSE;
2120 if (yyextra->lang==SrcLangExt::Fortran)
2121 {
2123 yyextra->isFixedForm = recognizeFixedForm(inBuf,fmt);
2124 }
Definition message.h:144
const char * qPrint(const char *s)
Definition qcstring.h:687
FortranFormat
Definition types.h:572
bool recognizeFixedForm(const QCString &contents, FortranFormat format)
Definition util.cpp:6860
FortranFormat convertFileNameFortranParserCode(QCString fn)
Definition util.cpp:6913
2125
2126 if (yyextra->lang==SrcLangExt::Markdown)
2127 {
2128 yyextra->nestingCount=0;
2129 BEGIN(CComment);
2130 yyextra->commentStack.push(yyextra->lineNr);
2131 }
2132 else
2133 {
2134 BEGIN(Scan);
2135 }
2136 yylex(yyscanner);
2137 while (!yyextra->condStack.empty())
2138 {
2139 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
2140 QCString sectionInfo(" ");
2141 if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data());
2142 warn(yyextra->fileName,ctx.lineNr,"Conditional section{}does not have "
2143 "a corresponding \\endcond command within this file.",sectionInfo.data());
2144 yyextra->condStack.pop();
2145 }
2146 if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt::Markdown && yyextra->lang!=SrcLangExt::Fortran)
2147 {
2148 QCString lines;
2149 bool first = true;
2150 while (!yyextra->commentStack.empty())
2151 {
2152 int lineNr = yyextra->commentStack.top();
2153 if (!first) lines += ", ";
2154 lines += QCString().setNum(lineNr);
2155 first = false;
2156 yyextra->commentStack.pop();
2157 }
2158 warn(yyextra->fileName,yyextra->lineNr,"Reached end of file while still inside a (nested) comment. "
2159 "Nesting level {} (possible line reference(s): {})",yyextra->nestingCount,lines);
2160 }
2161 yyextra->nestingCount = 0;
2163 {
2164 Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: {}\n"
2165 "output=[\n{}]\n-----------\n",fileName,yyextra->outBuf
2166 );
2167 }
2168 commentcnvYYlex_destroy(yyscanner);
@ CommentCnv
Definition debug.h:31
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:76
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:260
QCString & setNum(short n)
Definition qcstring.h:459
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:172
int yylex(void)
#define warn(file, line, fmt,...)
Definition message.h:97
2169}

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() [1/2]

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

Definition at line 1687 of file commentcnv.l.

1688{
1689 copyToOutput(yyscanner,std::string_view{s,(size_t)len});
static void copyToOutput(yyscan_t yyscanner, std::string_view s)
1690}

References copyToOutput().

◆ copyToOutput() [2/2]

void copyToOutput ( yyscan_t yyscanner,
std::string_view s )
inlinestatic

Definition at line 1645 of file commentcnv.l.

1646{
1647 int tabSize=Config_getInt(TAB_SIZE);
1648 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1649 size_t len = s.length();
1650 if (yyextra->skip) // only add newlines.
1651 {
1652 for (size_t i=0;i<len;i++)
1653 {
1654 switch(s[i])
1655 {
1656 case '\n':
1657 yyextra->outBuf+='\n';
1658 yyextra->lineNr++;
1659 yyextra->col=0;
1660 break;
1661 case '\t':
1662 yyextra->col+=tabSize-(yyextra->col%tabSize);
1663 break;
1664 default:
1665 yyextra->col++;
1666 break;
1667 }
1668 }
1669 }
1670 else if (len>0)
1671 {
1672 yyextra->outBuf+=s;
1673 for (size_t i=0;i<len;i++)
1674 {
1675 switch (s[i])
1676 {
1677 case '\n': yyextra->col=0;
1678 //fprintf(stderr,"---> copy %d\n",g_lineNr);
1679 yyextra->lineNr++; break;
1680 case '\t': yyextra->col+=tabSize-(yyextra->col%tabSize); break;
1681 default: yyextra->col++; break;
1682 }
1683 }
1684 }
1685}

References Config_getInt.

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 1711 of file commentcnv.l.

1712{
1713 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1714 if (yyextra->condStack.empty())
1715 {
1716 warn(yyextra->fileName,yyextra->lineNr,"Found \\endcond command without matching \\cond");
1717 yyextra->skip=FALSE;
1718 }
1719 else
1720 {
1721 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
1722 yyextra->skip=ctx.skip;
1723 yyextra->condStack.pop();
1724 }
1725 //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1726}

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 1760 of file commentcnv.l.

1761{
1762 QCString result;
1763 int p=0,i=-1;
1764 bool found=FALSE;
1765
1766 // find the character positions of the markers
1767 int m1 = text.find(marker);
1768 if (m1==-1) return result;
1769 int m2 = text.find(marker,m1+static_cast<int>(marker.length()));
1770 if (m2==-1) return result;
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
1771
1772 // find start and end line positions for the markers
1773 int l1=-1,l2=-1;
1774 while (!found && (i=text.find('\n',p))!=-1)
1775 {
1776 found = (p<=m1 && m1<i); // found the line with the start marker
1777 p=i+1;
1778 }
1779 l1=p;
1780 blockPos=p;
1781 int lp=i;
1782 if (found)
1783 {
1784 while ((i=text.find('\n',p))!=-1)
1785 {
1786 if (p<=m2 && m2<i) // found the line with the end marker
1787 {
1788 l2=p;
1789 break;
1790 }
1791 p=i+1;
1792 lp=i;
1793 }
1794 }
1795 if (l2==-1) // marker at last line without newline (see bug706874)
1796 {
1797 l2=lp;
1798 }
1799 return l2>l1 ? text.mid(l1,l2-l1) : QCString();
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
1800}

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

Referenced by readIncludeFile().

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 168 of file commentcnv.l.

168{return __FILE__;}

◆ handleCondSectionId()

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

Definition at line 1728 of file commentcnv.l.

1729{
1730 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1731 bool oldSkip=yyextra->skip;
1732 startCondSection(yyscanner,expression);
1733 if ((yyextra->condCtx==CComment || yyextra->readLineCtx==SComment) &&
1734 !oldSkip && yyextra->skip)
1735 {
1736 if (yyextra->lang!=SrcLangExt::Python &&
1737 yyextra->lang!=SrcLangExt::VHDL &&
1738 yyextra->lang!=SrcLangExt::Markdown &&
1739 yyextra->lang!=SrcLangExt::Fortran)
1740 {
1741 yyextra->outBuf+='*';
1742 yyextra->outBuf+='/';
1743 yyextra->col+=2;
1744 }
1745 }
1746 if (yyextra->readLineCtx==SComment)
1747 {
1748 BEGIN(SComment);
1749 }
1750 else
1751 {
1752 BEGIN(yyextra->condCtx);
1753 }
static void startCondSection(yyscan_t yyscanner, const QCString &sectId)
1754}

References startCondSection().

◆ insertCommentStart()

void insertCommentStart ( yyscan_t yyscanner)
static

Definition at line 1802 of file commentcnv.l.

1803{
1804 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1805 int startCol=yyextra->blockHeadCol;
1806 int contentCol=yyextra->insertCommentCol;
1807 int markerSpace=contentCol-startCol;
1808 //printf("insertCommentStart startCol=%d contentCol=%d mlBrief=%d insertCppCommentMarker=%d\n",
1809 // yyextra->blockHeadCol,yyextra->insertCommentCol,yyextra->mlBrief,yyextra->insertCppCommentMarker);
1810 std::string marker;
1811 if (yyextra->lang==SrcLangExt::Python) // need to insert # or space
1812 {
1813 if (yyextra->pythonDocString) // """! style comment
1814 {
1815 marker=" ";
1816 }
1817 else
1818 {
1819 marker="# ";
1820 }
1821 }
1822 else if (yyextra->lang==SrcLangExt::Fortran) // need to insert !!
1823 {
1824 marker="!! ";
1825 }
1826 else if (yyextra->lang==SrcLangExt::Markdown)
1827 {
1828 marker=" ";
1829 }
1830 else if (yyextra->insertCppCommentMarker) // need to insert ///
1831 {
1832 marker="/// ";
1833 if (startCol>0)
1834 {
1835 // insert `///` instead of '* '
1836 startCol--;
1837 markerSpace++;
1838 }
1839 }
1840 else // need to insert *
1841 {
1842 marker="* ";
1843 }
1844 int i=0;
1845 for (;i<startCol;i++)
1846 {
1847 copyToOutput(yyscanner," ");
1848 }
1849 if (static_cast<int>(marker.length())<=markerSpace && !yyextra->firstIncludeLine)
1850 {
1851 copyToOutput(yyscanner,marker);
1852 i+=marker.length();
1853 }
1854 for (;i<contentCol;i++)
1855 {
1856 copyToOutput(yyscanner," ");
1857 }
1858 yyextra->firstIncludeLine = false;
1859}

References copyToOutput().

Referenced by readIncludeFile().

◆ parseIncludeOptions()

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

Definition at line 1518 of file commentcnv.l.

1519{
1520 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1521
1522 //printf("parseIncludeOptions=%s\n",qPrint(s));
1523 size_t optIdxStart = s.find('{');
1524 size_t optIdxEnd = optIdxStart!=std::string::npos ? s.find("}",optIdxStart+1) : std::string::npos;
1525 std::string cmdName;
1526 StringVector optList;
1527 if (optIdxStart == std::string::npos) // no options
1528 {
1529 cmdName = stripWhiteSpace(s.substr(1)); // to remove {CMD}
1530 }
1531 else // options present
1532 {
1533 cmdName = stripWhiteSpace(s.substr(1,optIdxStart-1)); // to remove {CMD}
1534 optList = split(std::string{s.substr(optIdxStart+1,optIdxEnd-optIdxStart-1)},",");
1535 }
1536 bool isDoc = cmdName=="includedoc" || cmdName=="snippetdoc";
1537 for (const auto &opt : optList)
1538 {
1539 if (stripWhiteSpace(opt)==std::string_view{"doc"})
1540 {
1541 isDoc=true;
1542 break;
1543 }
1544 }
std::vector< std::string > StringVector
Definition containers.h:33
std::string_view stripWhiteSpace(std::string_view s)
Given a string view s, returns a new, narrower view on that string, skipping over any leading or trai...
Definition stringutil.h:72
StringVector split(const std::string &s, const std::string &delimiter)
split input string s by string delimiter delimiter.
Definition util.cpp:7135
1545
1546 if (isDoc)
1547 {
1548 for (const auto &opt : optList)
1549 {
1550 std::string_view locOpt = stripWhiteSpace(opt);
1551 size_t posEqual = locOpt.find('=');
1552 std::string_view option = posEqual!=std::string::npos ? stripWhiteSpace(locOpt.substr(0,posEqual)) : locOpt;
1553 std::string_view value = posEqual!=std::string::npos ? stripWhiteSpace(locOpt.substr(posEqual+1)) : std::string_view();
1554
1555 if (option==std::string_view{"doc"} && value.empty())
1556 {
1557 }
1558 else if (option==std::string_view{"raise"} && !value.empty())
1559 {
1560 yyextra->raiseIncrement = atoi(value.data());
1561 if (yyextra->raiseLevel+yyextra->raiseIncrement>=SectionType::MaxLevel) // check range
1562 {
1563 warn(yyextra->fileName,yyextra->lineNr,"Raising section level from {} to {}, exceeds allowed range [0-{}], adjusting",
1564 yyextra->raiseLevel,yyextra->raiseLevel+yyextra->raiseIncrement,SectionType::MaxLevel-1);
1565 yyextra->raiseIncrement = std::max(0,SectionType::MaxLevel-1-yyextra->raiseLevel);
1566 }
1567 }
1568 else if (option==std::string_view{"prefix"} && !value.empty())
1569 {
1570 yyextra->raisePrefix = value;
1571 }
1572 else
1573 {
1574 warn(yyextra->fileName,yyextra->lineNr,"Unsupported option '{}' for {} command",option, cmdName);
1575 }
1576 }
1577 }
static constexpr int MaxLevel
Definition section.h:39
1578
1579 return isDoc;
1580}

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

◆ readIncludeFile()

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

Definition at line 1861 of file commentcnv.l.

1862{
1863 //printf("readIncludeFile(inc=%s,blockId=%s)\n",qPrint(inc),qPrint(blockId));
1864 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1865 bool ambig = false;
1866 QCString absFileName = findFilePath(inc,ambig);
1867 FileInfo fi(absFileName.str());
1868 if (!absFileName.isEmpty() && fi.exists() && fi.isFile())
1869 {
1870 if (ambig)
1871 {
1872 warn_doc_error(yyextra->fileName,yyextra->lineNr,"included file name '{}' is ambiguous"
1873 "Possible candidates:\n{}",inc, showFileDefMatches(Doxygen::exampleNameLinkedMap,inc));
1874 }
1875 bool alreadyProcessed = std::any_of(
1876 yyextra->includeStack.begin(),
1877 yyextra->includeStack.end(),
1878 [&absFileName,&blockId](const auto &lfs)
1879 { return lfs->fileName==absFileName && lfs->blockId==blockId; }
1880 );
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:103
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
const std::string & str() const
Definition qcstring.h:552
#define warn_doc_error(file, line, fmt,...)
Definition message.h:112
QCString findFilePath(const QCString &file, bool &ambig)
Definition util.cpp:3502
QCString showFileDefMatches(const FileNameLinkedMap *fnMap, const QCString &n)
Definition util.cpp:3545
1881
1882 if (alreadyProcessed)
1883 {
1884 if (!blockId.isEmpty())
1885 {
1886 warn_doc_error(yyextra->fileName,yyextra->lineNr,"recursive usage of '\\snippet{{doc}}' block with name '{}' and file name '{}', skipping",
1887 blockId,absFileName);
1888 }
1889 else
1890 {
1891 warn_doc_error(yyextra->fileName,yyextra->lineNr,"recursive usage of '\\include{{doc}}' with file name '{}', skipping", absFileName);
1892 }
1893 return false;
1894 }
1895
1896 auto fs = std::make_unique<commentcnv_FileState>();
1897 if (!readInputFile(absFileName,fs->fileBuf,false))
1898 {
1899 warn_doc_error(yyextra->fileName,yyextra->lineNr,"\\{}{{doc}} file '{}' could not be read",blockId.isEmpty()?"include":"snippet",absFileName);
1900 fs.reset();
1901 return false;
1902 }
1903 int lineNr=1;
1904 if (!blockId.isEmpty())
1905 {
1906 QCString incText { fs->fileBuf };
1907 int count = incText.contains(blockId.data());
1908 if (count!=2)
1909 {
1910 warn_doc_error(yyextra->fileName,yyextra->lineNr,"block marked with {} for \\snippet{{doc}} should appear twice in file {}, found it {:d} times, skipping",
1911 blockId,absFileName,count);
1912 return false;
1913 }
1914 lineNr = lineBlock(incText, blockId);
1915 int blockPos = 0;
1916 incText = extractBlock(incText, blockId, blockPos);
1917 fs->fileBuf.clear();
1918 if (!incText.isEmpty())
1919 {
1920 fs->fileBuf.append(incText.str());
1921 }
1922 }
1923 int oldRaiseLevel = yyextra->raiseLevel;
1924 QCString oldRaiseLabel = yyextra->raiseLabel;
1925 yyextra->raiseLevel+=yyextra->raiseIncrement;
1926 yyextra->raiseLabel+=yyextra->raisePrefix;
1927 QCString lineStr=" \\ifile \""+absFileName+"\" \\iline " + std::to_string(lineNr)+" ";
1928 if (yyextra->raiseLevel>0)
1929 {
1930 lineStr+="\\iraise " + std::to_string(yyextra->raiseLevel)+" ";
1931 }
1932 if (!yyextra->raiseLabel.isEmpty())
1933 {
1934 lineStr+="\\iprefix \"" + yyextra->raiseLabel + "\" ";
1935 }
1936 lineStr+="\\ilinebr ";
1937 copyToOutput(yyscanner,lineStr.view());
std::string_view view() const
Definition qcstring.h:174
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:148
static QCString extractBlock(const QCString &text, const QCString &marker, int &blockPos)
Returns the section of text, in between a pair of markers.
int lineBlock(const QCString &text, const QCString &marker)
Returns the line number of the line following the line with the marker.
Definition util.cpp:6389
bool readInputFile(const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:6053
1938
1939 fs->fileName = absFileName;
1940 fs->bufState = YY_CURRENT_BUFFER;
1941 fs->oldLineNr = yyextra->lineNr;
1942 fs->oldFileName = yyextra->fileName;
1943 fs->oldState = yyextra->includeCtx;
1944 fs->oldFileBuf = yyextra->inBuf;
1945 fs->oldFileBufPos = yyextra->inBufPos;
1946 fs->oldIncludeCtx = yyextra->includeCtx;
1947 fs->oldRaiseLvl = oldRaiseLevel;
1948 fs->oldRaiseLbl = oldRaiseLabel;
1949 fs->blockId = blockId;
1950 yy_switch_to_buffer(yy_create_buffer(nullptr, YY_BUF_SIZE, yyscanner),yyscanner);
1951 yyextra->fileName = absFileName;
1952 yyextra->lineNr = lineNr;
1953 yyextra->inBuf = &fs->fileBuf;
1954 yyextra->inBufPos = 0;
1955 yyextra->includeStack.push_back(std::move(fs));
1956 insertCommentStart(yyscanner);
1957 //printf("switched to %s\n",qPrint(fileName));
1958 }
1959 else
1960 {
1961 warn_doc_error(yyextra->fileName,yyextra->lineNr,"\\{}{{doc}} file '{}' not found",blockId.isEmpty()?"include":"snippet",inc);
1962 return false;
1963 }
1964 return true;
static void insertCommentStart(yyscan_t yyscanner)
#define YY_BUF_SIZE
Definition commentcnv.l:19
1965}

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 replaceCppComment = false,
bool replaceCComment = false )
static

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

Definition at line 1970 of file commentcnv.l.

1971{
1972 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1973 if (s.empty()) return;
1974 size_t pos = s.find('{');
1975 std::string cmd { s.substr(1, pos!=std::string::npos ? pos-1 : s.length()-1) };
1976 auto &expAlias = yyextra->expandedAliases;
1977 if (std::find(expAlias.begin(),expAlias.end(),cmd)!=std::end(expAlias))
1978 {
1979 copyToOutput(yyscanner,s);
1980 return; // prevent recursive expansion
1981 }
1982 else if (cmd=="ialias")
1983 {
1984 if (s.length()>cmd.length()+3) // \cmd{value}
1985 {
1986 std::string value { s.substr(cmd.length()+2,s.length()-cmd.length()-3) };
1987 //printf("removing value '%s'\n",qPrint(value));
1988 expAlias.erase(std::remove(expAlias.begin(),expAlias.end(),value),expAlias.end());
1989 }
1990 return;
1991 }
1992 std::string result = resolveAliasCmd(s);
1993 if (yyextra->inVerbatim) // inside verbatim blocks (like @code...@endcode) only expand aliases if
1994 // their expansion contains the matching end block marker.
1995 {
1996 std::string blk = yyextra->blockName.str();
1997 assert(!blk.empty());
1998 bool isNamedCommand=isId(blk[0]); // true for e.g. @endcode, false for e.g. ~~~
1999 size_t i=0,p=0;
2000 bool found=false;
2001 while ((i=result.find(blk,p))!=std::string::npos && !found) // for each match of blk in result
2002 {
2003 found = !isNamedCommand || // e.g. '~~~' or '-->'
2004 (i>0 && (result[i-1]=='\\' || result[i-1]=='@') && !isId(result[i+blk.length()])); // e.g. '@endcode' but not ~endcode or @endcodex
2005 p = i+yyextra->blockName.length();
2006 }
2007 //printf("blk=%s result=%s found=%d\n",qPrint(blk),qPrint(result),found);
2008 if (!found) // treat alias as part of the verbatim block
2009 {
2010 copyToOutput(yyscanner,s);
2011 return;
2012 }
2013 }
2014 //printf("replaceAliases(%s)->'%s' replaceCppComment=%d replaceCComment=%d\n",qPrint(s),qPrint(result),replaceCppComment,replaceCComment);
2015 if (result!=s)
2016 {
2017 size_t numSpaces = yyextra->blockHeadCol>1 ? yyextra->blockHeadCol-1 : 0;
2018 std::string spaces(numSpaces,' ');
2019 if (replaceCppComment) // In case we are replacing a multiline /// comment by a C style comment
2020 // and we have new lines in the alias argument, we need to place back a /// for each new line
2021 // to prevent breaking the multiline comment into multiple C style comments
2022 {
2023 std::string replacement = "\n"+spaces+"///";
2024 result = substituteStringView(result,"\n",replacement);
2025 }
2026 else if (replaceCComment)
2027 {
2028 std::string replacement = "\n"+spaces+" * ";
2029 result = substituteStringView(result,"\n",replacement);
2030 }
2031 expAlias.push_back(cmd);
2032 // add a ialias command to allow expansion of cmd again
2033 result += " \\ilinebr \\ialias{";
2034 result += cmd;
2035 result += "}";
2036 for (int i=(int)result.length()-1; i>=0; i--)
2037 {
2038 unput(result[i]);
2039 }
2040 }
2041 else
2042 {
2043 copyToOutput(yyscanner,result);
2044 }
std::string resolveAliasCmd(std::string_view aliasCmd)
Definition aliases.cpp:504
std::string substituteStringView(std::string_view s, std::string_view toReplace, std::string_view replaceWith)
Returns a new string where occurrences of substring toReplace in string s are replaced by string repl...
Definition stringutil.h:50
bool isId(int c)
Definition util.h:208
2045}

References copyToOutput(), isId(), resolveAliasCmd(), and substituteStringView().

◆ replaceComment()

void replaceComment ( yyscan_t yyscanner,
int offset )
static

Definition at line 2058 of file commentcnv.l.

2059{
2060 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2061 if (yyextra->mlBrief || yyextra->skip)
2062 {
2063 copyToOutput(yyscanner,yytext,yyleng);
2064 }
2065 else
2066 {
2067 int i=computeIndent(&yytext[offset]);
2068 //printf("i=%d blockHeadCol=%d\n",i,yyextra->blockHeadCol);
2069 if (i==yyextra->blockHeadCol || i+1==yyextra->blockHeadCol)
2070 {
2071 replaceCommentMarker(yyscanner,std::string_view(yytext,yyleng));
2072 }
2073 else
2074 {
2075 copyToOutput(yyscanner," */");
2076 for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
2077 yyextra->inSpecialComment=FALSE;
2078 BEGIN(Scan);
2079 }
2080 }
static int computeIndent(const char *s)
static void replaceCommentMarker(yyscan_t yyscanner, std::string_view s)
2081}

References computeIndent(), copyToOutput(), FALSE, and replaceCommentMarker().

◆ replaceCommentMarker()

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

Definition at line 1583 of file commentcnv.l.

1584{
1585 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1586 if (s.empty()) return;
1587 size_t p = 0;
1588 size_t len = s.length();
1589 char c = 0;
1590 // copy leading blanks
1591 while (p<len && (c=s[p]) && (c==' ' || c=='\t' || c=='\n'))
1592 {
1593 yyextra->outBuf+=c;
1594 if (c=='\n') { yyextra->lineNr++; yyextra->col=0; } else { yyextra->col++; }
1595 p++;
1596 }
1597 // replace start of comment marker by blanks and the last character by a *
1598 int blanks=0;
1599 while (p<len && (c=s[p]) && (c=='/' || c=='!' || c=='#'))
1600 {
1601 blanks++;
1602 p++;
1603 if (p<len && s[p]=='<') // comment-after-item marker
1604 {
1605 blanks++;
1606 p++;
1607 }
1608 if (c=='!') // end after first !
1609 {
1610 break;
1611 }
1612 }
1613 if (blanks>0)
1614 {
1615 while (blanks>2)
1616 {
1617 yyextra->outBuf+=' ';
1618 yyextra->col++;
1619 blanks--;
1620 }
1621 if (blanks>1) { yyextra->outBuf+='*'; yyextra->col++; }
1622 yyextra->outBuf+=' ';
1623 yyextra->col++;
1624 }
1625 // copy comment line to output
1626 yyextra->outBuf+=s.substr(p);
1627 yyextra->col+=s.substr(p).length();
1628}

Referenced by replaceComment().

◆ startCondSection()

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

Definition at line 1698 of file commentcnv.l.

1699{
1700 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1701 //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1702 CondParser prs;
1703 bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
1704 yyextra->condStack.emplace(yyextra->lineNr,sectId,yyextra->skip);
1705 if (!expResult) // not enabled
1706 {
1707 yyextra->skip=TRUE;
1708 }
Copyright (C) 1997-2015 by Dimitri van Heesch.
Definition condparser.h:28
bool parse(const QCString &fileName, int lineNr, const QCString &expr)
Copyright (C) 1997-2015 by Dimitri van Heesch.
#define TRUE
Definition qcstring.h:37
1709}

References CondParser::parse(), and TRUE.

Referenced by handleCondSectionId().

◆ stateToString()

const char * stateToString ( int state)
static

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 258 of file commentcnv.l.

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

◆ yyread()

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

Definition at line 2048 of file commentcnv.l.

2049{
2050 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2051 int bytesInBuf = static_cast<int>(yyextra->inBuf->size())-yyextra->inBufPos;
2052 int bytesToCopy = std::min(max_size,bytesInBuf);
2053 memcpy(buf,yyextra->inBuf->data()+yyextra->inBufPos,bytesToCopy);
2054 yyextra->inBufPos+=bytesToCopy;
2055 return bytesToCopy;
2056}