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 replaceComment)
 copies string s with length len to the output, while replacing any alias commands found in the string.
 
static int yyread (yyscan_t yyscanner, char *buf, int max_size)
 
static void replaceComment (yyscan_t yyscanner, int offset)
 
static void clearCommentStack (yyscan_t yyscanner)
 
static bool readIncludeFile (yyscan_t yyscanner, const QCString &inc, const QCString &blockId)
 
static void insertCommentStart (yyscan_t yyscanner)
 
static bool parseIncludeOptions (yyscan_t yyscanner, std::string_view s)
 
static const char * getLexerFILE ()
 
int yylex (yyscan_t yyscanner)
 
static QCString extractBlock (const QCString &text, const QCString &marker, int &blockPos)
 Returns the section of text, in between a pair of markers.
 
void convertCppComments (const std::string &inBuf, std::string &outBuf, const std::string &fn)
 Converts the comments in a file.
 

Macro Definition Documentation

◆ YY_BUF_SIZE

#define YY_BUF_SIZE   10*1024*1024

◆ YY_INPUT

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

Definition at line 163 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()

static void clearCommentStack ( yyscan_t yyscanner)
static

Definition at line 1531 of file commentcnv.l.

1532{
1533 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1534 while (!yyextra->commentStack.empty()) yyextra->commentStack.pop();
1535}

Referenced by convertCppComments().

◆ computeIndent()

static int computeIndent ( const char * s)
inlinestatic

Definition at line 1469 of file commentcnv.l.

1470{
1471 int col=0;
1472 int tabSize=Config_getInt(TAB_SIZE);
1473 const char *p=s;
1474 char c = 0;
1475 while ((c=*p++))
1476 {
1477 if (c==' ') col++;
1478 else if (c=='\t') col+=tabSize-(col%tabSize);
1479 else break;
1480 }
1481 return col;
#define Config_getInt(name)
Definition config.h:34
1482}

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)

Definition at line 1920 of file commentcnv.l.

1921{
1922 QCString fileName { fn };
1923 yyscan_t yyscanner;
1924 commentcnvYY_state extra(&inBuf,outBuf);
1925 commentcnvYYlex_init_extra(&extra,&yyscanner);
This is an alternative implementation of QCString.
Definition qcstring.h:101
yyguts_t * yyscan_t
Definition code.l:24
1926#ifdef FLEX_DEBUG
1927 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
1928#endif
1929 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1930 //printf("convertCppComments(%s)\n",qPrint(fileName));
1931 yyextra->inBufPos = 0;
1932 yyextra->col = 0;
1933 yyextra->mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
1934 yyextra->skip = FALSE;
1935 yyextra->fileName = fileName;
1936 yyextra->lang = getLanguageFromFileName(fileName);
1937 yyextra->pythonDocString = FALSE;
1938 yyextra->lineNr = 1;
1939 yyextra->raiseLevel = 0;
1940 yyextra->raiseLabel = "";
1941 yyextra->raiseIncrement = 0;
1942 yyextra->raisePrefix = "";
1943 yyextra->insertCppCommentMarker=false;
1944 yyextra->expandedAliases.clear();
1945 while (!yyextra->condStack.empty()) yyextra->condStack.pop();
1946 clearCommentStack(yyscanner);
1947 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:5645
1948
1949 DebugLex debugLex(Debug::Lex_commentcnv,__FILE__, qPrint(fileName));
1950 yyextra->isFixedForm = FALSE;
1951 if (yyextra->lang==SrcLangExt::Fortran)
1952 {
1954 yyextra->isFixedForm = recognizeFixedForm(QCString(inBuf),fmt);
1955 }
Definition message.h:144
const char * qPrint(const char *s)
Definition qcstring.h:672
@ Fortran
Definition types.h:53
FortranFormat
Definition types.h:410
bool recognizeFixedForm(const QCString &contents, FortranFormat format)
Definition util.cpp:6767
FortranFormat convertFileNameFortranParserCode(QCString fn)
Definition util.cpp:6820
1956
1957 if (yyextra->lang==SrcLangExt::Markdown)
1958 {
1959 yyextra->nestingCount=0;
1960 BEGIN(CComment);
1961 yyextra->commentStack.push(yyextra->lineNr);
1962 }
1963 else
1964 {
1965 BEGIN(Scan);
1966 }
1967 yylex(yyscanner);
1968 while (!yyextra->condStack.empty())
1969 {
1970 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
1971 QCString sectionInfo(" ");
1972 if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data());
1973 warn(yyextra->fileName,ctx.lineNr,"Conditional section{}does not have "
1974 "a corresponding \\endcond command within this file.",sectionInfo.data());
1975 yyextra->condStack.pop();
1976 }
1977 if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt::Markdown && yyextra->lang!=SrcLangExt::Fortran)
1978 {
1979 QCString lines;
1980 bool first = true;
1981 while (!yyextra->commentStack.empty())
1982 {
1983 int lineNr = yyextra->commentStack.top();
1984 if (!first) lines += ", ";
1985 lines += QCString().setNum(lineNr);
1986 first = false;
1987 yyextra->commentStack.pop();
1988 }
1989 warn(yyextra->fileName,yyextra->lineNr,"Reached end of file while still inside a (nested) comment. "
1990 "Nesting level {} (possible line reference(s): {})",yyextra->nestingCount,lines);
1991 }
1992 yyextra->nestingCount = 0;
1994 {
1995 Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: {}\n"
1996 "output=[\n{}]\n-----------\n",fileName,yyextra->outBuf
1997 );
1998 }
1999 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:245
QCString & setNum(short n)
Definition qcstring.h:444
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:159
int yylex(void)
#define warn(file, line, fmt,...)
Definition message.h:97
@ Markdown
Definition types.h:57
2000}

References clearCommentStack(), Debug::CommentCnv, Config_getBool, convertFileNameFortranParserCode(), QCString::data(), FALSE, Fortran, getLanguageFromFileName(), Debug::isFlagSet(), Debug::Lex_commentcnv, commentcnvYY_CondCtx::lineNr, Markdown, Debug::print(), qPrint(), recognizeFixedForm(), commentcnvYY_CondCtx::sectionId, QCString::setNum(), QCString::sprintf(), QCString::stripWhiteSpace(), warn, and yylex().

Referenced by generateHtmlForComment(), and parseFile().

◆ copyToOutput() [1/2]

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

Definition at line 1526 of file commentcnv.l.

1527{
1528 copyToOutput(yyscanner,std::string_view{s,(size_t)len});
static void copyToOutput(yyscan_t yyscanner, std::string_view s)
1529}

References copyToOutput().

◆ copyToOutput() [2/2]

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

Definition at line 1484 of file commentcnv.l.

1485{
1486 int tabSize=Config_getInt(TAB_SIZE);
1487 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1488 size_t len = s.length();
1489 if (yyextra->skip) // only add newlines.
1490 {
1491 for (size_t i=0;i<len;i++)
1492 {
1493 switch(s[i])
1494 {
1495 case '\n':
1496 yyextra->outBuf+='\n';
1497 yyextra->lineNr++;
1498 yyextra->col=0;
1499 break;
1500 case '\t':
1501 yyextra->col+=tabSize-(yyextra->col%tabSize);
1502 break;
1503 default:
1504 yyextra->col++;
1505 break;
1506 }
1507 }
1508 }
1509 else if (len>0)
1510 {
1511 yyextra->outBuf+=s;
1512 for (size_t i=0;i<len;i++)
1513 {
1514 switch (s[i])
1515 {
1516 case '\n': yyextra->col=0;
1517 //fprintf(stderr,"---> copy %d\n",g_lineNr);
1518 yyextra->lineNr++; break;
1519 case '\t': yyextra->col+=tabSize-(yyextra->col%tabSize); break;
1520 default: yyextra->col++; break;
1521 }
1522 }
1523 }
1524}

References Config_getInt.

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

◆ endCondSection()

static void endCondSection ( yyscan_t yyscanner)
static

Definition at line 1550 of file commentcnv.l.

1551{
1552 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1553 if (yyextra->condStack.empty())
1554 {
1555 warn(yyextra->fileName,yyextra->lineNr,"Found \\endcond command without matching \\cond");
1556 yyextra->skip=FALSE;
1557 }
1558 else
1559 {
1560 const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
1561 yyextra->skip=ctx.skip;
1562 yyextra->condStack.pop();
1563 }
1564 //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1565}

References FALSE, commentcnvYY_CondCtx::skip, and warn.

◆ extractBlock()

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

1600{
1601 QCString result;
1602 int p=0,i=-1;
1603 bool found=FALSE;
bool found
Definition util.cpp:984
1604
1605 // find the character positions of the markers
1606 int m1 = text.find(marker);
1607 if (m1==-1) return result;
1608 int m2 = text.find(marker,m1+static_cast<int>(marker.length()));
1609 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:153
1610
1611 // find start and end line positions for the markers
1612 int l1=-1,l2=-1;
1613 while (!found && (i=text.find('\n',p))!=-1)
1614 {
1615 found = (p<=m1 && m1<i); // found the line with the start marker
1616 p=i+1;
1617 }
1618 l1=p;
1619 blockPos=p;
1620 int lp=i;
1621 if (found)
1622 {
1623 while ((i=text.find('\n',p))!=-1)
1624 {
1625 if (p<=m2 && m2<i) // found the line with the end marker
1626 {
1627 l2=p;
1628 break;
1629 }
1630 p=i+1;
1631 lp=i;
1632 }
1633 }
1634 if (l2==-1) // marker at last line without newline (see bug706874)
1635 {
1636 l2=lp;
1637 }
1638 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:226
1639}

References FALSE, QCString::find(), found, QCString::length(), and QCString::mid().

Referenced by readIncludeFile().

◆ getLexerFILE()

static const char * getLexerFILE ( )
inlinestatic

Definition at line 166 of file commentcnv.l.

166{return __FILE__;}

◆ handleCondSectionId()

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

Definition at line 1567 of file commentcnv.l.

1568{
1569 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1570 bool oldSkip=yyextra->skip;
1571 startCondSection(yyscanner,QCString(expression));
1572 if ((yyextra->condCtx==CComment || yyextra->readLineCtx==SComment) &&
1573 !oldSkip && yyextra->skip)
1574 {
1575 if (yyextra->lang!=SrcLangExt::Python &&
1576 yyextra->lang!=SrcLangExt::VHDL &&
1577 yyextra->lang!=SrcLangExt::Markdown &&
1578 yyextra->lang!=SrcLangExt::Fortran)
1579 {
1580 yyextra->outBuf+='*';
1581 yyextra->outBuf+='/';
1582 yyextra->col+=2;
1583 }
1584 }
1585 if (yyextra->readLineCtx==SComment)
1586 {
1587 BEGIN(SComment);
1588 }
1589 else
1590 {
1591 BEGIN(yyextra->condCtx);
1592 }
static void startCondSection(yyscan_t yyscanner, const QCString &sectId)
@ Python
Definition types.h:52
1593}

References Fortran, Markdown, Python, startCondSection(), and VHDL.

◆ insertCommentStart()

static void insertCommentStart ( yyscan_t yyscanner)
static

Definition at line 1641 of file commentcnv.l.

1642{
1643 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1644 int startCol=yyextra->blockHeadCol;
1645 int contentCol=yyextra->insertCommentCol;
1646 int markerSpace=contentCol-startCol;
1647 //printf("insertCommentStart startCol=%d contentCol=%d mlBrief=%d insertCppCommentMarker=%d\n",
1648 // yyextra->blockHeadCol,yyextra->insertCommentCol,yyextra->mlBrief,yyextra->insertCppCommentMarker);
1649 std::string marker;
1650 if (yyextra->lang==SrcLangExt::Python) // need to insert # or space
1651 {
1652 if (yyextra->pythonDocString) // """! style comment
1653 {
1654 marker=" ";
1655 }
1656 else
1657 {
1658 marker="# ";
1659 }
1660 }
1661 else if (yyextra->lang==SrcLangExt::Fortran) // need to insert !!
1662 {
1663 marker="!! ";
1664 }
1665 else if (yyextra->lang==SrcLangExt::Markdown)
1666 {
1667 marker=" ";
1668 }
1669 else if (yyextra->insertCppCommentMarker) // need to insert ///
1670 {
1671 marker="/// ";
1672 if (startCol>0)
1673 {
1674 // insert `///` instead of '* '
1675 startCol--;
1676 markerSpace++;
1677 }
1678 }
1679 else // need to insert *
1680 {
1681 marker="* ";
1682 }
1683 int i=0;
1684 for (;i<startCol;i++)
1685 {
1686 copyToOutput(yyscanner," ");
1687 }
1688 if (static_cast<int>(marker.length())<=markerSpace && !yyextra->firstIncludeLine)
1689 {
1690 copyToOutput(yyscanner,marker);
1691 i+=marker.length();
1692 }
1693 for (;i<contentCol;i++)
1694 {
1695 copyToOutput(yyscanner," ");
1696 }
1697 yyextra->firstIncludeLine = false;
1698}

References copyToOutput(), Fortran, Markdown, and Python.

Referenced by readIncludeFile().

◆ parseIncludeOptions()

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

Definition at line 1357 of file commentcnv.l.

1358{
1359 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1360
1361 //printf("parseIncludeOptions=%s\n",qPrint(QCString(s)));
1362 size_t optIdxStart = s.find('{');
1363 size_t optIdxEnd = optIdxStart!=std::string::npos ? s.find("}",optIdxStart+1) : std::string::npos;
1364 std::string cmdName;
1365 StringVector optList;
1366 if (optIdxStart == std::string::npos) // no options
1367 {
1368 cmdName = stripWhiteSpace(s.substr(1)); // to remove {CMD}
1369 }
1370 else // options present
1371 {
1372 cmdName = stripWhiteSpace(s.substr(1,optIdxStart-1)); // to remove {CMD}
1373 optList = split(std::string{s.substr(optIdxStart+1,optIdxEnd-optIdxStart-1)},",");
1374 }
1375 bool isDoc = cmdName=="includedoc" || cmdName=="snippetdoc";
1376 for (const auto &opt : optList)
1377 {
1378 if (stripWhiteSpace(opt)==std::string_view{"doc"})
1379 {
1380 isDoc=true;
1381 break;
1382 }
1383 }
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:7042
1384
1385 if (isDoc)
1386 {
1387 for (const auto &opt : optList)
1388 {
1389 std::string_view locOpt = stripWhiteSpace(opt);
1390 size_t posEqual = locOpt.find('=');
1391 std::string_view option = posEqual!=std::string::npos ? stripWhiteSpace(locOpt.substr(0,posEqual)) : locOpt;
1392 std::string_view value = posEqual!=std::string::npos ? stripWhiteSpace(locOpt.substr(posEqual+1)) : std::string_view();
1393
1394 if (option==std::string_view{"doc"} && value.empty())
1395 {
1396 }
1397 else if (option==std::string_view{"raise"} && !value.empty())
1398 {
1399 yyextra->raiseIncrement = atoi(value.data());
1400 if (yyextra->raiseLevel+yyextra->raiseIncrement>=SectionType::MaxLevel) // check range
1401 {
1402 warn(yyextra->fileName,yyextra->lineNr,"Raising section level from {} to {}, exceeds allowed range [0-{}], adjusting",
1403 yyextra->raiseLevel,yyextra->raiseLevel+yyextra->raiseIncrement,SectionType::MaxLevel-1);
1404 yyextra->raiseIncrement = std::max(0,SectionType::MaxLevel-1-yyextra->raiseLevel);
1405 }
1406 }
1407 else if (option==std::string_view{"prefix"} && !value.empty())
1408 {
1409 yyextra->raisePrefix = value;
1410 }
1411 else
1412 {
1413 warn(yyextra->fileName,yyextra->lineNr,"Unsupported option '{}' for {} command",option, cmdName);
1414 }
1415 }
1416 }
static constexpr int MaxLevel
Definition section.h:39
1417
1418 return isDoc;
1419}

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

◆ readIncludeFile()

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

Definition at line 1700 of file commentcnv.l.

1701{
1702 //printf("readIncludeFile(inc=%s,blockId=%s)\n",qPrint(inc),qPrint(blockId));
1703 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1704 bool ambig = false;
1705 QCString absFileName = findFilePath(inc,ambig);
1706 FileInfo fi(absFileName.str());
1707 if (!absFileName.isEmpty() && fi.exists() && fi.isFile())
1708 {
1709 if (ambig)
1710 {
1711 warn_doc_error(yyextra->fileName,yyextra->lineNr,"included file name '{}' is ambiguous"
1712 "Possible candidates:\n{}",inc, showFileDefMatches(Doxygen::exampleNameLinkedMap,inc));
1713 }
1714 bool alreadyProcessed = std::any_of(
1715 yyextra->includeStack.begin(),
1716 yyextra->includeStack.end(),
1717 [&absFileName,&blockId](const auto &lfs)
1718 { return lfs->fileName==absFileName && lfs->blockId==blockId; }
1719 );
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:103
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
const std::string & str() const
Definition qcstring.h:537
#define warn_doc_error(file, line, fmt,...)
Definition message.h:112
QCString findFilePath(const QCString &file, bool &ambig)
Definition util.cpp:3431
QCString showFileDefMatches(const FileNameLinkedMap *fnMap, const QCString &n)
Definition util.cpp:3474
1720
1721 if (alreadyProcessed)
1722 {
1723 if (!blockId.isEmpty())
1724 {
1725 warn_doc_error(yyextra->fileName,yyextra->lineNr,"recursive usage of '\\snippet{{doc}}' block with name '{}' and file name '{}', skipping",
1726 blockId,absFileName);
1727 }
1728 else
1729 {
1730 warn_doc_error(yyextra->fileName,yyextra->lineNr,"recursive usage of '\\include{{doc}}' with file name '{}', skipping", absFileName);
1731 }
1732 return false;
1733 }
1734
1735 auto fs = std::make_unique<commentcnv_FileState>();
1736 if (!readInputFile(absFileName,fs->fileBuf,false))
1737 {
1738 warn_doc_error(yyextra->fileName,yyextra->lineNr,"\\{}{{doc}} file '{}' could not be read",blockId.isEmpty()?"include":"snippet",absFileName);
1739 fs.reset();
1740 return false;
1741 }
1742 int lineNr=1;
1743 if (!blockId.isEmpty())
1744 {
1745 QCString incText { fs->fileBuf };
1746 int count = incText.contains(blockId.data());
1747 if (count!=2)
1748 {
1749 warn_doc_error(yyextra->fileName,yyextra->lineNr,"block marked with [{}] for \\snippet{{doc}} should appear twice in file {}, found it {:d} times, skipping",
1750 blockId,absFileName,count);
1751 return false;
1752 }
1753 lineNr = lineBlock(incText, blockId);
1754 int blockPos = 0;
1755 incText = extractBlock(incText, blockId, blockPos);
1756 fs->fileBuf.clear();
1757 if (!incText.isEmpty())
1758 {
1759 fs->fileBuf.append(incText.str());
1760 }
1761 }
1762 int oldRaiseLevel = yyextra->raiseLevel;
1763 QCString oldRaiseLabel = yyextra->raiseLabel;
1764 yyextra->raiseLevel+=yyextra->raiseIncrement;
1765 yyextra->raiseLabel+=yyextra->raisePrefix;
1766 QCString lineStr=" \\ifile \""+absFileName+"\" \\iline " + std::to_string(lineNr)+" ";
1767 if (yyextra->raiseLevel>0)
1768 {
1769 lineStr+="\\iraise " + std::to_string(yyextra->raiseLevel)+" ";
1770 }
1771 if (!yyextra->raiseLabel.isEmpty())
1772 {
1773 lineStr+="\\iprefix \"" + yyextra->raiseLabel + "\" ";
1774 }
1775 lineStr+="\\ilinebr ";
1776 copyToOutput(yyscanner,lineStr.view());
std::string_view view() const
Definition qcstring.h:161
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:143
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:6279
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:5937
1777
1778 fs->fileName = absFileName;
1779 fs->bufState = YY_CURRENT_BUFFER;
1780 fs->oldLineNr = yyextra->lineNr;
1781 fs->oldFileName = yyextra->fileName;
1782 fs->oldState = yyextra->includeCtx;
1783 fs->oldFileBuf = yyextra->inBuf;
1784 fs->oldFileBufPos = yyextra->inBufPos;
1785 fs->oldIncludeCtx = yyextra->includeCtx;
1786 fs->oldRaiseLvl = oldRaiseLevel;
1787 fs->oldRaiseLbl = oldRaiseLabel;
1788 fs->blockId = blockId;
1789 yy_switch_to_buffer(yy_create_buffer(nullptr, YY_BUF_SIZE, yyscanner),yyscanner);
1790 yyextra->fileName = absFileName;
1791 yyextra->lineNr = lineNr;
1792 yyextra->inBuf = &fs->fileBuf;
1793 yyextra->inBufPos = 0;
1794 yyextra->includeStack.push_back(std::move(fs));
1795 insertCommentStart(yyscanner);
1796 //printf("switched to %s\n",qPrint(fileName));
1797 }
1798 else
1799 {
1800 warn_doc_error(yyextra->fileName,yyextra->lineNr,"\\{}{{doc}} file '{}' not found",blockId.isEmpty()?"include":"snippet",inc);
1801 return false;
1802 }
1803 return true;
static void insertCommentStart(yyscan_t yyscanner)
#define YY_BUF_SIZE
Definition commentcnv.l:19
1804}

References QCString::contains(), copyToOutput(), QCString::data(), Doxygen::exampleNameLinkedMap, FileInfo::exists(), extractBlock(), findFilePath(), insertCommentStart(), QCString::isEmpty(), FileInfo::isFile(), lineBlock(), readInputFile(), showFileDefMatches(), QCString::str(), QCString::view(), warn_doc_error, and YY_BUF_SIZE.

◆ replaceAliases()

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

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

Definition at line 1809 of file commentcnv.l.

1810{
1811 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1812 if (s.empty()) return;
1813 size_t pos = s.find('{');
1814 std::string cmd { s.substr(1, pos!=std::string::npos ? pos-1 : s.length()-1) };
1815 auto &expAlias = yyextra->expandedAliases;
1816 if (std::find(expAlias.begin(),expAlias.end(),cmd)!=std::end(expAlias))
1817 {
1818 copyToOutput(yyscanner,s);
1819 return; // prevent recursive expansion
1820 }
1821 else if (cmd=="ialias")
1822 {
1823 if (s.length()>cmd.length()+3) // \cmd{value}
1824 {
1825 std::string value { s.substr(cmd.length()+2,s.length()-cmd.length()-3) };
1826 //printf("removing value '%s'\n",qPrint(value));
1827 expAlias.erase(std::remove(expAlias.begin(),expAlias.end(),value),expAlias.end());
1828 }
1829 return;
1830 }
1831 std::string result = resolveAliasCmd(s);
1832 if (yyextra->inVerbatim) // inside verbatim blocks (like @code...@endcode) only expand aliases if
1833 // their expansion contains the matching end block marker.
1834 {
1835 std::string blk = yyextra->blockName.str();
1836 assert(!blk.empty());
1837 bool isNamedCommand=isId(blk[0]); // true for e.g. @endcode, false for e.g. ~~~
1838 size_t i=0,p=0;
1839 bool found=false;
1840 while ((i=result.find(blk,p))!=std::string::npos && !found) // for each match of blk in result
1841 {
1842 found = !isNamedCommand || // e.g. '~~~' or '-->'
1843 (i>0 && (result[i-1]=='\\' || result[i-1]=='@') && !isId(result[i+blk.length()])); // e.g. '@endcode' but not ~endcode or @endcodex
1844 p = i+yyextra->blockName.length();
1845 }
1846 //printf("blk=%s result=%s found=%d\n",qPrint(blk),qPrint(result),found);
1847 if (!found) // treat alias as part of the verbatim block
1848 {
1849 copyToOutput(yyscanner,s);
1850 return;
1851 }
1852 }
1853 //printf("replaceAliases(%s)->'%s' replaceComment=%d\n",qPrint(s),qPrint(result),replaceComment);
1854 if (result!=s)
1855 {
1856 if (replaceComment) // In case we are replacing a multiline /// comment by a C style comment
1857 // and we have new lines in the alias argument, we need to place back a /// for each new line
1858 // to prevent breaking the multiline comment into multiple C style comments
1859 {
1860 result = substituteStringView(result,"\n","\n///");
1861 }
1862 expAlias.push_back(cmd);
1863 // add a ialias command to allow expansion of cmd again
1864 result += " \\ilinebr \\ialias{";
1865 result += cmd;
1866 result += "}";
1867 for (int i=(int)result.length()-1; i>=0; i--)
1868 {
1869 unput(result[i]);
1870 }
1871 }
1872 else
1873 {
1874 copyToOutput(yyscanner,result);
1875 }
std::string resolveAliasCmd(std::string_view aliasCmd)
Definition aliases.cpp:504
static void replaceComment(yyscan_t yyscanner, int offset)
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:206
1876}

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

◆ replaceComment()

static void replaceComment ( yyscan_t yyscanner,
int offset )
static

Definition at line 1889 of file commentcnv.l.

1890{
1891 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1892 if (yyextra->mlBrief || yyextra->skip)
1893 {
1894 copyToOutput(yyscanner,yytext,yyleng);
1895 }
1896 else
1897 {
1898 int i=computeIndent(&yytext[offset]);
1899 //printf("i=%d blockHeadCol=%d\n",i,yyextra->blockHeadCol);
1900 if (i==yyextra->blockHeadCol || i+1==yyextra->blockHeadCol)
1901 {
1902 replaceCommentMarker(yyscanner,std::string_view(yytext,yyleng));
1903 }
1904 else
1905 {
1906 copyToOutput(yyscanner," */");
1907 for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
1908 yyextra->inSpecialComment=FALSE;
1909 BEGIN(Scan);
1910 }
1911 }
static int computeIndent(const char *s)
static void replaceCommentMarker(yyscan_t yyscanner, std::string_view s)
1912}

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

Referenced by replaceAliases(), and stateToString().

◆ replaceCommentMarker()

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

Definition at line 1422 of file commentcnv.l.

1423{
1424 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1425 if (s.empty()) return;
1426 size_t p = 0;
1427 size_t len = s.length();
1428 char c = 0;
1429 // copy leading blanks
1430 while (p<len && (c=s[p]) && (c==' ' || c=='\t' || c=='\n'))
1431 {
1432 yyextra->outBuf+=c;
1433 if (c=='\n') { yyextra->lineNr++; yyextra->col=0; } else { yyextra->col++; }
1434 p++;
1435 }
1436 // replace start of comment marker by blanks and the last character by a *
1437 int blanks=0;
1438 while (p<len && (c=s[p]) && (c=='/' || c=='!' || c=='#'))
1439 {
1440 blanks++;
1441 p++;
1442 if (p<len && s[p]=='<') // comment-after-item marker
1443 {
1444 blanks++;
1445 p++;
1446 }
1447 if (c=='!') // end after first !
1448 {
1449 break;
1450 }
1451 }
1452 if (blanks>0)
1453 {
1454 while (blanks>2)
1455 {
1456 yyextra->outBuf+=' ';
1457 yyextra->col++;
1458 blanks--;
1459 }
1460 if (blanks>1) { yyextra->outBuf+='*'; yyextra->col++; }
1461 yyextra->outBuf+=' ';
1462 yyextra->col++;
1463 }
1464 // copy comment line to output
1465 yyextra->outBuf+=s.substr(p);
1466 yyextra->col+=s.substr(p).length();
1467}

Referenced by replaceComment().

◆ startCondSection()

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

Definition at line 1537 of file commentcnv.l.

1538{
1539 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1540 //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1541 CondParser prs;
1542 bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
1543 yyextra->condStack.emplace(yyextra->lineNr,sectId,yyextra->skip);
1544 if (!expResult) // not enabled
1545 {
1546 yyextra->skip=TRUE;
1547 }
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
1548}

References CondParser::parse(), and TRUE.

Referenced by handleCondSectionId().

◆ stateToString()

static const char * stateToString ( int state)
static

References replaceComment().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 251 of file commentcnv.l.

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

◆ yyread()

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

Definition at line 1879 of file commentcnv.l.

1880{
1881 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1882 int bytesInBuf = static_cast<int>(yyextra->inBuf->size())-yyextra->inBufPos;
1883 int bytesToCopy = std::min(max_size,bytesInBuf);
1884 memcpy(buf,yyextra->inBuf->data()+yyextra->inBufPos,bytesToCopy);
1885 yyextra->inBufPos+=bytesToCopy;
1886 return bytesToCopy;
1887}