Doxygen
Loading...
Searching...
No Matches
commentcnv.l File Reference
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stack>
#include <algorithm>
#include <deque>
#include <string_view>
#include "debug.h"
#include "message.h"
#include "config.h"
#include "doxygen.h"
#include "util.h"
#include "aliases.h"
#include "condparser.h"
#include "fileinfo.h"
#include "stringutil.h"
#include "regex.h"
#include "section.h"
#include <assert.h>
#include "doxygen_lex.h"
#include "commentcnv.l.h"
Include dependency graph for commentcnv.l:

Go to the source code of this file.

Classes

struct  commentcnvYY_CondCtx
struct  CommentCtx
struct  commentcnv_FileState
struct  commentcnvYY_state

Macros

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

Typedefs

typedef yyguts_t * yyscan_t

Functions

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

Macro Definition Documentation

◆ YY_BUF_SIZE

#define YY_BUF_SIZE   10*1024*1024

Definition at line 19 of file commentcnv.l.

Referenced by DocTokenizer::pushContext().

◆ YY_INPUT

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

Definition at line 165 of file commentcnv.l.

◆ YY_NO_INPUT

#define YY_NO_INPUT   1

Definition at line 58 of file commentcnv.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 59 of file commentcnv.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 29 of file commentcnv.l.

Typedef Documentation

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 31 of file commentcnv.l.

Function Documentation

◆ clearCommentStack()

void clearCommentStack ( yyscan_t yyscanner)
static

Definition at line 1707 of file commentcnv.l.

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

◆ computeIndent()

int computeIndent ( const char * s)
inlinestatic

Definition at line 1645 of file commentcnv.l.

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

◆ convertCppComments()

void convertCppComments ( const std::string & inBuf,
std::string & outBuf,
const std::string & fn )

Converts the comments in a file.

This function does three things:

  1. It converts multi-line C++ style comment blocks (that are aligned) to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO).
  2. It replaces aliases with their definition (see ALIASES)
  3. It handles conditional sections (cond...endcond blocks)

Definition at line 2104 of file commentcnv.l.

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

Referenced by generateHtmlForComment(), and parseFile().

◆ copyToOutput() [1/2]

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

Definition at line 1702 of file commentcnv.l.

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

◆ copyToOutput() [2/2]

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

Definition at line 1660 of file commentcnv.l.

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

Referenced by replaceComment().

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 1726 of file commentcnv.l.

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

References FALSE, and warn.

◆ extractBlock()

QCString extractBlock ( const QCString & text,
const QCString & marker,
int & blockPos )
static

Returns the section of text, in between a pair of markers.

Full lines are returned, excluding the lines on which the markers appear.

See also
routine lineBlock

Definition at line 1775 of file commentcnv.l.

1776{
1777 QCString result;
1778 int p=0,i=-1;
1779 bool found=FALSE;
1780
1781 // find the character positions of the markers
1782 int m1 = text.find(marker);
1783 if (m1==-1) return result;
1784 int m2 = text.find(marker,m1+static_cast<int>(marker.length()));
1785 if (m2==-1) return result;
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
1786
1787 // find start and end line positions for the markers
1788 int l1=-1,l2=-1;
1789 while (!found && (i=text.find('\n',p))!=-1)
1790 {
1791 found = (p<=m1 && m1<i); // found the line with the start marker
1792 p=i+1;
1793 }
1794 l1=p;
1795 blockPos=p;
1796 int lp=i;
1797 if (found)
1798 {
1799 while ((i=text.find('\n',p))!=-1)
1800 {
1801 if (p<=m2 && m2<i) // found the line with the end marker
1802 {
1803 l2=p;
1804 break;
1805 }
1806 p=i+1;
1807 lp=i;
1808 }
1809 }
1810 if (l2==-1) // marker at last line without newline (see bug706874)
1811 {
1812 l2=lp;
1813 }
1814 return l2>l1 ? text.mid(l1,l2-l1) : QCString();
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
1815}

References FALSE.

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 168 of file commentcnv.l.

168{return __FILE__;}

◆ handleCondSectionId()

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

Definition at line 1743 of file commentcnv.l.

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

◆ insertCommentStart()

void insertCommentStart ( yyscan_t yyscanner)
static

Definition at line 1817 of file commentcnv.l.

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

◆ parseIncludeOptions()

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

Definition at line 1533 of file commentcnv.l.

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

References stripWhiteSpace().

◆ readIncludeFile()

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

Definition at line 1876 of file commentcnv.l.

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

References Doxygen::exampleNameLinkedMap, and showFileDefMatches().

◆ replaceAliases()

void replaceAliases ( yyscan_t yyscanner,
std::string_view s,
bool replaceCppComment = false,
bool replaceCComment = false )
static

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

Definition at line 1985 of file commentcnv.l.

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

◆ replaceComment()

void replaceComment ( yyscan_t yyscanner,
int offset )
static

Definition at line 2073 of file commentcnv.l.

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

References copyToOutput().

◆ replaceCommentMarker()

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

Definition at line 1598 of file commentcnv.l.

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

◆ startCondSection()

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

Definition at line 1713 of file commentcnv.l.

1714{
1715 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1716 //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1717 CondParser prs;
1718 bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
1719 yyextra->condStack.emplace(yyextra->lineNr,sectId,yyextra->skip);
1720 if (!expResult) // not enabled
1721 {
1722 yyextra->skip=TRUE;
1723 }
Copyright (C) 1997-2015 by Dimitri van Heesch.
Definition condparser.h:28
bool parse(const QCString &fileName, int lineNr, const QCString &expr)
Copyright (C) 1997-2015 by Dimitri van Heesch.
#define TRUE
Definition qcstring.h:37
1724}

References TRUE.

◆ stateToString()

const char * stateToString ( int state)
static

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 258 of file commentcnv.l.

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

◆ yyread()

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

Definition at line 2063 of file commentcnv.l.

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