Ticket #28426: doxygen+tcl.patch

File doxygen+tcl.patch, 78.7 KB (added by l2g@…, 13 years ago)

Modified version of Rene Zaumseil's patch for Doxygen Tcl support

  • src/config.l

    void Config::check() 
    13051305    filePatternList.append("*.f");
    13061306    filePatternList.append("*.vhd");
    13071307    filePatternList.append("*.vhdl");
     1308    filePatternList.append("*.tcl");
    13081309    if (portable_fileSystemIsCaseSensitive())
    13091310    {
    13101311      // unix => case sensitive match => also include useful uppercase versions
    void Config::check() 
    13261327      filePatternList.append("*.F");
    13271328      filePatternList.append("*.VHD");
    13281329      filePatternList.append("*.VHDL");
     1330      filePatternList.append("*.TCL");
    13291331    }
    13301332  }
    13311333
  • src/configoptions.cpp

    void addConfigOptions(Config *cfg) 
    22812281                );
    22822282  cb->addDependency("HAVE_DOT");
    22832283  //----
     2284  cl = cfg->addList(
     2285                 "TCL_SUBST",
     2286                 "The TCL_SUBST tag contain a list of word-keyword pairs.\n"
     2287                 "When parsing tcl code each command name found as word in the list\n"
     2288                 "is substituted with the given keyword."
     2289                );
     2290  cl->addValue("");
     2291  //----
    22842292  cfg->addObsolete("USE_WINDOWS_ENCODING");
    22852293  //----
    22862294  cfg->addObsolete("DETAILS_AT_TOP");
  • src/definition.cpp

    static bool readCodeFragment(const char 
    563563    int c=0;
    564564    int col=0;
    565565    int lineNr=1;
     566    // for Tcl no preprocessing
     567    int length=strlen(fileName);
     568    if (length > 4 && strncmp(&fileName[length-4],".tcl",4)==0) {
     569      char myBuffer[1024];
     570
     571      if (endLine < startLine) return FALSE;
     572      result="";
     573      while (fgets(myBuffer,1023,f) != NULL) {
     574        if (lineNr >= startLine) {
     575          result += myBuffer;
     576        }
     577        if (++lineNr > endLine) {
     578          portable_fseek(f,0,SEEK_END);
     579          break;
     580        }
     581      }
     582      found = !result.isEmpty();
     583    }
    566584    // skip until the startLine has reached
    567585    while (lineNr<startLine && !feof(f))
    568586    {
  • src/docsets.cpp

    void DocSets::addIndexItem(Definition *c 
    279279    case SrcLangExt_F90:     lang="fortran"; break;    // Fortran
    280280    case SrcLangExt_VHDL:    lang="vhdl"; break;       // VHDL
    281281    case SrcLangExt_XML:     lang="xml"; break;        // DBUS XML
     282    case SrcLangExt_Tcl:     lang="tcl"; break;        // Tcl
    282283    case SrcLangExt_Unknown: lang="unknown"; break;   // should not happen!
    283284  }
    284285
  • src/doxygen.cpp

     
    7070#include "pyscanner.h"
    7171#include "fortranscanner.h"
    7272#include "dbusxmlscanner.h"
     73#include "tclscanner.h"
    7374#include "code.h"
    7475#include "objcache.h"
    7576#include "store.h"
    void initDoxygen() 
    91349135  Doxygen::parserManager->registerParser("fortran", new FortranLanguageScanner);
    91359136  Doxygen::parserManager->registerParser("vhdl",    new VHDLLanguageScanner);
    91369137  Doxygen::parserManager->registerParser("dbusxml", new DBusXMLScanner);
     9138  Doxygen::parserManager->registerParser("tcl",     new TclLanguageScanner);
    91379139
    91389140  // register any additional parsers here...
    91399141
  • src/libdoxygen.pro.in

    HEADERS = bufstr.h \ 
    151151                vhdldocgen.h \
    152152                vhdlscanner.h \
    153153                xmldocvisitor.h \
    154                 xmlgen.h
     154                xmlgen.h \
     155                tclscanner.h
    155156
    156157SOURCES      =  ce_lex.cpp \
    157158                ce_parse.cpp \
    SOURCES = ce_lex.cpp \ 
    237238                xmldocvisitor.cpp \
    238239                xmlgen.cpp \
    239240                dbusxmlscanner.cpp \
     241                tclscanner.cpp \
    240242
    241243win32:TMAKE_CXXFLAGS       += -DQT_NODLL
    242244win32-msvc:TMAKE_CXXFLAGS  += -Zm200
  • src/libdoxygen.t

    sub GenerateDep { 
    6969#$ GenerateDep("vhdlcode.cpp","vhdlcode.l");
    7070        $(LEX) -i -PvhdlcodeYY -t vhdlcode.l | $(INCBUFSIZE) >vhdlcode.cpp
    7171
     72#$ GenerateDep("tclscanner.cpp","tclscanner.l");
     73        $(LEX) -i -PtclscanYY -t tclscanner.l | $(INCBUFSIZE) >tclscanner.cpp
     74
    7275#$ GenerateDep("pre.cpp","pre.l");
    7376        $(LEX) -PpreYY -t pre.l | $(INCBUFSIZE) >pre.cpp
    7477
  • src/memberdef.cpp

    static bool writeDefArgumentList(OutputL 
    105105    // html and latex
    106106    if (htmlOn)  ol.enable(OutputGenerator::Html);
    107107    if (latexOn) ol.enable(OutputGenerator::Latex);
     108    // simple argument list for tcl
     109    if (md->getFileDef() && getLanguageFromFileName((md->getFileDef())->name())==SrcLangExt_Tcl)
     110    {
     111      Argument *a=defArgList->first();
     112      ol.startParameterName(FALSE);
     113      while (a) {
     114        if (a->defval.isEmpty())
     115        {
     116          ol.docify(a->name+" ");
     117        }
     118        else
     119        {
     120          ol.docify("?"+a->name+"? ");
     121        }
     122        a=defArgList->next();
     123      }
     124      ol.endParameterName(FALSE,FALSE,FALSE);
     125      ol.endMemberDocName();
     126      ol.disable(OutputGenerator::Html);
     127      ol.disable(OutputGenerator::Latex);
     128      ol.popGeneratorState();
     129      return TRUE;
     130    }
    108131    ol.endMemberDocName();
    109132    ol.startParameterList(!md->isObjCMethod());
    110133  }
    void MemberDef::_computeIsConstructor() 
    28072830      m_isConstructorCached = name()=="__construct" ? 2 : 1;
    28082831      return;
    28092832    }
     2833    else if (m_impl->fileDef &&
     2834             getLanguageFromFileName(m_impl->fileDef->name())==SrcLangExt_Tcl)
     2835    {                // for Tcl
     2836      m_isConstructorCached = name()=="constructor" ? 2 : 1;
     2837      return;
     2838    }
    28102839    else if (name()=="__init__" && m_impl->fileDef &&
    28112840             getLanguageFromFileName(m_impl->fileDef->name())==SrcLangExt_Python)
    28122841               // for Python
    void MemberDef::_computeIsDestructor() 
    28562885  {                // for PHP
    28572886    isDestructor = name()=="__destruct";
    28582887  }
     2888  else if (m_impl->fileDef &&
     2889      getLanguageFromFileName(m_impl->fileDef->name())==SrcLangExt_Tcl)
     2890  {                // for Tcl
     2891    isDestructor = name()=="destructor";
     2892  }
    28592893  else if (name()=="__del__" && m_impl->fileDef &&
    28602894           getLanguageFromFileName(m_impl->fileDef->name())==SrcLangExt_Python)
    28612895               // for Python
  • src/Makefile.in

    distclean: clean 
    4949               ce_parse.cpp ce_parse.h doxytag.cpp tag.cpp commentscan.cpp \
    5050               declinfo.cpp defargs.cpp commentcnv.cpp doctokenizer.cpp \
    5151               pycode.cpp pyscanner.cpp fortrancode.cpp fortranscanner.cpp \
    52                vhdlscanner.cpp vhdlcode.cpp
     52               vhdlscanner.cpp vhdlcode.cpp tclscanner.cpp
    5353
    5454FORCE:
  • src/util.cpp

    g_lang2extMap[] = 
    64306430  { "fortran",     "fortran", SrcLangExt_F90    },
    64316431  { "vhdl",        "vhdl",    SrcLangExt_VHDL   },
    64326432  { "dbusxml",     "dbusxml", SrcLangExt_XML    },
     6433  { "tcl",         "tcl",     SrcLangExt_Tcl    },
    64336434  { 0,             0,        (SrcLangExt)0      }
    64346435};
    64356436
    void initDefaultExtensionMapping() 
    64936494  updateLanguageMapping(".f90",   "fortran");
    64946495  updateLanguageMapping(".vhd",   "vhdl");
    64956496  updateLanguageMapping(".vhdl",  "vhdl");
     6497  updateLanguageMapping(".tcl",   "tcl");
    64966498  //updateLanguageMapping(".xml",   "dbusxml");
    64976499}
    64986500
  • src/util.h

    enum SrcLangExt 
    101101  SrcLangExt_Python  = 0x0800,
    102102  SrcLangExt_F90     = 0x1000,
    103103  SrcLangExt_VHDL    = 0x2000,
    104   SrcLangExt_XML     = 0x4000
     104  SrcLangExt_XML     = 0x4000,
     105  SrcLangExt_Tcl     = 0x8000
    105106};
    106107
    107108//--------------------------------------------------------------------
  • src/tclscanner.h

     
     1/******************************************************************************
     2 *
     3 *
     4 *
     5 * Copyright (C) 1997-2010 by Dimitri van Heesch.
     6 * Copyright (C) 2010      by Rene Zaumseil
     7 *
     8 * Permission to use, copy, modify, and distribute this software and its
     9 * documentation under the terms of the GNU General Public License is hereby
     10 * granted. No representations are made about the suitability of this software
     11 * for any purpose. It is provided "as is" without express or implied warranty.
     12 * See the GNU General Public License for more details.
     13 *
     14 * Documents produced by Doxygen are derivative works derived from the
     15 * input used in their production; they are not affected by this license.
     16 *
     17 */
     18
     19#ifndef SCANNER_TCL_H
     20#define SCANNER_TCL_H
     21
     22#include "parserintf.h"
     23
     24/** \brief Tcl language parser using state-based lexical scanning.
     25 *
     26 *  This is the Tcl language parser for doxygen.
     27 */
     28class TclLanguageScanner : public ParserInterface
     29{
     30  public:
     31    virtual ~TclLanguageScanner() {}
     32    void parseInput(const char *fileName,
     33                    const char *fileBuf,
     34                    Entry *root);
     35    bool needsPreprocessing(const QCString &extension);
     36    void parseCode(CodeOutputInterface &codeOutIntf,
     37                   const char *scopeName,
     38                   const QCString &input,
     39                   bool isExampleBlock,
     40                   const char *exampleName=0,
     41                   FileDef *fileDef=0,
     42                   int startLine=-1,
     43                   int endLine=-1,
     44                   bool inlineFragment=FALSE,
     45                   MemberDef *memberDef=0,
     46                   bool showLineNumbers=TRUE
     47                  );
     48    void resetCodeParserState();
     49    void parsePrototype(const char *text);
     50};
     51
     52#endif
  • src/tclscanner.l

     
     1/*****************************************************************************
     2 * Parser for Tcl subset
     3 *
     4 * Copyright (C) 2010      by Rene Zaumseil
     5 * based on the work of Dimitri van Heesch.
     6 *
     7 * Permission to use, copy, modify, and distribute this software and its
     8 * documentation under the terms of the GNU General Public License is hereby
     9 * granted. No representations are made about the suitability of this software
     10 * for any purpose. It is provided "as is" without express or implied warranty.
     11 * See the GNU General Public License for more details.
     12 *
     13 * Documents produced by Doxygen are derivative works derived from the
     14 * input used in their production; they are not affected by this license.
     15 *
     16 */
     17%{
     18#include <stdio.h>
     19#include <stdlib.h>
     20#include <assert.h>
     21#include <ctype.h>
     22#include <stdint.h>
     23
     24#include "qtbc.h"
     25#include <qarray.h>
     26#include <qstack.h>
     27#include <qregexp.h>
     28#include <unistd.h>
     29#include <qfile.h>
     30#include <qdict.h>
     31 
     32#include "entry.h"
     33#include "message.h"
     34#include "config.h"
     35#include "doxygen.h"
     36#include "util.h"
     37#include "defargs.h"
     38#include "language.h"
     39#include "commentscan.h"
     40#include "pre.h"
     41#include "tclscanner.h"
     42#include "outputlist.h"
     43#include "membername.h"
     44#include "searchindex.h"
     45#include "commentcnv.h"
     46#include "bufstr.h"
     47#include "portable.h"
     48
     49#include <stdarg.h>
     50#include <qstring.h>
     51#include <qstringlist.h>
     52#include <qlist.h>
     53#include <qmap.h>
     54
     55#define YY_NEVER_INTERACTIVE 1
     56
     57#define MAX_INCLUDE_DEPTH 10
     58
     59#define tcl_abort \
     60        fprintf(stderr,"%s#%d %s()",__FILE__,__LINE__,__FUNCTION__); \
     61        yy_push_state(ERROR); \
     62        yyless(0); \
     63        tcl_Abort
     64//#define TCL_DEBUG_FD NULL
     65#define TCL_WARN_FD stdout
     66#define tcl_warn \
     67        tcl_Warn("%.6d--(%s) %d# ",__LINE__,__FUNCTION__,yylineno); \
     68        tcl_Warn
     69#define TCL_DEBUG_FD NULL
     70//#define TCL_DEBUG_FD stdout
     71#define tcl_debug \
     72        tcl_Debug("%.6d--(%s) %d#%d ",__LINE__,__FUNCTION__,yylineno,yy_start_stack_ptr); \
     73        tcl_Debug
     74
     75//#define D printf("%.6d---(%s)%s\n",__LINE__,__FUNCTION__,yytext);
     76#define D
     77
     78// BEGIN of copy from tclUtil.c
     79// - Tcl_Interp removed
     80// - changes are marked with RZ
     81// #define's to adapt the code:
     82#define CONST           const
     83#define UCHAR           (unsigned char)
     84#define TCL_ERROR       1
     85#define TCL_OK          0
     86#define ckalloc         malloc
     87#define ckfree          free
     88#define TclCopyAndCollapse(size,src,dest) memcpy(dest,src,size); *(dest+size)=0
     89int
     90TclFindElement(
     91    CONST char *list,           /* Points to the first byte of a string
     92                                 * containing a Tcl list with zero or more
     93                                 * elements (possibly in braces). */
     94    int listLength,             /* Number of bytes in the list's string. */
     95    CONST char **elementPtr,    /* Where to put address of first significant
     96                                 * character in first element of list. */
     97    CONST char **nextPtr,       /* Fill in with location of character just
     98                                 * after all white space following end of
     99                                 * argument (next arg or end of list). */
     100    int *sizePtr,               /* If non-zero, fill in with size of
     101                                 * element. */
     102    int *bracePtr)              /* If non-zero, fill in with non-zero/zero to
     103                                 * indicate that arg was/wasn't in braces. */
     104{
     105    CONST char *p = list;
     106    CONST char *elemStart;      /* Points to first byte of first element. */
     107    CONST char *limit;          /* Points just after list's last byte. */
     108    int openBraces = 0;         /* Brace nesting level during parse. */
     109    int inQuotes = 0;
     110    int size = 0;               /* lint. */
     111//RZ    int numChars;
     112
     113    /*
     114     * Skim off leading white space and check for an opening brace or quote.
     115     * We treat embedded NULLs in the list as bytes belonging to a list
     116     * element.
     117     */
     118
     119    limit = (list + listLength);
     120    while ((p < limit) && (isspace(UCHAR(*p)))) { /* INTL: ISO space. */
     121        p++;
     122    }
     123    if (p == limit) {           /* no element found */
     124        elemStart = limit;
     125        goto done;
     126    }
     127
     128    if (*p == '{') {
     129        openBraces = 1;
     130        p++;
     131    } else if (*p == '"') {
     132        inQuotes = 1;
     133        p++;
     134    }
     135    elemStart = p;
     136    if (bracePtr != 0) {
     137        *bracePtr = openBraces;
     138    }
     139
     140    /*
     141     * Find element's end (a space, close brace, or the end of the string).
     142     */
     143
     144    while (p < limit) {
     145        switch (*p) {
     146            /*
     147             * Open brace: don't treat specially unless the element is in
     148             * braces. In this case, keep a nesting count.
     149             */
     150
     151        case '{':
     152            if (openBraces != 0) {
     153                openBraces++;
     154            }
     155            break;
     156
     157            /*
     158             * Close brace: if element is in braces, keep nesting count and
     159             * quit when the last close brace is seen.
     160             */
     161
     162        case '}':
     163            if (openBraces > 1) {
     164                openBraces--;
     165            } else if (openBraces == 1) {
     166                size = (p - elemStart);
     167                p++;
     168                if ((p >= limit)
     169                        || isspace(UCHAR(*p))) {        /* INTL: ISO space. */
     170                    goto done;
     171                }
     172
     173                /*
     174                 * Garbage after the closing brace; return an error.
     175                 */
     176
     177                return TCL_ERROR;
     178            }
     179            break;
     180
     181            /*
     182             * Backslash: skip over everything up to the end of the backslash
     183             * sequence.
     184             */
     185
     186        case '\\':
     187//RZ        Tcl_UtfBackslash(p, &numChars, NULL);
     188//RZ        p += (numChars - 1);
     189            p++; //RZ
     190            break;
     191
     192            /*
     193             * Space: ignore if element is in braces or quotes; otherwise
     194             * terminate element.
     195             */
     196
     197        case ' ':
     198        case '\f':
     199        case '\n':
     200        case '\r':
     201        case '\t':
     202        case '\v':
     203            if ((openBraces == 0) && !inQuotes) {
     204                size = (p - elemStart);
     205                goto done;
     206            }
     207            break;
     208
     209            /*
     210             * Double-quote: if element is in quotes then terminate it.
     211             */
     212
     213        case '"':
     214            if (inQuotes) {
     215                size = (p - elemStart);
     216                p++;
     217                if ((p >= limit)
     218                        || isspace(UCHAR(*p))) {        /* INTL: ISO space */
     219                    goto done;
     220                }
     221
     222                /*
     223                 * Garbage after the closing quote; return an error.
     224                 */
     225
     226                return TCL_ERROR;
     227            }
     228            break;
     229        }
     230        p++;
     231    }
     232
     233    /*
     234     * End of list: terminate element.
     235     */
     236
     237    if (p == limit) {
     238        if (openBraces != 0) {
     239            return TCL_ERROR;
     240        } else if (inQuotes) {
     241            return TCL_ERROR;
     242        }
     243        size = (p - elemStart);
     244    }
     245
     246  done:
     247    while ((p < limit) && (isspace(UCHAR(*p)))) { /* INTL: ISO space. */
     248        p++;
     249    }
     250    *elementPtr = elemStart;
     251    *nextPtr = p;
     252    if (sizePtr != 0) {
     253        *sizePtr = size;
     254    }
     255    return TCL_OK;
     256}
     257int
     258Tcl_SplitList(
     259    CONST char *list,           /* Pointer to string with list structure. */
     260    int *argcPtr,               /* Pointer to location to fill in with the
     261                                 * number of elements in the list. */
     262    CONST char ***argvPtr)      /* Pointer to place to store pointer to array
     263                                 * of pointers to list elements. */
     264{
     265    CONST char **argv, *l, *element;
     266    char *p;
     267    int length, size, i, result, elSize, brace;
     268
     269    /*
     270     * Figure out how much space to allocate. There must be enough space for
     271     * both the array of pointers and also for a copy of the list. To estimate
     272     * the number of pointers needed, count the number of space characters in
     273     * the list.
     274     */
     275
     276    for (size = 2, l = list; *l != 0; l++) {
     277        if (isspace(UCHAR(*l))) {                       /* INTL: ISO space. */
     278            size++;
     279
     280            /*
     281             * Consecutive space can only count as a single list delimiter.
     282             */
     283
     284            while (1) {
     285                char next = *(l + 1);
     286
     287                if (next == '\0') {
     288                    break;
     289                }
     290                ++l;
     291                if (isspace(UCHAR(next))) {             /* INTL: ISO space. */
     292                    continue;
     293                }
     294                break;
     295            }
     296        }
     297    }
     298    length = l - list;
     299    argv = (CONST char **) ckalloc((unsigned)
     300            ((size * sizeof(char *)) + length + 1));
     301    for (i = 0, p = ((char *) argv) + size*sizeof(char *);
     302            *list != 0;  i++) {
     303        CONST char *prevList = list;
     304
     305        result = TclFindElement(list, length, &element, &list,
     306                &elSize, &brace);
     307        length -= (list - prevList);
     308        if (result != TCL_OK) {
     309            ckfree((char *) argv);
     310            return result;
     311        }
     312        if (*element == 0) {
     313            break;
     314        }
     315        if (i >= size) {
     316            ckfree((char *) argv);
     317            return TCL_ERROR;
     318        }
     319        argv[i] = p;
     320        if (brace) {
     321            memcpy(p, element, (size_t) elSize);
     322            p += elSize;
     323            *p = 0;
     324            p++;
     325        } else {
     326            TclCopyAndCollapse(elSize, element, p);
     327            p += elSize+1;
     328        }
     329    }
     330
     331    argv[i] = NULL;
     332    *argvPtr = argv;
     333    *argcPtr = i;
     334    return TCL_OK;
     335}
     336// END of tclUtil.c
     337
     338void tcl_split_list(QString &str, QStringList &list)
     339{
     340  int argc;
     341  const char **argv;
     342
     343  list.clear();
     344  if (str.left(1)=="{" && str.right(1)=="}")
     345  {
     346    str=str.mid(1,str.length()-2);
     347  }
     348  else if (str.left(1)=="\"" && str.right(1)=="\"")
     349  {
     350    str=str.mid(1,str.length()-2);
     351  }
     352  if (Tcl_SplitList(str.ascii(),&argc,&argv) != TCL_OK)
     353  {
     354    list.append(str);
     355  }
     356  else
     357  {
     358    for (int i = 0; i < argc; i++)
     359    {
     360      list.append(argv[i]);
     361    }
     362    ckfree((char *) argv);
     363  }
     364}
     365
     366//! Structure containing information about current scan context.
     367typedef struct
     368{
     369  int type;
     370  QCString string_after;
     371  int line0; // start line of scan context
     372  int line1; // end line of scan context
     373  int start_stack_ptr; // value of scan context
     374  YY_BUFFER_STATE buffer_state; // value of scan context
     375  Entry *entry_ns; // current namespace
     376  Entry *entry_fn; // if set contains the current proc/method/constructor/destructor
     377  Entry *entry_cl; // if set contain the current class
     378  Entry *entry_scan; // current scan entry
     379  Protection protection; // current protections state
     380} tcl_scan;
     381
     382//* Structure containing all internal global variables.
     383static struct
     384{
     385  CodeOutputInterface * code; // if set then we are codifying the file
     386  int code_line; // current line of code
     387  int code_linenumbers; // if true create line numbers in code
     388  const char *code_font; // used font to codify
     389  bool config_autobrief; // value of configuration option
     390  QMap<QString,QString> config_subst; // map of configuration option values
     391  const char *   input_string; // file contents
     392  int           input_position; // position in file
     393  QCString      file_name; // name of used file
     394  ParserInterface *this_parser; // myself
     395  int command; // true if command was found
     396  int comment; // set true if comment was scaned
     397  int brace_level; // bookkeeping of braces
     398  int bracket_level; // bookkeeping of brackets
     399  int bracket_quote; // bookkeeping of quotes (toggles)
     400  int word_is; // type of current word
     401  int line_comment; // line number of comment
     402  int line_commentline; // line number of comment after command
     403  int line_command; // line number of command
     404  int line_body0; // start line of body
     405  int line_body1; // end line of body
     406  QString string_command; // contain current command
     407  QString string_commentline; // contain current comment after command
     408  QString string_commentcodify; // current comment string used in codifying
     409  QString string_comment; // contain current comment
     410  QString string_last; // contain last read word or part of word
     411  QString string; // temporary string value
     412  Entry*                entry_main; // top level entry
     413  Entry*                entry_file; // entry of current file
     414  Entry*                entry_current; // currently used entry
     415  Entry*                entry_inside; // contain entry of current scan context
     416  QStringList list_command; // list of command words
     417  QList<tcl_scan> scan; // stack of scan contexts
     418  QDict<Entry> ns; // all read namespace entries
     419  QDict<Entry> cl; // all read class entries
     420  QDict<Entry> fn; // all read function entries
     421  QList<Entry> entry; // list of all created entries, will be deleted after codifying
     422  Protection protection; // current protections state
     423} tcl;
     424
     425// scanner functions
     426static int yyread(char *buf,int max_size);
     427tcl_scan *tcl_scan_start(int type, QString content);
     428static void tcl_scan_end();
     429static void tcl_comment(int what,const char *text);
     430static void tcl_word(int what,const char *text);
     431static void tcl_command(int what,const char *text);
     432
     433// helper functions
     434
     435//! Create new entry.
     436// @return new initialised entry
     437Entry* tcl_entry_new()
     438{
     439  Entry *myEntry = new Entry;
     440  myEntry->section    = Entry::EMPTY_SEC;
     441  myEntry->name       = "";
     442//  myEntry->type       = "";
     443  myEntry->brief      = "";
     444//  myEntry->doc        = "";
     445  myEntry->protection = Package;
     446//  myEntry->mtype      = Method;
     447//  myEntry->virt       = Normal;
     448//  myEntry->stat       = FALSE;
     449  myEntry->fileName   = tcl.file_name;
     450  myEntry->lang       = SrcLangExt_Tcl;
     451  initGroupInfo(myEntry);
     452  // collect entries
     453  if (tcl.code==NULL)
     454  {
     455    tcl.entry.insert(0,myEntry);
     456  }
     457  return myEntry;
     458}
     459
     460//! Set protection level.
     461void tcl_protection(Entry *entry) {
     462  if (entry->protection!=Public&&entry->protection!=Protected&&entry->protection!=Private)
     463  {
     464    entry->protection = tcl.protection;
     465  }
     466  if (entry->protection!=Protected&&entry->protection!=Private)
     467  {
     468    entry->protection = Public;
     469  }
     470}
     471
     472//! Check name.
     473// @return 'ns' and 'name' of given current 'ns0' and 'name0'
     474static void tcl_name(const QString ns0, const QString name0, QString &ns, QString &name)
     475{
     476  QString myNm;
     477  int myStart;
     478
     479  if (strncmp(name0.ascii(),"::",2)==0)
     480  {
     481    myNm = name0.mid(2);
     482  }
     483  else if (ns0.length())
     484  {
     485    myNm = ns0 + "::" + name0;
     486  }
     487  else
     488  {
     489    myNm = name0;
     490  }
     491  myStart = myNm.findRev("::");
     492  if (myStart == -1)
     493  {
     494    ns = "";
     495    name = myNm;
     496  }
     497  else
     498  {
     499    ns = myNm.mid(0,myStart);
     500    name = myNm.mid(myStart+2);
     501  }
     502}
     503
     504// Check and return namespace entry.
     505// @return namespace entry
     506Entry* tcl_entry_namespace(const QString ns)
     507{
     508  Entry *myEntry;
     509  QString myNs = " ";
     510  if (strlen(ns.ascii())) {myNs = ns;}
     511
     512  myEntry = tcl.ns.find(myNs);
     513  if (myEntry == NULL)
     514  {
     515    myEntry = tcl_entry_new();
     516    myEntry->section    = Entry::NAMESPACE_SEC;
     517    myEntry->name       = ns.ascii();
     518    tcl.entry_main->addSubEntry(myEntry);
     519    tcl.ns.insert(ns,myEntry);
     520  }
     521  return myEntry;
     522}
     523
     524// Check and return class entry.
     525// @return class entry
     526Entry* tcl_entry_class(const QString cl)
     527{
     528  Entry *myEntry;
     529  QString myCl = " ";
     530  if (strlen(cl.ascii())) {myCl = cl;}
     531
     532  myEntry = tcl.cl.find(myCl);
     533  if (myEntry == NULL)
     534  {
     535    myEntry = tcl_entry_new();
     536    myEntry->section    = Entry::CLASS_SEC;
     537    myEntry->name       = cl.ascii();
     538    tcl.entry_main->addSubEntry(myEntry);
     539    tcl.cl.insert(cl,myEntry);
     540  }
     541  return myEntry;
     542}
     543
     544//! Check for keywords.
     545// @return 1 if keyword and 0 otherwise
     546static int tcl_keyword(QString str)
     547{
     548  static QStringList myList;
     549  static int myInit=1;
     550  if (myInit)
     551  {
     552// tcl keywords
     553    myList <<"append"<<"apply"<<"array"<<"auto_execok"<<"auto_import"<<"auto_load"<<"auto_mkindex"<<"auto_qualify"<<"auto_reset"<<"catch"<<"cd"<<"close"<<"concat"<<"eof"<<"exec"<<"exit"<<"fblocked"<<"fconfigure"<<"file"<<"flush"<<"foreach"<<"format"<<"gets"<<"global"<<"http"<<"if"<<"incr"<<"info"<<"join"<<"lappend"<<"lassign"<<"lindex"<<"linsert"<<"llength"<<"load"<<"lrange"<<"lrepeat"<<"lreplace"<<"lreverse"<<"lset"<<"namespace"<<"parray"<<"pid"<<"pkg_mkIndex"<<"proc"<<"puts"<<"pwd"<<"registry"<<"rename"<<"return"<<"scan"<<"set"<<"split"<<"tclLog"<<"tcl_endOfWord"<<"tcl_findLibrary"<<"tcl_startOfNextWord"<<"tcl_startOfPreviousWord"<<"tcl_wordBreakAfter"<<"tcl_wordBreakBefore"<<"tell"<<"time"<<"unknown"<<"upvar"<<"variable"<<"vwait";
     554// tk keywords
     555    myList <<"bell"<<"bind"<<"clipboard"<<"console"<<"consoleinterp"<<"event"<<"focus"<<"grid"<<"pack"<<"place"<<"tkwait"<<"winfo"<<"wm"<<"bindtags"<<"destroy"<<"lower"<<"option"<<"raise"<<"send"<<"tkerror"<<"tkwait"<<"tk_bisque"<<"tk_focusNext"<<"tk_focusPrev"<<"tk_focusFollowsMouse"<<"tk_popup"<<"tk_setPalette"<<"tk_textCut"<<"tk_TextCopy"<<"tk_textPaste"<<"chooseColor"<<"tk_chooseColor"<<"tk_chooseDirectory"<<"tk_dialog"<<"tk_getOpenFile"<<"tkDialog"<<"tk_getSaveFile"<<"tk_messageBox"<<"button"<<"canvas"<<"checkbutton"<<"entry"<<"frame"<<"image"<<"label"<<"labelframe"<<"listbox"<<"menu"<<"menubutton"<<"message"<<"panedwindow"<<"radiobutton"<<"scale"<<"scrollbar"<<"spinbox"<<"toplevel";
     556    myList.sort();
     557    myInit=0;
     558  }
     559  str=str.stripWhiteSpace();
     560  if (str.left(2)=="::") {str=str.mid(2);}
     561  if (myList.findIndex(str) != -1) return(1);
     562  return 0;
     563}
     564
     565//! End codifying with special font class.
     566static void tcl_font_end()
     567{
     568  if (tcl.code==NULL) return;
     569  if (tcl.code_font)
     570  {
     571    tcl.code->endFontClass();
     572    tcl.code_font=NULL;
     573  }
     574}
     575
     576//! Codify 'str' with special font class 's'.
     577static void tcl_codify(const char *s,char *str)
     578{
     579  if (tcl.code==NULL||str==NULL) return;
     580  if (s)
     581  {
     582    tcl_font_end();
     583    tcl.code->startFontClass(s);
     584    tcl.code_font=s;
     585  }
     586  char *p=str,*sp=p;
     587  char c;
     588  bool done=FALSE;
     589  while (!done)
     590  {
     591    sp=p;
     592    while ((c=*p++) && c!='\n') {}
     593    if (c=='\n')
     594    {
     595      tcl.code_line++;
     596      *(p-1)='\0';
     597      tcl.code->codify(sp);
     598      //tcl_font_end();
     599      tcl.code->endCodeLine();
     600      if (tcl.code_linenumbers) {
     601        tcl.code->writeLineNumber(0,0,0,tcl.code_line);
     602      }
     603    }
     604    else
     605    {
     606      tcl.code->codify(sp);
     607      done=TRUE;
     608    }
     609  }
     610  tcl_font_end();
     611}
     612
     613//! Codify 'str' with special font class 's'.
     614static void tcl_codify(const char *s,const char *str)
     615{
     616  if (tcl.code==NULL) return;
     617  char *tmp= (char *) malloc(strlen(str)+1);
     618  strcpy(tmp, str);
     619  tcl_codify(s,tmp);
     620  free(tmp);
     621}
     622
     623//! Codify 'str' with special font class 's'.
     624static void tcl_codify(const char *s,QString str)
     625{
     626  if (tcl.code==NULL) return;
     627  char *tmp= (char *) malloc(str.length()+1);
     628  strcpy(tmp, str.data());
     629  tcl_codify(s,tmp);
     630  free(tmp);
     631}
     632
     633//! Codify 'str' with special font class 's'.
     634static void tcl_codify(const char *s,QCString str)
     635{
     636  if (tcl.code==NULL) return;
     637  char *tmp= (char *) malloc(str.length()+1);
     638  strcpy(tmp, str);
     639  tcl_codify(s,tmp);
     640  free(tmp);
     641}
     642
     643//! Print abort message.
     644static void tcl_Abort(const char *format, ...)
     645{
     646  va_list myList;
     647
     648  fprintf(stderr,"=== Error in file %s line: %d, state: %d ===\n",tcl.file_name.data(),yylineno,YY_START);
     649  va_start(myList, format);
     650  vfprintf(stderr,format, myList);
     651  va_end(myList);
     652  fprintf(stderr,"\n===\n");
     653   
     654  EntryListIterator eli(*tcl.entry_main->children());
     655  Entry *ce;
     656  bool start=FALSE;
     657
     658  for (;(ce=eli.current());++eli)
     659  {
     660     if (ce == tcl.entry_file) start=TRUE;
     661     if (start) ce->reset();
     662  }
     663}
     664
     665//! Print warning message.
     666static void tcl_Warn(const char *format, ...)
     667{
     668  va_list myList;
     669  FILE *fd=TCL_WARN_FD;
     670
     671  if (fd==NULL) return;
     672  va_start(myList, format);
     673  vfprintf(fd, format, myList);
     674  fputc('\n',fd);
     675  va_end(myList);
     676}
     677
     678//! Print debug message.
     679static void tcl_Debug(const char *format, ...)
     680{
     681  va_list myList;
     682  FILE *fd=TCL_DEBUG_FD;
     683
     684  if (fd==NULL) return;
     685  va_start(myList, format);
     686  vfprintf(fd, format, myList);
     687  fputc('\n',fd);
     688  va_end(myList);
     689}
     690/*
     691//! Print debug message.
     692static void tcl_Debug(const tcl_scan *s,const char *format, ...)
     693{
     694  va_list myList;
     695  FILE *fd=TCL_DEBUG_FD;
     696
     697  if (fd==NULL) return;
     698  va_start(myList, format);
     699  vfprintf(fd, format, myList);
     700  va_end(myList);
     701  fprintf(fd, ": tcl_scan[%d,%d] stack=%d type=%d name='%s'\n",
     702        s->line0,s->line1,s->start_stack_ptr,s->type,s->entry_ns->name.data());
     703}
     704
     705//! Print debug message.
     706static void tcl_Debug(const Entry *e,const char *format, ...)
     707{
     708  va_list myList;
     709  FILE *fd=TCL_DEBUG_FD;
     710
     711  if (fd==NULL) return;
     712  va_start(myList, format);
     713  vfprintf(fd, format, myList);
     714  va_end(myList);
     715  fprintf(fd,": Entry '%s' type=%s, section=0x%x file=%s (%d children)\n",
     716    (const char*)e->name, (const char*)e->type, e->section,
     717    (const char*)e->fileName, e->children()->count());
     718}
     719*/
     720//-----------------------------------------------------------------------------
     721#undef  YY_INPUT
     722#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
     723//-----------------------------------------------------------------------------
     724%}
     725ws              ([ \t]|\\\n)
     726
     727%option yylineno
     728%option noyywrap
     729%option stack
     730
     731%x ERROR
     732%x TOP
     733%x COMMAND
     734%x WORD
     735%x COMMENT
     736%x COMMENT_NL
     737%x COMMENT_CODE
     738%x COMMENT_VERB
     739%x COMMENTLINE
     740%x COMMENTLINE_NL
     741%x STRING
     742%x QUOTE
     743%x BRACE
     744%x BRACKET
     745%%
     746<ERROR>. {
     747D
     748  yyterminate();
     749}
     750<<EOF>> {
     751D
     752  if (tcl.scan.count()<1)
     753  {// error
     754D
     755    tcl_abort("stack empty");
     756    yyterminate();
     757  }
     758  else if (tcl.scan.count()==1)
     759  {// exit, check on input?
     760D
     761    yyterminate();
     762  }
     763  else
     764  {// continue
     765D
     766    tcl_command(-1,"");
     767    tcl_scan_end();
     768  }
     769}
     770<TOP>"#" {
     771D
     772  yyless(0);
     773  tcl.line_comment=yylineno;
     774  tcl_comment(0,"");
     775}
     776<TOP>({ws}|[\;\n])+ {
     777D
     778  tcl_codify(NULL,yytext);
     779}
     780<TOP>. {
     781D
     782  yyless(0);
     783  tcl.line_command=yylineno;
     784  tcl_command(0,"");
     785}
     786
     787<COMMENT>[ \t]* {
     788D
     789  tcl_codify("comment",yytext);
     790}
     791<COMMENT>"##".*\\\n {
     792D
     793  tcl_codify("comment",yytext);
     794  QString t=yytext;
     795  t = t.mid(2,t.length()-3);
     796  t.append('\n');
     797  tcl_comment(1,t.ascii());
     798  yy_push_state(COMMENT_NL);
     799}
     800<COMMENT>"##".*\n {
     801D
     802  tcl_codify("comment",yytext);
     803  tcl_comment(1,yytext+2);
     804}
     805<COMMENT>"#"[@\\]"code"\n[ \t]*[^#] {
     806D
     807  QString t=yytext;
     808  tcl_codify("comment",t.left(7));
     809  tcl_comment(2,"\n@code\n");
     810  yyless(7);
     811  yy_push_state(COMMENT_CODE);
     812}
     813<COMMENT_CODE>"#"[@\\]"endcode"\n {
     814D
     815  QString t=yytext;
     816  t = t.left(t.length()-10);
     817  tcl_comment(2,t.ascii());
     818  tcl_comment(2,"\n@endcode\n");
     819  yy_pop_state();
     820  yyless(0);
     821}
     822<COMMENT_CODE>.*\n {
     823D
     824  yymore();
     825}
     826<COMMENT>"#"[@\\]"verbatim"\n[ \t]*[^#] {
     827D
     828  QString t=yytext;
     829  tcl_codify("comment",t.left(11));
     830  tcl_comment(2,"\n@verbatim\n");
     831  yyless(11);
     832  yy_push_state(COMMENT_VERB);
     833}
     834<COMMENT_VERB>"#"[@\\]"endverbatim"\n {
     835D
     836  QString t=yytext;
     837  t = t.left(t.length()-14);
     838  tcl_comment(2,t.ascii());
     839  tcl_comment(2,"\n@endverbatim\n");
     840  yy_pop_state();
     841  yyless(0);
     842}
     843<COMMENT_VERB>.*\n {
     844D
     845  yymore();
     846}
     847<COMMENT>"#".*\\\n {
     848D
     849  tcl_codify("comment",yytext);
     850  QString t=yytext;
     851  t = t.mid(1,t.length()-3);
     852  t.append('\n');
     853  tcl_comment(2,t.ascii());
     854  yy_push_state(COMMENT_NL);
     855}
     856<COMMENT_NL>.*\\\n {
     857D
     858  tcl_codify("comment",yytext);
     859  tcl_comment(2,yytext);
     860}
     861<COMMENT_NL>.*\n {
     862D
     863  tcl_codify("comment",yytext);
     864  tcl_comment(2,yytext);
     865  yy_pop_state();
     866}
     867<COMMENT>"#".*"" {
     868D
     869  QString t=yytext;
     870  t = t.mid(0,t.length()-1);
     871  tcl_codify("comment",t.ascii());
     872  t = t.mid(1,t.length());
     873  tcl_comment(-2,t.ascii());
     874  unput('');
     875}
     876<COMMENT>"#".*\n {
     877D
     878  tcl_codify("comment",yytext);
     879  tcl_comment(2,yytext+1);
     880}
     881<COMMENT>"" {
     882D
     883  tcl_comment(-2,yytext);
     884}
     885<COMMENT>.|\n {
     886D
     887  yyless(0);
     888  tcl_comment(-2,yytext);
     889}
     890
     891<COMMENTLINE>[ \t]* {
     892D
     893  tcl.string_commentcodify += yytext;
     894}
     895<COMMENTLINE>"#<".*\\\n {
     896D
     897  tcl.string_commentcodify += yytext;
     898  QString t=yytext;
     899  t = t.mid(2,t.length()-4);
     900  t.append('\n');
     901  tcl.string_commentline += t;
     902  yy_push_state(COMMENTLINE_NL);
     903}
     904<COMMENTLINE>"#<".*\n {
     905D
     906  tcl.string_commentcodify += yytext;
     907  tcl.string_commentline += (yytext+2);
     908}
     909<COMMENTLINE_NL>.*\\\n {
     910D
     911  tcl.string_commentcodify += yytext;
     912  QString t=yytext;
     913  t = t.left(t.length()-3);
     914  t.append('\n');
     915  tcl.string_commentline += t;
     916}
     917<COMMENTLINE_NL>.*\n {
     918D
     919  tcl.string_commentcodify += yytext;
     920  tcl.string_commentline += yytext;
     921  yy_pop_state();
     922}
     923<COMMENTLINE_NL>.*"" {
     924D
     925  QString t=yytext;
     926  t = t.left(t.length()-1);
     927  tcl.string_commentcodify += t;
     928  tcl.string_commentline += t;
     929  yy_pop_state();
     930  unput('');
     931}
     932<COMMENTLINE>.|\n {
     933D
     934  yy_pop_state();
     935  if (tcl.string_commentline.length())
     936  {
     937    tcl.entry_current->brief = tcl.string_commentline;
     938    tcl.entry_current->briefLine = tcl.line_commentline;
     939    tcl.entry_current->briefFile = tcl.file_name;
     940  }
     941  yyless(0);
     942  tcl_command(-1,tcl.string_commentcodify.ascii());
     943  tcl.string_commentline="";
     944  tcl.string_commentcodify="";
     945}
     946
     947<COMMAND>{ws}*[\;]{ws}*"#<" {
     948D
     949  tcl.string_commentcodify = yytext;
     950  tcl.string_commentcodify = tcl.string_commentcodify.left(tcl.string_commentcodify.length()-2);
     951  tcl.string_commentline = "";
     952  tcl.line_commentline = yylineno;
     953  tcl.line_body1=yylineno;
     954  unput('<');
     955  unput('#');
     956  yy_push_state(COMMENTLINE);
     957}
     958<COMMAND>"" {
     959D
     960  tcl.string_commentcodify = "";
     961  tcl.string_commentline = "";
     962  tcl.line_body1=yylineno-1;
     963  tcl_command(-1,"");
     964}
     965<COMMAND>{ws}*[;\n] {
     966D
     967  tcl.string_commentcodify = "";
     968  tcl.string_commentline = "";
     969  tcl.line_body1=yylineno-1;
     970  tcl_command(-1,yytext);
     971}
     972<COMMAND>{ws}+ {
     973D
     974  tcl_command(1,yytext);
     975}
     976<COMMAND>"{*}". {
     977D
     978  tcl.word_is = WORD;
     979  tcl.string_last = "{*}";
     980  tcl_word(0,&yytext[3]);
     981}
     982<COMMAND>. {
     983D
     984  switch (yytext[0])
     985  {
     986    case '{': tcl.word_is = BRACE; break;
     987    case '[': tcl.word_is = BRACKET; break;
     988    case '"': tcl.word_is = QUOTE; break;
     989    default: tcl.word_is = WORD;
     990  }
     991  tcl.string_last = "";
     992  tcl_word(0,yytext);
     993}
     994
     995<WORD>"\\\\" |
     996<WORD>"\\"[\{\}\[\]\;\" \t] {
     997  tcl_word(1,yytext);
     998}
     999<WORD>"\\\n" {
     1000  tcl_word(2,yytext);
     1001}
     1002<WORD>"{" {
     1003  tcl_word(3,yytext);
     1004}
     1005<WORD>"}" {
     1006  tcl_word(4,yytext);
     1007}
     1008<WORD>"[" {
     1009  tcl_word(5,yytext);
     1010}
     1011<WORD>"]" {
     1012  tcl_word(6,yytext);
     1013}
     1014<WORD>"\"" {
     1015  tcl_word(7,yytext);
     1016}
     1017<WORD>" " {
     1018  tcl_word(8,yytext);
     1019}
     1020<WORD>"\t" {
     1021  tcl_word(9,yytext);
     1022}
     1023<WORD>";" {
     1024  tcl_word(10,yytext);
     1025}
     1026<WORD>"\n" {
     1027  tcl_word(11,yytext);
     1028}
     1029<WORD>"" {
     1030  tcl_word(12,yytext);
     1031}
     1032<WORD>. {
     1033  tcl_word(1,yytext);
     1034}
     1035%%
     1036
     1037//! Start new scan context for given 'content'.
     1038// @return created new scan context.
     1039tcl_scan *tcl_scan_start(int type, QString content, const char *after)
     1040{
     1041  tcl_scan *myScan;
     1042  QString myName;
     1043  char c[2]=" ";
     1044
     1045  myScan=tcl.scan.at(0);
     1046  myScan->line1=yylineno;
     1047  myScan->start_stack_ptr=yy_start_stack_ptr;
     1048  yy_push_state(TOP);
     1049
     1050  myScan=new tcl_scan;
     1051  myScan->type = type;
     1052  myScan->string_after=after;
     1053
     1054  switch (myScan->type)
     1055  {
     1056    case QUOTE: c[0]='"';
     1057tcl_debug("+++\" %d\n?%s?",tcl.line_body0,content.ascii());
     1058      break;
     1059    case BRACE: c[0]='{';
     1060tcl_debug("+++{ %d\n?%s?",tcl.line_body0,content.ascii());
     1061      break;
     1062    case BRACKET: c[0]='[';
     1063tcl_debug("+++[ %d\n?%s?",tcl.line_body0,content.ascii());
     1064      break;
     1065    default:
     1066tcl_debug("+++. %d\n?%s?",tcl.line_body0,content.ascii());
     1067      break;
     1068  }
     1069  if (c[0]!=' ')
     1070  {
     1071    tcl_codify(NULL,c);
     1072    content = content.mid(1,content.length()-2);
     1073    content += "";// for detection end of scan context
     1074tcl_debug("???%s?",content.ascii());
     1075  }
     1076  myScan->entry_ns = tcl.scan.at(0)->entry_ns;
     1077  myScan->entry_cl = tcl.scan.at(0)->entry_cl;
     1078  myScan->entry_fn = tcl.scan.at(0)->entry_fn;
     1079  myScan->entry_scan = tcl.entry_current;
     1080  myScan->buffer_state=yy_scan_string(content.ascii());
     1081  myScan->line0=tcl.line_body0;
     1082  myScan->line1=tcl.line_body1;
     1083  yylineno=myScan->line0;
     1084  myScan->start_stack_ptr=yy_start_stack_ptr;
     1085  myScan->protection = tcl.protection;
     1086
     1087  tcl.entry_inside = myScan->entry_scan;
     1088  tcl.entry_current = tcl_entry_new();
     1089  tcl.scan.insert(0,myScan);
     1090  yy_switch_to_buffer(myScan->buffer_state);
     1091  return (myScan);
     1092}
     1093
     1094//! Close current scan context.
     1095static void tcl_scan_end()
     1096{
     1097  tcl_scan *myScan;
     1098  char c[2]=" ";
     1099
     1100  myScan=tcl.scan.at(0);
     1101  switch (myScan->type)
     1102  {
     1103    case QUOTE: c[0]='"'; break;
     1104    case BRACE: c[0]='}'; break;
     1105    case BRACKET: c[0]=']'; break;
     1106  }
     1107  if (c[0]!=' ') {tcl_codify(NULL,c);}
     1108  if (myScan->string_after.length()) {tcl_codify("comment",myScan->string_after);}
     1109  yy_delete_buffer(myScan->buffer_state);
     1110  tcl.scan.removeFirst();
     1111  yy_pop_state();
     1112  myScan=tcl.scan.at(0);
     1113  tcl.entry_inside = myScan->entry_scan;
     1114tcl_debug("---%d",myScan->line1);
     1115  yy_switch_to_buffer(myScan->buffer_state);
     1116  yylineno=myScan->line1;
     1117  tcl.protection = myScan->protection;
     1118}
     1119
     1120//! Handling of word parsing.
     1121static void tcl_word(int what,const char *text) {
     1122  static char myList[1024]="";// nesting level list
     1123  static int myLevel=0;// number of current nesting level
     1124  static int myWhite=0;// set true when next char should be whitespace
     1125  static char myWord;// internal state
     1126
     1127  switch (what)
     1128  {
     1129  case 0:// start
     1130    yy_push_state(WORD);
     1131    switch (text[0])
     1132    {
     1133      case '{':
     1134      case '[':
     1135      case '"': myWord = text[0]; break;
     1136      default: myWord = '.';
     1137    }
     1138    myList[0]=myWord;
     1139    myLevel=1;
     1140    myWhite=0;
     1141  break;
     1142  case 1:// all other chars
     1143    if (myWhite)
     1144    {// {x}y "x"y
     1145      tcl_abort("expected word separator: %s",text);
     1146      return;
     1147    }
     1148    if (myLevel==0)
     1149    {
     1150      myWord='.';
     1151      myList[0]=myWord;
     1152      myLevel=1;
     1153    }
     1154  break;
     1155  case 2:// \\\n
     1156    if (myLevel==0)
     1157    {
     1158      myWord=' ';
     1159      yy_pop_state();
     1160      yyless(0);
     1161tcl_debug("(\\\n) ?%s?",tcl.string_last.ascii());
     1162      return;
     1163    }
     1164    switch (myList[myLevel-1])
     1165    {
     1166      case '{':
     1167      case '[':
     1168      case '"':
     1169      break;
     1170      case '.':
     1171        if (myLevel==1)
     1172        {
     1173          myWord=' ';
     1174          yy_pop_state();
     1175          yyless(0);
     1176tcl_debug("(\\\n) ?%s?",tcl.string_last.ascii());
     1177          return;
     1178        }
     1179      break;
     1180    }
     1181    myWhite=0;
     1182  break;
     1183  case 3:// {
     1184    if (myWhite)
     1185    {// {x}{ "x"{
     1186      tcl_abort("expected word separator: %s",text);
     1187      return;
     1188    }
     1189    switch (myList[myLevel-1])
     1190    {
     1191      case '{':
     1192      case '[':
     1193        myList[myLevel++]='{';
     1194      break;
     1195      case '"':
     1196      case '.':
     1197      break;
     1198    }
     1199    myWhite=0;
     1200  break;
     1201  case 4:// }
     1202    if (myWhite)
     1203    {// {x}{ "x"{
     1204      tcl_abort("expected word separator: %s",text);
     1205      return;
     1206    }
     1207    switch (myList[myLevel-1])
     1208    {
     1209      case '{':// {{x}}
     1210        myLevel--;
     1211        if (myLevel==0) {myWhite=1;}
     1212      break;
     1213      case '[':
     1214      case '"':
     1215      case '.':
     1216      break;
     1217    }
     1218  break;
     1219  case 5:// [
     1220    if (myWhite)
     1221    {// {x}[
     1222      tcl_abort("expected word separator: %s",text);
     1223      return;
     1224    }
     1225    switch (myList[myLevel-1])
     1226    {
     1227      case '{':
     1228      break;
     1229      case '[':
     1230      case '"':
     1231      case '.':
     1232        myList[myLevel++]='[';
     1233      break;
     1234    }
     1235    myWhite=0;
     1236  break;
     1237  case 6:// ]
     1238    if (myWhite)
     1239    {// {x}]
     1240      tcl_abort("expected word separator: %s",text);
     1241      return;
     1242    }
     1243    switch (myList[myLevel-1])
     1244    {
     1245      case '{':
     1246      break;
     1247      case '[':
     1248        myLevel--;
     1249      break;
     1250      case '"':
     1251      case '.':
     1252      break;
     1253    }
     1254    myWhite=0;
     1255  break;
     1256  case 7:// "
     1257    if (myWhite)
     1258    {// {x}"
     1259      tcl_abort("expected word separator: %s",text);
     1260      return;
     1261    }
     1262    switch (myList[myLevel-1])
     1263    {
     1264      case '{':
     1265      break;
     1266      case '[':
     1267        myList[myLevel++]='"';
     1268      break;
     1269      case '"':
     1270        myLevel--;
     1271      case '.':
     1272      break;
     1273    }
     1274  break;
     1275  case 8:// ' '
     1276  case 9:// \t
     1277  case 10:// ;
     1278  case 11:// \n
     1279  case 12://
     1280    if (myLevel==0)
     1281    {
     1282      myWord=' ';
     1283      yy_pop_state();
     1284      yyless(0);
     1285tcl_debug("(%d) ?%s?",what,tcl.string_last.ascii());
     1286      return;
     1287    }
     1288    switch (myList[myLevel-1])
     1289    {
     1290      case '{':
     1291      case '[':
     1292      case '"':
     1293      break;
     1294      case '.':
     1295        if (myLevel==1)
     1296        {
     1297          myWord=' ';
     1298          yy_pop_state();
     1299          yyless(0);
     1300tcl_debug("(.%d) ?%s?",what,tcl.string_last.ascii());
     1301          return;
     1302        }
     1303        else
     1304        {
     1305          myLevel--;
     1306        }
     1307      break;
     1308    }
     1309    myWhite=0;
     1310  break;
     1311  default:
     1312    tcl_abort("wrong state: %d",what);
     1313    return;
     1314  }
     1315  tcl.string_last += text;
     1316}
     1317
     1318//! Handling of comment parsing.
     1319static void tcl_comment(int what,const char *text)
     1320{
     1321  if (what==0)
     1322  { // begin of comment
     1323    if (tcl.comment)
     1324    {
     1325      tcl_abort("comment in comment");
     1326      return;
     1327    }
     1328    yy_push_state(COMMENT);
     1329tcl_debug("+++%s",text);
     1330    tcl.string_comment="";
     1331    tcl.comment=0;
     1332  }
     1333  else if (what==1)
     1334  { // start new comment
     1335    if (tcl.comment)
     1336    {
     1337      tcl_comment(99,""); // inbody
     1338    }
     1339    tcl.string_comment=text;
     1340    tcl.comment=1;
     1341  }
     1342  else if (what==2)
     1343  { // add to comment
     1344    if (tcl.comment)
     1345    {
     1346      tcl.string_comment+=text;
     1347    }
     1348  }
     1349  else if (what==-1 || what == -2)
     1350  { // end of comment without/with command
     1351    if (tcl.comment)
     1352    {
     1353      tcl.string_last=tcl.string_comment;
     1354      tcl_comment(100+what,"");
     1355    }
     1356    else
     1357    {
     1358      tcl.string_last = "";
     1359tcl_debug("---%s",(const char *)tcl.string_comment);
     1360    }
     1361    yy_pop_state();
     1362    tcl.string_comment="";
     1363    tcl.comment=0;
     1364  }
     1365  else if (what==98 || what==99)
     1366  { // 98=new 99=inbody
     1367    if (tcl.this_parser && tcl.string_comment.length())
     1368    {
     1369tcl_debug("---%s",(const char *)tcl.string_comment);
     1370      int myPos=0;
     1371      bool myNew=0;
     1372      int myLine=tcl.line_comment;
     1373      BufStr myI(1024);
     1374      BufStr myO(1024);
     1375      Protection myProt=tcl.protection;
     1376
     1377      // resolve ALIASES
     1378      myI.addArray("/*!",3);
     1379      myI.addArray(tcl.string_comment.ascii(),tcl.string_comment.length());
     1380      myI.addArray("*/",2);
     1381      convertCppComments(&myI,&myO,tcl.file_name);
     1382      myO.dropFromStart(3);
     1383      myO.shrink(myO.curPos()-2);
     1384      myO.addChar('\0');
     1385      QCString myDoc = myO.data();
     1386      if (what==99)
     1387      { // inbody comment file or namespace or class or proc/metho
     1388        int myPos0;
     1389        int myLine0;
     1390        Entry myEntry0; // used to test parsing
     1391        Entry *myEntry;
     1392
     1393        Entry *myEntry1=tcl.scan.at(0)->entry_ns;
     1394        if (tcl.scan.at(0)->entry_fn)
     1395        {
     1396          myEntry1=tcl.scan.at(0)->entry_fn;
     1397        }
     1398        else if (tcl.scan.at(0)->entry_cl)
     1399        {
     1400          myEntry1=tcl.scan.at(0)->entry_cl;
     1401        }
     1402
     1403        myPos0=myPos;
     1404        myLine0=myLine;
     1405        while (parseCommentBlock(tcl.this_parser, &myEntry0, myDoc, tcl.file_name,
     1406          myLine, FALSE, tcl.config_autobrief, FALSE, myProt, myPos, myNew))
     1407        {
     1408          if (myNew)
     1409          { // we need a new entry in this case
     1410            myNew=0;
     1411            myEntry = tcl_entry_new();
     1412            parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name,
     1413              myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
     1414            tcl.entry_inside->addSubEntry(myEntry);
     1415          }
     1416          else
     1417          { // we can add to current entry in this case
     1418            parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name,
     1419              myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
     1420          }
     1421          myPos0=myPos;
     1422          myLine0=myLine;
     1423        }
     1424        if (myNew)
     1425        { // we need a new entry
     1426          myNew=0;
     1427          myEntry = tcl_entry_new();
     1428          parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name,
     1429            myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
     1430          tcl.entry_inside->addSubEntry(myEntry);
     1431        }
     1432        else
     1433        { // we can add to current entry
     1434          parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name,
     1435            myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
     1436        }
     1437      }
     1438      else
     1439      { // new entry
     1440        tcl.entry_current = tcl_entry_new();
     1441        while (parseCommentBlock(tcl.this_parser, tcl.entry_current, myDoc,
     1442          tcl.file_name, myLine, FALSE, tcl.config_autobrief, FALSE,
     1443          myProt, myPos, myNew))
     1444        {
     1445          if (myNew)
     1446          {
     1447            tcl.entry_inside->addSubEntry(tcl.entry_current);
     1448            tcl.entry_current = tcl_entry_new();
     1449          }
     1450          else
     1451          {
     1452            tcl.entry_current->section = tcl.entry_inside->section;
     1453            tcl.entry_current->name = tcl.entry_inside->name;
     1454          }
     1455        }
     1456        if (myNew)
     1457        {
     1458          tcl.entry_inside->addSubEntry(tcl.entry_current);
     1459          tcl.entry_current = tcl_entry_new();
     1460        }
     1461        else
     1462        {
     1463          tcl.entry_current->section = tcl.entry_inside->section;
     1464          tcl.entry_current->name = tcl.entry_inside->name;
     1465        }
     1466      }
     1467      if (tcl.protection != myProt)
     1468      {
     1469        tcl.scan.at(0)->protection = tcl.protection = myProt;
     1470      }
     1471    }
     1472  }
     1473  else
     1474  {
     1475    tcl_abort("what %d",what);
     1476    return;
     1477  }
     1478}
     1479
     1480//! Parse given \c arglist .
     1481static void tcl_command_ARGLIST(QString &arglist)
     1482{
     1483  Argument *myArg;
     1484  QStringList myArgs;
     1485  QString myArglist="";
     1486
     1487  if (tcl.entry_current->argList==NULL)
     1488  {
     1489    tcl.entry_current->argList=new ArgumentList;
     1490  }
     1491  tcl_split_list(arglist,myArgs);
     1492  for (uint i=0;i<myArgs.count();i++)
     1493  {
     1494    QStringList myArgs1;
     1495    myArg=new Argument;
     1496
     1497    tcl_split_list(*myArgs.at(i),myArgs1);
     1498    if (myArgs1.count()==2)
     1499    {
     1500      myArg->name= *myArgs1.at(0);
     1501      myArg->defval= *myArgs1.at(1);
     1502      if (myArg->defval.isEmpty())
     1503      {
     1504        myArg->defval = " ";
     1505      }
     1506      myArglist = myArglist + "?" + myArg->name.data() + "? ";
     1507    }
     1508    else
     1509    {
     1510      myArg->name= *myArgs.at(i);
     1511      myArglist = myArglist + myArg->name.data() + " ";
     1512    }
     1513    tcl.entry_current->argList->append(myArg);
     1514  }
     1515  arglist = myArglist;
     1516  tcl.entry_current->args = arglist;
     1517}
     1518
     1519//! Handle all other commands.
     1520static void tcl_command_OTHER(const char *text)
     1521{
     1522  for (unsigned int i=0; i< tcl.list_command.count(); i++)
     1523  {
     1524    if (i==0 && tcl_keyword(*tcl.list_command.at(i)))
     1525    {
     1526      tcl_codify("keyword",*tcl.list_command.at(i));
     1527    }
     1528    else
     1529    {
     1530      tcl_codify(NULL,*tcl.list_command.at(i));
     1531    }
     1532  }
     1533  tcl_codify(NULL,text);
     1534}
     1535
     1536//! Handle \c proc statements.
     1537static void tcl_command_PROC(const char *text)
     1538{
     1539  QString myNs, myName;
     1540  Entry *myEntryNs, *myEntry;
     1541  tcl_scan *myScan = tcl.scan.at(0);
     1542
     1543  tcl_codify("keyword",*tcl.list_command.at(0));
     1544  tcl_codify(NULL,*tcl.list_command.at(1));
     1545  tcl_codify(NULL,*tcl.list_command.at(2));
     1546  tcl_codify(NULL,*tcl.list_command.at(3));
     1547  tcl_codify(NULL,*tcl.list_command.at(4));
     1548  tcl_codify(NULL,*tcl.list_command.at(5));
     1549  tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName);
     1550  if (myNs.length())
     1551  {
     1552    myEntryNs = tcl_entry_namespace(myNs);
     1553  }
     1554  else
     1555  {
     1556    myEntryNs = myScan->entry_ns;
     1557  }
     1558  tcl.entry_current->section = Entry::FUNCTION_SEC;
     1559  tcl.entry_current->mtype = Method;
     1560  tcl.entry_current->name = myName;
     1561  tcl.entry_current->startLine = tcl.line_command;
     1562  tcl.entry_current->bodyLine = tcl.line_body0;
     1563  tcl.entry_current->endBodyLine = tcl.line_body1;
     1564  tcl_protection(tcl.entry_current);
     1565  tcl_command_ARGLIST(*tcl.list_command.at(4));
     1566  myEntryNs->addSubEntry(tcl.entry_current);
     1567  myEntry = tcl.entry_current;
     1568  tcl.fn.insert(myName,myEntry);
     1569  myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(6),text);
     1570  myScan->entry_ns = myEntryNs;
     1571  myScan->entry_cl = NULL;
     1572  myScan->entry_fn = myEntry;
     1573}
     1574
     1575//! Handle \c itcl::body statements.
     1576static void tcl_command_ITCL_BODY(const char *text)
     1577{
     1578  QString myNs, myName;
     1579  Entry *myEntryNs, *myEntryCl, *myEntry;
     1580  tcl_scan *myScan = tcl.scan.at(0);
     1581
     1582  tcl_codify("keyword",*tcl.list_command.at(0));
     1583  tcl_codify(NULL,*tcl.list_command.at(1));
     1584  tcl_codify(NULL,*tcl.list_command.at(2));
     1585  tcl_codify(NULL,*tcl.list_command.at(3));
     1586  tcl_codify(NULL,*tcl.list_command.at(4));
     1587  tcl_codify(NULL,*tcl.list_command.at(5));
     1588  tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName);
     1589  if (myNs.length())
     1590  {
     1591    myEntryNs = tcl_entry_namespace(myNs);
     1592    myEntryCl = tcl_entry_class(myNs);
     1593  }
     1594  else
     1595  {
     1596    myEntryNs = myScan->entry_ns;
     1597    myEntryCl = myScan->entry_cl;
     1598  }
     1599  tcl_command_ARGLIST(*tcl.list_command.at(4));
     1600  myEntry = tcl.fn.find(myName);
     1601  if (myEntry != NULL)
     1602  {
     1603    tcl.entry_current->section = Entry::EMPTY_SEC;
     1604    if (myEntry->args.isEmpty())
     1605    {
     1606      myEntry->args = tcl.entry_current->args;
     1607      myEntry->argList = tcl.entry_current->argList;
     1608    }
     1609    if (myEntry->brief.isEmpty())
     1610    {
     1611      myEntry->brief = tcl.entry_current->brief;
     1612      myEntry->briefFile = tcl.entry_current->briefFile;
     1613      myEntry->briefLine = tcl.entry_current->briefLine;
     1614    }
     1615    else if (!tcl.entry_current->brief.isEmpty())
     1616    {
     1617      myEntry->doc.append("\n<p>\n");
     1618      myEntry->doc.append(tcl.entry_current->brief);
     1619    }
     1620    if (myEntry->doc.isEmpty())
     1621    {
     1622      myEntry->doc = tcl.entry_current->doc;
     1623      myEntry->docFile = tcl.entry_current->docFile;
     1624      myEntry->docLine = tcl.entry_current->docLine;
     1625    }
     1626    else if (!tcl.entry_current->doc.isEmpty())
     1627    {
     1628      myEntry->doc.append("\n<p>\n");
     1629      myEntry->doc.append(tcl.entry_current->doc);
     1630    }
     1631    myEntry->bodyLine = tcl.line_body0;
     1632    myEntry->endBodyLine = tcl.line_body1;
     1633  } else {// should not happen, may be ignore?
     1634    tcl.entry_current->section = Entry::FUNCTION_SEC;
     1635    tcl.entry_current->mtype = Method;
     1636    tcl.entry_current->name = myName;
     1637    tcl.entry_current->startLine = tcl.line_command;
     1638    tcl.entry_current->bodyLine = tcl.line_body0;
     1639    tcl.entry_current->endBodyLine = tcl.line_body1;
     1640    tcl_protection(tcl.entry_current);
     1641    tcl.fn.insert(myName,tcl.entry_current);
     1642    myEntryCl->addSubEntry(tcl.entry_current);
     1643    myEntry = tcl.entry_current;
     1644  }
     1645  myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(6),text);
     1646  myScan->entry_ns = myEntryNs;
     1647  myScan->entry_cl = myEntryCl;
     1648  myScan->entry_fn = myEntry;
     1649}
     1650
     1651//! Handle \c oo::define method and method inside \c itcl::class statements.
     1652static void tcl_command_METHOD(const char *text)
     1653{
     1654  QString myNs, myName;
     1655  Entry *myEntryNs, *myEntryCl, *myEntry;
     1656  tcl_scan *myScan = tcl.scan.at(0);
     1657
     1658  tcl_codify("keyword",*tcl.list_command.at(0));
     1659  tcl_codify(NULL,*tcl.list_command.at(1));
     1660  tcl_codify(NULL,*tcl.list_command.at(2));
     1661  tcl_codify(NULL,*tcl.list_command.at(3));
     1662  tcl_codify(NULL,*tcl.list_command.at(4));
     1663  tcl_codify(NULL,*tcl.list_command.at(5));
     1664  tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName);
     1665  if (myNs.length())
     1666  {
     1667    myEntryNs = tcl_entry_namespace(myNs);
     1668    myEntryCl = tcl_entry_class(myNs);
     1669  }
     1670  else
     1671  {
     1672    myEntryNs = myScan->entry_ns;
     1673    myEntryCl = myScan->entry_cl;
     1674  }
     1675  tcl.entry_current->section = Entry::FUNCTION_SEC;
     1676  tcl.entry_current->mtype = Method;
     1677  tcl.entry_current->name = myName;
     1678  tcl.entry_current->startLine = tcl.line_command;
     1679  tcl.entry_current->bodyLine = tcl.line_body0;
     1680  tcl.entry_current->endBodyLine = tcl.line_body1;
     1681  tcl_protection(tcl.entry_current);
     1682  tcl_command_ARGLIST(*tcl.list_command.at(4));
     1683  myEntryCl->addSubEntry(tcl.entry_current);
     1684  tcl.fn.insert(myName,tcl.entry_current);
     1685  myEntry = tcl.entry_current;
     1686  myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(6),text);
     1687  myScan->entry_ns = myEntryNs;
     1688  myScan->entry_cl = myEntryCl;
     1689  myScan->entry_fn = myEntry;
     1690}
     1691
     1692//! Handle \c constructor statements inside class definitions.
     1693static void tcl_command_CONSTRUCTOR(const char *text)
     1694{
     1695  QString myNs, myName;
     1696  Entry *myEntryNs, *myEntryCl, *myEntry;
     1697  tcl_scan *myScan = tcl.scan.at(0);
     1698
     1699  tcl_codify("keyword",*tcl.list_command.at(0));
     1700  tcl_codify(NULL,*tcl.list_command.at(1));
     1701  tcl_codify(NULL,*tcl.list_command.at(2));
     1702  tcl_codify(NULL,*tcl.list_command.at(3));
     1703  tcl_name(myScan->entry_ns->name,*tcl.list_command.at(0),myNs,myName);
     1704  if (myNs.length())
     1705  {
     1706    myEntryNs = tcl_entry_namespace(myNs);
     1707    myEntryCl = tcl_entry_class(myNs);
     1708  }
     1709  else
     1710  {
     1711    myEntryNs = myScan->entry_ns;
     1712    myEntryCl = myScan->entry_cl;
     1713  }
     1714  tcl.entry_current->section = Entry::FUNCTION_SEC;
     1715  tcl.entry_current->mtype = Method;
     1716  tcl.entry_current->name = myName;
     1717  tcl.entry_current->startLine = tcl.line_command;
     1718  tcl.entry_current->bodyLine = tcl.line_body0;
     1719  tcl.entry_current->endBodyLine = tcl.line_body1;
     1720  tcl_protection(tcl.entry_current);
     1721  tcl_command_ARGLIST(*tcl.list_command.at(2));
     1722  myEntryCl->addSubEntry(tcl.entry_current);
     1723  myEntry = tcl.entry_current;
     1724  tcl.fn.insert(myName,myEntry);
     1725  myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(4),text);
     1726  myScan->entry_ns = myEntryNs;
     1727  myScan->entry_cl = myEntryCl;
     1728  myScan->entry_fn = myEntry;
     1729}
     1730
     1731//! Handle \c destructor statements inside class definitions.
     1732static void tcl_command_DESTRUCTOR(const char *text)
     1733{
     1734  QString myNs, myName;
     1735  Entry *myEntryNs, *myEntryCl, *myEntry;
     1736  tcl_scan *myScan = tcl.scan.at(0);
     1737
     1738  tcl_codify("keyword",*tcl.list_command.at(0));
     1739  tcl_codify(NULL,*tcl.list_command.at(1));
     1740  tcl_name(myScan->entry_ns->name,*tcl.list_command.at(0),myNs,myName);
     1741  if (myNs.length())
     1742  {
     1743    myEntryNs = tcl_entry_namespace(myNs);
     1744    myEntryCl = tcl_entry_class(myNs);
     1745  }
     1746  else
     1747  {
     1748    myEntryNs = myScan->entry_ns;
     1749    myEntryCl = myScan->entry_cl;
     1750  }
     1751  tcl.entry_current->section = Entry::FUNCTION_SEC;
     1752  tcl.entry_current->mtype = Method;
     1753  tcl.entry_current->name = myName;
     1754  tcl.entry_current->startLine = tcl.line_command;
     1755  tcl.entry_current->bodyLine = tcl.line_body0;
     1756  tcl.entry_current->endBodyLine = tcl.line_body1;
     1757  tcl_protection(tcl.entry_current);
     1758  myEntryCl->addSubEntry(tcl.entry_current);
     1759  myEntry = tcl.entry_current;
     1760  tcl.fn.insert(myName,myEntry);
     1761  myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(2),text);
     1762  myScan->entry_ns = myEntryNs;
     1763  myScan->entry_cl = myEntryCl;
     1764  myScan->entry_fn = myEntry;
     1765}
     1766
     1767//! Handle \c namespace statements.
     1768static void tcl_command_NAMESPACE(const char *text)
     1769{
     1770  QString myNs, myName, myStr;
     1771  Entry *myEntryNs=NULL;
     1772  tcl_scan *myScan = tcl.scan.at(0);
     1773
     1774  tcl_codify("keyword",*tcl.list_command.at(0));
     1775  tcl_codify(NULL,*tcl.list_command.at(1));
     1776  tcl_codify("keyword",*tcl.list_command.at(2));
     1777  tcl_codify(NULL,*tcl.list_command.at(3));
     1778  tcl_codify(NULL,*tcl.list_command.at(4));
     1779  tcl_codify(NULL,*tcl.list_command.at(5));
     1780  tcl_name(myScan->entry_ns->name,*tcl.list_command.at(4),myNs,myName);
     1781  if (myNs.length())
     1782  {
     1783    myName = myNs+"::"+myName;
     1784  }
     1785  tcl.entry_current->section = Entry::NAMESPACE_SEC;
     1786  tcl.entry_current->name = myName;
     1787  tcl.entry_current->startLine = tcl.line_command;
     1788  tcl.entry_current->bodyLine = tcl.line_body0;
     1789  tcl.entry_current->endBodyLine = tcl.line_body1;
     1790  tcl.entry_main->addSubEntry(tcl.entry_current);
     1791  tcl.ns.insert(myName,tcl.entry_current);
     1792  myEntryNs = tcl.entry_current;
     1793  myStr = *tcl.list_command.at(6);
     1794  if (tcl.list_command.count() > 7)
     1795  {
     1796    for (uint i=7;i<tcl.list_command.count();i++)
     1797    {
     1798      myStr.append(*tcl.list_command.at(i));
     1799    }
     1800    tcl.word_is=STRING;
     1801  }
     1802  myScan = tcl_scan_start(tcl.word_is,myStr,text);
     1803  myScan->entry_ns = myEntryNs;
     1804  myScan->entry_cl = NULL;
     1805  myScan->entry_fn = NULL;
     1806}
     1807
     1808//! Handle \c itcl::class statements.
     1809static void tcl_command_ITCL_CLASS(const char *text)
     1810{
     1811  QString myNs, myName, myStr;
     1812  Entry *myEntryNs, *myEntryCl;
     1813  tcl_scan *myScan = tcl.scan.at(0);
     1814
     1815  tcl_codify("keyword",*tcl.list_command.at(0));
     1816  tcl_codify(NULL,*tcl.list_command.at(1));
     1817  tcl_codify("NULL",*tcl.list_command.at(2));
     1818  tcl_codify("NULL",*tcl.list_command.at(3));
     1819  tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName);
     1820  if (myNs.length())
     1821  {
     1822    myName = myNs+"::"+myName;
     1823  }
     1824  tcl.entry_current->section = Entry::CLASS_SEC;
     1825  tcl.entry_current->name = myName;
     1826  tcl.entry_current->startLine = tcl.line_command;
     1827  tcl.entry_current->bodyLine = tcl.line_body0;
     1828  tcl.entry_current->endBodyLine = tcl.line_body1;
     1829  tcl.entry_main->addSubEntry(tcl.entry_current);
     1830  myEntryNs = tcl_entry_namespace(myName);
     1831  tcl.cl.insert(myName,tcl.entry_current);
     1832  myEntryCl = tcl.entry_current;
     1833  myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(4),text);
     1834  myScan->entry_ns = myEntryNs;
     1835  myScan->entry_cl = myEntryCl;
     1836  myScan->entry_fn = NULL;
     1837}
     1838
     1839//! Handle \c oo::class statements.
     1840static void tcl_command_OO_CLASS(const char *text)
     1841{
     1842  QString myNs, myName, myStr;
     1843  Entry *myEntryNs, *myEntryCl;
     1844  tcl_scan *myScan = tcl.scan.at(0);
     1845
     1846  tcl_codify("keyword",*tcl.list_command.at(0));
     1847  tcl_codify(NULL,*tcl.list_command.at(1));
     1848  tcl_codify("NULL",*tcl.list_command.at(2));
     1849  tcl_codify("NULL",*tcl.list_command.at(3));
     1850  tcl_codify("NULL",*tcl.list_command.at(4));
     1851  tcl_codify("NULL",*tcl.list_command.at(5));
     1852  tcl_name(myScan->entry_ns->name,*tcl.list_command.at(4),myNs,myName);
     1853  if (myNs.length())
     1854  {
     1855    myName = myNs+"::"+myName;
     1856  }
     1857  tcl.entry_current->section = Entry::CLASS_SEC;
     1858  tcl.entry_current->name = myName;
     1859  tcl.entry_current->startLine = tcl.line_command;
     1860  tcl.entry_current->bodyLine = tcl.line_body0;
     1861  tcl.entry_current->endBodyLine = tcl.line_body1;
     1862  tcl.entry_main->addSubEntry(tcl.entry_current);
     1863  myEntryNs = tcl_entry_namespace(myName);
     1864  tcl.cl.insert(myName,tcl.entry_current);
     1865  myEntryCl = tcl.entry_current;
     1866  myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(6),text);
     1867  myScan->entry_ns = myEntryNs;
     1868  myScan->entry_cl = myEntryCl;
     1869  myScan->entry_fn = NULL;
     1870}
     1871
     1872//! Handle \c oo::define statements.
     1873static void tcl_command_OO_DEFINE(const char *text)
     1874{
     1875  QString myNs, myName, myStr;
     1876  Entry *myEntryNs, *myEntryCl;
     1877  tcl_scan *myScan = tcl.scan.at(0);
     1878
     1879  tcl_codify("keyword",*tcl.list_command.at(0));
     1880  tcl_codify(NULL,*tcl.list_command.at(1));
     1881  tcl_codify("NULL",*tcl.list_command.at(2));
     1882  tcl_codify("NULL",*tcl.list_command.at(3));
     1883  tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName);
     1884  if (myNs.length())
     1885  {
     1886    myName = myNs+"::"+myName;
     1887  }
     1888  myEntryNs = tcl_entry_namespace(myName);
     1889  myEntryCl = tcl_entry_class(myName);
     1890  myStr = *tcl.list_command.at(4);
     1891  if (tcl.list_command.count() > 5)
     1892  {
     1893    for (uint i=5;i<tcl.list_command.count();i++)
     1894    {
     1895      myStr.append(*tcl.list_command.at(i));
     1896    }
     1897    tcl.word_is=STRING;
     1898  }
     1899  myScan = tcl_scan_start(tcl.word_is,myStr,text);
     1900  myScan->entry_ns = myEntryNs;
     1901  myScan->entry_cl = myEntryCl;
     1902  myScan->entry_fn = NULL;
     1903}
     1904
     1905//! Handle \c variable statements.
     1906static void tcl_command_VARIABLE(const char *text, int inclass)
     1907{
     1908  QString myNs, myName;
     1909  Entry *myEntry;
     1910  tcl_scan *myScan = tcl.scan.at(0);
     1911
     1912  tcl_codify("keyword",*tcl.list_command.at(0));
     1913  for (unsigned int i=1; i< tcl.list_command.count(); i++)
     1914  {
     1915    tcl_codify(NULL,*tcl.list_command.at(i));
     1916  }
     1917  tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName);
     1918  if (myNs.length())
     1919  {// qualified variables go into namespace
     1920    myEntry = tcl_entry_namespace(myNs);
     1921    tcl.entry_current->stat = true;
     1922  }
     1923  else
     1924  {
     1925    if (inclass)
     1926    {
     1927      myEntry = myScan->entry_cl;
     1928      tcl.entry_current->stat = false;
     1929    }
     1930    else
     1931    {
     1932      myEntry = myScan->entry_ns;
     1933      tcl.entry_current->stat = true;
     1934    }
     1935  }
     1936  tcl.entry_current->section = Entry::VARIABLE_SEC;
     1937  tcl.entry_current->name = myName;
     1938  tcl.entry_current->startLine = tcl.line_command;
     1939  tcl.entry_current->bodyLine = tcl.line_body0;
     1940  tcl.entry_current->endBodyLine = tcl.line_body1;
     1941  tcl_protection(tcl.entry_current);
     1942  myEntry->addSubEntry(tcl.entry_current);
     1943  tcl.entry_current = tcl_entry_new();
     1944  tcl_codify("comment",text);
     1945}
     1946
     1947//! Handling of command parsing.
     1948static void tcl_command(int what,const char *text)
     1949{
     1950  if (what==0)
     1951  {
     1952    tcl.scan.at(0)->line1=yylineno;// current line in scan context
     1953    tcl.line_body0=yylineno;// start line of command
     1954tcl_debug("+++%s",text);
     1955    yy_push_state(COMMAND);
     1956    tcl.list_command.clear();
     1957    tcl.string_command="";
     1958    tcl.string_last="";
     1959    tcl.command=1;
     1960    return;
     1961  }
     1962  if (what==1)
     1963  {
     1964    if (tcl.string_last.length())
     1965    {
     1966      tcl.list_command.append(tcl.string_last);
     1967      tcl.string_last="";
     1968    }
     1969    if (text) {
     1970      tcl.list_command.append(text);
     1971    }
     1972    return;
     1973  }
     1974  if (what!=-1)
     1975  {// should not happen
     1976    tcl_abort("what %d",what);
     1977    return;
     1978  }
     1979  tcl_debug("---");
     1980  if (tcl.command==0)
     1981  {
     1982    return;//TODO check on inside comment
     1983  }
     1984  if (tcl.string_last != "")
     1985  {// get last word
     1986    tcl.list_command.append(tcl.string_last);
     1987    tcl.string_last="";
     1988  }
     1989  yy_pop_state();
     1990
     1991  // check command
     1992  QString myStr = *tcl.list_command.at(0);
     1993  int myLevel = 0;
     1994  Protection myProt = tcl.protection;
     1995
     1996  if (tcl.list_command.count() < 3)
     1997  {
     1998    tcl_command_OTHER(text);
     1999    goto command_end;
     2000  }
     2001  // remove leading "::" and apply TCL_SUBST
     2002  if (myStr.left(2)=="::") myStr = myStr.mid(2);
     2003  if (tcl.config_subst.contains(myStr)) {myStr=tcl.config_subst[myStr];}
     2004  if (strcmp("private",myStr)==0)
     2005  {
     2006    tcl.protection = Private;
     2007    myLevel = 1;
     2008  }
     2009  else if (strcmp("protected",myStr)==0)
     2010  {
     2011    tcl.protection = Protected;
     2012    myLevel = 1;
     2013  }
     2014  else if (strcmp("public",myStr)==0)
     2015  {
     2016    tcl.protection = Public;
     2017    myLevel = 1;
     2018  }
     2019  if (myLevel)
     2020  {
     2021    tcl_codify("keyword",*tcl.list_command.at(0));
     2022    tcl_codify(NULL,*tcl.list_command.at(1));
     2023    tcl.list_command.remove(tcl.list_command.at(1));
     2024    tcl.list_command.remove(tcl.list_command.at(0));
     2025    if (tcl.list_command.count()==1)
     2026    {
     2027      tcl_scan *myScan = tcl.scan.at(0);
     2028      myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(0),text);
     2029      myProt = tcl.protection;
     2030      goto command_end;
     2031    }
     2032    myStr       = *tcl.list_command.at(0);
     2033    // remove leading "::" and apply TCL_SUBST
     2034    if (myStr.left(2)=="::") myStr = myStr.mid(2);
     2035    if (tcl.config_subst.contains(myStr)) {myStr=tcl.config_subst[myStr];}
     2036  }
     2037  if (strcmp("proc",myStr)==0)
     2038  {
     2039    if (tcl.list_command.count() == 5)
     2040    {// itcl::proc
     2041      tcl.list_command.append("");
     2042      tcl.list_command.append("");
     2043    }
     2044    if (tcl.list_command.count() != 7) {goto command_warn;}
     2045    tcl_command_PROC(text);
     2046    goto command_end;
     2047  }
     2048  if (strcmp("method",myStr)==0)
     2049  {
     2050    if (tcl.list_command.count() == 5)
     2051    {// itcl::method
     2052      tcl.list_command.append("");
     2053      tcl.list_command.append("");
     2054    }
     2055    if (tcl.list_command.count() != 7) {goto command_warn;}
     2056    tcl_command_METHOD(text);
     2057    goto command_end;
     2058  }
     2059  if (strcmp("constructor",myStr)==0)
     2060  {
     2061    if (tcl.list_command.count() != 5) {goto command_warn;}
     2062    tcl_command_CONSTRUCTOR(text);
     2063    goto command_end;
     2064  }
     2065  if (strcmp("destructor",myStr)==0)
     2066  {
     2067    if (tcl.list_command.count() != 3) {goto command_warn;}
     2068    tcl_command_DESTRUCTOR(text);
     2069    goto command_end;
     2070  }
     2071  if (strcmp("namespace",myStr)==0)
     2072  {
     2073    if (strcmp("eval",*tcl.list_command.at(2))==0)
     2074    {
     2075      if (tcl.list_command.count() < 7) {goto command_warn;}
     2076      tcl_command_NAMESPACE(text);
     2077      goto command_end;
     2078    }
     2079    tcl_command_OTHER(text);
     2080    goto command_end;
     2081  }
     2082  if (strcmp("itcl::class",myStr)==0)
     2083  {
     2084    if (tcl.list_command.count() != 5) {goto command_warn;}
     2085    tcl_command_ITCL_CLASS(text);
     2086    goto command_end;
     2087  }
     2088  if (strcmp("itcl::body",myStr)==0)
     2089  {
     2090    if (tcl.list_command.count() != 7) {goto command_warn;}
     2091    tcl_command_ITCL_BODY(text);
     2092    goto command_end;
     2093  }
     2094  if (strcmp("oo::class",myStr)==0)
     2095  {
     2096    if (strcmp("create",*tcl.list_command.at(2))==0)
     2097    {
     2098      if (tcl.list_command.count() != 7) {goto command_warn;}
     2099      tcl_command_OO_CLASS(text);
     2100      goto command_end;
     2101    }
     2102    tcl_command_OTHER(text);
     2103    goto command_end;
     2104  }
     2105  if (strcmp("oo::define",myStr)==0)
     2106  {
     2107    if (tcl.list_command.count() < 5) {goto command_warn;}
     2108    tcl_command_OO_DEFINE(text);
     2109    goto command_end;
     2110  }
     2111  if (strcmp("variable",myStr)==0)
     2112  {
     2113    if (tcl.list_command.count() < 3) {goto command_warn;}
     2114    if (tcl.scan.at(0)->entry_fn == NULL)
     2115    {// only parsed outside functions
     2116      tcl_command_VARIABLE(text,tcl.scan.at(0)->entry_cl!=NULL&&tcl.scan.at(0)->entry_cl->name!="");
     2117      goto command_end;
     2118    }
     2119  }
     2120  if (strcmp("common",myStr)==0)
     2121  {
     2122    if (tcl.list_command.count() < 3) {goto command_warn;}
     2123    if (tcl.scan.at(0)->entry_fn == NULL)
     2124    {// only parsed outside functions
     2125      tcl_command_VARIABLE(text,0);
     2126      goto command_end;
     2127    }
     2128  }
     2129  if (strcmp("inherit",myStr)==0 || strcmp("superclass",myStr)==0)
     2130  {
     2131    if (tcl.list_command.count() < 3) {goto command_warn;}
     2132    if (tcl.scan.at(0)->entry_cl!=NULL&&tcl.scan.at(0)->entry_cl->name!="")
     2133    {
     2134      for (unsigned int i = 2; i < tcl.list_command.count(); i++)
     2135      {
     2136        tcl.scan.at(0)->entry_cl->extends->append(new BaseInfo(*tcl.list_command.at(i),Public,Normal));
     2137      }
     2138    }
     2139  }
     2140  tcl_command_OTHER(text);
     2141  goto command_end;
     2142  command_warn:
     2143    tcl_warn("count=%d: %s",tcl.list_command.count(),tcl.list_command.join(" ").ascii());
     2144    tcl_command_OTHER(text);
     2145  command_end:
     2146    tcl.list_command.clear();
     2147    tcl.command = 0;
     2148    tcl.protection = myProt;
     2149}
     2150
     2151//----------------------------------------------------------------------------
     2152//! Common initializations.
     2153static void tcl_init()
     2154{
     2155  // Get values from option TCL_SUBST
     2156  QStrList myStrLst = Config_getList("TCL_SUBST");
     2157  if (myStrLst.count()%2 != 0) {
     2158    tcl.config_subst.clear();
     2159  } else {
     2160    for (unsigned int i=0; i < myStrLst.count(); i=i+2) {
     2161      tcl.config_subst[myStrLst.at(i)] = myStrLst.at(i+1);
     2162    }
     2163  }
     2164 
     2165  tcl.code = NULL;
     2166  tcl.code_font=NULL;
     2167  tcl.code_line=1;
     2168  tcl.code_linenumbers=1;
     2169  tcl.config_autobrief = Config_getBool("JAVADOC_AUTOBRIEF");
     2170  tcl.input_string = NULL;
     2171  tcl.input_position = 0;
     2172  tcl.file_name = NULL;
     2173  tcl.this_parser = NULL;
     2174  tcl.command=0;
     2175  tcl.comment=0;
     2176  tcl.brace_level=0;
     2177  tcl.bracket_level=0;
     2178  tcl.bracket_quote=0;
     2179  tcl.word_is=WORD;
     2180  tcl.string_command="";
     2181  tcl.string_commentline="";
     2182  tcl.string_commentcodify="";
     2183  tcl.string_comment    = "";
     2184  tcl.string_last       = "";
     2185  tcl.entry_main        = NULL;
     2186  tcl.entry_file        = NULL;
     2187  tcl.entry_current     = NULL;
     2188  tcl.entry_inside      = NULL;
     2189  tcl.list_command.clear();
     2190  tcl.scan.clear();
     2191  tcl.ns.clear();
     2192  tcl.cl.clear();
     2193  tcl.fn.clear();
     2194  yylineno              = 1;
     2195  tcl.protection        = Public;
     2196}
     2197
     2198//! Start parsing.
     2199static void tcl_parse()
     2200{
     2201  tcl_scan *myScan;
     2202
     2203  tcl.entry_file          = tcl_entry_new();
     2204  tcl.entry_file->name    = tcl.file_name;
     2205  tcl.entry_file->section = Entry::SOURCE_SEC;
     2206  tcl.entry_file->protection = Public;
     2207  tcl.entry_main->addSubEntry(tcl.entry_file);
     2208  tcl.entry_current = tcl_entry_new();
     2209
     2210  tclscanYYrestart( tclscanYYin );
     2211  BEGIN( TOP );
     2212  yylineno=1;
     2213  myScan = new tcl_scan;
     2214  myScan->type=STRING;
     2215  myScan->string_after="";
     2216  myScan->line0=yylineno;
     2217  myScan->line1=yylineno;
     2218  myScan->start_stack_ptr=yy_start_stack_ptr;
     2219  myScan->buffer_state=YY_CURRENT_BUFFER;
     2220  myScan->entry_ns=tcl_entry_namespace("");
     2221  myScan->entry_cl=tcl_entry_class("");
     2222  myScan->entry_fn=NULL;
     2223  tcl.entry_inside = myScan->entry_ns;
     2224  tcl.entry_inside = tcl.entry_file;
     2225  myScan->entry_scan = myScan->entry_ns;
     2226  tcl.scan.insert(0,myScan);
     2227
     2228  tclscanYYlex();
     2229  tcl.scan.clear();
     2230  tcl.ns.clear();
     2231  tcl.cl.clear();
     2232  tcl.fn.clear();
     2233  tcl.entry.clear();
     2234}
     2235
     2236//! Parse text file and build up entry tree.
     2237void TclLanguageScanner::parseInput(const char *fileName,const char *input,Entry *root)
     2238{
     2239  QFile            myFile;
     2240
     2241  myFile.setName(fileName);
     2242  if (!myFile.open(IO_ReadOnly)) return;
     2243
     2244  printf("Parsing '%s'...\n",fileName);
     2245  groupEnterFile(fileName,yylineno);
     2246
     2247  tcl_init();
     2248  tcl.code = NULL;
     2249  tcl.input_string = input;
     2250  tcl.file_name = fileName;
     2251  tcl.this_parser = this;
     2252  tcl.entry_main          = root; /* toplevel entry */
     2253  tcl_parse();
     2254
     2255  groupLeaveFile(tcl.file_name,yylineno);
     2256  root->program.resize(0);
     2257  myFile.close();
     2258}
     2259
     2260//! Parse file and codify.
     2261void TclLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf,
     2262                   const char * scopeName,
     2263                   const QCString & input,
     2264                   bool isExampleBlock,
     2265                   const char * exampleName,
     2266                   FileDef * fileDef,
     2267                   int startLine,
     2268                   int endLine,
     2269                   bool inlineFragment,
     2270                   MemberDef *memberDef,
     2271                   bool showLineNumbers
     2272                  )
     2273{
     2274  (void)scopeName;
     2275  (void)exampleName;
     2276  (void)fileDef;
     2277  (void)endLine;
     2278  (void)inlineFragment;
     2279  (void)memberDef;
     2280
     2281  if (input.isEmpty()) return;
     2282/*
     2283  QString myStr="Codifying..";
     2284  if (scopeName) {myStr+=" scope=";myStr+=scopeName;}
     2285  if (exampleName) {myStr+=" example=";myStr+=exampleName;}
     2286  if (memberDef) {myStr+=" member=";myStr+=memberDef->memberTypeName();
     2287        myStr+=" ";myStr+=memberDef->qualifiedName();}
     2288  if (fileDef) {myStr+=" file=";myStr+=fileDef->fileName();}
     2289 
     2290printf("%s (%d,%d) %d %d\n====%s\n====\n",myStr.ascii(),startLine,endLine,isExampleBlock,inlineFragment,input.data());
     2291*/
     2292  QCString myInput = input;
     2293  if (input.at(input.length()-1) != '\n') {
     2294    myInput += "\n";
     2295  }
     2296  if (isExampleBlock) {tcl_codify(NULL,input);return;}
     2297  tcl_init();
     2298  tcl.code = &codeOutIntf;
     2299  if (startLine<0) {
     2300    startLine=1;
     2301  }
     2302  yylineno=startLine;
     2303  tcl.code_linenumbers = showLineNumbers;
     2304  tcl.code_line=yylineno;
     2305  if (tcl.code_linenumbers) {
     2306    tcl.code->writeLineNumber(0,0,0,tcl.code_line);
     2307  }
     2308  tcl.input_string = myInput.data();
     2309  tcl.file_name = "";
     2310  tcl.this_parser = NULL;
     2311  tcl.entry_main = tcl_entry_new();
     2312  tcl_parse();
     2313  tcl.scan.clear();
     2314  tcl.ns.clear();
     2315  tcl.cl.clear();
     2316  tcl.fn.clear();
     2317  tcl.entry.clear();
     2318}
     2319
     2320bool TclLanguageScanner::needsPreprocessing(const QCString &extension)
     2321{
     2322  (void)extension;
     2323  return FALSE;
     2324}
     2325
     2326void TclLanguageScanner::resetCodeParserState()
     2327{
     2328}
     2329
     2330void TclLanguageScanner::parsePrototype(const char *text)
     2331{
     2332  (void)text;
     2333}
     2334
     2335static int yyread(char *buf,int max_size)
     2336{
     2337  int c=0;
     2338
     2339  *buf = '\0';
     2340  while ( c < max_size && tcl.input_string[tcl.input_position] )
     2341  {
     2342    *buf = tcl.input_string[tcl.input_position++] ;
     2343    c++; buf++;
     2344  }
     2345  //printf("Read from=%d size=%d max=%d c=%d\n",tcl.input_position,strlen(&tcl.input_string[tcl.input_position]),max_size,c);
     2346  return c;
     2347}
     2348
     2349//----------------------------------------------------------------------------
     2350
     2351#if !defined(YY_FLEX_SUBMINOR_VERSION)
     2352//----------------------------------------------------------------------------
     2353extern "C" { // some bogus code to keep the compiler happy
     2354  void fscannerYYdummy() { yy_flex_realloc(0,0); }
     2355}
     2356#endif
     2357
  • doc/docblocks.doc

    C> input parameter 
    480480      end function A
    481481\endverbatim
    482482
     483\section tclblocks Documentation blocks in Tcl
     484
     485Doxygen documentation can be included in normal Tcl comments.
     486
     487To start a new documentation block start a line with \c ## (two hashes).
     488All following comment lines and continuation lines will be added to this
     489block. The block ends with a line not starting with a \c # (hash sign).
     490
     491A brief documentation can be added with \c ;#< (semicolon, hash and
     492lower then sign). The brief documentation also ends at a line not starting
     493with a \c # (hash sign).
     494
     495Inside doxygen comment blocks all normal doxygen markings are supported.
     496The ony difference are described in the following two paragraphs.
     497
     498If a doxygen comment block ends with a line containing only
     499\c #\\code or \c #\@code all code until a line only containing \c #\\endcode
     500or \c #\@endcode is added to the generated documentation as code block.
     501
     502If a doxygen comment block ends with a line containing only
     503\c #\\verbatim or \c #\@verbatim all code until a line only containing
     504\c #\\endverbatim or \c #\@endverbatim is added verbatim to the generated
     505documentation.
     506
     507To detect namespaces, classes, functions and variables the following
     508Tcl commands are recognized. Documentation blocks can be put on the lines
     509before the command.
     510
     511<ul>
     512<li><tt>namespace eval ..</tt> Namespace
     513<li><tt>proc ..</tt> Function
     514<li><tt>variable ..</tt> Variable
     515<li><tt>common ..</tt> Common variable
     516<li><tt>itcl::class ..</tt> Class
     517<li><tt>itcl::body ..</tt> Class method body definition
     518<li><tt>oo::class create ..</tt> Class
     519<li><tt>oo::define ..</tt> OO Class definition
     520<li><tt>method ..</tt> Class method definitions
     521<li><tt>constructor ..</tt> Class constructor
     522<li><tt>destructor ..</tt> Class destructor
     523<li><tt>public ..</tt> Set protection level
     524<li><tt>protected ..</tt> Set protection level
     525<li><tt>private ..</tt> Set protection level
     526</ul>
     527
     528To use your own keywords you an map these keyword to the recognized commands
     529using the \ref cfg_tcl_subs "TCL_SUBST" entry in the config file.
     530The entry contain a list of word-keyword mappings. To use the itcl::*
     531commands without the leading namespace use p.e.:
     532
     533\verbatim TCL_SUBST = class itcl:class body itcl:body \endverbatim
     534
     535Following is a example using doxygen style comments:
     536
     537\include tclexample.tcl
     538 \htmlonly
     539 Click <a href="$(DOXYGEN_DOCDIR)/examples/tclexample/html/index.html">here</a>
     540 for the corresponding HTML documentation that is generated by doxygen.
     541 \endhtmlonly
     542
     543\htmlonly
     544Go to the <a href="lists.html">next</a> section or return to the
     545 <a href="index.html">index</a>.
     546\endhtmlonly
     547
    483548*/
  • examples/Makefile.in

    all: class/html/index.html \ 
    2424     memgrp/html/index.html \
    2525     docstring/html/index.html \
    2626     pyexample/html/index.html \
     27     tclexample/html/index.html \
    2728     mux/html/index.html \
    2829     manual/html/index.html
    2930
    clean: 
    3132        rm -rf  class define enum file func page relates author \
    3233                par overload example include qtstyle jdstyle structcmd \
    3334                autolink tag restypedef afterdoc template tag group diagrams \
    34                 memgrp docstring pyexample mux manual
     35                memgrp docstring pyexample tclexample mux manual
    3536
    3637class/html/index.html: class.h class.cfg
    3738        $(DOXYGEN)/bin/doxygen class.cfg
    memgrp/html/index.html: memgrp.cpp memgr 
    104105pyexample/html/index.html: pyexample.py pyexample.cfg
    105106        $(DOXYGEN)/bin/doxygen pyexample.cfg
    106107
     108tclexample/html/index.html: tclexample.tcl tclexample.cfg
     109        $(DOXYGEN)/bin/doxygen tclexample.cfg
     110
    107111mux/html/index.html: mux.vhdl mux.cfg
    108112        $(DOXYGEN)/bin/doxygen mux.cfg
    109113
  • examples/Makefile.win.in

    all: class/html/index.html \ 
    2525     memgrp/html/index.html \
    2626     docstring/html/index.html \
    2727     pyexample/html/index.html \
     28     tclexample/html/index.html \
    2829     mux/html/index.html \
    2930     manual/html/index.html
    3031
    3132clean:
    32         del /s/y class define enum file pyexample docstring
     33        del /s/y class define enum file pyexample tclexample docstring
    3334        del /s/y func page relates author
    3435        del /s/y par overload example include qtstyle
    3536        del /s/y jdstyle structcmd autolink resdefine mux manual
    memgrp/html/index.html: memgrp.cpp memgr 
    104105pyexample/html/index.html: pyexample.py pyexample.cfg
    105106        $(DOXYDIR)\doxygen pyexample.cfg
    106107
     108tclexample/html/index.html: tclexample.tcl tclexample.cfg
     109        $(DOXYDIR)\doxygen tclexample.cfg
     110
    107111mux/html/index.html: mux.vhdl mux.cfg
    108112        $(DOXYDIR)\doxygen mux.cfg
    109113
  • examples/tclexample.cfg

     
     1PROJECT_NAME     = "Tcl"
     2OUTPUT_DIRECTORY = tclexample
     3GENERATE_LATEX   = NO
     4GENERATE_MAN     = NO
     5GENERATE_RTF     = NO
     6CASE_SENSE_NAMES = NO
     7INPUT            = tclexample.tcl
     8QUIET            = YES
     9JAVADOC_AUTOBRIEF = YES
     10SEARCHENGINE     = NO
     11INLINE_SOURCES   = YES
     12EXTRACT_ALL      = YES
     13EXTRACT_PRIVATE  = YES
  • examples/tclexample.tcl

     
     1## \file tclexample.tcl
     2# File documentation.
     3#\verbatim
     4
     5# Startup code:\
     6exec tclsh "$0" "$@"
     7#\endverbatim
     8## Documented namespace \c ns .
     9# The code is inserted here:
     10#\code
     11namespace eval ns {
     12  ## Documented proc \c ns_proc .
     13  # param[in] arg some argument
     14  proc ns_proc {arg} {}
     15  ## Documented var \c ns_var .
     16  # Some documentation.
     17  variable ns_var
     18  ## Documented itcl class \c itcl_class .
     19  itcl::class itcl_class {
     20    ## Create object.
     21    constructor {args} {eval $args}
     22    ## Destroy object.
     23    destructor {exit}
     24    ## Documented itcl method \c itcl_method_x .
     25    # param[in] arg Argument
     26    private method itcl_method_x {arg}
     27    ## Documented itcl method \c itcl_method_y .
     28    # param[in] arg Argument
     29    protected method itcl_method_y {arg} {}
     30    ## Documented itcl method \c itcl_method_z .
     31    # param[in] arg Argument
     32    public method itcl_method_z {arg} {}
     33    ## Documented common itcl var \c itcl_Var .
     34    common itcl_Var
     35    ## \protectedsection
     36   
     37    variable itcl_var1;#< Documented itcl var \c itcl_var1 .
     38    variable itcl_var2;#< Documented itcl var \c itcl_var2 .
     39  }
     40  ## Documented oo class \c oo_class .
     41  oo::class create oo_class {
     42    ## Create object.
     43    # Configure with args
     44    constructor {args} {eval $args}
     45    ## Destroy object.
     46    # Exit.
     47    destructor {exit}
     48    ## Documented oo var \c oo_var .
     49    # Defined inside class
     50    variable oo_var
     51    ## \private Documented oo method \c oo_method_x .
     52    # param[in] arg Argument
     53    method oo_method_x {arg} {}
     54    ## \protected Documented oo method \c oo_method_y .
     55    # param[in] arg Argument
     56    method oo_method_y {arg} {}
     57    ## \public Documented oo method \c oo_method_z .
     58    # param[in] arg Argument
     59    method oo_method_z {arg} {}
     60  }
     61}
     62#\endcode
     63
     64itcl::body ::ns::itcl_class::itcl_method_x {argx} {
     65  puts "$argx OK"
     66}
     67
     68oo::define ns::oo_class {
     69  ## \public Outside defined variable \c oo_var_out .
     70  # Inside oo_class
     71  variable oo_var_out
     72}
     73
     74## Documented global proc \c glob_proc .
     75# param[in] arg Argument
     76proc glob_proc {arg} {puts $arg}
     77
     78variable glob_var;#< Documented global var \c glob_var\
     79  with newline
     80#< and continued line
     81
     82# end of file