Imported Upstream version 1.9.8
[platform/upstream/doxygen.git] / src / commentcnv.l
index 4cc9da9..85cec27 100644 (file)
@@ -1,12 +1,10 @@
 /*****************************************************************************
  *
- * 
- *
- * Copyright (C) 1997-2014 by Dimitri van Heesch.
+ * Copyright (C) 1997-2023 by Dimitri van Heesch.
  *
  * Permission to use, copy, modify, and distribute this software and its
- * documentation under the terms of the GNU General Public License is hereby 
- * granted. No representations are made about the suitability of this software 
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
  * for any purpose. It is provided "as is" without express or implied warranty.
  * See the GNU General Public License for more details.
  *
  * input used in their production; they are not affected by this license.
  *
  */
+%option never-interactive
+%option prefix="commentcnvYY"
+%option reentrant
+%option extra-type="struct commentcnvYY_state *"
+%top{
+#include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
+}
 
 %{
 
-#define YY_NEVER_INTERACTIVE 1
 
-  
 #include <stdio.h>
 #include <stdlib.h>
-
-#include <qstack.h>
-#include <qregexp.h>
-#include <qtextstream.h>
-#include <qglobal.h>
+#include <stack>
+#include <algorithm>
 
 #include "bufstr.h"
 #include "debug.h"
 #include "config.h"
 #include "doxygen.h"
 #include "util.h"
+#include "aliases.h"
 #include "condparser.h"
 
 #include <assert.h>
 
 #define YY_NO_INPUT 1
+#define YY_NO_UNISTD_H 1
 
-#define ADDCHAR(c)    g_outBuf->addChar(c)
-#define ADDARRAY(a,s) g_outBuf->addArray(a,s)
-  
-struct CondCtx
+#define ADDCHAR(c)    yyextra->outBuf.addChar(c)
+#define ADDARRAY(a,s) yyextra->outBuf.addArray(a,s)
+
+#define USE_STATE2STRING 0
+
+struct commentcnvYY_CondCtx
 {
-  CondCtx(int line,QCString id,bool b) 
+  commentcnvYY_CondCtx(int line,const QCString &id,bool b)
     : lineNr(line),sectionId(id), skip(b) {}
   int lineNr;
   QCString sectionId;
   bool skip;
 };
-  
+
 struct CommentCtx
 {
-  CommentCtx(int line) 
+  CommentCtx(int line)
     : lineNr(line) {}
   int lineNr;
 };
-  
-static BufStr * g_inBuf;
-static BufStr * g_outBuf;
-static int      g_inBufPos;
-static int      g_col;
-static int      g_blockHeadCol;
-static bool     g_mlBrief;
-static int      g_readLineCtx;
-static bool     g_skip;
-static QCString g_fileName;
-static int      g_lineNr;
-static int      g_condCtx;
-static QStack<CondCtx> g_condStack;
-static QStack<CommentCtx> g_commentStack;
-static QCString g_blockName;
-static int      g_lastCommentContext;
-static bool     g_inSpecialComment;
-static bool     g_inRoseComment;
-static int      g_stringContext;
-static int      g_charContext;
-static int      g_javaBlock;
-static bool     g_specialComment;
 
-static QCString g_aliasString;
-static int      g_blockCount;
-static bool     g_lastEscaped;
-static int      g_lastBlockContext;
-static bool     g_pythonDocString;
-static int      g_nestingCount;
+struct commentcnvYY_state
+{
+  commentcnvYY_state(const BufStr &i,BufStr &o) : inBuf(i), outBuf(o) {}
+  const BufStr &inBuf;
+  BufStr &outBuf;
+  int      inBufPos = 0;
+  int      col = 0;
+  int      blockHeadCol = 0;
+  bool     mlBrief = FALSE;
+  int      readLineCtx = 0;
+  bool     skip = FALSE;
+  QCString fileName;
+  int      lineNr = 0;
+  int      condCtx = 0;
+  std::stack<commentcnvYY_CondCtx> condStack;
+  std::stack<int> commentStack;
+  QCString blockName;
+  int      lastCommentContext = 0;
+  bool     inSpecialComment = FALSE;
+  bool     inRoseComment= FALSE;
+  int      stringContext = 0;
+  int      charContext = 0;
+  int      javaBlock = 0;
+  bool     specialComment = FALSE;
 
-static SrcLangExt g_lang;
-static bool       isFixedForm; // For Fortran
+  QCString aliasString;
+  int      blockCount = 0;
+  bool     lastEscaped = FALSE;
+  int      lastBlockContext= 0;
+  bool     pythonDocString = FALSE;
+  int      nestingCount= 0;
 
-static void replaceCommentMarker(const char *s,int len)
-{
-  const char *p=s;
-  char c;
-  // copy leading blanks
-  while ((c=*p) && (c==' ' || c=='\t' || c=='\n')) 
-  {
-    ADDCHAR(c);
-    g_lineNr += c=='\n';
-    p++;
-  }
-  // replace start of comment marker by blanks and the last character by a *
-  int blanks=0;
-  while ((c=*p) && (c=='/' || c=='!' || c=='#')) 
-  {
-    blanks++;
-    p++;
-    if (*p=='<') // comment-after-item marker 
-    { 
-      blanks++;
-      p++; 
-    }
-    if (c=='!') // end after first !
-    {
-      break;
-    }
-  }
-  if (blanks>0)
-  {
-    while (blanks>2)
-    {
-      ADDCHAR(' ');
-      blanks--;
-    }
-    if (blanks>1) ADDCHAR('*');
-    ADDCHAR(' ');
-  }
-  // copy comment line to output
-  ADDARRAY(p,len-(int)(p-s));
-}
+  bool     vhdl = FALSE; // for VHDL old style --! comment
 
-static inline int computeIndent(const char *s)
-{
-  int col=0;
-  static int tabSize=Config_getInt("TAB_SIZE");
-  const char *p=s;
-  char c;
-  while ((c=*p++))
-  {
-    if (c==' ') col++;
-    else if (c=='\t') col+=tabSize-(col%tabSize); 
-    else break;
-  }
-  return col;
-}
+  SrcLangExt lang = SrcLangExt_Unknown;
+  bool       isFixedForm = FALSE; // For Fortran
+};
 
-static inline void copyToOutput(const char *s,int len)
-{
-  int i;
-  if (g_skip) // only add newlines.
-  {
-    for (i=0;i<len;i++) 
-    {
-      if (s[i]=='\n') 
-      {
-       ADDCHAR('\n');
-       //fprintf(stderr,"---> skip %d\n",g_lineNr);
-       g_lineNr++;
-      }
-    }
-  }
-  else if (len>0)
-  {
-    ADDARRAY(s,len);
-    static int tabSize=Config_getInt("TAB_SIZE");
-    for (i=0;i<len;i++) 
-    {
-      switch (s[i])
-      {
-       case '\n': g_col=0; 
-                  //fprintf(stderr,"---> copy %d\n",g_lineNr);
-                  g_lineNr++; break;
-       case '\t': g_col+=tabSize-(g_col%tabSize); break;
-       default:   g_col++; break;
-      }
-    }
-  }
-}
+#if USE_STATE2STRING
+static const char *stateToString(int state);
+#endif
+static inline int computeIndent(const char *s);
 
-static void startCondSection(const char *sectId)
-{
-  //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
-  CondParser prs;
-  bool expResult = prs.parse(g_fileName,g_lineNr,sectId);
-  g_condStack.push(new CondCtx(g_lineNr,sectId,g_skip));
-  if (!expResult) // not enabled
-  {
-    g_skip=TRUE;
-  }
-}
+static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len);
+static inline 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,const QCString &s);
+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 void endCondSection()
-{
-  if (g_condStack.isEmpty())
-  {
-    warn(g_fileName,g_lineNr,"Found \\endcond command without matching \\cond");
-    g_skip=FALSE;
-  }
-  else
-  {
-    CondCtx *ctx = g_condStack.pop();
-    g_skip=ctx->skip;
-  }
-  //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
-}
 
-/** copies string \a s with length \a len to the output, while 
- *  replacing any alias commands found in the string.
- */
-static void replaceAliases(const char *s)
-{
-  QCString result = resolveAliasCmd(s);
-  //printf("replaceAliases(%s)->'%s'\n",s,result.data());
-  copyToOutput(result,result.length());
-}
 
 
 #undef  YY_INPUT
-#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
-static int yyread(char *buf,int max_size)
-{
-  int bytesInBuf = g_inBuf->curPos()-g_inBufPos;
-  int bytesToCopy = QMIN(max_size,bytesInBuf);
-  memcpy(buf,g_inBuf->data()+g_inBufPos,bytesToCopy);
-  g_inBufPos+=bytesToCopy;
-  return bytesToCopy;
-}
-
-void replaceComment(int offset);
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
 
 %}
 
+MAILADDR   ("mailto:")?[a-z_A-Z0-9\x80-\xff.+-]+"@"[a-z_A-Z0-9\x80-\xff-]+("."[a-z_A-Z0-9\x80-\xff\-]+)+[a-z_A-Z0-9\x80-\xff\-]+
+
 %option noyywrap
 
 %x Scan
@@ -241,64 +141,133 @@ void replaceComment(int offset);
 %x SkipChar
 %x SComment
 %x CComment
+%x CNComment
 %x Verbatim
 %x VerbatimCode
 %x ReadLine
 %x CondLine
 %x ReadAliasArgs
 
+  //- start: NUMBER -------------------------------------------------------------------------
+  // Note same defines in code.l: keep in sync
+DECIMAL_INTEGER  [1-9][0-9']*[0-9]?[uU]?[lL]?[lL]?
+HEXADECIMAL_INTEGER  "0"[xX][0-9a-zA-Z']+[0-9a-zA-Z]?
+OCTAL_INTEGER  "0"[0-7][0-7']+[0-7]?
+BINARY_INTEGER  "0"[bB][01][01']*[01]?
+INTEGER_NUMBER {DECIMAL_INTEGER}|{HEXADECIMAL_INTEGER}|{OCTAL_INTEGER}|{BINARY_INTEGER}
+
+FP_SUF [fFlL]
+
+DIGIT_SEQ [0-9][0-9']*[0-9]?
+FRAC_CONST {DIGIT_SEQ}"."|{DIGIT_SEQ}?"."{DIGIT_SEQ}
+FP_EXP [eE][+-]?{DIGIT_SEQ}
+DEC_FP1 {FRAC_CONST}{FP_EXP}?{FP_SUF}?
+DEC_FP2 {DIGIT_SEQ}{FP_EXP}{FP_SUF}
+
+HEX_DIGIT_SEQ [0-9a-fA-F][0-9a-fA-F']*[0-9a-fA-F]?
+HEX_FRAC_CONST {HEX_DIGIT_SEQ}"."|{HEX_DIGIT_SEQ}?"."{HEX_DIGIT_SEQ}
+BIN_EXP [pP][+-]?{DIGIT_SEQ}
+HEX_FP1 "0"[xX]{HEX_FRAC_CONST}{BIN_EXP}{FP_SUF}?
+HEX_FP2 "0"[xX]{HEX_DIGIT_SEQ}{BIN_EXP}{FP_SUF}?
+
+FLOAT_DECIMAL {DEC_FP1}|{DEC_FP2}
+FLOAT_HEXADECIMAL {HEX_FP1}|{HEX_FP2}
+FLOAT_NUMBER {FLOAT_DECIMAL}|{FLOAT_HEXADECIMAL}
+NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER}
+  //- end: NUMBER ---------------------------------------------------------------------------
+
+  // C start comment
+CCS   "/\*"
+  // C end comment
+CCE   "*\/"
+  // Cpp comment
+CPPC  "/\/"
+
+  // Optional any character
+ANYopt .*
+
+  // Optional white space
+WSopt [ \t\r]*
+  // readline non special
+RLopt [^\\@\n\*\/]*
+  // Optional slash
+SLASHopt [/]*
+
 %%
 
-<Scan>[^"'!\/\n\\#-,]*              { /* eat anything that is not " / , or \n */ 
-                                       copyToOutput(yytext,(int)yyleng);
+<Scan>{NUMBER}                     { //Note similar code in code.l
+                                      if (yyextra->lang!=SrcLangExt_Cpp) REJECT;
+                                      copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    }
+<Scan>[^"'!\/\n\\#,\-=; \t]*        { /* eat anything that is not " / , or \n */
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
                                     }
-<Scan>[,]                           { /* eat , so we have a nice separator in long initialization lines */ 
-                                       copyToOutput(yytext,(int)yyleng);
+<Scan>[,= ;\t]                      { /* eat , so we have a nice separator in long initialization lines */
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
                                     }
 <Scan>"\"\"\""!                     { /* start of python long comment */
-                                     if (g_lang!=SrcLangExt_Python)
+                                     if (yyextra->lang!=SrcLangExt_Python)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                       g_pythonDocString = TRUE;
-                                       g_nestingCount=0;
-                                       g_commentStack.clear(); /*  to be on the save side */
-                                       copyToOutput(yytext,(int)yyleng);
+                                       yyextra->pythonDocString = TRUE;
+                                       yyextra->nestingCount=1;
+                                       clearCommentStack(yyscanner); /*  to be on the save side */
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
+                                      BEGIN(CComment);
+                                       yyextra->commentStack.push(yyextra->lineNr);
+                                    }
+                                   }
+<Scan>"\"\"\""                     { /* start of python long comment */
+                                     if (yyextra->lang!=SrcLangExt_Python)
+                                    {
+                                      REJECT;
+                                    }
+                                     else if (Config_getBool(PYTHON_DOCSTRING))
+                                     {
+                                      REJECT;
+                                     }
+                                    else
+                                    { /* handle as if """! */
+                                       yyextra->pythonDocString = TRUE;
+                                       yyextra->nestingCount=1;
+                                       clearCommentStack(yyscanner); /*  to be on the save side */
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
                                       BEGIN(CComment);
-                                       g_commentStack.push(new CommentCtx(g_lineNr));
+                                       yyextra->commentStack.push(yyextra->lineNr);
                                     }
                                    }
 <Scan>![><!]/.*\n         {
-                                     if (g_lang!=SrcLangExt_Fortran)
+                                     if (yyextra->lang!=SrcLangExt_Fortran)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                       copyToOutput(yytext,(int)yyleng); 
-                                       g_nestingCount=0;
-                                       g_commentStack.clear(); /*  to be on the save side */
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
+                                       yyextra->nestingCount=0; // Fortran doesn't have an end comment
+                                       clearCommentStack(yyscanner); /*  to be on the save side */
                                       BEGIN(CComment);
-                                       g_commentStack.push(new CommentCtx(g_lineNr));
+                                       yyextra->commentStack.push(yyextra->lineNr);
                                     }
                                   }
 <Scan>[Cc\*][><!]/.*\n    {
-                                     if (g_lang!=SrcLangExt_Fortran)
+                                     if (yyextra->lang!=SrcLangExt_Fortran)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                       /* check for fixed format; we might have some conditional as part of multilene if like C<5 .and. & */
-                                       if (isFixedForm && (g_col == 0))
+                                       /* check for fixed format; we might have some conditional as part of multiline if like C<5 .and. & */
+                                       if (yyextra->isFixedForm && (yyextra->col == 0))
                                        {
-                                         copyToOutput(yytext,(int)yyleng); 
-                                         g_nestingCount=0;
-                                         g_commentStack.clear(); /*  to be on the save side */
+                                         copyToOutput(yyscanner,yytext,(int)yyleng);
+                                         yyextra->nestingCount=0; // Fortran doesn't have an end comment
+                                         clearCommentStack(yyscanner); /*  to be on the save side */
                                         BEGIN(CComment);
-                                         g_commentStack.push(new CommentCtx(g_lineNr));
+                                         yyextra->commentStack.push(yyextra->lineNr);
                                       }
                                       else
                                       {
@@ -307,25 +276,25 @@ void replaceComment(int offset);
                                     }
                                   }
 <Scan>!.*\n               {
-                                    if (g_lang!=SrcLangExt_Fortran)
+                                    if (yyextra->lang!=SrcLangExt_Fortran)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                       copyToOutput(yytext,(int)yyleng); 
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
                                     }
                                    }
 <Scan>[Cc\*].*\n                  {
-                                    if (g_lang!=SrcLangExt_Fortran)
+                                    if (yyextra->lang!=SrcLangExt_Fortran)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                       if (g_col == 0)
+                                       if (yyextra->col == 0)
                                        {
-                                         copyToOutput(yytext,(int)yyleng); 
+                                         copyToOutput(yyscanner,yytext,(int)yyleng);
                                       }
                                       else
                                       {
@@ -333,25 +302,25 @@ void replaceComment(int offset);
                                       }
                                     }
                                    }
-<Scan>"\""                         { /* start of a string */ 
-                                     copyToOutput(yytext,(int)yyleng); 
-                                    g_stringContext = YY_START;
-                                    BEGIN(SkipString); 
+<Scan>"\""                         { /* start of a string */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    yyextra->stringContext = YY_START;
+                                    BEGIN(SkipString);
                                    }
 <Scan>'                                   {
-                                     copyToOutput(yytext,(int)yyleng); 
-                                    g_charContext = YY_START;
-                                     if (g_lang!=SrcLangExt_VHDL)
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    yyextra->charContext = YY_START;
+                                     if (yyextra->lang!=SrcLangExt_VHDL)
                                      {
                                       BEGIN(SkipChar);
                                      }
                                   }
-<Scan>\n                           { /* new line */ 
-                                     copyToOutput(yytext,(int)yyleng); 
+<Scan>\n                           { /* new line */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
-<Scan>"//!"/.*\n[ \t]*"//"[\/!][^\/] | /* start C++ style special comment block */
-<Scan>("///"[/]*)/[^/].*\n[ \t]*"//"[\/!][^\/] { /* start C++ style special comment block */
-                                    if (g_mlBrief) 
+<Scan>{CPPC}"!"/.*\n[ \t]*{CPPC}[\/!][^\/] | /* start C++ style special comment block */
+<Scan>({CPPC}"/"[/]*)/[^/].*\n[ \t]*{CPPC}[\/!][^\/] { /* start C++ style special comment block */
+                                    if (yyextra->mlBrief)
                                     {
                                       REJECT; // bail out if we do not need to convert
                                     }
@@ -362,172 +331,249 @@ void replaceComment(int offset);
                                       {
                                         while (i<(int)yyleng && yytext[i]=='/') i++;
                                       }
-                                      g_blockHeadCol=g_col;
-                                      copyToOutput("/**",3); 
-                                      replaceAliases(yytext+i);
-                                      g_inSpecialComment=TRUE;
-                                      //BEGIN(SComment); 
-                                      g_readLineCtx=SComment;
+                                      yyextra->blockHeadCol=yyextra->col;
+                                      copyToOutput(yyscanner,"/**",3);
+                                      replaceAliases(yyscanner,QCString(yytext+i));
+                                      yyextra->inSpecialComment=TRUE;
+                                      //BEGIN(SComment);
+                                      yyextra->readLineCtx=SComment;
                                       BEGIN(ReadLine);
                                     }
                                    }
-<Scan>"//##Documentation".*/\n    { /* Start of Rational Rose ANSI C++ comment block */
-                                     if (g_mlBrief) REJECT;
+<Scan>{CPPC}"##Documentation"{ANYopt}/\n          { /* Start of Rational Rose ANSI C++ comment block */
+                                     if (yyextra->mlBrief) REJECT;
                                      int i=17; //=strlen("//##Documentation");
-                                    g_blockHeadCol=g_col;
-                                    copyToOutput("/**",3);
-                                    replaceAliases(yytext+i);
-                                    g_inRoseComment=TRUE;
+                                    yyextra->blockHeadCol=yyextra->col;
+                                    copyToOutput(yyscanner,"/**",3);
+                                    replaceAliases(yyscanner,QCString(yytext+i));
+                                    yyextra->inRoseComment=TRUE;
                                     BEGIN(SComment);
                                   }
-<Scan>"//"/.*\n                           { /* one line C++ comment */ 
-                                    g_inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
-                                    copyToOutput(yytext,(int)yyleng); 
-                                    g_readLineCtx=YY_START;
+<Scan>{CPPC}[!\/]/.*\n[ \t]*{CPPC}[|\/][ \t]*[@\\]"}" { // next line contains an end marker, see bug 752712
+                                    yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    yyextra->readLineCtx=YY_START;
+                                    BEGIN(ReadLine);
+                                   }
+<Scan>{CPPC}/.*\n                         { /* one line C++ comment */
+                                    yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    yyextra->readLineCtx=YY_START;
                                     BEGIN(ReadLine);
                                   }
-<Scan>"/**/"                       { /* avoid matching next rule for empty C comment, see bug 711723 */
-                                     copyToOutput(yytext,(int)yyleng);
+<Scan>{CCS}{CCE}                       { /* avoid matching next rule for empty C comment, see bug 711723 */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                   }
+<Scan>{CCS}[*!]?                          { /* start of a C comment */
+                                     if (yyextra->lang==SrcLangExt_Python)
+                                    {
+                                      REJECT;
+                                     }
+                                    yyextra->specialComment=(int)yyleng==3;
+                                     yyextra->nestingCount=1;
+                                     clearCommentStack(yyscanner); /*  to be on the save side */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                     if (yyextra->specialComment)
+                                      BEGIN(CComment);
+                                     else
+                                      BEGIN(CNComment);
+                                     yyextra->commentStack.push(yyextra->lineNr);
                                    }
-<Scan>"/*"[*!]?                           { /* start of a C comment */
-                                    g_specialComment=(int)yyleng==3;
-                                     g_nestingCount=0;
-                                     g_commentStack.clear(); /*  to be on the save side */
-                                     copyToOutput(yytext,(int)yyleng); 
-                                    BEGIN(CComment); 
-                                     g_commentStack.push(new CommentCtx(g_lineNr));
+<Scan>"#"[^\n]*\n                  {
+                                     if (yyextra->lang!=SrcLangExt_PHP)
+                                    {
+                                      REJECT;
+                                    }
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
 <Scan>"#"("#")?                           {
-                                     if (g_lang!=SrcLangExt_Python)
+                                     if (yyextra->lang!=SrcLangExt_Python)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                       copyToOutput(yytext,(int)yyleng); 
-                                       g_nestingCount=0;
-                                       g_commentStack.clear(); /*  to be on the save side */
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
+                                       yyextra->nestingCount=0; // Python doesn't have an end comment for #
+                                       clearCommentStack(yyscanner); /*  to be on the save side */
                                       BEGIN(CComment);
-                                       g_commentStack.push(new CommentCtx(g_lineNr));
+                                       yyextra->commentStack.push(yyextra->lineNr);
+                                    }
+                                  }
+<Scan>"--"[^!][^\n]*              {
+                                     if (yyextra->lang!=SrcLangExt_VHDL)
+                                    {
+                                      REJECT;
+                                    }
+                                    else
+                                    {
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
                                     }
                                   }
 <Scan>"--!"                       {
-                                     if (g_lang!=SrcLangExt_VHDL)
+                                     if (yyextra->lang!=SrcLangExt_VHDL)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                       copyToOutput(yytext,(int)yyleng); 
-                                       g_nestingCount=0;
-                                       g_commentStack.clear(); /*  to be on the save side */
+                                       yyextra->vhdl = TRUE;
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
+                                       yyextra->nestingCount=0;  // VHDL doesn't have an end comment
+                                       clearCommentStack(yyscanner); /*  to be on the save side */
                                       BEGIN(CComment);
-                                       g_commentStack.push(new CommentCtx(g_lineNr));
+                                       yyextra->commentStack.push(yyextra->lineNr);
                                     }
                                   }
 <Scan>![><!]                      {
-                                     if (g_lang!=SrcLangExt_Fortran)
+                                     if (yyextra->lang!=SrcLangExt_Fortran)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                       copyToOutput(yytext,(int)yyleng); 
-                                       g_nestingCount=0;
-                                       g_commentStack.clear(); /*  to be on the save side */
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
+                                       yyextra->nestingCount=0;  // Fortran doesn't have an end comment
+                                       clearCommentStack(yyscanner); /*  to be on the save side */
                                       BEGIN(CComment);
-                                       g_commentStack.push(new CommentCtx(g_lineNr));
+                                       yyextra->commentStack.push(yyextra->lineNr);
                                     }
                                   }
-<CComment>"{@code"/[ \t\n]        {
-                                     copyToOutput("@code",5); 
-                                    g_lastCommentContext = YY_START;
-                                    g_javaBlock=1;
-                                    g_blockName=&yytext[1];
+<CComment,CNComment,ReadLine>{MAILADDR}       |
+<CComment,CNComment,ReadLine>"<"{MAILADDR}">" { // Mail address, to prevent seeing e.g x@code-factory.org as start of a code block
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                   }
+<CComment>"{"[ \t]*"@code"/[ \t\n] {
+                                     copyToOutput(yyscanner,"@iliteral{code}",15);
+                                    yyextra->lastCommentContext = YY_START;
+                                    yyextra->javaBlock=1;
+                                    yyextra->blockName=&yytext[1];
                                      BEGIN(VerbatimCode);
                                   }
-<CComment,ReadLine>[\\@]("dot"|"code"|"msc")/[^a-z_A-Z0-9] { /* start of a verbatim block */
-                                     copyToOutput(yytext,(int)yyleng); 
-                                    g_lastCommentContext = YY_START;
-                                    g_javaBlock=0;
-                                    g_blockName=&yytext[1];
+<CComment>"{"[ \t]*"@literal"/[ \t\n] {
+                                     copyToOutput(yyscanner,"@iliteral",9);
+                                    yyextra->lastCommentContext = YY_START;
+                                    yyextra->javaBlock=1;
+                                    yyextra->blockName=&yytext[1];
+                                     BEGIN(VerbatimCode);
+                                  }
+<CComment,ReadLine>^[ \t]*("```"[`]*|"~~~"[~]*) { /* start of markdown code block */
+                                     if (!Config_getBool(MARKDOWN_SUPPORT))
+                                     {
+                                       REJECT;
+                                     }
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                     yyextra->lastCommentContext = YY_START;
+                                     yyextra->javaBlock=0;
+                                     yyextra->blockName=QCString(yytext).stripWhiteSpace().left(3); // take the ``` or ~~~ part
+                                     BEGIN(VerbatimCode);
+                                   }
+<CComment,ReadLine>[\\@]("dot"|"code"|"msc"|"startuml")/[^a-z_A-Z0-9] { /* start of a verbatim block */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    yyextra->lastCommentContext = YY_START;
+                                    yyextra->javaBlock=0;
+                                     if (qstrcmp(&yytext[1],"startuml")==0)
+                                     {
+                                       yyextra->blockName="uml";
+                                     }
+                                     else
+                                     {
+                                      yyextra->blockName=&yytext[1];
+                                     }
                                      BEGIN(VerbatimCode);
                                   }
-<CComment,ReadLine>[\\@]("f$"|"f["|"f{"[a-z]*) {
-                                     copyToOutput(yytext,(int)yyleng); 
-                                    g_blockName=&yytext[1];
-                                    if (g_blockName.at(1)=='[')
+<CComment,ReadLine>[\\@]("f$"|"f["|"f{"|"f(") {
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    yyextra->blockName=&yytext[1];
+                                    if (yyextra->blockName.at(1)=='[')
                                     {
-                                      g_blockName.at(1)=']';
+                                      yyextra->blockName.at(1)=']';
                                     }
-                                    else if (g_blockName.at(1)=='{')
+                                    else if (yyextra->blockName.at(1)=='{')
                                     {
-                                      g_blockName.at(1)='}';
+                                      yyextra->blockName.at(1)='}';
                                     }
-                                    g_lastCommentContext = YY_START;
+                                    else if (yyextra->blockName.at(1)=='(')
+                                    {
+                                      yyextra->blockName.at(1)=')';
+                                    }
+                                    yyextra->lastCommentContext = YY_START;
                                     BEGIN(Verbatim);
                                   }
-<CComment,ReadLine>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
-                                     copyToOutput(yytext,(int)yyleng); 
-                                    g_blockName=&yytext[1];
-                                    g_lastCommentContext = YY_START;
+<CComment,ReadLine>[\\@]("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    yyextra->blockName=&yytext[1];
+                                    yyextra->lastCommentContext = YY_START;
                                      BEGIN(Verbatim);
                                    }
-<Scan>.                            { /* any ather character */
-                                     copyToOutput(yytext,(int)yyleng); 
+<Scan>"\\\""                       { /* escaped double quote */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                   }
+<Scan>"\\\\"                       { /* escaped backslash */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                   }
+<Scan>.                            { /* any other character */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
-<Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"docbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}") { /* end of verbatim block */
-                                     copyToOutput(yytext,(int)yyleng);
-                                    if (yytext[1]=='f') // end of formula
+<Verbatim>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    if (&yytext[1]==yyextra->blockName) // end of formula
                                     {
-                                      BEGIN(g_lastCommentContext);
+                                      BEGIN(yyextra->lastCommentContext);
                                     }
-                                    else if (&yytext[4]==g_blockName)
+                                    else if (&yytext[4]==yyextra->blockName)
                                     {
-                                      BEGIN(g_lastCommentContext);
+                                      BEGIN(yyextra->lastCommentContext);
                                     }
                                    }
 <VerbatimCode>"{"                 {
-                                     if (g_javaBlock==0)
+                                     if (yyextra->javaBlock==0)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                      g_javaBlock++;
-                                       copyToOutput(yytext,(int)yyleng);
+                                      yyextra->javaBlock++;
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
                                     }
                                    }
 <VerbatimCode>"}"                 {
-                                     if (g_javaBlock==0)
+                                     if (yyextra->javaBlock==0)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                      g_javaBlock--;
-                                      if (g_javaBlock==0)
+                                      yyextra->javaBlock--;
+                                      if (yyextra->javaBlock==0)
                                       {
-                                         copyToOutput(" @endcode ",10);
-                                        BEGIN(g_lastCommentContext);
+                                         copyToOutput(yyscanner," @endiliteral ",14);
+                                        BEGIN(yyextra->lastCommentContext);
                                       }
                                       else
                                       {
-                                         copyToOutput(yytext,(int)yyleng);
+                                         copyToOutput(yyscanner,yytext,(int)yyleng);
                                       }
                                     }
                                   }
-<VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc") { /* end of verbatim block */
-                                     copyToOutput(yytext,(int)yyleng);
-                                    if (&yytext[4]==g_blockName)
+<VerbatimCode>("```"[`]*|"~~~"[~]*) { /* end of markdown code block */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                     if (yytext[0]==yyextra->blockName[0])
+                                     {
+                                       BEGIN(yyextra->lastCommentContext);
+                                     }
+                                   }
+<VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc"|"enduml") { /* end of verbatim block */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    if (&yytext[4]==yyextra->blockName)
                                     {
-                                      BEGIN(g_lastCommentContext);
+                                      BEGIN(yyextra->lastCommentContext);
                                     }
                                    }
-<VerbatimCode>^[ \t]*"//"[\!\/]?   { /* skip leading comments */
-                                    if (!g_inSpecialComment)
+<VerbatimCode>^[ \t]*{CPPC}[\!\/]?   { /* skip leading comments */
+                                    if (!yyextra->inSpecialComment)
                                     {
-                                       copyToOutput(yytext,(int)yyleng); 
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
                                     }
                                      else
                                      {
@@ -536,25 +582,25 @@ void replaceComment(int offset);
                                        {
                                          l++;
                                        }
-                                       copyToOutput(yytext,l);
+                                       copyToOutput(yyscanner,yytext,l);
                                        if (yyleng-l==3) // ends with //! or ///
                                        {
-                                         copyToOutput(" * ",3);
+                                         copyToOutput(yyscanner," * ",3);
                                        }
                                        else // ends with //
                                        {
-                                         copyToOutput("//",2);
+                                         copyToOutput(yyscanner,"//",2);
                                        }
                                      }
                                   }
-<Verbatim,VerbatimCode>[^@\/\\\n{}]* { /* any character not a backslash or new line or } */
-                                     copyToOutput(yytext,(int)yyleng); 
+<Verbatim,VerbatimCode>[^`~@\/\\\n{}]* { /* any character not a backslash or new line or } */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
 <Verbatim,VerbatimCode>\n         { /* new line in verbatim block */
-                                     copyToOutput(yytext,(int)yyleng); 
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
-<Verbatim>^[ \t]*"///"             {
-                                    if (g_blockName=="dot" || g_blockName=="msc" || g_blockName.at(0)=='f')
+<Verbatim>^[ \t]*{CPPC}[/!]          {
+                                    if (yyextra->blockName=="dot" || yyextra->blockName=="msc" || yyextra->blockName=="uml" || yyextra->blockName.at(0)=='f')
                                     {
                                       // see bug 487871, strip /// from dot images and formulas.
                                        int l=0;
@@ -562,8 +608,8 @@ void replaceComment(int offset);
                                        {
                                          l++;
                                        }
-                                       copyToOutput(yytext,l);
-                                      copyToOutput("   ",3);
+                                       copyToOutput(yyscanner,yytext,l);
+                                      copyToOutput(yyscanner,"   ",3);
                                     }
                                     else // even slashes are verbatim (e.g. \verbatim, \code)
                                     {
@@ -571,207 +617,298 @@ void replaceComment(int offset);
                                     }
                                   }
 <Verbatim,VerbatimCode>.          { /* any other character */
-                                     copyToOutput(yytext,(int)yyleng); 
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
 <SkipString>\\.                    { /* escaped character in string */
-                                     copyToOutput(yytext,(int)yyleng); 
+                                     if (yyextra->lang==SrcLangExt_Fortran || yyextra->lang==SrcLangExt_VHDL)
+                                     {
+                                       unput(yytext[1]);
+                                       copyToOutput(yyscanner,yytext,1);
+                                     }
+                                     else
+                                     {
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
+                                     }
                                    }
-<SkipString>"\""                          { /* end of string */ 
-                                     copyToOutput(yytext,(int)yyleng); 
-                                    BEGIN(g_stringContext); 
+<SkipString>"\""                          { /* end of string */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    BEGIN(yyextra->stringContext);
                                    }
-<SkipString>.                      { /* any other string character */ 
-                                     copyToOutput(yytext,(int)yyleng); 
+<SkipString>.                      { /* any other string character */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
-<SkipString>\n                     { /* new line inside string (illegal for some compilers) */ 
-                                     copyToOutput(yytext,(int)yyleng); 
+<SkipString>\n                     { /* new line inside string (illegal for some compilers) */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
 <SkipChar>\\.                     { /* escaped character */
-                                     copyToOutput(yytext,(int)yyleng); 
+                                     if (yyextra->lang==SrcLangExt_Fortran || yyextra->lang==SrcLangExt_VHDL)
+                                     {
+                                       unput(yytext[1]);
+                                       copyToOutput(yyscanner,yytext,1);
+                                     }
+                                     else
+                                     {
+                                       copyToOutput(yyscanner,yytext,(int)yyleng);
+                                     }
                                    }
-<SkipChar>'                        { /* end of character literal */ 
-                                     copyToOutput(yytext,(int)yyleng); 
-                                     BEGIN(g_charContext);
+<SkipChar>'                        { /* end of character literal */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                     BEGIN(yyextra->charContext);
                                    }
-<SkipChar>.                        { /* any other string character */ 
-                                     copyToOutput(yytext,(int)yyleng); 
+<SkipChar>.                        { /* any other string character */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
 <SkipChar>\n                       { /* new line character */
-                                     copyToOutput(yytext,(int)yyleng); 
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
 
-<CComment>[^\\!@*\n{\"\/]*           { /* anything that is not a '*' or command */ 
-                                     copyToOutput(yytext,(int)yyleng); 
+<CComment,CNComment>[^ `~<\\!@*\n{\"\/]*     { /* anything that is not a '*' or command */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
-<CComment>"*"+[^*/\\@\n{\"]*       { /* stars without slashes */
-                                     copyToOutput(yytext,(int)yyleng); 
+<CComment,CNComment>"*"+[^*\/\\@\n{\"]*      { /* stars without slashes */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
 <CComment>"\"\"\""                 { /* end of Python docstring */
-                                     if (g_lang!=SrcLangExt_Python)
+                                     if (yyextra->lang!=SrcLangExt_Python)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                       g_pythonDocString = FALSE;
-                                      copyToOutput(yytext,(int)yyleng);
+                                       yyextra->nestingCount--;
+                                       yyextra->pythonDocString = FALSE;
+                                      copyToOutput(yyscanner,yytext,(int)yyleng);
                                       BEGIN(Scan);
                                     }
                                   }
-<CComment>\n                       { /* new line in comment */
-                                     copyToOutput(yytext,(int)yyleng); 
+<CComment,CNComment>\n                       { /* new line in comment */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                      /* in case of Fortran always end of comment */
-                                    if (g_lang==SrcLangExt_Fortran)
+                                    if (yyextra->lang==SrcLangExt_Fortran)
                                     {
                                       BEGIN(Scan);
                                     }
                                    }
-<CComment>"/"+"*"                  { /* nested C comment */
-                                     g_nestingCount++;
-                                     g_commentStack.push(new CommentCtx(g_lineNr));
-                                     copyToOutput(yytext,(int)yyleng); 
+<CComment,CNComment>"/""/"+/"*/"   { /* we are already in C-comment so not a start of a nested comment but
+                                      * just the end of the comment (the end part is handled later). */
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
-<CComment>"*"+"/"                  { /* end of C comment */
-                                     if (g_lang==SrcLangExt_Python)
+<CComment,CNComment>"/"+"*"                  { /* nested C comment */
+                                     if (yyextra->lang==SrcLangExt_Python ||
+                                         yyextra->lang==SrcLangExt_Markdown)
+                                    {
+                                      REJECT;
+                                     }
+                                     yyextra->nestingCount++;
+                                     yyextra->commentStack.push(yyextra->lineNr);
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
+                                   }
+<CComment,CNComment>"*"+"/"                  { /* end of C comment */
+                                     if (yyextra->lang==SrcLangExt_Python ||
+                                         yyextra->lang==SrcLangExt_Markdown)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                      copyToOutput(yytext,(int)yyleng);
-                                       if (g_nestingCount<=0)
+                                      copyToOutput(yyscanner,yytext,(int)yyleng);
+                                       yyextra->nestingCount--;
+                                       if (yyextra->nestingCount<=0)
                                        {
                                         BEGIN(Scan);
                                        }
                                        else
                                        {
-                                         g_nestingCount--;
-                                         delete g_commentStack.pop();
+                                         //yyextra->nestingCount--;
+                                         yyextra->commentStack.pop();
                                        }
                                     }
                                    }
-<CComment>"\n"/[ \t]*[^#]         { /* end of Python comment */
-                                     if (g_lang!=SrcLangExt_Python || g_pythonDocString)
+  /* Python an VHDL share CComment,CNComment, so special attention for ending comments is required */
+<CComment,CNComment>"\n"/[ \t]*"#"        {
+                                     if (yyextra->lang!=SrcLangExt_VHDL)
+                                     {
+                                       REJECT;
+                                     }
+                                     else
+                                     {
+                                       if (yyextra->vhdl) // inside --! comment
+                                       {
+                                         yyextra->vhdl = FALSE;
+                                        copyToOutput(yyscanner,yytext,(int)yyleng);
+                                        BEGIN(Scan);
+                                       }
+                                       else // C-type comment
+                                       {
+                                         REJECT;
+                                       }
+                                     }
+                                   }
+<CComment,CNComment>"\n"/[ \t]*"-"        {
+                                     if (yyextra->lang!=SrcLangExt_Python || yyextra->pythonDocString)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                      copyToOutput(yytext,(int)yyleng);
+                                      copyToOutput(yyscanner,yytext,(int)yyleng);
                                       BEGIN(Scan);
                                     }
-                                  }
-<CComment>"\n"/[ \t]*[^\-]        { /* end of VHDL comment */
-                                     if (g_lang!=SrcLangExt_VHDL)
-                                    {
+                                   }
+<CComment,CNComment>"\n"/[ \t]*[^ \t#\-]          {
+                                     if (yyextra->lang==SrcLangExt_Python)
+                                     {
+                                       if (yyextra->pythonDocString)
+                                       {
+                                         REJECT;
+                                       }
+                                       else
+                                       {
+                                        copyToOutput(yyscanner,yytext,(int)yyleng);
+                                        BEGIN(Scan);
+                                       }
+                                     }
+                                     else if (yyextra->lang==SrcLangExt_VHDL)
+                                     {
+                                       if (yyextra->vhdl) // inside --! comment
+                                       {
+                                         yyextra->vhdl = FALSE;
+                                        copyToOutput(yyscanner,yytext,(int)yyleng);
+                                        BEGIN(Scan);
+                                       }
+                                       else // C-type comment
+                                       {
+                                         REJECT;
+                                       }
+                                     }
+                                     else
+                                     {
                                       REJECT;
-                                    }
-                                    else
-                                    {
-                                      copyToOutput(yytext,(int)yyleng);
-                                      BEGIN(Scan);
-                                    }
-                                  }
+                                     }
+                                   }
    /* removed for bug 674842 (bug was introduced in rev 768)
-<CComment>"'"                     {
-                                    g_charContext = YY_START;
-                                    copyToOutput(yytext,(int)yyleng);
+<CComment,CNComment>"'"                           {
+                                    yyextra->charContext = YY_START;
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
                                     BEGIN(SkipChar);
                                   }
-<CComment>"\""                    {
-                                    g_stringContext = YY_START;
-                                    copyToOutput(yytext,(int)yyleng);
+<CComment,CNComment>"\""                          {
+                                    yyextra->stringContext = YY_START;
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
                                     BEGIN(SkipString);
                                   }
    */
-<CComment>.                       {
-                                     copyToOutput(yytext,(int)yyleng); 
+<CComment,CNComment>.                     {
+                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                   }
-<SComment>^[ \t]*"///"[\/]*/\n     {
-                                    replaceComment(0);
+<SComment>^[ \t]*{CPPC}"/"{SLASHopt}/\n     {
+                                    replaceComment(yyscanner,0);
                                   }
-<SComment>\n[ \t]*"///"[\/]*/\n    {
-                                     replaceComment(1); 
+<SComment>\n[ \t]*{CPPC}"/"{SLASHopt}/\n    {
+                                     replaceComment(yyscanner,1);
                                    }
-<SComment>^[ \t]*"///"[^\/\n]/.*\n { 
-                                    replaceComment(0);
-                                    g_readLineCtx=YY_START;
+<SComment>^[ \t]*{CPPC}"/"[^\/\n]/.*\n {
+                                    replaceComment(yyscanner,0);
+                                    yyextra->readLineCtx=YY_START;
                                     BEGIN(ReadLine);
                                   }
-<SComment>\n[ \t]*"///"[^\/\n]/.*\n  { 
-                                     replaceComment(1); 
-                                    g_readLineCtx=YY_START;
+<SComment>\n[ \t]*{CPPC}[\/!]("<")?[ \t]*[\\@]"}".*\n {
+                                     /* See Bug 752712: end the multiline comment when finding a @} or \} command */
+                                     copyToOutput(yyscanner," */",3);
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    yyextra->inSpecialComment=FALSE;
+                                    yyextra->inRoseComment=FALSE;
+                                    BEGIN(Scan);
+                                   }
+<SComment>\n[ \t]*{CPPC}"/"[^\/\n]/.*\n  {
+                                     replaceComment(yyscanner,1);
+                                    yyextra->readLineCtx=YY_START;
                                     BEGIN(ReadLine);
                                   }
-<SComment>^[ \t]*"//!"             |    // just //!
-<SComment>^[ \t]*"//!<"/.*\n       |    // or   //!< something
-<SComment>^[ \t]*"//!"[^<]/.*\n    {    // or   //!something
-                                    replaceComment(0);
-                                    g_readLineCtx=YY_START;
+<SComment>^[ \t]*{CPPC}"!"             |    // just //!
+<SComment>^[ \t]*{CPPC}"!<"/.*\n       |    // or   //!< something
+<SComment>^[ \t]*{CPPC}"!"[^<]/.*\n    {    // or   //!something
+                                    replaceComment(yyscanner,0);
+                                    yyextra->readLineCtx=YY_START;
                                     BEGIN(ReadLine);
                                    }
-<SComment>\n[ \t]*"//!"            |
-<SComment>\n[ \t]*"//!<"/.*\n      |
-<SComment>\n[ \t]*"//!"[^<\n]/.*\n { 
-                                     replaceComment(1); 
-                                    g_readLineCtx=YY_START;
+<SComment>\n[ \t]*{CPPC}"!"            |
+<SComment>\n[ \t]*{CPPC}"!<"/.*\n      |
+<SComment>\n[ \t]*{CPPC}"!"[^<\n]/.*\n {
+                                     replaceComment(yyscanner,1);
+                                    yyextra->readLineCtx=YY_START;
                                     BEGIN(ReadLine);
                                    }
-<SComment>^[ \t]*"//##"/.*\n       {
-                                     if (!g_inRoseComment)
+<SComment>^[ \t]*{CPPC}"##"/.*\n       {
+                                     if (!yyextra->inRoseComment)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                      replaceComment(0);
-                                      g_readLineCtx=YY_START;
+                                      replaceComment(yyscanner,0);
+                                      yyextra->readLineCtx=YY_START;
                                       BEGIN(ReadLine);
                                     }
                                    }
-<SComment>\n[ \t]*"//##"/.*\n      {
-                                     if (!g_inRoseComment)
+<SComment>\n[ \t]*{CPPC}"##"/.*\n      {
+                                     if (!yyextra->inRoseComment)
                                     {
                                       REJECT;
                                     }
                                     else
                                     {
-                                       replaceComment(1); 
-                                      g_readLineCtx=YY_START;
+                                       replaceComment(yyscanner,1);
+                                      yyextra->readLineCtx=YY_START;
                                       BEGIN(ReadLine);
                                     }
                                    }
 <SComment>\n                      { /* end of special comment */
-                                     copyToOutput(" */",3); 
-                                    copyToOutput(yytext,(int)yyleng); 
-                                    g_inSpecialComment=FALSE;
-                                    g_inRoseComment=FALSE;
-                                    BEGIN(Scan); 
+                                     copyToOutput(yyscanner," */",3);
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    yyextra->inSpecialComment=FALSE;
+                                    yyextra->inRoseComment=FALSE;
+                                     yyextra->readLineCtx = Scan; // reset, otherwise there will be problems with:
+                                                                  //   static void handleCondSectionId
+                                    BEGIN(Scan);
                                    }
-<ReadLine>[^\\@\n]*/\n            {
-                                    copyToOutput(yytext,(int)yyleng);
-                                     BEGIN(g_readLineCtx);
-                                  }
-<CComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
-                                    copyToOutput(yytext,(int)yyleng);
+<ReadLine>{CCS}"*"                    {
+                                    copyToOutput(yyscanner,"/&zwj;**",8);
+                                  }
+<ReadLine>{CCE}                     {
+                                    copyToOutput(yyscanner,"*&zwj;/",7);
+                                  }
+<ReadLine>"*"                      {
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
+                                  }
+<ReadLine>{RLopt}                  {
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
+                                  }
+<ReadLine>{RLopt}/\n               {
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
+                                    BEGIN(yyextra->readLineCtx);
+                                  }
+<CComment,CNComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
                                   }
 <CComment,ReadLine>[\\@]"cond"/[^a-z_A-Z0-9]      { // conditional section
-                                    g_condCtx = YY_START; 
+                                    yyextra->condCtx = YY_START;
                                     BEGIN(CondLine);
                                   }
 <CComment,ReadLine>[\\@]"endcond"/[^a-z_A-Z0-9] { // end of conditional section
-                                    bool oldSkip=g_skip;
-                                    endCondSection();
-                                    if (YY_START==CComment && oldSkip && !g_skip) 
+                                    bool oldSkip=yyextra->skip;
+                                    endCondSection(yyscanner);
+                                    if (YY_START==CComment && oldSkip && !yyextra->skip)
                                     {
                                       //printf("** Adding start of comment!\n");
-                                      if (g_lang!=SrcLangExt_Python &&
-                                          g_lang!=SrcLangExt_VHDL &&
-                                          g_lang!=SrcLangExt_Fortran)
+                                      if (yyextra->lang!=SrcLangExt_Python &&
+                                          yyextra->lang!=SrcLangExt_VHDL &&
+                                          yyextra->lang!=SrcLangExt_Markdown &&
+                                          yyextra->lang!=SrcLangExt_Fortran)
                                       {
                                         ADDCHAR('/');
                                         ADDCHAR('*');
-                                        if (g_specialComment)
+                                        if (yyextra->specialComment)
                                         {
                                           ADDCHAR('*');
                                         }
@@ -779,261 +916,380 @@ void replaceComment(int offset);
                                     }
                                    }
 <CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
-                                    bool oldSkip=g_skip;
-                                     startCondSection(yytext);
-                                    if ((g_condCtx==CComment || g_readLineCtx==SComment) && 
-                                         !oldSkip && g_skip) 
-                                    {
-                                      if (g_lang!=SrcLangExt_Python &&
-                                          g_lang!=SrcLangExt_VHDL &&
-                                          g_lang!=SrcLangExt_Fortran)
-                                      {
-                                        ADDCHAR('*');
-                                        ADDCHAR('/');
-                                      }
-                                    }
-                                     if (g_readLineCtx==SComment)
-                                     {
-                                       BEGIN(SComment);
-                                     }
-                                     else
-                                     {
-                                      BEGIN(g_condCtx);
-                                     }
+                                     handleCondSectionId(yyscanner,yytext);
                                   }
-<CondLine>[ \t]*
-<CComment,ReadLine>[\\@]"cond"[ \t\r]*/\n |
+<CComment,ReadLine>[\\@]"cond"{WSopt}/\n {
+                                    yyextra->condCtx=YY_START;
+                                     handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
+                                   }
+<CondLine>\n                      |
 <CondLine>.                       { // forgot section id?
-                                    if (YY_START!=CondLine) g_condCtx=YY_START;
-                                    bool oldSkip=g_skip;
-                                    startCondSection(" "); // fake section id causing the section to be hidden unconditionally
-                                    if ((g_condCtx==CComment || g_readLineCtx==SComment) && 
-                                         !oldSkip && g_skip) 
-                                    {
-                                      //printf("** Adding terminator for comment!\n");
-                                      if (g_lang!=SrcLangExt_Python &&
-                                          g_lang!=SrcLangExt_VHDL)
-                                      {
-                                        ADDCHAR('*');
-                                        ADDCHAR('/');
-                                      }
-                                    }
-                                    if (*yytext=='\n') g_lineNr++;
-                                     if (g_readLineCtx==SComment)
-                                     {
-                                       BEGIN(SComment);
-                                     }
-                                     else
-                                     {
-                                      BEGIN(g_condCtx);
-                                     }
+                                     handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
+                                    if (*yytext=='\n') { yyextra->lineNr++; copyToOutput(yyscanner,"\n",1);}
                                   }
-<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*  { // expand alias without arguments
-                                    replaceAliases(yytext);
+<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9-]*  { // expand alias without arguments
+                                    replaceAliases(yyscanner,QCString(yytext));
                                   }
-<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments
-                                     g_lastBlockContext=YY_START;
-                                    g_blockCount=1;
-                                    g_aliasString=yytext;
-                                    g_lastEscaped=0;
+<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9-]*"{" { // expand alias with arguments
+                                     yyextra->lastBlockContext=YY_START;
+                                    yyextra->blockCount=1;
+                                    yyextra->aliasString=yytext;
+                                    yyextra->lastEscaped=0;
                                     BEGIN( ReadAliasArgs );
                                   }
-<ReadAliasArgs>^[ \t]*"//"[/!]/[^\n]+   { // skip leading special comments (see bug 618079)
+<ReadAliasArgs>^[ \t]*{CPPC}[/!]/[^\n]+   { // skip leading special comments (see bug 618079)
                                   }
-<ReadAliasArgs>"*/"               { // oops, end of comment in the middle of an alias?
-                                     if (g_lang==SrcLangExt_Python)
+<ReadAliasArgs>{CCE}              { // oops, end of comment in the middle of an alias?
+                                     if (yyextra->lang==SrcLangExt_Python)
                                     {
                                       REJECT;
                                     }
                                     else // abort the alias, restart scanning
                                     {
-                                      copyToOutput(g_aliasString,g_aliasString.length());
-                                      copyToOutput(yytext,(int)yyleng);
+                                      copyToOutput(yyscanner,yyextra->aliasString.data(),yyextra->aliasString.length());
+                                      copyToOutput(yyscanner,yytext,(int)yyleng);
                                       BEGIN(Scan);
                                     }
                                   }
 <ReadAliasArgs>[^{}\n\\\*]+       {
-                                     g_aliasString+=yytext;
-                                    g_lastEscaped=FALSE;
+                                     yyextra->aliasString+=yytext;
+                                    yyextra->lastEscaped=FALSE;
                                   }
 <ReadAliasArgs>"\\"               {
-                                     if (g_lastEscaped)  g_lastEscaped=FALSE;
-                                     else                g_lastEscaped=TRUE;
-                                     g_aliasString+=yytext;
+                                     if (yyextra->lastEscaped)  yyextra->lastEscaped=FALSE;
+                                     else                yyextra->lastEscaped=TRUE;
+                                     yyextra->aliasString+=yytext;
                                    }
 <ReadAliasArgs>\n                 {
-                                     g_aliasString+=yytext;
-                                     g_lineNr++;
-                                    g_lastEscaped=FALSE;
+                                     yyextra->aliasString+=yytext;
+                                     yyextra->lineNr++;
+                                    yyextra->lastEscaped=FALSE;
                                   }
 <ReadAliasArgs>"{"                {
-                                     g_aliasString+=yytext;
-                                     if (!g_lastEscaped) g_blockCount++;
-                                    g_lastEscaped=FALSE;
+                                     yyextra->aliasString+=yytext;
+                                     if (!yyextra->lastEscaped) yyextra->blockCount++;
+                                    yyextra->lastEscaped=FALSE;
                                    }
 <ReadAliasArgs>"}"                {
-                                     g_aliasString+=yytext;
-                                    if (!g_lastEscaped) g_blockCount--;
-                                    if (g_blockCount==0)
+                                     yyextra->aliasString+=yytext;
+                                    if (!yyextra->lastEscaped) yyextra->blockCount--;
+                                    if (yyextra->blockCount==0)
                                     {
-                                      replaceAliases(g_aliasString);
-                                      BEGIN( g_lastBlockContext );
+                                      replaceAliases(yyscanner,yyextra->aliasString);
+                                      BEGIN( yyextra->lastBlockContext );
                                     }
-                                    g_lastEscaped=FALSE;
+                                    yyextra->lastEscaped=FALSE;
                                   }
 <ReadAliasArgs>.                  {
-                                     g_aliasString+=yytext;
-                                    g_lastEscaped=FALSE;
+                                     yyextra->aliasString+=yytext;
+                                    yyextra->lastEscaped=FALSE;
                                   }
 <ReadLine>.                       {
-                                    copyToOutput(yytext,(int)yyleng);
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
                                   }
 
+<*>.                               {
+                                    copyToOutput(yyscanner,yytext,(int)yyleng);
+                                   }
+  /*
+<*>\n  { fprintf(stderr,"Lex scanner %s (%s) default rule newline for state %s.\n", __FILE__, qPrint(yyextra->fileName),stateToString(YY_START));}
+  */
 %%
 
-void replaceComment(int offset)
+static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len)
 {
-  if (g_mlBrief || g_skip)
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  const char *p=s;
+  char c;
+  // copy leading blanks
+  while ((c=*p) && (c==' ' || c=='\t' || c=='\n'))
   {
-    copyToOutput(yytext,(int)yyleng);
+    ADDCHAR(c);
+    yyextra->lineNr += c=='\n';
+    p++;
   }
-  else
+  // replace start of comment marker by blanks and the last character by a *
+  int blanks=0;
+  while ((c=*p) && (c=='/' || c=='!' || c=='#'))
   {
-    //printf("replaceComment(%s)\n",yytext);
-    int i=computeIndent(&yytext[offset]);
-    if (i==g_blockHeadCol)
+    blanks++;
+    p++;
+    if (*p=='<') // comment-after-item marker
     {
-      replaceCommentMarker(yytext,(int)yyleng);
+      blanks++;
+      p++;
     }
-    else
+    if (c=='!') // end after first !
+    {
+      break;
+    }
+  }
+  if (blanks>0)
+  {
+    while (blanks>2)
     {
-      copyToOutput(" */",3);
-      int i;for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
-      g_inSpecialComment=FALSE;
-      BEGIN(Scan);                                            
-    }                                                         
+      ADDCHAR(' ');
+      blanks--;
+    }
+    if (blanks>1) ADDCHAR('*');
+    ADDCHAR(' ');
   }
+  // copy comment line to output
+  ADDARRAY(p,len-(int)(p-s));
 }
 
-// simplified way to know if this is fixed form
-// duplicate in fortrancode.l
-static bool recognizeFixedForm(const char* contents)
+static inline int computeIndent(const char *s)
+{
+  int col=0;
+  int tabSize=Config_getInt(TAB_SIZE);
+  const char *p=s;
+  char c;
+  while ((c=*p++))
+  {
+    if (c==' ') col++;
+    else if (c=='\t') col+=tabSize-(col%tabSize);
+    else break;
+  }
+  return col;
+}
+
+static inline void copyToOutput(yyscan_t yyscanner,const char *s,int len)
+{
+  int tabSize=Config_getInt(TAB_SIZE);
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  int i;
+  if (yyextra->skip) // only add newlines.
+  {
+    for (i=0;i<len;i++)
+    {
+      switch(s[i])
+      {
+        case '\n':
+         ADDCHAR('\n');
+         yyextra->lineNr++;
+          yyextra->col=0;
+          break;
+        case '\t':
+          yyextra->col+=tabSize-(yyextra->col%tabSize);
+          break;
+        default:
+          yyextra->col++;
+          break;
+      }
+    }
+  }
+  else if (len>0)
+  {
+    ADDARRAY(s,len);
+    for (i=0;i<len;i++)
+    {
+      switch (s[i])
+      {
+       case '\n': yyextra->col=0;
+                  //fprintf(stderr,"---> copy %d\n",g_lineNr);
+                  yyextra->lineNr++; break;
+       case '\t': yyextra->col+=tabSize-(yyextra->col%tabSize); break;
+       default:   yyextra->col++; break;
+      }
+    }
+  }
+}
+
+static void clearCommentStack(yyscan_t yyscanner)
 {
-  int column=0;
-  bool skipLine=FALSE;
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  while (!yyextra->commentStack.empty()) yyextra->commentStack.pop();
+}
 
-  for(int i=0;;i++) {
-    column++;
+static void startCondSection(yyscan_t yyscanner,const QCString &sectId)
+{
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
+  CondParser prs;
+  bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
+  yyextra->condStack.push(commentcnvYY_CondCtx(yyextra->lineNr,sectId,yyextra->skip));
+  if (!expResult) // not enabled
+  {
+    yyextra->skip=TRUE;
+  }
+}
 
-    switch(contents[i]) {
-      case '\n':
-        column=0;
-        skipLine=FALSE;
-        break;
-      case ' ':
-        break;
-      case '\000':
-        return FALSE;
-      case 'C':
-      case 'c':
-      case '*':
-        if(column==1) return TRUE;
-        if(skipLine) break;
-        return FALSE;
-      case '!':
-        if(column>1 && column<7) return FALSE;
-        skipLine=TRUE;
-        break;
-      default:
-        if(skipLine) break;
-        if(column==7) return TRUE;
-        return FALSE;
+static void endCondSection(yyscan_t yyscanner)
+{
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  if (yyextra->condStack.empty())
+  {
+    warn(yyextra->fileName,yyextra->lineNr,"Found \\endcond command without matching \\cond");
+    yyextra->skip=FALSE;
+  }
+  else
+  {
+    const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
+    yyextra->skip=ctx.skip;
+    yyextra->condStack.pop();
+  }
+  //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
+}
+
+static void handleCondSectionId(yyscan_t yyscanner,const char *expression)
+{
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  bool oldSkip=yyextra->skip;
+  startCondSection(yyscanner,QCString(expression));
+  if ((yyextra->condCtx==CComment || yyextra->readLineCtx==SComment) &&
+      !oldSkip && yyextra->skip)
+  {
+    if (yyextra->lang!=SrcLangExt_Python &&
+        yyextra->lang!=SrcLangExt_VHDL &&
+        yyextra->lang!=SrcLangExt_Markdown &&
+        yyextra->lang!=SrcLangExt_Fortran)
+    {
+      ADDCHAR('*');
+      ADDCHAR('/');
     }
   }
-  return FALSE;
+  if (yyextra->readLineCtx==SComment)
+  {
+    BEGIN(SComment);
+  }
+  else
+  {
+    BEGIN(yyextra->condCtx);
+  }
+}
+
+/** copies string \a s with length \a len to the output, while
+ *  replacing any alias commands found in the string.
+ */
+static void replaceAliases(yyscan_t yyscanner,const QCString &s)
+{
+  QCString result = resolveAliasCmd(s);
+  //printf("replaceAliases(%s)->'%s'\n",qPrint(s),qPrint(result));
+  copyToOutput(yyscanner,result.data(),result.length());
 }
 
 
+static int yyread(yyscan_t yyscanner,char *buf,int max_size)
+{
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  int bytesInBuf = static_cast<int>(yyextra->inBuf.curPos())-yyextra->inBufPos;
+  int bytesToCopy = std::min(max_size,bytesInBuf);
+  memcpy(buf,yyextra->inBuf.data()+yyextra->inBufPos,bytesToCopy);
+  yyextra->inBufPos+=bytesToCopy;
+  return bytesToCopy;
+}
+
+static void replaceComment(yyscan_t yyscanner,int offset)
+{
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  if (yyextra->mlBrief || yyextra->skip)
+  {
+    copyToOutput(yyscanner,yytext,(int)yyleng);
+  }
+  else
+  {
+    //printf("replaceComment(%s)\n",yytext);
+    int i=computeIndent(&yytext[offset]);
+    if (i==yyextra->blockHeadCol)
+    {
+      replaceCommentMarker(yyscanner,yytext,(int)yyleng);
+    }
+    else
+    {
+      copyToOutput(yyscanner," */",3);
+      for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
+      yyextra->inSpecialComment=FALSE;
+      BEGIN(Scan);
+    }
+  }
+}
+
 /*! This function does three things:
  *  -# 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).
  *  -# It replaces aliases with their definition (see ALIASES)
  *  -# It handles conditional sections (cond...endcond blocks)
  */
-void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
+void convertCppComments(const BufStr &inBuf,BufStr &outBuf,const QCString &fileName)
 {
+  yyscan_t yyscanner;
+  commentcnvYY_state extra(inBuf,outBuf);
+  commentcnvYYlex_init_extra(&extra,&yyscanner);
+#ifdef FLEX_DEBUG
+  commentcnvYYset_debug(Debug::isFlagSet(Debug::Lex_commentcnv)?1:0,yyscanner);
+#endif
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   //printf("convertCppComments(%s)\n",fileName);
-  g_inBuf    = inBuf;
-  g_outBuf   = outBuf;
-  g_inBufPos = 0;
-  g_col      = 0;
-  g_mlBrief = Config_getBool("MULTILINE_CPP_IS_BRIEF");
-  g_skip     = FALSE;
-  g_fileName = fileName;
-  g_lang = getLanguageFromFileName(fileName);
-  g_pythonDocString = FALSE;
-  g_lineNr   = 1;
-  g_condStack.clear();
-  g_condStack.setAutoDelete(TRUE);
-  g_commentStack.clear();
-  g_commentStack.setAutoDelete(TRUE);
+  yyextra->inBufPos = 0;
+  yyextra->col      = 0;
+  yyextra->mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
+  yyextra->skip     = FALSE;
+  yyextra->fileName = fileName;
+  yyextra->lang = getLanguageFromFileName(fileName);
+  yyextra->pythonDocString = FALSE;
+  yyextra->lineNr   = 1;
+  while (!yyextra->condStack.empty()) yyextra->condStack.pop();
+  clearCommentStack(yyscanner);
+  yyextra->vhdl = FALSE;
 
-  printlex(yy_flex_debug, TRUE, __FILE__, fileName);
-  isFixedForm = FALSE;
-  if (g_lang==SrcLangExt_Fortran)
+  DebugLex debugLex(Debug::Lex_commentcnv,__FILE__, qPrint(fileName));
+  yyextra->isFixedForm = FALSE;
+  if (yyextra->lang==SrcLangExt_Fortran)
   {
-    isFixedForm = recognizeFixedForm(inBuf->data());
+    FortranFormat fmt = convertFileNameFortranParserCode(fileName);
+    yyextra->isFixedForm = recognizeFixedForm(QCString(inBuf.data()),fmt);
   }
 
-  if (g_lang==SrcLangExt_Markdown)
+  if (yyextra->lang==SrcLangExt_Markdown)
   {
-    g_nestingCount=0;
+    yyextra->nestingCount=0;
     BEGIN(CComment);
-    g_commentStack.push(new CommentCtx(g_lineNr));
+    yyextra->commentStack.push(yyextra->lineNr);
   }
   else
   {
     BEGIN(Scan);
   }
-  yylex();
-  while (!g_condStack.isEmpty())
+  yylex(yyscanner);
+  while (!yyextra->condStack.empty())
   {
-    CondCtx *ctx = g_condStack.pop();
-    QCString sectionInfo = " ";
-    if (ctx->sectionId!=" ") sectionInfo.sprintf(" with label %s ",ctx->sectionId.data()); 
-    warn(g_fileName,ctx->lineNr,"Conditional section%sdoes not have "
+    const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
+    QCString sectionInfo(" ");
+    if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data());
+    warn(yyextra->fileName,ctx.lineNr,"Conditional section%sdoes not have "
        "a corresponding \\endcond command within this file.",sectionInfo.data());
+    yyextra->condStack.pop();
   }
-  if (g_nestingCount>0 || (YY_START==CComment && g_lang!=SrcLangExt_Markdown))
+  if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt_Markdown && yyextra->lang!=SrcLangExt_Fortran)
   {
-    QCString tmp= "(probable line reference: ";
+    QCString tmp("(probable line reference: ");
     bool first = TRUE;
-    while (!g_commentStack.isEmpty())
+    while (!yyextra->commentStack.empty())
     {
-      CommentCtx *ctx = g_commentStack.pop();
+      int lineNr = yyextra->commentStack.top();
       if (!first) tmp += ", ";
-      tmp += QCString().setNum(ctx->lineNr);
+      tmp += QCString().setNum(lineNr);
       first = FALSE;
-      delete ctx;
+      yyextra->commentStack.pop();
     }
     tmp += ")";
-    warn(g_fileName,g_lineNr,"Reached end of file while still inside a (nested) comment. "
-        "Nesting level %d %s",g_nestingCount+1,tmp.data()); // add one for "normal" expected end of comment
+    warn(yyextra->fileName,yyextra->lineNr,"Reached end of file while still inside a (nested) comment. "
+        "Nesting level %d %s",yyextra->nestingCount,tmp.data());
   }
-  g_commentStack.clear();
+  yyextra->nestingCount = 0;
   if (Debug::isFlagSet(Debug::CommentCnv))
   {
-    g_outBuf->at(g_outBuf->curPos())='\0';
-    msg("-------------\n%s\n-------------\n",g_outBuf->data());
+    yyextra->outBuf.at(yyextra->outBuf.curPos())='\0';
+    Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: %s\n"
+                 "output=[\n%s]\n-----------\n",qPrint(fileName),yyextra->outBuf.data()
+                );
   }
-  printlex(yy_flex_debug, FALSE, __FILE__, fileName);
+  commentcnvYYlex_destroy(yyscanner);
 }
 
 
 //----------------------------------------------------------------------------
-#if !defined(YY_FLEX_SUBMINOR_VERSION) 
-extern "C" { // some bogus code to keep the compiler happy
-    void commentcnvYYdummy() { yy_flex_realloc(0,0); } 
-}
-#endif
 
+#if USE_STATE2STRING
+#include "commentcnv.l.h"
+#endif