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

◆ YY_NO_INPUT

#define YY_NO_INPUT   1

Definition at line 62 of file commentcnv.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

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

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

Referenced by convertCppComments().

◆ computeIndent()

int computeIndent ( const char * s)
inlinestatic

Definition at line 1654 of file commentcnv.l.

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

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

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

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

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

References copyToOutput().

◆ copyToOutput() [2/2]

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

Definition at line 1669 of file commentcnv.l.

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

References Config_getInt.

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 1735 of file commentcnv.l.

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

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

1809{
1810 DString result;
1811 size_t p=0, i = DString::npos;
1812 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:178
1813
1814 // find the character positions of the markers
1815 size_t m1 = text.find(marker);
1816 if (m1==DString::npos) return result;
1817 size_t m2 = text.find(marker,m1+marker.length());
1818 if (m2==DString::npos) return result;
size_t find(char c, size_t pos=0) const
Definition dstring.h:239
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151
1819
1820 // find start and end line positions for the markers
1821 size_t l1=DString::npos, l2=DString::npos;
1822 while (!found && (i=text.find('\n',p))!=DString::npos)
1823 {
1824 found = (p<=m1 && m1<i); // found the line with the start marker
1825 p=i+1;
1826 }
1827 l1=p;
1828 blockPos=p;
1829 size_t lp=i;
1830 if (found)
1831 {
1832 while ((i=text.find('\n',p))!=DString::npos)
1833 {
1834 if (p<=m2 && m2<i) // found the line with the end marker
1835 {
1836 l2=p;
1837 break;
1838 }
1839 p=i+1;
1840 lp=i;
1841 }
1842 }
1843 if (l2==DString::npos) // marker at last line without newline (see bug706874)
1844 {
1845 l2=lp;
1846 }
1847 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:318
1848}

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

Referenced by readIncludeFile().

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 172 of file commentcnv.l.

172{return __FILE__;}

◆ handleCondSectionId()

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

Definition at line 1752 of file commentcnv.l.

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

References startCondSection().

◆ insertCommentStart()

void insertCommentStart ( yyscan_t yyscanner)
static

Definition at line 1850 of file commentcnv.l.

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

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

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

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

Referenced by readIncludeFile().

◆ parseIncludeOptions()

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

Definition at line 1542 of file commentcnv.l.

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

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

◆ readIncludeFile()

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

Definition at line 1909 of file commentcnv.l.

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

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

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

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

◆ replaceComment()

void replaceComment ( yyscan_t yyscanner,
int offset )
static

Definition at line 2106 of file commentcnv.l.

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

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

◆ replaceCommentMarker()

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

Definition at line 1607 of file commentcnv.l.

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

Referenced by replaceComment().

◆ startCondSection()

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

Definition at line 1722 of file commentcnv.l.

1723{
1724 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1725 //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1726 CondParser prs;
1727 bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
1728 yyextra->condStack.emplace(yyextra->lineNr,sectId,yyextra->skip);
1729 if (!expResult) // not enabled
1730 {
1731 yyextra->skip=true;
1732 }
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.
1733}

References CondParser::parse().

Referenced by handleCondSectionId().

◆ stateToString()

const char * stateToString ( int state)
static

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 264 of file commentcnv.l.

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

◆ yyread()

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

Definition at line 2096 of file commentcnv.l.

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