Doxygen
Loading...
Searching...
No Matches
commentcnv.l File Reference
#include <stdint.h>
#include "commentcnv.h"
#include <algorithm>
#include <deque>
#include <stack>
#include <string>
#include <string_view>
#include <vector>
#include "aliases.h"
#include "condparser.h"
#include "config.h"
#include "debug.h"
#include "doxygen.h"
#include "filedef.h"
#include "fileinfo.h"
#include "filename.h"
#include "fortranscanner.h"
#include "message.h"
#include "section.h"
#include "stringutil.h"
#include "util.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 DString &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 DString &inc, const DString &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 int lineBlock (const DString &text, const DString &marker)
 Returns the line number of the line following the line with the marker.
static DString extractBlock (const DString &text, const DString &marker, size_t &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 at line 171 of file commentcnv.l.

◆ YY_NO_INPUT

#define YY_NO_INPUT   1

Definition at line 64 of file commentcnv.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 65 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 1718 of file commentcnv.l.

1719{
1720 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1721 while (!yyextra->commentStack.empty()) yyextra->commentStack.pop();
1722}

Referenced by convertCppComments().

◆ computeIndent()

int computeIndent ( const char * s)
inlinestatic

Definition at line 1656 of file commentcnv.l.

1657{
1658 int col=0;
1659 int tabSize=Config_getInt(TAB_SIZE);
1660 const char *p=s;
1661 char c = 0;
1662 while ((c=*p++))
1663 {
1664 if (c==' ') col++;
1665 else if (c=='\t') col+=tabSize-(col%tabSize);
1666 else break;
1667 }
1668 return col;
#define Config_getInt(name)
Definition config.h:34
1669}

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

2144{
2145 DString fileName { fn };
2146 yyscan_t yyscanner;
2147 commentcnvYY_state extra(&inBuf,outBuf);
2148 commentcnvYYlex_init_extra(&extra,&yyscanner);
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:88
yyguts_t * yyscan_t
Definition code.l:24
2149#ifdef FLEX_DEBUG
2150 commentcnvYYset_debug(Debug::isFlagSet(Debug::Lex_commentcnv)?1:0,yyscanner);
@ Lex_commentcnv
Definition debug.h:55
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:132
2151#endif
2152 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2153 //printf("convertCppComments(%s)\n",qPrint(fileName));
2154 yyextra->inBufPos = 0;
2155 yyextra->col = 0;
2156 yyextra->mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
2157 yyextra->skip = false;
2158 yyextra->fileName = fileName;
2159 yyextra->lang = getLanguageFromFileName(fileName);
2160 yyextra->pythonDocString = false;
2161 yyextra->lineNr = 1;
2162 yyextra->raiseLevel = 0;
2163 yyextra->raiseLabel = "";
2164 yyextra->raiseIncrement = 0;
2165 yyextra->raisePrefix = "";
2166 yyextra->insertCppCommentMarker=false;
2167 yyextra->expandedAliases.clear();
2168 while (!yyextra->condStack.empty()) yyextra->condStack.pop();
2169 clearCommentStack(yyscanner);
2170 yyextra->vhdl = false;
static void clearCommentStack(yyscan_t yyscanner)
#define Config_getBool(name)
Definition config.h:33
SrcLangExt getLanguageFromFileName(const DString &fileName, SrcLangExt defLang)
Definition util.cpp:4169
2171
2172 DebugLex debugLex(Debug::Lex_commentcnv,__FILE__, qPrint(fileName));
2173 yyextra->isFixedForm = false;
2174 if (yyextra->lang==SrcLangExt::Fortran)
2175 {
2177 yyextra->isFixedForm = recognizeFixedForm(inBuf,fmt);
2178 }
const char * qPrint(const char *s)
Definition dstring.h:787
bool recognizeFixedForm(const DString &contents, FortranFormat format)
FortranFormat convertFileNameFortranParserCode(const DString &fn)
Definition message.h:144
FortranFormat
Definition types.h:612
2179
2180 if (yyextra->lang==SrcLangExt::Markdown)
2181 {
2182 yyextra->nestingCount=0;
2183 BEGIN(CComment);
2184 yyextra->commentStack.push(yyextra->lineNr);
2185 }
2186 else
2187 {
2188 BEGIN(Scan);
2189 }
2190 yylex(yyscanner);
2191 while (!yyextra->condStack.empty())
2192 {
2193 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
2194 DString sectionInfo(" ");
2195 if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data());
2196 warn(yyextra->fileName,ctx.lineNr,"Conditional section{}does not have "
2197 "a corresponding \\endcond command within this file.",sectionInfo.data());
2198 yyextra->condStack.pop();
2199 }
2200 if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt::Markdown && yyextra->lang!=SrcLangExt::Fortran)
2201 {
2202 DString lines;
2203 bool first = true;
2204 while (!yyextra->commentStack.empty())
2205 {
2206 int lineNr = yyextra->commentStack.top();
2207 if (!first) lines += ", ";
2208 lines += DString().setNum(lineNr);
2209 first = false;
2210 yyextra->commentStack.pop();
2211 }
2212 warn(yyextra->fileName,yyextra->lineNr,"Reached end of file while still inside a (nested) comment. "
2213 "Nesting level {} (possible line reference(s): {})",yyextra->nestingCount,lines);
2214 }
2215 yyextra->nestingCount = 0;
2217 {
2218 Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: {}\n"
2219 "output=[\n{}]\n-----------\n",fileName,yyextra->outBuf
2220 );
2221 }
2222 commentcnvYYlex_destroy(yyscanner);
DString & setNum(short n)
Definition dstring.h:556
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:341
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:161
@ CommentCnv
Definition debug.h:32
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:78
int yylex(void)
#define warn(file, line, fmt,...)
Definition message.h:97
2223}

References clearCommentStack(), Debug::CommentCnv, Config_getBool, convertFileNameFortranParserCode(), DString::data(), getLanguageFromFileName(), Debug::isFlagSet(), Debug::Lex_commentcnv, commentcnvYY_CondCtx::lineNr, Debug::print(), qPrint(), recognizeFixedForm(), commentcnvYY_CondCtx::sectionId, DString::setNum(), DString::sprintf(), DString::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 1713 of file commentcnv.l.

1714{
1715 copyToOutput(yyscanner,std::string_view{s,(size_t)len});
static void copyToOutput(yyscan_t yyscanner, std::string_view s)
1716}

References copyToOutput().

◆ copyToOutput() [2/2]

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

Definition at line 1671 of file commentcnv.l.

1672{
1673 int tabSize=Config_getInt(TAB_SIZE);
1674 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1675 size_t len = s.length();
1676 if (yyextra->skip) // only add newlines.
1677 {
1678 for (size_t i=0;i<len;i++)
1679 {
1680 switch(s[i])
1681 {
1682 case '\n':
1683 yyextra->outBuf+='\n';
1684 yyextra->lineNr++;
1685 yyextra->col=0;
1686 break;
1687 case '\t':
1688 yyextra->col+=tabSize-(yyextra->col%tabSize);
1689 break;
1690 default:
1691 yyextra->col++;
1692 break;
1693 }
1694 }
1695 }
1696 else if (len>0)
1697 {
1698 yyextra->outBuf+=s;
1699 for (size_t i=0;i<len;i++)
1700 {
1701 switch (s[i])
1702 {
1703 case '\n': yyextra->col=0;
1704 //fprintf(stderr,"---> copy %d\n",g_lineNr);
1705 yyextra->lineNr++; break;
1706 case '\t': yyextra->col+=tabSize-(yyextra->col%tabSize); break;
1707 default: yyextra->col++; break;
1708 }
1709 }
1710 }
1711}

References Config_getInt.

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 1737 of file commentcnv.l.

1738{
1739 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1740 if (yyextra->condStack.empty())
1741 {
1742 warn(yyextra->fileName,yyextra->lineNr,"Found \\endcond command without matching \\cond");
1743 yyextra->skip=false;
1744 }
1745 else
1746 {
1747 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
1748 yyextra->skip=ctx.skip;
1749 yyextra->condStack.pop();
1750 }
1751 //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1752}

References commentcnvYY_CondCtx::skip, and warn.

◆ extractBlock()

DString extractBlock ( const DString & text,
const DString & marker,
size_t & 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 1810 of file commentcnv.l.

1811{
1812 DString result;
1813 size_t p=0, i = DString::npos;
1814 bool found = false;
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:182
1815
1816 // find the character positions of the markers
1817 size_t m1 = text.find(marker);
1818 if (m1==DString::npos) return result;
1819 size_t m2 = text.find(marker,m1+marker.length());
1820 if (m2==DString::npos) return result;
size_t find(char c, size_t pos=0) const
Definition dstring.h:243
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:155
1821
1822 // find start and end line positions for the markers
1823 size_t l1=DString::npos, l2=DString::npos;
1824 while (!found && (i=text.find('\n',p))!=DString::npos)
1825 {
1826 found = (p<=m1 && m1<i); // found the line with the start marker
1827 p=i+1;
1828 }
1829 l1=p;
1830 blockPos=p;
1831 size_t lp=i;
1832 if (found)
1833 {
1834 while ((i=text.find('\n',p))!=DString::npos)
1835 {
1836 if (p<=m2 && m2<i) // found the line with the end marker
1837 {
1838 l2=p;
1839 break;
1840 }
1841 p=i+1;
1842 lp=i;
1843 }
1844 }
1845 if (l2==DString::npos) // marker at last line without newline (see bug706874)
1846 {
1847 l2=lp;
1848 }
1849 return l1!=DString::npos && l2!=DString::npos && l2>l1 ? text.mid(l1,l2-l1) : DString();
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:322
1850}

References DString::find(), DString::length(), DString::mid(), and DString::npos.

Referenced by readIncludeFile().

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 174 of file commentcnv.l.

174{return __FILE__;}

◆ handleCondSectionId()

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

Definition at line 1754 of file commentcnv.l.

1755{
1756 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1757 bool oldSkip=yyextra->skip;
1758 startCondSection(yyscanner,expression);
1759 if ((yyextra->condCtx==CComment || yyextra->readLineCtx==SComment) &&
1760 !oldSkip && yyextra->skip)
1761 {
1762 if (yyextra->lang!=SrcLangExt::Python &&
1763 yyextra->lang!=SrcLangExt::VHDL &&
1764 yyextra->lang!=SrcLangExt::Markdown &&
1765 yyextra->lang!=SrcLangExt::Fortran)
1766 {
1767 yyextra->outBuf+='*';
1768 yyextra->outBuf+='/';
1769 yyextra->col+=2;
1770 }
1771 }
1772 if (yyextra->readLineCtx==SComment)
1773 {
1774 BEGIN(SComment);
1775 }
1776 else
1777 {
1778 BEGIN(yyextra->condCtx);
1779 }
static void startCondSection(yyscan_t yyscanner, const DString &sectId)
1780}

References startCondSection().

◆ insertCommentStart()

void insertCommentStart ( yyscan_t yyscanner)
static

Definition at line 1852 of file commentcnv.l.

1853{
1854 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1855 size_t startCol=yyextra->blockHeadCol;
1856 size_t contentCol=yyextra->insertCommentCol;
1857 size_t markerSpace=contentCol-startCol;
1858 //printf("insertCommentStart startCol=%d contentCol=%d mlBrief=%d insertCppCommentMarker=%d\n",
1859 // yyextra->blockHeadCol,yyextra->insertCommentCol,yyextra->mlBrief,yyextra->insertCppCommentMarker);
1860 std::string marker;
1861 if (yyextra->lang==SrcLangExt::Python) // need to insert # or space
1862 {
1863 if (yyextra->pythonDocString) // """! style comment
1864 {
1865 marker=" ";
1866 }
1867 else
1868 {
1869 marker="# ";
1870 }
1871 }
1872 else if (yyextra->lang==SrcLangExt::Fortran) // need to insert !!
1873 {
1874 marker="!! ";
1875 }
1876 else if (yyextra->lang==SrcLangExt::Markdown)
1877 {
1878 marker=" ";
1879 }
1880 else if (yyextra->insertCppCommentMarker) // need to insert ///
1881 {
1882 marker="/// ";
1883 if (startCol>0)
1884 {
1885 // insert `///` instead of '* '
1886 startCol--;
1887 markerSpace++;
1888 }
1889 }
1890 else // need to insert *
1891 {
1892 marker="* ";
1893 }
1894 size_t i=0;
1895 for (;i<startCol;i++)
1896 {
1897 copyToOutput(yyscanner," ");
1898 }
1899 if (marker.length()<=markerSpace && !yyextra->firstIncludeLine)
1900 {
1901 copyToOutput(yyscanner,marker);
1902 i+=static_cast<int>(marker.length());
1903 }
1904 for (;i<contentCol;i++)
1905 {
1906 copyToOutput(yyscanner," ");
1907 }
1908 yyextra->firstIncludeLine = false;
1909}

References copyToOutput().

Referenced by readIncludeFile().

◆ lineBlock()

int lineBlock ( const DString & text,
const DString & marker )
static

Returns the line number of the line following the line with the marker.

See also
routine extractBlock

Definition at line 1785 of file commentcnv.l.

1786{
1787 int result = 1;
1788
1789 // find the character positions of the first marker
1790 size_t m1 = text.find(marker);
1791 if (m1==DString::npos) return result;
1792
1793 // find start line positions for the markers
1794 bool found=false;
1795 size_t p=0, i=0;
1796 while (!found && (i=text.find('\n',p))!=DString::npos)
1797 {
1798 found = (p<=m1 && m1<i); // found the line with the start marker
1799 p=i+1;
1800 result++;
1801 }
1802 return result;
1803}

References DString::find(), and DString::npos.

Referenced by readIncludeFile().

◆ parseIncludeOptions()

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

Definition at line 1544 of file commentcnv.l.

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

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

◆ readIncludeFile()

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

Definition at line 1911 of file commentcnv.l.

1912{
1913 //printf("readIncludeFile(inc=%s,blockId=%s)\n",qPrint(inc),qPrint(blockId));
1914 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1915 bool ambig = false;
1916 DString absFileName = findExampleFilePath(inc,ambig);
1917 FileInfo fi(absFileName.str());
1918 if (!absFileName.empty() && fi.exists() && fi.isFile())
1919 {
1920 if (ambig)
1921 {
1922 warn_doc_error(yyextra->fileName,yyextra->lineNr,"included file name '{}' is ambiguous"
1923 "Possible candidates:\n{}",inc, Doxygen::exampleNameLinkedMap->showFileDefMatches(inc));
1924 }
1925 bool alreadyProcessed = std::any_of(
1926 yyextra->includeStack.begin(),
1927 yyextra->includeStack.end(),
1928 [&absFileName,&blockId](const auto &lfs)
1929 { return lfs->fileName==absFileName && lfs->blockId==blockId; }
1930 );
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:152
const std::string & str() const
Definition dstring.h:649
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:95
Minimal replacement for QFileInfo.
Definition fileinfo.h:26
DString showFileDefMatches(const DString &n) const
Returns a list of file definitions in fnMap that match the file name n.
Definition filename.cpp:131
#define warn_doc_error(file, line, fmt,...)
Definition message.h:112
DString findExampleFilePath(const DString &file, bool &ambig)
Definition util.cpp:2452
1931
1932 if (alreadyProcessed)
1933 {
1934 if (!blockId.empty())
1935 {
1936 warn_doc_error(yyextra->fileName,yyextra->lineNr,"recursive usage of '\\snippet{{doc}}' block with name '{}' and file name '{}', skipping",
1937 blockId,absFileName);
1938 }
1939 else
1940 {
1941 warn_doc_error(yyextra->fileName,yyextra->lineNr,"recursive usage of '\\include{{doc}}' with file name '{}', skipping", absFileName);
1942 }
1943 return false;
1944 }
1945
1946 auto fs = std::make_unique<commentcnv_FileState>();
1947 if (!readInputFile(absFileName,fs->fileBuf,false))
1948 {
1949 warn_doc_error(yyextra->fileName,yyextra->lineNr,"\\{}{{doc}} file '{}' could not be read",blockId.empty()?"include":"snippet",absFileName);
1950 fs.reset();
1951 return false;
1952 }
1953 int lineNr=1;
1954 if (!blockId.empty())
1955 {
1956 DString incText { fs->fileBuf };
1957 int count = incText.contains(blockId.data());
1958 if (count!=2)
1959 {
1960 warn_doc_error(yyextra->fileName,yyextra->lineNr,"block marked with {} for \\snippet{{doc}} should appear twice in file {}, found it {:d} times, skipping",
1961 blockId,absFileName,count);
1962 return false;
1963 }
1964 lineNr = lineBlock(incText, blockId);
1965 size_t blockPos = 0;
1966 incText = extractBlock(incText, blockId, blockPos);
1967 fs->fileBuf.clear();
1968 if (!incText.empty())
1969 {
1970 fs->fileBuf.append(incText.str());
1971 }
1972 }
1973 int oldRaiseLevel = yyextra->raiseLevel;
1974 DString oldRaiseLabel = yyextra->raiseLabel;
1975 yyextra->raiseLevel+=yyextra->raiseIncrement;
1976 yyextra->raiseLabel+=yyextra->raisePrefix;
1977 DString lineStr=" \\ifile \""+absFileName+"\" \\iline " + std::to_string(lineNr)+" ";
1978 if (yyextra->raiseLevel>0)
1979 {
1980 lineStr+="\\iraise " + std::to_string(yyextra->raiseLevel)+" ";
1981 }
1982 if (!yyextra->raiseLabel.empty())
1983 {
1984 lineStr+="\\iprefix \"" + yyextra->raiseLabel + "\" ";
1985 }
1986 lineStr+="\\ilinebr ";
1987 copyToOutput(yyscanner,lineStr.view());
std::string_view view() const
Definition dstring.h:166
int contains(char c, bool cs=true) const
Definition dstring.cpp:85
static DString extractBlock(const DString &text, const DString &marker, size_t &blockPos)
Returns the section of text, in between a pair of markers.
static int lineBlock(const DString &text, const DString &marker)
Returns the line number of the line following the line with the marker.
bool readInputFile(const DString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:4375
1988
1989 fs->fileName = absFileName;
1990 fs->bufState = YY_CURRENT_BUFFER;
1991 fs->oldLineNr = yyextra->lineNr;
1992 fs->oldFileName = yyextra->fileName;
1993 fs->oldState = yyextra->includeCtx;
1994 fs->oldFileBuf = yyextra->inBuf;
1995 fs->oldFileBufPos = yyextra->inBufPos;
1996 fs->oldIncludeCtx = yyextra->includeCtx;
1997 fs->oldRaiseLvl = oldRaiseLevel;
1998 fs->oldRaiseLbl = oldRaiseLabel;
1999 fs->blockId = blockId;
2000 yy_switch_to_buffer(yy_create_buffer(nullptr, YY_BUF_SIZE, yyscanner),yyscanner);
2001 yyextra->fileName = absFileName;
2002 yyextra->lineNr = lineNr;
2003 yyextra->inBuf = &fs->fileBuf;
2004 yyextra->inBufPos = 0;
2005 yyextra->includeStack.push_back(std::move(fs));
2006 insertCommentStart(yyscanner);
2007 //printf("switched to %s\n",qPrint(fileName));
2008 }
2009 else
2010 {
2011 warn_doc_error(yyextra->fileName,yyextra->lineNr,"\\{}{{doc}} file '{}' not found",blockId.empty()?"include":"snippet",inc);
2012 return false;
2013 }
2014 return true;
void push_back(char c)
Definition dstring.h:206
static void insertCommentStart(yyscan_t yyscanner)
#define YY_BUF_SIZE
Definition commentcnv.l:19
2015}

References DString::contains(), copyToOutput(), DString::data(), DString::empty(), Doxygen::exampleNameLinkedMap, FileInfo::exists(), extractBlock(), findExampleFilePath(), insertCommentStart(), FileInfo::isFile(), lineBlock(), DString::push_back(), readInputFile(), FileNameLinkedMap::showFileDefMatches(), DString::str(), DString::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 2020 of file commentcnv.l.

2021{
2022 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2023 if (s.empty()) return;
2024 size_t pos = s.find('{');
2025 std::string cmd { s.substr(1, pos!=std::string::npos ? pos-1 : s.length()-1) };
2026 auto &expAlias = yyextra->expandedAliases;
2027 if (std::find(expAlias.begin(),expAlias.end(),cmd)!=std::end(expAlias))
2028 {
2029 copyToOutput(yyscanner,s);
2030 return; // prevent recursive expansion
2031 }
2032 else if (cmd=="ialias")
2033 {
2034 if (s.length()>cmd.length()+3) // \cmd{value}
2035 {
2036 std::string value { s.substr(cmd.length()+2,s.length()-cmd.length()-3) };
2037 //printf("removing value '%s'\n",qPrint(value));
2038 expAlias.erase(std::remove(expAlias.begin(),expAlias.end(),value),expAlias.end());
2039 }
2040 return;
2041 }
2042 std::string result = resolveAliasCmd(s);
2043 if (yyextra->inVerbatim) // inside verbatim blocks (like @code...@endcode) only expand aliases if
2044 // their expansion contains the matching end block marker.
2045 {
2046 std::string blk = yyextra->blockName.str();
2047 assert(!blk.empty());
2048 bool isNamedCommand=isId(blk[0]); // true for e.g. @endcode, false for e.g. ~~~
2049 size_t i=0,p=0;
2050 bool found=false;
2051 while ((i=result.find(blk,p))!=std::string::npos && !found) // for each match of blk in result
2052 {
2053 found = !isNamedCommand || // e.g. '~~~' or '-->'
2054 (i>0 && (result[i-1]=='\\' || result[i-1]=='@') && !isId(result[i+blk.length()])); // e.g. '@endcode' but not ~endcode or @endcodex
2055 p = i+yyextra->blockName.length();
2056 }
2057 //printf("blk=%s result=%s found=%d\n",qPrint(blk),qPrint(result),found);
2058 if (!found) // treat alias as part of the verbatim block
2059 {
2060 copyToOutput(yyscanner,s);
2061 return;
2062 }
2063 }
2064 //printf("replaceAliases(%s)->'%s' replaceCppComment=%d replaceCComment=%d\n",qPrint(s),qPrint(result),replaceCppComment,replaceCComment);
2065 if (result!=s)
2066 {
2067 size_t numSpaces = yyextra->blockHeadCol>1 ? yyextra->blockHeadCol-1 : 0;
2068 std::string spaces(numSpaces,' ');
2069 if (replaceCppComment) // In case we are replacing a multiline /// comment by a C style comment
2070 // and we have new lines in the alias argument, we need to place back a /// for each new line
2071 // to prevent breaking the multiline comment into multiple C style comments
2072 {
2073 std::string replacement = "\n"+spaces+"///";
2074 result = substituteStringView(result,"\n",replacement);
2075 }
2076 else if (replaceCComment)
2077 {
2078 std::string replacement = "\n"+spaces+" * ";
2079 result = substituteStringView(result,"\n",replacement);
2080 }
2081 expAlias.push_back(cmd);
2082 // add a ialias command to allow expansion of cmd again
2083 result += " \\ilinebr \\ialias{";
2084 result += cmd;
2085 result += "}";
2086 for (int i=(int)result.length()-1; i>=0; i--)
2087 {
2088 unput(result[i]);
2089 }
2090 }
2091 else
2092 {
2093 copyToOutput(yyscanner,result);
2094 }
std::string resolveAliasCmd(std::string_view aliasCmd)
Definition aliases.cpp:496
bool isId(int c)
Returns true if c is a valid character for an identifier.
Definition dstring.h:899
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:53
2095}

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

◆ replaceComment()

void replaceComment ( yyscan_t yyscanner,
int offset )
static

Definition at line 2108 of file commentcnv.l.

2109{
2110 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2111 if (yyextra->mlBrief || yyextra->skip)
2112 {
2113 copyToOutput(yyscanner,yytext,yyleng);
2114 }
2115 else
2116 {
2117 size_t i=computeIndent(&yytext[offset]);
2118 //printf("i=%d blockHeadCol=%d\n",i,yyextra->blockHeadCol);
2119 if (i==yyextra->blockHeadCol || i+1==yyextra->blockHeadCol)
2120 {
2121 replaceCommentMarker(yyscanner,std::string_view(yytext,yyleng));
2122 }
2123 else
2124 {
2125 copyToOutput(yyscanner," */");
2126 for (i = yyleng; i>0; )
2127 {
2128 --i;
2129 unput(yytext[i]);
2130 }
2131 yyextra->inSpecialComment=false;
2132 BEGIN(Scan);
2133 }
2134 }
static int computeIndent(const char *s)
static void replaceCommentMarker(yyscan_t yyscanner, std::string_view s)
2135}

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

◆ replaceCommentMarker()

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

Definition at line 1609 of file commentcnv.l.

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

Referenced by replaceComment().

◆ startCondSection()

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

Definition at line 1724 of file commentcnv.l.

1725{
1726 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1727 //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1728 CondParser prs;
1729 bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
1730 yyextra->condStack.emplace(yyextra->lineNr,sectId,yyextra->skip);
1731 if (!expResult) // not enabled
1732 {
1733 yyextra->skip=true;
1734 }
Copyright (C) 1997-2026 by Dimitri van Heesch.
Definition condparser.h:29
bool parse(const DString &fileName, int lineNr, const DString &expr)
parses and evaluates the given expression.
1735}

References CondParser::parse().

Referenced by handleCondSectionId().

◆ stateToString()

const char * stateToString ( int state)
static

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 266 of file commentcnv.l.

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

◆ yyread()

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

Definition at line 2098 of file commentcnv.l.

2099{
2100 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2101 int bytesInBuf = static_cast<int>(yyextra->inBuf->size())-yyextra->inBufPos;
2102 int bytesToCopy = std::min(max_size,bytesInBuf);
2103 memcpy(buf,yyextra->inBuf->data()+yyextra->inBufPos,bytesToCopy);
2104 yyextra->inBufPos+=bytesToCopy;
2105 return bytesToCopy;
2106}