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:3982

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

1708{
1709 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1710 while (!yyextra->commentStack.empty()) yyextra->commentStack.pop();
1711}

Referenced by convertCppComments().

◆ computeIndent()

int computeIndent ( const char * s)
inlinestatic

Definition at line 1645 of file commentcnv.l.

1646{
1647 int col=0;
1648 int tabSize=Config_getInt(TAB_SIZE);
1649 const char *p=s;
1650 char c = 0;
1651 while ((c=*p++))
1652 {
1653 if (c==' ') col++;
1654 else if (c=='\t') col+=tabSize-(col%tabSize);
1655 else break;
1656 }
1657 return col;
#define Config_getInt(name)
Definition config.h:34
1658}

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)
Parameters
inBufinput buffer holding the file content.
outBufoutput buffer to which the results after conversion are written to.
fnthe name of the file from which the comments originate.

The following is converted:

  • C++ style multiline doxygen comments are converted to C style doxygen comments.
  • conditional sections are processed.
  • aliases are expanded.

Definition at line 2104 of file commentcnv.l.

2105{
2106 QCString fileName { fn };
2107 yyscan_t yyscanner;
2108 commentcnvYY_state extra(&inBuf,outBuf);
2109 commentcnvYYlex_init_extra(&extra,&yyscanner);
This is an alternative implementation of QCString.
Definition qcstring.h:101
yyguts_t * yyscan_t
Definition code.l:24
2110#ifdef FLEX_DEBUG
2111 commentcnvYYset_debug(Debug::isFlagSet(Debug::Lex_commentcnv)?1:0,yyscanner);
@ Lex_commentcnv
Definition debug.h:54
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:133
2112#endif
2113 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2114 //printf("convertCppComments(%s)\n",qPrint(fileName));
2115 yyextra->inBufPos = 0;
2116 yyextra->col = 0;
2117 yyextra->mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
2118 yyextra->skip = FALSE;
2119 yyextra->fileName = fileName;
2120 yyextra->lang = getLanguageFromFileName(fileName);
2121 yyextra->pythonDocString = FALSE;
2122 yyextra->lineNr = 1;
2123 yyextra->raiseLevel = 0;
2124 yyextra->raiseLabel = "";
2125 yyextra->raiseIncrement = 0;
2126 yyextra->raisePrefix = "";
2127 yyextra->insertCppCommentMarker=false;
2128 yyextra->expandedAliases.clear();
2129 while (!yyextra->condStack.empty()) yyextra->condStack.pop();
2130 clearCommentStack(yyscanner);
2131 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:5221
2132
2133 DebugLex debugLex(Debug::Lex_commentcnv,__FILE__, qPrint(fileName));
2134 yyextra->isFixedForm = FALSE;
2135 if (yyextra->lang==SrcLangExt::Fortran)
2136 {
2138 yyextra->isFixedForm = recognizeFixedForm(inBuf,fmt);
2139 }
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:6351
FortranFormat convertFileNameFortranParserCode(QCString fn)
Definition util.cpp:6404
2140
2141 if (yyextra->lang==SrcLangExt::Markdown)
2142 {
2143 yyextra->nestingCount=0;
2144 BEGIN(CComment);
2145 yyextra->commentStack.push(yyextra->lineNr);
2146 }
2147 else
2148 {
2149 BEGIN(Scan);
2150 }
2151 yylex(yyscanner);
2152 while (!yyextra->condStack.empty())
2153 {
2154 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
2155 QCString sectionInfo(" ");
2156 if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data());
2157 warn(yyextra->fileName,ctx.lineNr,"Conditional section{}does not have "
2158 "a corresponding \\endcond command within this file.",sectionInfo.data());
2159 yyextra->condStack.pop();
2160 }
2161 if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt::Markdown && yyextra->lang!=SrcLangExt::Fortran)
2162 {
2163 QCString lines;
2164 bool first = true;
2165 while (!yyextra->commentStack.empty())
2166 {
2167 int lineNr = yyextra->commentStack.top();
2168 if (!first) lines += ", ";
2169 lines += QCString().setNum(lineNr);
2170 first = false;
2171 yyextra->commentStack.pop();
2172 }
2173 warn(yyextra->fileName,yyextra->lineNr,"Reached end of file while still inside a (nested) comment. "
2174 "Nesting level {} (possible line reference(s): {})",yyextra->nestingCount,lines);
2175 }
2176 yyextra->nestingCount = 0;
2178 {
2179 Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: {}\n"
2180 "output=[\n{}]\n-----------\n",fileName,yyextra->outBuf
2181 );
2182 }
2183 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:77
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
2184}

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

1703{
1704 copyToOutput(yyscanner,std::string_view{s,(size_t)len});
static void copyToOutput(yyscan_t yyscanner, std::string_view s)
1705}

References copyToOutput().

◆ copyToOutput() [2/2]

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

Definition at line 1660 of file commentcnv.l.

1661{
1662 int tabSize=Config_getInt(TAB_SIZE);
1663 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1664 size_t len = s.length();
1665 if (yyextra->skip) // only add newlines.
1666 {
1667 for (size_t i=0;i<len;i++)
1668 {
1669 switch(s[i])
1670 {
1671 case '\n':
1672 yyextra->outBuf+='\n';
1673 yyextra->lineNr++;
1674 yyextra->col=0;
1675 break;
1676 case '\t':
1677 yyextra->col+=tabSize-(yyextra->col%tabSize);
1678 break;
1679 default:
1680 yyextra->col++;
1681 break;
1682 }
1683 }
1684 }
1685 else if (len>0)
1686 {
1687 yyextra->outBuf+=s;
1688 for (size_t i=0;i<len;i++)
1689 {
1690 switch (s[i])
1691 {
1692 case '\n': yyextra->col=0;
1693 //fprintf(stderr,"---> copy %d\n",g_lineNr);
1694 yyextra->lineNr++; break;
1695 case '\t': yyextra->col+=tabSize-(yyextra->col%tabSize); break;
1696 default: yyextra->col++; break;
1697 }
1698 }
1699 }
1700}

References Config_getInt.

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 1726 of file commentcnv.l.

1727{
1728 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1729 if (yyextra->condStack.empty())
1730 {
1731 warn(yyextra->fileName,yyextra->lineNr,"Found \\endcond command without matching \\cond");
1732 yyextra->skip=FALSE;
1733 }
1734 else
1735 {
1736 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
1737 yyextra->skip=ctx.skip;
1738 yyextra->condStack.pop();
1739 }
1740 //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1741}

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

1776{
1777 QCString result;
1778 int p=0,i=-1;
1779 bool found=FALSE;
1780
1781 // find the character positions of the markers
1782 int m1 = text.find(marker);
1783 if (m1==-1) return result;
1784 int m2 = text.find(marker,m1+static_cast<int>(marker.length()));
1785 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
1786
1787 // find start and end line positions for the markers
1788 int l1=-1,l2=-1;
1789 while (!found && (i=text.find('\n',p))!=-1)
1790 {
1791 found = (p<=m1 && m1<i); // found the line with the start marker
1792 p=i+1;
1793 }
1794 l1=p;
1795 blockPos=p;
1796 int lp=i;
1797 if (found)
1798 {
1799 while ((i=text.find('\n',p))!=-1)
1800 {
1801 if (p<=m2 && m2<i) // found the line with the end marker
1802 {
1803 l2=p;
1804 break;
1805 }
1806 p=i+1;
1807 lp=i;
1808 }
1809 }
1810 if (l2==-1) // marker at last line without newline (see bug706874)
1811 {
1812 l2=lp;
1813 }
1814 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
1815}

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

1744{
1745 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1746 bool oldSkip=yyextra->skip;
1747 startCondSection(yyscanner,expression);
1748 if ((yyextra->condCtx==CComment || yyextra->readLineCtx==SComment) &&
1749 !oldSkip && yyextra->skip)
1750 {
1751 if (yyextra->lang!=SrcLangExt::Python &&
1752 yyextra->lang!=SrcLangExt::VHDL &&
1753 yyextra->lang!=SrcLangExt::Markdown &&
1754 yyextra->lang!=SrcLangExt::Fortran)
1755 {
1756 yyextra->outBuf+='*';
1757 yyextra->outBuf+='/';
1758 yyextra->col+=2;
1759 }
1760 }
1761 if (yyextra->readLineCtx==SComment)
1762 {
1763 BEGIN(SComment);
1764 }
1765 else
1766 {
1767 BEGIN(yyextra->condCtx);
1768 }
static void startCondSection(yyscan_t yyscanner, const QCString &sectId)
1769}

References startCondSection().

◆ insertCommentStart()

void insertCommentStart ( yyscan_t yyscanner)
static

Definition at line 1817 of file commentcnv.l.

1818{
1819 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1820 int startCol=yyextra->blockHeadCol;
1821 int contentCol=yyextra->insertCommentCol;
1822 int markerSpace=contentCol-startCol;
1823 //printf("insertCommentStart startCol=%d contentCol=%d mlBrief=%d insertCppCommentMarker=%d\n",
1824 // yyextra->blockHeadCol,yyextra->insertCommentCol,yyextra->mlBrief,yyextra->insertCppCommentMarker);
1825 std::string marker;
1826 if (yyextra->lang==SrcLangExt::Python) // need to insert # or space
1827 {
1828 if (yyextra->pythonDocString) // """! style comment
1829 {
1830 marker=" ";
1831 }
1832 else
1833 {
1834 marker="# ";
1835 }
1836 }
1837 else if (yyextra->lang==SrcLangExt::Fortran) // need to insert !!
1838 {
1839 marker="!! ";
1840 }
1841 else if (yyextra->lang==SrcLangExt::Markdown)
1842 {
1843 marker=" ";
1844 }
1845 else if (yyextra->insertCppCommentMarker) // need to insert ///
1846 {
1847 marker="/// ";
1848 if (startCol>0)
1849 {
1850 // insert `///` instead of '* '
1851 startCol--;
1852 markerSpace++;
1853 }
1854 }
1855 else // need to insert *
1856 {
1857 marker="* ";
1858 }
1859 int i=0;
1860 for (;i<startCol;i++)
1861 {
1862 copyToOutput(yyscanner," ");
1863 }
1864 if (static_cast<int>(marker.length())<=markerSpace && !yyextra->firstIncludeLine)
1865 {
1866 copyToOutput(yyscanner,marker);
1867 i+=static_cast<int>(marker.length());
1868 }
1869 for (;i<contentCol;i++)
1870 {
1871 copyToOutput(yyscanner," ");
1872 }
1873 yyextra->firstIncludeLine = false;
1874}

References copyToOutput().

Referenced by readIncludeFile().

◆ parseIncludeOptions()

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

Definition at line 1533 of file commentcnv.l.

1534{
1535 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1536
1537 //printf("parseIncludeOptions=%s\n",qPrint(s));
1538 size_t optIdxStart = s.find('{');
1539 size_t optIdxEnd = optIdxStart!=std::string::npos ? s.find("}",optIdxStart+1) : std::string::npos;
1540 std::string cmdName;
1541 StringVector optList;
1542 if (optIdxStart == std::string::npos) // no options
1543 {
1544 cmdName = stripWhiteSpace(s.substr(1)); // to remove {CMD}
1545 }
1546 else // options present
1547 {
1548 cmdName = stripWhiteSpace(s.substr(1,optIdxStart-1)); // to remove {CMD}
1549 optList = split(std::string{s.substr(optIdxStart+1,optIdxEnd-optIdxStart-1)},",");
1550 }
1551 bool isDoc = cmdName=="includedoc" || cmdName=="snippetdoc";
1552 for (const auto &opt : optList)
1553 {
1554 if (stripWhiteSpace(opt)==std::string_view{"doc"})
1555 {
1556 isDoc=true;
1557 break;
1558 }
1559 }
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:6626
1560
1561 if (isDoc)
1562 {
1563 for (const auto &opt : optList)
1564 {
1565 std::string_view locOpt = stripWhiteSpace(opt);
1566 size_t posEqual = locOpt.find('=');
1567 std::string_view option = posEqual!=std::string::npos ? stripWhiteSpace(locOpt.substr(0,posEqual)) : locOpt;
1568 std::string_view value = posEqual!=std::string::npos ? stripWhiteSpace(locOpt.substr(posEqual+1)) : std::string_view();
1569
1570 if (option==std::string_view{"doc"} && value.empty())
1571 {
1572 }
1573 else if (option==std::string_view{"raise"} && !value.empty())
1574 {
1575 yyextra->raiseIncrement = atoi(value.data());
1576 if (yyextra->raiseLevel+yyextra->raiseIncrement>=SectionType::MaxLevel) // check range
1577 {
1578 warn(yyextra->fileName,yyextra->lineNr,"Raising section level from {} to {}, exceeds allowed range [0-{}], adjusting",
1579 yyextra->raiseLevel,yyextra->raiseLevel+yyextra->raiseIncrement,SectionType::MaxLevel-1);
1580 yyextra->raiseIncrement = std::max(0,SectionType::MaxLevel-1-yyextra->raiseLevel);
1581 }
1582 }
1583 else if (option==std::string_view{"prefix"} && !value.empty())
1584 {
1585 yyextra->raisePrefix = value;
1586 }
1587 else
1588 {
1589 warn(yyextra->fileName,yyextra->lineNr,"Unsupported option '{}' for {} command",option, cmdName);
1590 }
1591 }
1592 }
static constexpr int MaxLevel
Definition section.h:39
1593
1594 return isDoc;
1595}

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

◆ readIncludeFile()

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

Definition at line 1876 of file commentcnv.l.

1877{
1878 //printf("readIncludeFile(inc=%s,blockId=%s)\n",qPrint(inc),qPrint(blockId));
1879 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1880 bool ambig = false;
1881 QCString absFileName = findFilePath(inc,ambig);
1882 FileInfo fi(absFileName.str());
1883 if (!absFileName.isEmpty() && fi.exists() && fi.isFile())
1884 {
1885 if (ambig)
1886 {
1887 warn_doc_error(yyextra->fileName,yyextra->lineNr,"included file name '{}' is ambiguous"
1888 "Possible candidates:\n{}",inc, showFileDefMatches(Doxygen::exampleNameLinkedMap,inc));
1889 }
1890 bool alreadyProcessed = std::any_of(
1891 yyextra->includeStack.begin(),
1892 yyextra->includeStack.end(),
1893 [&absFileName,&blockId](const auto &lfs)
1894 { return lfs->fileName==absFileName && lfs->blockId==blockId; }
1895 );
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:102
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:2986
QCString showFileDefMatches(const FileNameLinkedMap *fnMap, const QCString &n)
Definition util.cpp:3029
1896
1897 if (alreadyProcessed)
1898 {
1899 if (!blockId.isEmpty())
1900 {
1901 warn_doc_error(yyextra->fileName,yyextra->lineNr,"recursive usage of '\\snippet{{doc}}' block with name '{}' and file name '{}', skipping",
1902 blockId,absFileName);
1903 }
1904 else
1905 {
1906 warn_doc_error(yyextra->fileName,yyextra->lineNr,"recursive usage of '\\include{{doc}}' with file name '{}', skipping", absFileName);
1907 }
1908 return false;
1909 }
1910
1911 auto fs = std::make_unique<commentcnv_FileState>();
1912 if (!readInputFile(absFileName,fs->fileBuf,false))
1913 {
1914 warn_doc_error(yyextra->fileName,yyextra->lineNr,"\\{}{{doc}} file '{}' could not be read",blockId.isEmpty()?"include":"snippet",absFileName);
1915 fs.reset();
1916 return false;
1917 }
1918 int lineNr=1;
1919 if (!blockId.isEmpty())
1920 {
1921 QCString incText { fs->fileBuf };
1922 int count = incText.contains(blockId.data());
1923 if (count!=2)
1924 {
1925 warn_doc_error(yyextra->fileName,yyextra->lineNr,"block marked with {} for \\snippet{{doc}} should appear twice in file {}, found it {:d} times, skipping",
1926 blockId,absFileName,count);
1927 return false;
1928 }
1929 lineNr = lineBlock(incText, blockId);
1930 int blockPos = 0;
1931 incText = extractBlock(incText, blockId, blockPos);
1932 fs->fileBuf.clear();
1933 if (!incText.isEmpty())
1934 {
1935 fs->fileBuf.append(incText.str());
1936 }
1937 }
1938 int oldRaiseLevel = yyextra->raiseLevel;
1939 QCString oldRaiseLabel = yyextra->raiseLabel;
1940 yyextra->raiseLevel+=yyextra->raiseIncrement;
1941 yyextra->raiseLabel+=yyextra->raisePrefix;
1942 QCString lineStr=" \\ifile \""+absFileName+"\" \\iline " + std::to_string(lineNr)+" ";
1943 if (yyextra->raiseLevel>0)
1944 {
1945 lineStr+="\\iraise " + std::to_string(yyextra->raiseLevel)+" ";
1946 }
1947 if (!yyextra->raiseLabel.isEmpty())
1948 {
1949 lineStr+="\\iprefix \"" + yyextra->raiseLabel + "\" ";
1950 }
1951 lineStr+="\\ilinebr ";
1952 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:5878
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:5560
1953
1954 fs->fileName = absFileName;
1955 fs->bufState = YY_CURRENT_BUFFER;
1956 fs->oldLineNr = yyextra->lineNr;
1957 fs->oldFileName = yyextra->fileName;
1958 fs->oldState = yyextra->includeCtx;
1959 fs->oldFileBuf = yyextra->inBuf;
1960 fs->oldFileBufPos = yyextra->inBufPos;
1961 fs->oldIncludeCtx = yyextra->includeCtx;
1962 fs->oldRaiseLvl = oldRaiseLevel;
1963 fs->oldRaiseLbl = oldRaiseLabel;
1964 fs->blockId = blockId;
1965 yy_switch_to_buffer(yy_create_buffer(nullptr, YY_BUF_SIZE, yyscanner),yyscanner);
1966 yyextra->fileName = absFileName;
1967 yyextra->lineNr = lineNr;
1968 yyextra->inBuf = &fs->fileBuf;
1969 yyextra->inBufPos = 0;
1970 yyextra->includeStack.push_back(std::move(fs));
1971 insertCommentStart(yyscanner);
1972 //printf("switched to %s\n",qPrint(fileName));
1973 }
1974 else
1975 {
1976 warn_doc_error(yyextra->fileName,yyextra->lineNr,"\\{}{{doc}} file '{}' not found",blockId.isEmpty()?"include":"snippet",inc);
1977 return false;
1978 }
1979 return true;
static void insertCommentStart(yyscan_t yyscanner)
#define YY_BUF_SIZE
Definition commentcnv.l:19
1980}

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

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

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

◆ replaceComment()

void replaceComment ( yyscan_t yyscanner,
int offset )
static

Definition at line 2073 of file commentcnv.l.

2074{
2075 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2076 if (yyextra->mlBrief || yyextra->skip)
2077 {
2078 copyToOutput(yyscanner,yytext,yyleng);
2079 }
2080 else
2081 {
2082 int i=computeIndent(&yytext[offset]);
2083 //printf("i=%d blockHeadCol=%d\n",i,yyextra->blockHeadCol);
2084 if (i==yyextra->blockHeadCol || i+1==yyextra->blockHeadCol)
2085 {
2086 replaceCommentMarker(yyscanner,std::string_view(yytext,yyleng));
2087 }
2088 else
2089 {
2090 copyToOutput(yyscanner," */");
2091 for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
2092 yyextra->inSpecialComment=FALSE;
2093 BEGIN(Scan);
2094 }
2095 }
static int computeIndent(const char *s)
static void replaceCommentMarker(yyscan_t yyscanner, std::string_view s)
2096}

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

◆ replaceCommentMarker()

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

Definition at line 1598 of file commentcnv.l.

1599{
1600 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1601 if (s.empty()) return;
1602 size_t p = 0;
1603 size_t len = s.length();
1604 char c = 0;
1605 // copy leading blanks
1606 while (p<len && (c=s[p]) && (c==' ' || c=='\t' || c=='\n'))
1607 {
1608 yyextra->outBuf+=c;
1609 if (c=='\n') { yyextra->lineNr++; yyextra->col=0; } else { yyextra->col++; }
1610 p++;
1611 }
1612 // replace start of comment marker by blanks and the last character by a *
1613 int blanks=0;
1614 while (p<len && (c=s[p]) && (c=='/' || c=='!' || c=='#'))
1615 {
1616 blanks++;
1617 p++;
1618 if (p<len && s[p]=='<') // comment-after-item marker
1619 {
1620 blanks++;
1621 p++;
1622 }
1623 if (c=='!') // end after first !
1624 {
1625 break;
1626 }
1627 }
1628 if (blanks>0)
1629 {
1630 while (blanks>2)
1631 {
1632 yyextra->outBuf+=' ';
1633 yyextra->col++;
1634 blanks--;
1635 }
1636 if (blanks>1) { yyextra->outBuf+='*'; yyextra->col++; }
1637 yyextra->outBuf+=' ';
1638 yyextra->col++;
1639 }
1640 // copy comment line to output
1641 yyextra->outBuf+=s.substr(p);
1642 yyextra->col+=static_cast<int>(s.substr(p).length());
1643}

Referenced by replaceComment().

◆ startCondSection()

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

Definition at line 1713 of file commentcnv.l.

1714{
1715 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1716 //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1717 CondParser prs;
1718 bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
1719 yyextra->condStack.emplace(yyextra->lineNr,sectId,yyextra->skip);
1720 if (!expResult) // not enabled
1721 {
1722 yyextra->skip=TRUE;
1723 }
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
1724}

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:6950
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 if (yyextra->inSpecialComment || yyextra->specialComment || yyextra->lang==SrcLangExt::Markdown)
627 {
628 yyextra->lastCommentContext = YY_START;
629 yyextra->javaBlock=0;
630 if (qstrcmp(&yytext[1],"startuml")==0)
631 {
632 yyextra->blockName="enduml";
633 }
634 else
635 {
636 yyextra->blockName=QCString("end")+&yytext[1];
637 }
638 yyextra->inVerbatim=true;
639 yyextra->verbatimLine=yyextra->lineNr;
640 BEGIN(VerbatimCode);
641 }
642 }
int qstrcmp(const char *str1, const char *str2)
Definition qcstring.h:69
643<CComment,ReadLine,IncludeFile>"\\`" {
644 copyToOutput(yyscanner,yytext,yyleng);
645 }
646<CComment,ReadLine,IncludeFile>"```" { // skip ``` if not at the start of the line
647 copyToOutput(yyscanner,yytext,yyleng);
648 }
649<CComment,ReadLine,IncludeFile>"`"{1,2} {
650 if (!Config_getBool(MARKDOWN_SUPPORT))
651 {
652 REJECT;
653 }
654 copyToOutput(yyscanner,yytext,yyleng);
655 if (yyextra->inSpecialComment || yyextra->specialComment || yyextra->lang==SrcLangExt::Markdown)
656 {
657 yyextra->lastCommentContext = YY_START;
658 yyextra->javaBlock=0;
659 yyextra->blockName=yytext;
660 yyextra->inVerbatim=true;
661 yyextra->verbatimLine=yyextra->lineNr;
662 BEGIN(VerbatimCode);
663 }
664 }
665<CComment,ReadLine,IncludeFile>{CMD}("f$"|"f["|"f{"|"f(") {
666 copyToOutput(yyscanner,yytext,yyleng);
667 if (yyextra->inSpecialComment || yyextra->specialComment || yyextra->lang==SrcLangExt::Markdown)
668 {
669 yyextra->blockName=&yytext[1];
670 if (yyextra->blockName.at(1)=='[')
671 {
672 yyextra->blockName.at(1)=']';
673 }
674 else if (yyextra->blockName.at(1)=='{')
675 {
676 yyextra->blockName.at(1)='}';
677 }
678 else if (yyextra->blockName.at(1)=='(')
679 {
680 yyextra->blockName.at(1)=')';
681 }
682 yyextra->lastCommentContext = YY_START;
683 yyextra->inVerbatim=true;
684 yyextra->verbatimLine=yyextra->lineNr;
685 BEGIN(Verbatim);
686 }
687 }
688<CComment,ReadLine,IncludeFile>"<!--!" { /* HTML comment doxygen command*/
689 if (yyextra->inVerbatim) REJECT;
690 //copyToOutput(yyscanner," ",5);
691 yyextra->inHtmlDoxygenCommand=true;
692 }
693<CComment,ReadLine,IncludeFile>"-->" { /* potential end HTML comment doxygen command*/
694 if (yyextra->inHtmlDoxygenCommand)
695 {
696 yyextra->inHtmlDoxygenCommand=false;
697 }
698 else
699 {
700 copyToOutput(yyscanner,yytext,yyleng);
701 }
702 }
703<CComment,ReadLine,IncludeFile>"<!--" { /* HTML comment */
704 copyToOutput(yyscanner,yytext,yyleng);
705 if (yyextra->inSpecialComment || yyextra->specialComment || yyextra->lang==SrcLangExt::Markdown)
706 {
707 yyextra->blockName="-->";
708 yyextra->lastCommentContext = YY_START;
709 yyextra->inVerbatim=true;
710 yyextra->verbatimLine=yyextra->lineNr;
711 BEGIN(Verbatim);
712 }
713 }
714<CComment,ReadLine,IncludeFile>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
715 copyToOutput(yyscanner,yytext,yyleng);
716 if (yyextra->inSpecialComment || yyextra->specialComment || yyextra->lang==SrcLangExt::Markdown)
717 {
718 yyextra->blockName=QCString("end")+&yytext[1];
719 yyextra->lastCommentContext = YY_START;
720 yyextra->inVerbatim=true;
721 yyextra->verbatimLine=yyextra->lineNr;
722 BEGIN(Verbatim);
723 }
724 }
725<Scan>"\\\"" { /* escaped double quote */
726 copyToOutput(yyscanner,yytext,yyleng);
727 }
728<Scan>"\\\\" { /* escaped backslash */
729 copyToOutput(yyscanner,yytext,yyleng);
730 }
731<Scan>. { /* any other character */
732 copyToOutput(yyscanner,yytext,yyleng);
733 }
734<Verbatim>{CMD}("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */
735 copyToOutput(yyscanner,yytext,yyleng);
736 if (&yytext[1]==yyextra->blockName) // end of command or formula
737 {
738 yyextra->inVerbatim=false;
739 BEGIN(yyextra->lastCommentContext);
740 }
741 }
742<Verbatim>"-->" {
743 copyToOutput(yyscanner,yytext,yyleng);
744 if (yytext==yyextra->blockName)
745 {
746 yyextra->inVerbatim=false;
747 BEGIN(yyextra->lastCommentContext);
748 }
749 }
750<VerbatimCode>"{" {
751 if (yyextra->javaBlock==0)
752 {
753 REJECT;
754 }
755 else
756 {
757 yyextra->javaBlock++;
758 copyToOutput(yyscanner,yytext,yyleng);
759 }
760 }
761<VerbatimCode>"}" {
762 if (yyextra->javaBlock==0)
763 {
764 REJECT;
765 }
766 else
767 {
768 yyextra->javaBlock--;
769 if (yyextra->javaBlock==0)
770 {
771 copyToOutput(yyscanner," @endiliteral ");
772 yyextra->inVerbatim=false;
773 BEGIN(yyextra->lastCommentContext);
774 }
775 else
776 {
777 copyToOutput(yyscanner,yytext,yyleng);
778 }
779 }
780 }
781<VerbatimCode>("```"[`]*|"~~~"[~]*) { /* end of markdown code block */
782 if (yytext[0]=='`' && (yyextra->blockName=="`" || yyextra->blockName=="``")) // ``` type block inside single or double backtick "block"
783 {
784 // copy the end block marker
785 copyToOutput(yyscanner,yytext,yyleng);
786 }
787 else
788 {
789 copyToOutput(yyscanner,yytext,yyleng);
790 if (yytext[0]==yyextra->blockName[0])
791 {
792 yyextra->inVerbatim=false;
793 BEGIN(yyextra->lastCommentContext);
794 }
795 }
796 }
797<VerbatimCode>"''" {
798 copyToOutput(yyscanner,yytext,yyleng);
799 if (!Config_getBool(MARKDOWN_STRICT) && yyextra->blockName=="``") // support for ``text''
800 {
801 yyextra->inVerbatim=false;
802 BEGIN(yyextra->lastCommentContext);
803 }
804 }
805<VerbatimCode>"'" {
806 copyToOutput(yyscanner,yytext,yyleng);
807 if (!Config_getBool(MARKDOWN_STRICT) && yyextra->blockName=="`") // support for `text'
808 {
809 yyextra->inVerbatim=false;
810 BEGIN(yyextra->lastCommentContext);
811 }
812 }
813<VerbatimCode>"`"{1,2} {
814 copyToOutput(yyscanner,yytext,yyleng);
815 if (yytext==yyextra->blockName)
816 {
817 yyextra->inVerbatim=false;
818 BEGIN(yyextra->lastCommentContext);
819 }
820 }
821<VerbatimCode>{CMD}("enddot"|"endcode"|"endmsc"|"enduml")/("{")? { // end of verbatim block
822 copyToOutput(yyscanner,yytext,yyleng);
823 if (&yytext[1]==yyextra->blockName)
824 {
825 yyextra->inVerbatim=false;
826 BEGIN(yyextra->lastCommentContext);
827 }
828 }
829<VerbatimCode>^[ \t]*{CPPC}[\!\/]? { /* skip leading comments */
830 if (!yyextra->inSpecialComment || yyextra->mlBrief)
831 {
832 copyToOutput(yyscanner,yytext,yyleng);
833 }
834 else
835 {
836 int l=0;
837 while (yytext[l]==' ' || yytext[l]=='\t')
838 {
839 l++;
840 }
841 copyToOutput(yyscanner,yytext,l);
842 if (yyleng-l==3) // ends with //! or ///
843 {
844 copyToOutput(yyscanner," * ");
845 }
846 else // ends with //
847 {
848 copyToOutput(yyscanner,"//");
849 }
850 }
851 }
852<Verbatim,VerbatimCode>[^`'~@\/\-\\\n{}]* { /* any character not a backslash or new line or } */
853 copyToOutput(yyscanner,yytext,yyleng);
854 }
855<Verbatim,VerbatimCode>[^`'~@\/\-\\\n{}]+/\n{B}*"//" {
856 if (yyextra->lastCommentContext!=ReadLine)
857 {
858 REJECT;
859 }
860 else
861 {
862 copyToOutput(yyscanner,yytext,yyleng);
863 }
864 }
865<Verbatim,VerbatimCode>[^`'~@\/\-\\\n{}]+/\n { /* premature end of comment block */
866 if (yyextra->lastCommentContext==ReadLine)
867 {
868 yyextra->inVerbatim=false;
869 BEGIN(yyextra->lastCommentContext);
870 }
871 copyToOutput(yyscanner,yytext,yyleng);
872 }
873<Verbatim,VerbatimCode>\n { /* new line in verbatim block */
874 copyToOutput(yyscanner,yytext,yyleng);
875 if (yyextra->lastCommentContext == IncludeFile)
876 {
877 insertCommentStart(yyscanner);
878 }
879 }
880<Verbatim>^[ \t]*{CPPC}[/!] {
881 if (yyextra->blockName=="enddot" || yyextra->blockName=="endmsc" || yyextra->blockName=="enduml" || yyextra->blockName.at(0)=='f')
882 {
883 // see bug 487871, strip /// from dot images and formulas.
884 int l=0;
885 while (yytext[l]==' ' || yytext[l]=='\t')
886 {
887 l++;
888 }
889 copyToOutput(yyscanner,yytext,l);
890 copyToOutput(yyscanner," ");
891 }
892 else // even slashes are verbatim (e.g. \verbatim, \code)
893 {
894 REJECT;
895 }
896 }
897<Verbatim,VerbatimCode>. { /* any other character */
898 copyToOutput(yyscanner,yytext,yyleng);
899 }
900<SkipString>\\. { /* escaped character in string */
901 if (yyextra->lang==SrcLangExt::Fortran || yyextra->lang==SrcLangExt::VHDL)
902 {
903 unput(yytext[1]);
904 copyToOutput(yyscanner,yytext,1);
905 }
906 else
907 {
908 copyToOutput(yyscanner,yytext,yyleng);
909 }
910 }
911<SkipString>"\"" { /* end of string */
912 copyToOutput(yyscanner,yytext,yyleng);
913 BEGIN(yyextra->stringContext);
914 }
915<SkipString>. { /* any other string character */
916 copyToOutput(yyscanner,yytext,yyleng);
917 }
918<SkipString>\n { /* new line inside string (illegal for some compilers) */
919 copyToOutput(yyscanner,yytext,yyleng);
920 }
921<SkipVerbString>[^"\n]+ {
922 copyToOutput(yyscanner,yytext,yyleng);
923 }
924<SkipVerbString>\"\" { // escaped quote
925 copyToOutput(yyscanner,yytext,yyleng);
926 }
927<SkipVerbString>"\"" { /* end of string */
928 copyToOutput(yyscanner,yytext,yyleng);
929 BEGIN(yyextra->stringContext);
930 }
931<SkipVerbString>. {
932 copyToOutput(yyscanner,yytext,yyleng);
933 }
934<SkipVerbString>\n {
935 copyToOutput(yyscanner,yytext,yyleng);
936 }
937<SkipChar>\\. { /* escaped character */
938 if (yyextra->lang==SrcLangExt::Fortran || yyextra->lang==SrcLangExt::VHDL)
939 {
940 unput(yytext[1]);
941 copyToOutput(yyscanner,yytext,1);
942 }
943 else
944 {
945 copyToOutput(yyscanner,yytext,yyleng);
946 }
947 }
948<SkipChar>' { /* end of character literal */
949 copyToOutput(yyscanner,yytext,yyleng);
950 BEGIN(yyextra->charContext);
951 }
952<SkipChar>. { /* any other string character */
953 copyToOutput(yyscanner,yytext,yyleng);
954 }
955<SkipChar>\n { /* new line character */
956 copyToOutput(yyscanner,yytext,yyleng);
957 }
958
959<CComment,CNComment>[^ `~<\\!@*\n{\"'\/-`]* { /* anything that is not a '*' or command */
960 copyToOutput(yyscanner,yytext,yyleng);
961 }
962<CComment,CNComment>^{B}*"*"+[^*\/<\\@\n{\"`]* { /* stars without slashes */
963 if (yyextra->lang==SrcLangExt::Markdown) REJECT;
964 yyextra->col = computeIndent(yytext);
965 if (yyextra->col>yyextra->blockHeadCol)
966 {
967 //printf("new blockHeadCol=%d\n",yyextra->blockHeadCol);
968 yyextra->blockHeadCol=yyextra->col;
969 }
970 copyToOutput(yyscanner,yytext,yyleng);
971 }
972<CComment>"'''" |
973<CComment>"\"\"\"" { /* end of Python docstring */
974 if (yyextra->lang!=SrcLangExt::Python)
975 {
976 REJECT;
977 }
978 else if (yyextra->pythonDocStringChar != yytext[0])
979 {
980 copyToOutput(yyscanner,yytext,yyleng);
981 }
982 else
983 {
984 yyextra->nestingCount--;
985 yyextra->pythonDocString = FALSE;
986 yyextra->pythonDocStringChar = '\0';
987 copyToOutput(yyscanner,yytext,yyleng);
988 BEGIN(Scan);
989 }
990 }
991<CComment,CNComment>\n { /* new line in comment */
992 copyToOutput(yyscanner,yytext,yyleng);
993 /* in case of Fortran always end of comment */
994 if (yyextra->lang==SrcLangExt::Fortran)
995 {
996 BEGIN(Scan);
997 }
998 }
999<CComment,CNComment>"/""/"+/"*/" { /* we are already in C-comment so not a start of a nested comment but
1000 * just the end of the comment (the end part is handled later). */
1001 copyToOutput(yyscanner,yytext,yyleng);
1002 }
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
const char * comment
1003<CComment,CNComment>"/"+"*" { /* nested C comment */
1004 if (yyextra->lang==SrcLangExt::Python ||
1005 yyextra->lang==SrcLangExt::Markdown)
1006 {
1007 REJECT;
1008 }
1009 yyextra->nestingCount++;
1010 yyextra->commentStack.push(yyextra->lineNr);
1011 copyToOutput(yyscanner,yytext,yyleng);
1012 }
1013<CComment,CNComment>^{B}*"*"+"/" |
1014<CComment,CNComment>"*"+"/" { /* end of C comment */
1015 if (yyextra->lang==SrcLangExt::Python ||
1016 yyextra->lang==SrcLangExt::Markdown)
1017 {
1018 REJECT;
1019 }
1020 else
1021 {
1022 copyToOutput(yyscanner,yytext,yyleng);
1023 yyextra->nestingCount--;
1024 if (yyextra->nestingCount<=0)
1025 {
1026 BEGIN(Scan);
1027 }
1028 else
1029 {
1030 //yyextra->nestingCount--;
1031 yyextra->commentStack.pop();
1032 }
1033 }
1034 }
1035 /* Python an VHDL share CComment,CNComment, so special attention for ending comments is required */
1036<CComment,CNComment>"\n"/[ \t]*"#" {
1037 if (yyextra->lang!=SrcLangExt::VHDL)
1038 {
1039 REJECT;
1040 }
1041 else
1042 {
1043 if (yyextra->vhdl) // inside --! comment
1044 {
1045 yyextra->vhdl = FALSE;
1046 copyToOutput(yyscanner,yytext,yyleng);
1047 BEGIN(Scan);
1048 }
1049 else // C-type comment
1050 {
1051 REJECT;
1052 }
1053 }
1054 }
1055<CComment,CNComment>"\n"/[ \t]*"-" {
1056 if (yyextra->lang!=SrcLangExt::Python || yyextra->pythonDocString)
1057 {
1058 REJECT;
1059 }
1060 else
1061 {
1062 copyToOutput(yyscanner,yytext,yyleng);
1063 BEGIN(Scan);
1064 }
1065 }
1066<CComment,CNComment>"\n"/[ \t]*[^ \t#\-] {
1067 if (yyextra->lang==SrcLangExt::Python)
1068 {
1069 if (yyextra->pythonDocString)
1070 {
1071 REJECT;
1072 }
1073 else
1074 {
1075 copyToOutput(yyscanner,yytext,yyleng);
1076 BEGIN(Scan);
1077 }
1078 }
1079 else if (yyextra->lang==SrcLangExt::VHDL)
1080 {
1081 if (yyextra->vhdl) // inside --! comment
1082 {
1083 yyextra->vhdl = FALSE;
1084 copyToOutput(yyscanner,yytext,yyleng);
1085 BEGIN(Scan);
1086 }
1087 else // C-type comment
1088 {
1089 REJECT;
1090 }
1091 }
1092 else
1093 {
1094 REJECT;
1095 }
1096 }
1097 /* removed for bug 674842 (bug was introduced in rev 768)
1098<CComment,CNComment>"'" {
1099 yyextra->charContext = YY_START;
1100 copyToOutput(yyscanner,yytext,yyleng);
1101 BEGIN(SkipChar);
1102 }
1103<CComment,CNComment>"\"" {
1104 yyextra->stringContext = YY_START;
1105 copyToOutput(yyscanner,yytext,yyleng);
1106 BEGIN(SkipString);
1107 }
1108 */
1109<CComment,CNComment>{CMD}"~"[a-z_A-Z-]* { // language switch command
1110 if (yyextra->lang!=SrcLangExt::Markdown) REJECT;
1111 QCString langId = QCString(yytext).mid(2);
1112 if (!langId.isEmpty() &&
1113 qstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE),langId)!=0)
1114 { // enable language specific section
1115 if (!Config_isAvailableEnum(OUTPUT_LANGUAGE,langId))
1116 {
1117 warn(yyextra->fileName,yyextra->lineNr,
1118 "non supported language '{}' specified in '{}'",langId,QCString(yytext).stripWhiteSpace());
1119 }
1120 BEGIN(SkipLang);
1121 }
1122 }
#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:530
1123<CComment,CNComment>{CMD}{CMD} |
1124<CComment,CNComment>. {
1125 copyToOutput(yyscanner,yytext,yyleng);
1126 }
1127<SkipLang>{CMD}"~"[a-zA-Z-]* { /* language switch */
1128 QCString langId(&yytext[2]);
1129 if (!langId.isEmpty() && !Config_isAvailableEnum(OUTPUT_LANGUAGE,langId))
1130 {
1131 warn(yyextra->fileName,yyextra->lineNr,
1132 "non supported language '{}' specified in '{}'",langId,QCString(yytext).stripWhiteSpace());
1133 }
1134 else if (langId.isEmpty() ||
1135 qstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE),langId)==0)
1136 { // enable language specific section
1137 BEGIN(CComment);
1138 }
1139 }
1140<SkipLang>[^*@\\\n]* { /* any character not a *, @, backslash or new line */
1141 }
1142<SkipLang>\n { /* new line in language block, needed for keeping track of line numbers */
1143 copyToOutput(yyscanner,yytext,yyleng);
1144 }
1145<SkipLang>. { /* any other character */
1146 }
1147<SComment>^[ \t]*{CPPC}"/"{SLASHopt}/\n {
1148 replaceComment(yyscanner,0);
1149 }
static void replaceComment(yyscan_t yyscanner, int offset)
1150<SComment>\n[ \t]*{CPPC}"/"{SLASHopt}/\n {
1151 replaceComment(yyscanner,1);
1152 }
1153<SComment>^[ \t]*{CPPC}"/"[^\/\n]/.*\n {
1154 replaceComment(yyscanner,0);
1155 yyextra->readLineCtx=YY_START;
1156 YY_CURRENT_BUFFER->yy_at_bol=1;
1157 BEGIN(ReadLine);
1158 }
1159<SComment>\n[ \t]*{CPPC}[\/!]("<")?[ \t]*{CMD}"}".*\n {
1160 /* See Bug 752712: end the multiline comment when finding a @} or \} command */
1161 copyToOutput(yyscanner," */");
1162 copyToOutput(yyscanner,yytext,yyleng);
1163 yyextra->inSpecialComment=false;
1164 yyextra->inRoseComment=false;
1165 BEGIN(Scan);
1166 }
1167<SComment>\n[ \t]*{CPPC}"/"[^\\@\/\n]/.*\n {
1168 replaceComment(yyscanner,1);
1169 yyextra->readLineCtx=YY_START;
1170 YY_CURRENT_BUFFER->yy_at_bol=1;
1171 BEGIN(ReadLine);
1172 }
1173<SComment>^[ \t]*{CPPC}"!" | // just //!
1174<SComment>^[ \t]*{CPPC}"!<"/.*\n | // or //!< something
1175<SComment>^[ \t]*{CPPC}"!"[^<]/.*\n { // or //!something
1176 replaceComment(yyscanner,0);
1177 yyextra->readLineCtx=YY_START;
1178 YY_CURRENT_BUFFER->yy_at_bol=1;
1179 BEGIN(ReadLine);
1180 }
1181<SComment>\n[ \t]*{CPPC}"!" |
1182<SComment>\n[ \t]*{CPPC}"!<"/.*\n |
1183<SComment>\n[ \t]*{CPPC}"!"[^<\n]/.*\n {
1184 replaceComment(yyscanner,1);
1185 yyextra->readLineCtx=YY_START;
1186 YY_CURRENT_BUFFER->yy_at_bol=1;
1187 BEGIN(ReadLine);
1188 }
1189<SComment>^[ \t]*{CPPC}"##"/.*\n {
1190 if (!yyextra->inRoseComment)
1191 {
1192 REJECT;
1193 }
1194 else
1195 {
1196 replaceComment(yyscanner,0);
1197 yyextra->readLineCtx=YY_START;
1198 YY_CURRENT_BUFFER->yy_at_bol=1;
1199 BEGIN(ReadLine);
1200 }
1201 }
1202<SComment>\n[ \t]*{CPPC}"##"/.*\n {
1203 if (!yyextra->inRoseComment)
1204 {
1205 REJECT;
1206 }
1207 else
1208 {
1209 replaceComment(yyscanner,1);
1210 yyextra->readLineCtx=YY_START;
1211 YY_CURRENT_BUFFER->yy_at_bol=1;
1212 BEGIN(ReadLine);
1213 }
1214 }
1215<SComment>\n { /* end of special comment */
1216 copyToOutput(yyscanner," */");
1217 copyToOutput(yyscanner,yytext,yyleng);
1218 yyextra->inSpecialComment=FALSE;
1219 yyextra->inRoseComment=FALSE;
1220 yyextra->insertCppCommentMarker=false;
1221 yyextra->readLineCtx = Scan; // reset, otherwise there will be problems with:
1222 // static void handleCondSectionId
1223 BEGIN(Scan);
1224 }
1225<ReadLine,CopyLine>{CCS}"*" {
1226 copyToOutput(yyscanner,"/&zwj;**");
1227 }
1228<ReadLine,CopyLine>{CCE} {
1229 copyToOutput(yyscanner,"*&zwj;/");
1230 }
1231<ReadLine,CopyLine>"*" {
1232 copyToOutput(yyscanner,yytext,yyleng);
1233 }
1234<ReadLine,CopyLine>{RL} {
1235 copyToOutput(yyscanner,yytext,yyleng);
1236 }
1237<ReadLine,CopyLine>{RL}/{B}{CMD}"ilinebr"{B} {
1238 copyToOutput(yyscanner,yytext,yyleng);
1239 }
1240<ReadLine,CopyLine>{RLopt}/\n {
1241 copyToOutput(yyscanner,yytext,yyleng);
1242 yyextra->insertCppCommentMarker=false;
1243 BEGIN(yyextra->readLineCtx);
1244 }
1245<CComment,CNComment,ReadLine>"\<" { /* escaped html comment */
1246 copyToOutput(yyscanner,yytext,yyleng);
1247 }
1248<CComment,CNComment,ReadLine>{CMD}{CMD}[~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
1249 copyToOutput(yyscanner,yytext,yyleng);
1250 }
1251
1252<CComment,ReadLine,IncludeFile>{CMD}("include"{OPTS}|"includedoc"{OPTS}*) {
1253 if (!parseIncludeOptions(yyscanner,std::string_view{yytext,static_cast<size_t>(yyleng)})) REJECT;
1254 yyextra->includeCtx = YY_START;
1255 yyextra->firstIncludeLine = true;
1256 yyextra->insertCommentCol = yyextra->col;
1257 if (!yyextra->insertCppCommentMarker && (yyextra->includeCtx==ReadLine || yyextra->includeCtx==IncludeFile))
1258 {
1259 yyextra->insertCppCommentMarker = yyextra->mlBrief;
1260 }
1261 //printf("blockHeadCol=%d insertCommentCol=%d\n",yyextra->blockHeadCol, yyextra->insertCommentCol);
1262 BEGIN(IncludeDoc);
1263 }
static bool parseIncludeOptions(yyscan_t yyscanner, std::string_view s)
1264<CComment,ReadLine,IncludeFile>{CMD}("snippet"{OPTS}|"snippetdoc"{OPTS}*) {
1265 if (!parseIncludeOptions(yyscanner,std::string_view{yytext,static_cast<size_t>(yyleng)})) REJECT;
1266 yyextra->includeCtx = YY_START;
1267 yyextra->firstIncludeLine = true;
1268 yyextra->insertCommentCol = yyextra->col;
1269 if (!yyextra->insertCppCommentMarker && (yyextra->includeCtx==ReadLine || yyextra->includeCtx==IncludeFile))
1270 {
1271 yyextra->insertCppCommentMarker = yyextra->mlBrief;
1272 }
1273 //printf("blockHeadCol=%d insertCommentCol=%d\n",yyextra->blockHeadCol, yyextra->insertCommentCol);
1274 BEGIN(SnippetDoc);
1275 }
1276<IncludeDoc,SnippetDoc>{B}*
1277<IncludeDoc>{FILEMASK}|"\""[^\n\"]+"\"" {
1278 QCString fileName=yytext;
1279 if (yytext[0]=='"')
1280 {
1281 fileName=fileName.mid(1,fileName.length()-2); // strip quotes
1282 }
1283 if (readIncludeFile(yyscanner,fileName,""))
1284 {
1285 BEGIN(IncludeFile);
1286 }
1287 else
1288 {
1289 BEGIN(yyextra->includeCtx);
1290 }
1291 }
static bool readIncludeFile(yyscan_t yyscanner, const QCString &inc, const QCString &blockId)
1292<SnippetDoc>({FILEMASK}|"\""[^\n\"]+"\""){B}+ {
1293 yyextra->snippetFileName=yytext;
1294 yyextra->snippetFileName=yyextra->snippetFileName.stripWhiteSpace();
1295 if (yyextra->snippetFileName == "this") yyextra->snippetFileName=yyextra->fileName;
1296 yyextra->snippetName = "";
1297 BEGIN(SnippetDocTag);
1298 }
1299<SnippetDocTag>[^\\@\n]+ {
1300 yyextra->snippetName += yytext;
1301 }
1302<SnippetDocTag>{CMD} {
1303 yyextra->snippetName += yytext;
1304 }
1305<SnippetDocTag>(\n|{CMD}"ilinebr") {
1306 for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
1307 yyextra->snippetName = yyextra->snippetName.stripWhiteSpace();
1308 QCString blockId = "["+yyextra->snippetName+"]";
1309 if (readIncludeFile(yyscanner,yyextra->snippetFileName,blockId))
1310 {
1311 BEGIN(IncludeFile);
1312 }
1313 else
1314 {
1315 BEGIN(yyextra->includeCtx);
1316 }
1317 }
1318
1319<IncludeDoc,SnippetDoc>\n {
1320 copyToOutput(yyscanner,yytext,yyleng);
1321 insertCommentStart(yyscanner);
1322 // missing file name
1323 //warn(yyextra->fileName,yyextra->lineNr,"Found \\include{{doc}} command without valid file name argument");
1324 BEGIN(yyextra->includeCtx);
1325 }
1326<IncludeDoc,SnippetDoc>. { // invalid character
1327 copyToOutput(yyscanner,yytext,yyleng);
1328 BEGIN(yyextra->includeCtx);
1329 }
1330<CComment,ReadLine,IncludeFile>{CMD}"cond"/[^a-z_A-Z0-9] { // conditional section
1331 yyextra->condCtx = YY_START;
1332 BEGIN(CondLine);
1333 }
1334<CComment,ReadLine,IncludeFile>{CMD}"endcond"/[^a-z_A-Z0-9] { // end of conditional section
1335 bool oldSkip=yyextra->skip;
1336 endCondSection(yyscanner);
1337 if (YY_START==CComment && oldSkip && !yyextra->skip)
1338 {
1339 //printf("** Adding start of comment!\n");
1340 if (yyextra->lang!=SrcLangExt::Python &&
1341 yyextra->lang!=SrcLangExt::VHDL &&
1342 yyextra->lang!=SrcLangExt::Markdown &&
1343 yyextra->lang!=SrcLangExt::Fortran)
1344 {
1345 yyextra->outBuf+='/';
1346 yyextra->outBuf+='*';
1347 yyextra->col+=2;
1348 if (yyextra->specialComment)
1349 {
1350 yyextra->outBuf+='*';
1351 yyextra->col++;
1352 }
1353 }
1354 }
1355 }
static void endCondSection(yyscan_t yyscanner)
1356<CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
1357 handleCondSectionId(yyscanner,yytext);
1358 }
static void handleCondSectionId(yyscan_t yyscanner, const char *expression)
1359<CComment,ReadLine,IncludeFile>{CMD}"cond"{WSopt}/\n {
1360 yyextra->condCtx=YY_START;
1361 handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
1362 }
1363<CondLine>\n |
1364<CondLine>. { // forgot section id?
1365 handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
1366 if (*yytext=='\n') { copyToOutput(yyscanner,"\n");}
1367 }
1368<CComment,ReadLine,IncludeFile,Verbatim,VerbatimCode>{CMD}[a-z_A-Z][a-z_A-Z0-9-]* { // expand alias without arguments
1369 bool inCppComment = YY_START==ReadLine && yyextra->readLineCtx==SComment;
1370 bool inCComment = YY_START==CComment && yyextra->blockHeadCol>0;
1371 replaceAliases(yyscanner,yytext,inCppComment,inCComment);
1372 }
1373<CComment,ReadLine,IncludeFile,Verbatim,VerbatimCode>{B}?{CMD}"ilinebr"{B}{CMD}"ialias{" { // expand alias with arguments
1374 yyextra->lastBlockContext=YY_START;
1375 yyextra->blockCount=1;
1376 int extraSpace = (yytext[0]==' '? 1:0);
1377 yyextra->aliasString=yytext+9+extraSpace;
1378 yyextra->aliasCmd=yytext+9+extraSpace;
1379 yyextra->lastEscaped=0;
1380 BEGIN( ReadAliasArgs );
1381 }
1382<CComment,ReadLine,IncludeFile,Verbatim,VerbatimCode>{CMD}[a-z_A-Z][a-z_A-Z0-9-]*"{" { // expand alias with arguments
1383 yyextra->lastBlockContext=YY_START;
1384 yyextra->blockCount=1;
1385 yyextra->aliasString=yytext;
1386 yyextra->aliasCmd=yytext;
1387 yyextra->lastEscaped=0;
1388 BEGIN( ReadAliasArgs );
1389 }
1390<ReadAliasArgs>^[ \t]*"*" {
1391 int indent=computeIndent(yytext)-1;
1392 if (indent>yyextra->blockHeadCol) // assume part of block marker
1393 {
1394 yyextra->aliasString+=yytext;
1395 }
1396 else
1397 {
1398 // skip leading *
1399 }
1400 }
1401<ReadAliasArgs>^[ \t]*{CPPC}[/!]/[^\n]* { // skip leading special comments (see bug 618079)
1402 }
1403<ReadAliasArgs>[^{}\n\\\*]+ {
1404 yyextra->aliasString+=yytext;
1405 yyextra->lastEscaped=FALSE;
1406 }
1407<ReadAliasArgs>"\\" {
1408 if (yyextra->lastEscaped) yyextra->lastEscaped=FALSE;
1409 else yyextra->lastEscaped=TRUE;
1410 yyextra->aliasString+=yytext;
1411 }
1412<ReadAliasArgs>{CMD}("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */
1413 yyextra->aliasString+=yytext;
1414 if (yyextra->inVerbatim && &yytext[1]==yyextra->blockName)
1415 // For verbatim sections we do not support matching end block markers inside
1416 // alias arguments. Instead this will end the verbatim block.
1417 // This is needed to support an alias definition
1418 // like startalign=" \latexonly\noalign{\endlatexonly" were otherwise
1419 // the scanner would try to find a matching closing brace for noalign and then
1420 // skip over the \endlatexonly command.
1421 {
1422 copyToOutput(yyscanner,yyextra->aliasString.view());
1423 yyextra->inVerbatim=false;
1424 BEGIN(yyextra->lastCommentContext);
1425 }
1426 }
1427<ReadAliasArgs>\n {
1428 yyextra->aliasString+=yytext;
1429 yyextra->lastEscaped=FALSE;
1430 if (yyextra->inVerbatim) // for verbatim sections we do not support multi-line
1431 // alias arguments.
1432 {
1433 copyToOutput(yyscanner,yyextra->aliasString.view());
1434 BEGIN( yyextra->lastBlockContext );
1435 }
1436 }
1437<ReadAliasArgs>"{" {
1438 yyextra->aliasString+=yytext;
1439 if (!yyextra->lastEscaped) yyextra->blockCount++;
1440 yyextra->lastEscaped=FALSE;
1441 }
1442<ReadAliasArgs>"}" {
1443 yyextra->aliasString+=yytext;
1444 if (!yyextra->lastEscaped) yyextra->blockCount--;
1445 if (yyextra->blockCount==0)
1446 {
1447 bool inCppComment = yyextra->lastBlockContext==ReadLine && yyextra->readLineCtx==SComment;
1448 bool inCComment = yyextra->lastBlockContext==CComment && yyextra->blockHeadCol>0;
1449 replaceAliases(yyscanner,yyextra->aliasString.view(),inCppComment,inCComment);
1450 BEGIN( yyextra->lastBlockContext );
1451 }
1452 yyextra->lastEscaped=FALSE;
1453 }
1454<ReadAliasArgs>. {
1455 yyextra->aliasString+=yytext;
1456 yyextra->lastEscaped=FALSE;
1457 }
1458<CopyLine>. {
1459 copyToOutput(yyscanner,yytext,yyleng);
1460 }
1461<CopyLine>\n {
1462 copyToOutput(yyscanner,yytext,yyleng);
1463 yyextra->insertCppCommentMarker=false;
1464 BEGIN(yyextra->readLineCtx);
1465 }
1466<ReadLine>{CMD}{CMD} |
1467<ReadLine>. {
1468 copyToOutput(yyscanner,yytext,yyleng);
1469 }
1470<IncludeFile>. {
1471 copyToOutput(yyscanner,yytext,yyleng);
1472 }
1473<IncludeFile>\n {
1474 copyToOutput(yyscanner,yytext,yyleng);
1475 insertCommentStart(yyscanner);
1476 }
1477<*>. {
1478 copyToOutput(yyscanner,yytext,yyleng);
1479 }
1480<<EOF>> {
1481 if (YY_START == ReadAliasArgs)
1482 {
1483 warn(yyextra->fileName,yyextra->lineNr,
1484 "Reached end of file while still searching closing '}}' of an alias argument (probable start: '{}')",
1485 yyextra->aliasCmd);
1486 }
1487 else if (YY_START==Verbatim || YY_START==VerbatimCode)
1488 {
1489 warn(yyextra->fileName,yyextra->lineNr,
1490 "Reached end of file while still searching closing '{}' of a verbatim block starting at line {}",
1491 yyextra->blockName,yyextra->verbatimLine);
1492 }
1493 if (yyextra->includeStack.empty())
1494 {
1495 yyextra->insertCppCommentMarker=false;
1496 yyterminate();
1497 }
1498 else // switch back to parent file
1499 {
1500 std::unique_ptr<commentcnv_FileState> &fs = yyextra->includeStack.back();
1501 YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER;
1502 yy_switch_to_buffer(fs->bufState, yyscanner);
1503 yy_delete_buffer(oldBuf, yyscanner);
1504 BEGIN(fs->oldState);
1505 yyextra->fileName = fs->oldFileName;
1506 yyextra->lineNr = fs->oldLineNr;
1507 yyextra->inBuf = fs->oldFileBuf;
1508 yyextra->inBufPos = fs->oldFileBufPos;
1509 yyextra->includeCtx = fs->oldIncludeCtx;
1510 QCString lineStr= " \\ifile \""+yyextra->fileName+"\" \\iline "+QCString().setNum(yyextra->lineNr)+" ";
1511 if (fs->oldRaiseLvl!=yyextra->raiseLevel)
1512 {
1513 lineStr+="\\iraise " + std::to_string(fs->oldRaiseLvl)+ " ";
1514 }
1515 if (fs->oldRaiseLbl!=yyextra->raiseLabel)
1516 {
1517 lineStr+="\\iprefix \"" + fs->oldRaiseLbl + "\" ";
1518 }
1519 lineStr+="\\ilinebr ";
1520 yyextra->raiseLevel = fs->oldRaiseLvl;
1521 yyextra->raiseLabel = fs->oldRaiseLbl;
1522 copyToOutput(yyscanner,lineStr.view());
1523 yyextra->includeStack.pop_back();
1524 //printf("<<EOF>> switch back to %s line %d inbufPos=%d outbufPos=%d\n",
1525 // qPrint(yyextra->fileName),yyextra->lineNr,yyextra->inBufPos,yyextra->outBuf.curPos());
1526 }
1527 }
1528 /*
#define yyterminate()
1529<*>\n { fprintf(stderr,"Lex scanner %s (%s) default rule newline for state %s.\n", __FILE__, qPrint(yyextra->fileName),stateToString(YY_START));}
1530 */
1531%%

◆ yyread()

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

Definition at line 2063 of file commentcnv.l.

2064{
2065 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2066 int bytesInBuf = static_cast<int>(yyextra->inBuf->size())-yyextra->inBufPos;
2067 int bytesToCopy = std::min(max_size,bytesInBuf);
2068 memcpy(buf,yyextra->inBuf->data()+yyextra->inBufPos,bytesToCopy);
2069 yyextra->inBufPos+=bytesToCopy;
2070 return bytesToCopy;
2071}