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

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

Referenced by convertCppComments().

◆ computeIndent()

int computeIndent ( const char * s)
inlinestatic

Definition at line 1657 of file commentcnv.l.

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

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

2176{
2177 DString fileName { fn };
2178 yyscan_t yyscanner;
2179 commentcnvYY_state extra(&inBuf,outBuf);
2180 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
2181#ifdef FLEX_DEBUG
2182 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
2183#endif
2184 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2185 //printf("convertCppComments(%s)\n",qPrint(fileName));
2186 yyextra->inBufPos = 0;
2187 yyextra->col = 0;
2188 yyextra->mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
2189 yyextra->skip = false;
2190 yyextra->fileName = fileName;
2191 yyextra->lang = getLanguageFromFileName(fileName);
2192 yyextra->pythonDocString = false;
2193 yyextra->lineNr = 1;
2194 yyextra->raiseLevel = 0;
2195 yyextra->raiseLabel = "";
2196 yyextra->raiseIncrement = 0;
2197 yyextra->raisePrefix = "";
2198 yyextra->insertCppCommentMarker=false;
2199 yyextra->expandedAliases.clear();
2200 while (!yyextra->condStack.empty()) yyextra->condStack.pop();
2201 clearCommentStack(yyscanner);
2202 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:4177
2203
2204 DebugLex debugLex(Debug::Lex_commentcnv,__FILE__, qPrint(fileName));
2205 yyextra->isFixedForm = false;
2206 if (yyextra->lang==SrcLangExt::Fortran)
2207 {
2209 yyextra->isFixedForm = recognizeFixedForm(inBuf,fmt);
2210 }
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
2211
2212 if (yyextra->lang==SrcLangExt::Markdown)
2213 {
2214 yyextra->nestingCount=0;
2215 BEGIN(CComment);
2216 yyextra->commentStack.push(yyextra->lineNr);
2217 }
2218 else
2219 {
2220 BEGIN(Scan);
2221 }
2222 yylex(yyscanner);
2223 while (!yyextra->condStack.empty())
2224 {
2225 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
2226 DString sectionInfo(" ");
2227 if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data());
2228 warn(yyextra->fileName,ctx.lineNr,"Conditional section{}does not have "
2229 "a corresponding \\endcond command within this file.",sectionInfo.data());
2230 yyextra->condStack.pop();
2231 }
2232 if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt::Markdown && yyextra->lang!=SrcLangExt::Fortran)
2233 {
2234 DString lines;
2235 bool first = true;
2236 while (!yyextra->commentStack.empty())
2237 {
2238 int lineNr = yyextra->commentStack.top();
2239 if (!first) lines += ", ";
2240 lines += DString().setNum(lineNr);
2241 first = false;
2242 yyextra->commentStack.pop();
2243 }
2244 warn(yyextra->fileName,yyextra->lineNr,"Reached end of file while still inside a (nested) comment. "
2245 "Nesting level {} (possible line reference(s): {})",yyextra->nestingCount,lines);
2246 }
2247 yyextra->nestingCount = 0;
2249 {
2250 Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: {}\n"
2251 "output=[\n{}]\n-----------\n",fileName,yyextra->outBuf
2252 );
2253 }
2254 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
2255}

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

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

References copyToOutput().

◆ copyToOutput() [2/2]

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

Definition at line 1672 of file commentcnv.l.

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

References Config_getInt.

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 1738 of file commentcnv.l.

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

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

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

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

Referenced by readIncludeFile().

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 173 of file commentcnv.l.

173{return __FILE__;}

◆ handleCondSectionId()

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

Definition at line 1755 of file commentcnv.l.

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

References startCondSection().

◆ insertCommentStart()

void insertCommentStart ( yyscan_t yyscanner)
static

Definition at line 1853 of file commentcnv.l.

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

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

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

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

Referenced by readIncludeFile().

◆ parseIncludeOptions()

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

Definition at line 1545 of file commentcnv.l.

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

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

◆ readIncludeFile()

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

Definition at line 1912 of file commentcnv.l.

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

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

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

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

◆ replaceComment()

void replaceComment ( yyscan_t yyscanner,
int offset )
static

Definition at line 2109 of file commentcnv.l.

2110{
2111 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2112 if (yyextra->mlBrief || yyextra->skip)
2113 {
2114 copyToOutput(yyscanner,yytext,yyleng);
2115 }
2116 else
2117 {
2118 size_t i=computeIndent(&yytext[offset]);
2119 // A line in another column starts a new block, since it may document something
2120 // else. If both the block and the line have a marker ending in '<' (//!< or ///<),
2121 // they both document the member in front of them. The line then still starts a new
2122 // block, but a C style one: handed back to the scanner as a single //!< line it
2123 // would become the brief description, ahead of the lines that come before it
2124 // (see issue #5266).
2125 bool afterMember = yyleng>0 && yytext[yyleng-1]=='<';
2126 // The '<' of the line that started the block is not part of the text matched at that
2127 // point, so look at what was written for it: "/*!" or "/**", then '<' if it had one.
2128 bool headAfterMember = yyextra->blockHeadPos!=std::string::npos &&
2129 yyextra->blockHeadPos+3<yyextra->outBuf.size() &&
2130 yyextra->outBuf[yyextra->blockHeadPos+3]=='<';
2131 bool sameEntity = afterMember && headAfterMember;
2132 //printf("i=%d blockHeadCol=%d\n",i,yyextra->blockHeadCol);
2133 if (i==yyextra->blockHeadCol || i+1==yyextra->blockHeadCol)
2134 {
2135 replaceCommentMarker(yyscanner,std::string_view(yytext,yyleng));
2136 }
2137 else if (sameEntity)
2138 {
2139 // start the new block on this line, after the newline and the indentation
2140 size_t p=offset;
2141 while (p<(size_t)yyleng && (yytext[p]==' ' || yytext[p]=='\t')) p++;
2142 bool javadoc = yytext[p+2]=='/';
2143 copyToOutput(yyscanner," */");
2144 copyToOutput(yyscanner,std::string_view(yytext,p));
2145 yyextra->blockHeadCol=i+1;
2146 yyextra->blockHeadPos=yyextra->outBuf.size();
2147 // With AUTOBRIEF the first sentence of this block would become the brief description
2148 // when the lines before it did not give one, so use the style AUTOBRIEF does not apply to.
2149 bool qtAuto = Config_getBool(QT_AUTOBRIEF);
2150 bool jdAuto = Config_getBool(JAVADOC_AUTOBRIEF);
2151 if (javadoc && jdAuto && !qtAuto) javadoc=false;
2152 else if (!javadoc && qtAuto && !jdAuto) javadoc=true;
2153 copyToOutput(yyscanner,javadoc ? "/**<" : "/*!<");
2154 }
2155 else
2156 {
2157 copyToOutput(yyscanner," */");
2158 for (i = yyleng; i>0; )
2159 {
2160 --i;
2161 unput(yytext[i]);
2162 }
2163 yyextra->inSpecialComment=false;
2164 BEGIN(Scan);
2165 }
2166 }
static int computeIndent(const char *s)
static void replaceCommentMarker(yyscan_t yyscanner, std::string_view s)
2167}

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

◆ replaceCommentMarker()

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

Definition at line 1610 of file commentcnv.l.

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

Referenced by replaceComment().

◆ startCondSection()

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

Definition at line 1725 of file commentcnv.l.

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

References CondParser::parse().

Referenced by handleCondSectionId().

◆ stateToString()

const char * stateToString ( int state)
static

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 265 of file commentcnv.l.

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

◆ yyread()

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

Definition at line 2099 of file commentcnv.l.

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