/***************************************************************************** * Parser for Tcl subset * * Copyright (C) 2010 by Rene Zaumseil * based on the work of Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * */ %{ #include #include #include #include #include "qtbc.h" #include #include #include #include #include #include #include "entry.h" #include "message.h" #include "config.h" #include "doxygen.h" #include "util.h" #include "defargs.h" #include "language.h" #include "commentscan.h" #include "pre.h" #include "tclscanner.h" #include "outputlist.h" #include "membername.h" #include "searchindex.h" #include "commentcnv.h" #include "bufstr.h" #include "portable.h" #include #include #include #include //#include #define HAS_TCL_SUBST 0 #define YY_NEVER_INTERACTIVE 1 #define MAX_INCLUDE_DEPTH 10 #define tcl_abort \ fprintf(stderr,"%s#%d %s()",__FILE__,__LINE__,__FUNCTION__); \ yy_push_state(ERROR); \ yyless(0); \ tcl_Abort //#define TCL_DEBUG_FD NULL #define TCL_WARN_FD stdout #define tcl_warn \ tcl_Warn("%.6d--(%s) %d# ",__LINE__,__FUNCTION__,yylineno); \ tcl_Warn #define TCL_DEBUG_FD NULL //#define TCL_DEBUG_FD stdout #define tcl_debug \ tcl_Debug("%.6d--(%s) %d#%d ",__LINE__,__FUNCTION__,yylineno,yy_start_stack_ptr); \ tcl_Debug //#define D printf("%.6d---(%s)%s\n",__LINE__,__FUNCTION__,yytext); #define D // BEGIN of copy from tclUtil.c // - Tcl_Interp removed // - changes are marked with RZ // #define's to adapt the code: #define CONST const #define UCHAR (unsigned char) #define TCL_ERROR 1 #define TCL_OK 0 #define ckalloc malloc #define ckfree free #define TclCopyAndCollapse(size,src,dest) memcpy(dest,src,size); *(dest+size)=0 int TclFindElement( CONST char *list, /* Points to the first byte of a string * containing a Tcl list with zero or more * elements (possibly in braces). */ int listLength, /* Number of bytes in the list's string. */ CONST char **elementPtr, /* Where to put address of first significant * character in first element of list. */ CONST char **nextPtr, /* Fill in with location of character just * after all white space following end of * argument (next arg or end of list). */ int *sizePtr, /* If non-zero, fill in with size of * element. */ int *bracePtr) /* If non-zero, fill in with non-zero/zero to * indicate that arg was/wasn't in braces. */ { CONST char *p = list; CONST char *elemStart; /* Points to first byte of first element. */ CONST char *limit; /* Points just after list's last byte. */ int openBraces = 0; /* Brace nesting level during parse. */ int inQuotes = 0; int size = 0; /* lint. */ //RZ int numChars; /* * Skim off leading white space and check for an opening brace or quote. * We treat embedded NULLs in the list as bytes belonging to a list * element. */ limit = (list + listLength); while ((p < limit) && (isspace(UCHAR(*p)))) { /* INTL: ISO space. */ p++; } if (p == limit) { /* no element found */ elemStart = limit; goto done; } if (*p == '{') { openBraces = 1; p++; } else if (*p == '"') { inQuotes = 1; p++; } elemStart = p; if (bracePtr != 0) { *bracePtr = openBraces; } /* * Find element's end (a space, close brace, or the end of the string). */ while (p < limit) { switch (*p) { /* * Open brace: don't treat specially unless the element is in * braces. In this case, keep a nesting count. */ case '{': if (openBraces != 0) { openBraces++; } break; /* * Close brace: if element is in braces, keep nesting count and * quit when the last close brace is seen. */ case '}': if (openBraces > 1) { openBraces--; } else if (openBraces == 1) { size = (p - elemStart); p++; if ((p >= limit) || isspace(UCHAR(*p))) { /* INTL: ISO space. */ goto done; } /* * Garbage after the closing brace; return an error. */ return TCL_ERROR; } break; /* * Backslash: skip over everything up to the end of the backslash * sequence. */ case '\\': //RZ Tcl_UtfBackslash(p, &numChars, NULL); //RZ p += (numChars - 1); p++; //RZ break; /* * Space: ignore if element is in braces or quotes; otherwise * terminate element. */ case ' ': case '\f': case '\n': case '\r': case '\t': case '\v': if ((openBraces == 0) && !inQuotes) { size = (p - elemStart); goto done; } break; /* * Double-quote: if element is in quotes then terminate it. */ case '"': if (inQuotes) { size = (p - elemStart); p++; if ((p >= limit) || isspace(UCHAR(*p))) { /* INTL: ISO space */ goto done; } /* * Garbage after the closing quote; return an error. */ return TCL_ERROR; } break; } p++; } /* * End of list: terminate element. */ if (p == limit) { if (openBraces != 0) { return TCL_ERROR; } else if (inQuotes) { return TCL_ERROR; } size = (p - elemStart); } done: while ((p < limit) && (isspace(UCHAR(*p)))) { /* INTL: ISO space. */ p++; } *elementPtr = elemStart; *nextPtr = p; if (sizePtr != 0) { *sizePtr = size; } return TCL_OK; } int Tcl_SplitList( CONST char *list, /* Pointer to string with list structure. */ int *argcPtr, /* Pointer to location to fill in with the * number of elements in the list. */ CONST char ***argvPtr) /* Pointer to place to store pointer to array * of pointers to list elements. */ { CONST char **argv, *l, *element; char *p; int length, size, i, result, elSize, brace; /* * Figure out how much space to allocate. There must be enough space for * both the array of pointers and also for a copy of the list. To estimate * the number of pointers needed, count the number of space characters in * the list. */ for (size = 2, l = list; *l != 0; l++) { if (isspace(UCHAR(*l))) { /* INTL: ISO space. */ size++; /* * Consecutive space can only count as a single list delimiter. */ while (1) { char next = *(l + 1); if (next == '\0') { break; } ++l; if (isspace(UCHAR(next))) { /* INTL: ISO space. */ continue; } break; } } } length = l - list; argv = (CONST char **) ckalloc((unsigned) ((size * sizeof(char *)) + length + 1)); for (i = 0, p = ((char *) argv) + size*sizeof(char *); *list != 0; i++) { CONST char *prevList = list; result = TclFindElement(list, length, &element, &list, &elSize, &brace); length -= (list - prevList); if (result != TCL_OK) { ckfree((char *) argv); return result; } if (*element == 0) { break; } if (i >= size) { ckfree((char *) argv); return TCL_ERROR; } argv[i] = p; if (brace) { memcpy(p, element, (size_t) elSize); p += elSize; *p = 0; p++; } else { TclCopyAndCollapse(elSize, element, p); p += elSize+1; } } argv[i] = NULL; *argvPtr = argv; *argcPtr = i; return TCL_OK; } // END of tclUtil.c void tcl_split_list(QString &str, QStringList &list) { int argc; const char **argv; list.clear(); if (str.left(1)=="{" && str.right(1)=="}") { str=str.mid(1,str.length()-2); } else if (str.left(1)=="\"" && str.right(1)=="\"") { str=str.mid(1,str.length()-2); } if (Tcl_SplitList(str.ascii(),&argc,&argv) != TCL_OK) { list.append(str); } else { for (int i = 0; i < argc; i++) { list.append(argv[i]); } ckfree((char *) argv); } } //! Structure containing information about current scan context. typedef struct { int type; QCString string_after; int line0; // start line of scan context int line1; // end line of scan context int start_stack_ptr; // value of scan context YY_BUFFER_STATE buffer_state; // value of scan context Entry *entry_ns; // current namespace Entry *entry_fn; // if set contains the current proc/method/constructor/destructor Entry *entry_cl; // if set contain the current class Entry *entry_scan; // current scan entry Protection protection; // current protections state } tcl_scan; //* Structure containing all internal global variables. static struct { CodeOutputInterface * code; // if set then we are codifying the file int code_line; // current line of code int code_linenumbers; // if true create line numbers in code const char *code_font; // used font to codify bool config_autobrief; // value of configuration option #if HAS_TCL_SUBST QMap config_subst; // map of configuration option values #endif const char * input_string; // file contents int input_position; // position in file QCString file_name; // name of used file ParserInterface *this_parser; // myself int command; // true if command was found int comment; // set true if comment was scaned int brace_level; // bookkeeping of braces int bracket_level; // bookkeeping of brackets int bracket_quote; // bookkeeping of quotes (toggles) int word_is; // type of current word int line_comment; // line number of comment int line_commentline; // line number of comment after command int line_command; // line number of command int line_body0; // start line of body int line_body1; // end line of body QString string_command; // contain current command QString string_commentline; // contain current comment after command QString string_commentcodify; // current comment string used in codifying QString string_comment; // contain current comment QString string_last; // contain last read word or part of word QString string; // temporary string value Entry* entry_main; // top level entry Entry* entry_file; // entry of current file Entry* entry_current; // currently used entry Entry* entry_inside; // contain entry of current scan context QStringList list_command; // list of command words QList scan; // stack of scan contexts QDict ns; // all read namespace entries QDict cl; // all read class entries QDict fn; // all read function entries QList entry; // list of all created entries, will be deleted after codifying Protection protection; // current protections state } tcl; // scanner functions static int yyread(char *buf,int max_size); tcl_scan *tcl_scan_start(int type, QString content); static void tcl_scan_end(); static void tcl_comment(int what,const char *text); static void tcl_word(int what,const char *text); static void tcl_command(int what,const char *text); // helper functions //! Create new entry. // @return new initialised entry Entry* tcl_entry_new() { Entry *myEntry = new Entry; myEntry->section = Entry::EMPTY_SEC; myEntry->name = ""; // myEntry->type = ""; myEntry->brief = ""; // myEntry->doc = ""; myEntry->protection = Package; // myEntry->mtype = Method; // myEntry->virt = Normal; // myEntry->stat = FALSE; myEntry->fileName = tcl.file_name; myEntry->lang = SrcLangExt_Tcl; initGroupInfo(myEntry); // collect entries if (tcl.code==NULL) { tcl.entry.insert(0,myEntry); } return myEntry; } //! Set protection level. void tcl_protection(Entry *entry) { if (entry->protection!=Public&&entry->protection!=Protected&&entry->protection!=Private) { entry->protection = tcl.protection; } if (entry->protection!=Protected&&entry->protection!=Private) { entry->protection = Public; } } //! Check name. // @return 'ns' and 'name' of given current 'ns0' and 'name0' static void tcl_name(const QString ns0, const QString name0, QString &ns, QString &name) { QString myNm; int myStart; if (strncmp(name0.ascii(),"::",2)==0) { myNm = name0.mid(2); } else if (ns0.length()) { myNm = ns0 + "::" + name0; } else { myNm = name0; } myStart = myNm.findRev("::"); if (myStart == -1) { ns = ""; name = myNm; } else { ns = myNm.mid(0,myStart); name = myNm.mid(myStart+2); } } // Check and return namespace entry. // @return namespace entry Entry* tcl_entry_namespace(const QString ns) { Entry *myEntry; QString myNs = " "; if (strlen(ns.ascii())) {myNs = ns;} myEntry = tcl.ns.find(myNs); if (myEntry == NULL) { myEntry = tcl_entry_new(); myEntry->section = Entry::NAMESPACE_SEC; myEntry->name = ns.ascii(); tcl.entry_main->addSubEntry(myEntry); tcl.ns.insert(ns,myEntry); } return myEntry; } // Check and return class entry. // @return class entry Entry* tcl_entry_class(const QString cl) { Entry *myEntry; QString myCl = " "; if (strlen(cl.ascii())) {myCl = cl;} myEntry = tcl.cl.find(myCl); if (myEntry == NULL) { myEntry = tcl_entry_new(); myEntry->section = Entry::CLASS_SEC; myEntry->name = cl.ascii(); tcl.entry_main->addSubEntry(myEntry); tcl.cl.insert(cl,myEntry); } return myEntry; } //! Check for keywords. // @return 1 if keyword and 0 otherwise static int tcl_keyword(QString str) { static QStringList myList; static int myInit=1; if (myInit) { // tcl keywords 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"; // tk keywords 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"; myList.sort(); myInit=0; } str=str.stripWhiteSpace(); if (str.left(2)=="::") {str=str.mid(2);} if (myList.findIndex(str) != -1) return(1); return 0; } //! End codifying with special font class. static void tcl_font_end() { if (tcl.code==NULL) return; if (tcl.code_font) { tcl.code->endFontClass(); tcl.code_font=NULL; } } //! Codify 'str' with special font class 's'. static void tcl_codify(const char *s,char *str) { if (tcl.code==NULL||str==NULL) return; if (s) { tcl_font_end(); tcl.code->startFontClass(s); tcl.code_font=s; } char *p=str,*sp=p; char c; bool done=FALSE; while (!done) { sp=p; while ((c=*p++) && c!='\n') {} if (c=='\n') { tcl.code_line++; *(p-1)='\0'; tcl.code->codify(sp); //tcl_font_end(); tcl.code->endCodeLine(); if (tcl.code_linenumbers) { tcl.code->writeLineNumber(0,0,0,tcl.code_line); } } else { tcl.code->codify(sp); done=TRUE; } } tcl_font_end(); } //! Codify 'str' with special font class 's'. static void tcl_codify(const char *s,const char *str) { if (tcl.code==NULL) return; char *tmp= (char *) malloc(strlen(str)+1); strcpy(tmp, str); tcl_codify(s,tmp); free(tmp); } //! Codify 'str' with special font class 's'. static void tcl_codify(const char *s,QString str) { if (tcl.code==NULL) return; char *tmp= (char *) malloc(str.length()+1); strcpy(tmp, str.data()); tcl_codify(s,tmp); free(tmp); } //! Codify 'str' with special font class 's'. static void tcl_codify(const char *s,QCString str) { if (tcl.code==NULL) return; char *tmp= (char *) malloc(str.length()+1); strcpy(tmp, str); tcl_codify(s,tmp); free(tmp); } //! Print abort message. static void tcl_Abort(const char *format, ...) { va_list myList; fprintf(stderr,"=== Error in file %s line: %d, state: %d ===\n",tcl.file_name.data(),yylineno,YY_START); va_start(myList, format); vfprintf(stderr,format, myList); va_end(myList); fprintf(stderr,"\n===\n"); EntryListIterator eli(*tcl.entry_main->children()); Entry *ce; bool start=FALSE; for (;(ce=eli.current());++eli) { if (ce == tcl.entry_file) start=TRUE; if (start) ce->reset(); } } //! Print warning message. static void tcl_Warn(const char *format, ...) { va_list myList; FILE *fd=TCL_WARN_FD; if (fd==NULL) return; va_start(myList, format); vfprintf(fd, format, myList); fputc('\n',fd); va_end(myList); } //! Print debug message. static void tcl_Debug(const char *format, ...) { va_list myList; FILE *fd=TCL_DEBUG_FD; if (fd==NULL) return; va_start(myList, format); vfprintf(fd, format, myList); fputc('\n',fd); va_end(myList); } /* //! Print debug message. static void tcl_Debug(const tcl_scan *s,const char *format, ...) { va_list myList; FILE *fd=TCL_DEBUG_FD; if (fd==NULL) return; va_start(myList, format); vfprintf(fd, format, myList); va_end(myList); fprintf(fd, ": tcl_scan[%d,%d] stack=%d type=%d name='%s'\n", s->line0,s->line1,s->start_stack_ptr,s->type,s->entry_ns->name.data()); } //! Print debug message. static void tcl_Debug(const Entry *e,const char *format, ...) { va_list myList; FILE *fd=TCL_DEBUG_FD; if (fd==NULL) return; va_start(myList, format); vfprintf(fd, format, myList); va_end(myList); fprintf(fd,": Entry '%s' type=%s, section=0x%x file=%s (%d children)\n", (const char*)e->name, (const char*)e->type, e->section, (const char*)e->fileName, e->children()->count()); } */ //----------------------------------------------------------------------------- #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); //----------------------------------------------------------------------------- %} ws ([ \t]|\\\n) %option yylineno %option noyywrap %option stack %x ERROR %x TOP %x COMMAND %x WORD %x COMMENT %x COMMENT_NL %x COMMENT_CODE %x COMMENT_VERB %x COMMENTLINE %x COMMENTLINE_NL %x STRING %x QUOTE %x BRACE %x BRACKET %% . { D yyterminate(); } <> { D if (tcl.scan.count()<1) {// error D tcl_abort("stack empty"); yyterminate(); } else if (tcl.scan.count()==1) {// exit, check on input? D yyterminate(); } else {// continue D tcl_command(-1,""); tcl_scan_end(); } } "#" { D yyless(0); tcl.line_comment=yylineno; tcl_comment(0,""); } ({ws}|[\;\n])+ { D tcl_codify(NULL,yytext); } . { D yyless(0); tcl.line_command=yylineno; tcl_command(0,""); } [ \t]* { D tcl_codify("comment",yytext); } "##".*\\\n { D tcl_codify("comment",yytext); QString t=yytext; t = t.mid(2,t.length()-3); t.append('\n'); tcl_comment(1,t.ascii()); yy_push_state(COMMENT_NL); } "##".*\n { D tcl_codify("comment",yytext); tcl_comment(1,yytext+2); } "#"[@\\]"code"\n[ \t]*[^#] { D QString t=yytext; tcl_codify("comment",t.left(7)); tcl_comment(2,"\n@code\n"); yyless(7); yy_push_state(COMMENT_CODE); } "#"[@\\]"endcode"\n { D QString t=yytext; t = t.left(t.length()-10); tcl_comment(2,t.ascii()); tcl_comment(2,"\n@endcode\n"); yy_pop_state(); yyless(0); } .*\n { D yymore(); } "#"[@\\]"verbatim"\n[ \t]*[^#] { D QString t=yytext; tcl_codify("comment",t.left(11)); tcl_comment(2,"\n@verbatim\n"); yyless(11); yy_push_state(COMMENT_VERB); } "#"[@\\]"endverbatim"\n { D QString t=yytext; t = t.left(t.length()-14); tcl_comment(2,t.ascii()); tcl_comment(2,"\n@endverbatim\n"); yy_pop_state(); yyless(0); } .*\n { D yymore(); } "#".*\\\n { D tcl_codify("comment",yytext); QString t=yytext; t = t.mid(1,t.length()-3); t.append('\n'); tcl_comment(2,t.ascii()); yy_push_state(COMMENT_NL); } .*\\\n { D tcl_codify("comment",yytext); tcl_comment(2,yytext); } .*\n { D tcl_codify("comment",yytext); tcl_comment(2,yytext); yy_pop_state(); } "#".*\x1A { D QString t=yytext; t = t.mid(0,t.length()-1); tcl_codify("comment",t.ascii()); t = t.mid(1,t.length()); tcl_comment(-2,t.ascii()); unput(0x1A); } "#".*\n { D tcl_codify("comment",yytext); tcl_comment(2,yytext+1); } \x1A { D tcl_comment(-2,yytext); } .|\n { D yyless(0); tcl_comment(-2,yytext); } [ \t]* { D tcl.string_commentcodify += yytext; } "#<".*\\\n { D tcl.string_commentcodify += yytext; QString t=yytext; t = t.mid(2,t.length()-4); t.append('\n'); tcl.string_commentline += t; yy_push_state(COMMENTLINE_NL); } "#<".*\n { D tcl.string_commentcodify += yytext; tcl.string_commentline += (yytext+2); } .*\\\n { D tcl.string_commentcodify += yytext; QString t=yytext; t = t.left(t.length()-3); t.append('\n'); tcl.string_commentline += t; } .*\n { D tcl.string_commentcodify += yytext; tcl.string_commentline += yytext; yy_pop_state(); } .*\x1A { D QString t=yytext; t = t.left(t.length()-1); tcl.string_commentcodify += t; tcl.string_commentline += t; yy_pop_state(); unput(0x1A); } .|\n { D yy_pop_state(); if (tcl.string_commentline.length()) { tcl.entry_current->brief = tcl.string_commentline; tcl.entry_current->briefLine = tcl.line_commentline; tcl.entry_current->briefFile = tcl.file_name; } yyless(0); tcl_command(-1,tcl.string_commentcodify.ascii()); tcl.string_commentline=""; tcl.string_commentcodify=""; } {ws}*[\;]{ws}*"#<" { D tcl.string_commentcodify = yytext; tcl.string_commentcodify = tcl.string_commentcodify.left(tcl.string_commentcodify.length()-2); tcl.string_commentline = ""; tcl.line_commentline = yylineno; tcl.line_body1=yylineno; unput('<'); unput('#'); yy_push_state(COMMENTLINE); } \x1A { D tcl.string_commentcodify = ""; tcl.string_commentline = ""; tcl.line_body1=yylineno-1; tcl_command(-1,""); } {ws}*[;\n] { D tcl.string_commentcodify = ""; tcl.string_commentline = ""; tcl.line_body1=yylineno-1; tcl_command(-1,yytext); } {ws}+ { D tcl_command(1,yytext); } "{*}". { D tcl.word_is = WORD; tcl.string_last = "{*}"; tcl_word(0,&yytext[3]); } . { D switch (yytext[0]) { case '{': tcl.word_is = BRACE; break; case '[': tcl.word_is = BRACKET; break; case '"': tcl.word_is = QUOTE; break; default: tcl.word_is = WORD; } tcl.string_last = ""; tcl_word(0,yytext); } "\\\\" | "\\"[\{\}\[\]\;\" \t] { tcl_word(1,yytext); } "\\\n" { tcl_word(2,yytext); } "{" { tcl_word(3,yytext); } "}" { tcl_word(4,yytext); } "[" { tcl_word(5,yytext); } "]" { tcl_word(6,yytext); } "\"" { tcl_word(7,yytext); } " " { tcl_word(8,yytext); } "\t" { tcl_word(9,yytext); } ";" { tcl_word(10,yytext); } "\n" { tcl_word(11,yytext); } \x1A { tcl_word(12,yytext); } . { tcl_word(1,yytext); } %% //! Start new scan context for given 'content'. // @return created new scan context. tcl_scan *tcl_scan_start(int type, QString content, const char *after) { tcl_scan *myScan; QString myName; char c[2]=" "; myScan=tcl.scan.at(0); myScan->line1=yylineno; myScan->start_stack_ptr=yy_start_stack_ptr; yy_push_state(TOP); myScan=new tcl_scan; myScan->type = type; myScan->string_after=after; switch (myScan->type) { case QUOTE: c[0]='"'; tcl_debug("+++\" %d\n?%s?",tcl.line_body0,content.ascii()); break; case BRACE: c[0]='{'; tcl_debug("+++{ %d\n?%s?",tcl.line_body0,content.ascii()); break; case BRACKET: c[0]='['; tcl_debug("+++[ %d\n?%s?",tcl.line_body0,content.ascii()); break; default: tcl_debug("+++. %d\n?%s?",tcl.line_body0,content.ascii()); break; } if (c[0]!=' ') { tcl_codify(NULL,c); content = content.mid(1,content.length()-2); content += (char)0x1A;// for detection end of scan context tcl_debug("???%s?",content.ascii()); } myScan->entry_ns = tcl.scan.at(0)->entry_ns; myScan->entry_cl = tcl.scan.at(0)->entry_cl; myScan->entry_fn = tcl.scan.at(0)->entry_fn; myScan->entry_scan = tcl.entry_current; myScan->buffer_state=yy_scan_string(content.ascii()); myScan->line0=tcl.line_body0; myScan->line1=tcl.line_body1; yylineno=myScan->line0; myScan->start_stack_ptr=yy_start_stack_ptr; myScan->protection = tcl.protection; tcl.entry_inside = myScan->entry_scan; tcl.entry_current = tcl_entry_new(); tcl.scan.insert(0,myScan); yy_switch_to_buffer(myScan->buffer_state); return (myScan); } //! Close current scan context. static void tcl_scan_end() { tcl_scan *myScan; char c[2]=" "; myScan=tcl.scan.at(0); switch (myScan->type) { case QUOTE: c[0]='"'; break; case BRACE: c[0]='}'; break; case BRACKET: c[0]=']'; break; } if (c[0]!=' ') {tcl_codify(NULL,c);} if (myScan->string_after.length()) {tcl_codify("comment",myScan->string_after);} yy_delete_buffer(myScan->buffer_state); tcl.scan.removeFirst(); yy_pop_state(); myScan=tcl.scan.at(0); tcl.entry_inside = myScan->entry_scan; tcl_debug("---%d",myScan->line1); yy_switch_to_buffer(myScan->buffer_state); yylineno=myScan->line1; tcl.protection = myScan->protection; } //! Handling of word parsing. static void tcl_word(int what,const char *text) { static char myList[1024]="";// nesting level list static int myLevel=0;// number of current nesting level static int myWhite=0;// set true when next char should be whitespace static char myWord;// internal state switch (what) { case 0:// start yy_push_state(WORD); switch (text[0]) { case '{': case '[': case '"': myWord = text[0]; break; default: myWord = '.'; } myList[0]=myWord; myLevel=1; myWhite=0; break; case 1:// all other chars if (myWhite) {// {x}y "x"y tcl_abort("expected word separator: %s",text); return; } if (myLevel==0) { myWord='.'; myList[0]=myWord; myLevel=1; } break; case 2:// \\\n if (myLevel==0) { myWord=' '; yy_pop_state(); yyless(0); tcl_debug("(\\\n) ?%s?",tcl.string_last.ascii()); return; } switch (myList[myLevel-1]) { case '{': case '[': case '"': break; case '.': if (myLevel==1) { myWord=' '; yy_pop_state(); yyless(0); tcl_debug("(\\\n) ?%s?",tcl.string_last.ascii()); return; } break; } myWhite=0; break; case 3:// { if (myWhite) {// {x}{ "x"{ tcl_abort("expected word separator: %s",text); return; } switch (myList[myLevel-1]) { case '{': case '[': myList[myLevel++]='{'; break; case '"': case '.': break; } myWhite=0; break; case 4:// } if (myWhite) {// {x}{ "x"{ tcl_abort("expected word separator: %s",text); return; } switch (myList[myLevel-1]) { case '{':// {{x}} myLevel--; if (myLevel==0) {myWhite=1;} break; case '[': case '"': case '.': break; } break; case 5:// [ if (myWhite) {// {x}[ tcl_abort("expected word separator: %s",text); return; } switch (myList[myLevel-1]) { case '{': break; case '[': case '"': case '.': myList[myLevel++]='['; break; } myWhite=0; break; case 6:// ] if (myWhite) {// {x}] tcl_abort("expected word separator: %s",text); return; } switch (myList[myLevel-1]) { case '{': break; case '[': myLevel--; break; case '"': case '.': break; } myWhite=0; break; case 7:// " if (myWhite) {// {x}" tcl_abort("expected word separator: %s",text); return; } switch (myList[myLevel-1]) { case '{': break; case '[': myList[myLevel++]='"'; break; case '"': myLevel--; case '.': break; } break; case 8:// ' ' case 9:// \t case 10:// ; case 11:// \n case 12:// \x1A if (myLevel==0) { myWord=' '; yy_pop_state(); yyless(0); tcl_debug("(%d) ?%s?",what,tcl.string_last.ascii()); return; } switch (myList[myLevel-1]) { case '{': case '[': case '"': break; case '.': if (myLevel==1) { myWord=' '; yy_pop_state(); yyless(0); tcl_debug("(.%d) ?%s?",what,tcl.string_last.ascii()); return; } else { myLevel--; } break; } myWhite=0; break; default: tcl_abort("wrong state: %d",what); return; } tcl.string_last += text; } //! Handling of comment parsing. static void tcl_comment(int what,const char *text) { if (what==0) { // begin of comment if (tcl.comment) { tcl_abort("comment in comment"); return; } yy_push_state(COMMENT); tcl_debug("+++%s",text); tcl.string_comment=""; tcl.comment=0; } else if (what==1) { // start new comment if (tcl.comment) { tcl_comment(99,""); // inbody } tcl.string_comment=text; tcl.comment=1; } else if (what==2) { // add to comment if (tcl.comment) { tcl.string_comment+=text; } } else if (what==-1 || what == -2) { // end of comment without/with command if (tcl.comment) { tcl.string_last=tcl.string_comment; tcl_comment(100+what,""); } else { tcl.string_last = ""; tcl_debug("---%s",(const char *)tcl.string_comment); } yy_pop_state(); tcl.string_comment=""; tcl.comment=0; } else if (what==98 || what==99) { // 98=new 99=inbody if (tcl.this_parser && tcl.string_comment.length()) { tcl_debug("---%s",(const char *)tcl.string_comment); int myPos=0; bool myNew=0; int myLine=tcl.line_comment; BufStr myI(1024); BufStr myO(1024); Protection myProt=tcl.protection; // resolve ALIASES myI.addArray("/*!",3); myI.addArray(tcl.string_comment.ascii(),tcl.string_comment.length()); myI.addArray("*/",2); convertCppComments(&myI,&myO,tcl.file_name); myO.dropFromStart(3); myO.shrink(myO.curPos()-2); myO.addChar('\0'); QCString myDoc = myO.data(); if (what==99) { // inbody comment file or namespace or class or proc/metho int myPos0; int myLine0; Entry myEntry0; // used to test parsing Entry *myEntry; Entry *myEntry1=tcl.scan.at(0)->entry_ns; if (tcl.scan.at(0)->entry_fn) { myEntry1=tcl.scan.at(0)->entry_fn; } else if (tcl.scan.at(0)->entry_cl) { myEntry1=tcl.scan.at(0)->entry_cl; } myPos0=myPos; myLine0=myLine; while (parseCommentBlock(tcl.this_parser, &myEntry0, myDoc, tcl.file_name, myLine, FALSE, tcl.config_autobrief, FALSE, myProt, myPos, myNew)) { if (myNew) { // we need a new entry in this case myNew=0; myEntry = tcl_entry_new(); parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); tcl.entry_inside->addSubEntry(myEntry); } else { // we can add to current entry in this case parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); } myPos0=myPos; myLine0=myLine; } if (myNew) { // we need a new entry myNew=0; myEntry = tcl_entry_new(); parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); tcl.entry_inside->addSubEntry(myEntry); } else { // we can add to current entry parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); } } else { // new entry tcl.entry_current = tcl_entry_new(); while (parseCommentBlock(tcl.this_parser, tcl.entry_current, myDoc, tcl.file_name, myLine, FALSE, tcl.config_autobrief, FALSE, myProt, myPos, myNew)) { if (myNew) { tcl.entry_inside->addSubEntry(tcl.entry_current); tcl.entry_current = tcl_entry_new(); } else { tcl.entry_current->section = tcl.entry_inside->section; tcl.entry_current->name = tcl.entry_inside->name; } } if (myNew) { tcl.entry_inside->addSubEntry(tcl.entry_current); tcl.entry_current = tcl_entry_new(); } else { tcl.entry_current->section = tcl.entry_inside->section; tcl.entry_current->name = tcl.entry_inside->name; } } if (tcl.protection != myProt) { tcl.scan.at(0)->protection = tcl.protection = myProt; } } } else { tcl_abort("what %d",what); return; } } //! Parse given \c arglist . static void tcl_command_ARGLIST(QString &arglist) { Argument *myArg; QStringList myArgs; QString myArglist=""; if (tcl.entry_current->argList==NULL) { tcl.entry_current->argList=new ArgumentList; } tcl_split_list(arglist,myArgs); for (uint i=0;iname= *myArgs1.at(0); myArg->defval= *myArgs1.at(1); if (myArg->defval.isEmpty()) { myArg->defval = " "; } myArglist = myArglist + "?" + myArg->name.data() + "? "; } else { myArg->name= *myArgs.at(i); myArglist = myArglist + myArg->name.data() + " "; } tcl.entry_current->argList->append(myArg); } arglist = myArglist; tcl.entry_current->args = arglist; } //! Handle all other commands. static void tcl_command_OTHER(const char *text) { for (unsigned int i=0; i< tcl.list_command.count(); i++) { if (i==0 && tcl_keyword(*tcl.list_command.at(i))) { tcl_codify("keyword",*tcl.list_command.at(i)); } else { tcl_codify(NULL,*tcl.list_command.at(i)); } } tcl_codify(NULL,text); } //! Handle \c proc statements. static void tcl_command_PROC(const char *text) { QString myNs, myName; Entry *myEntryNs, *myEntry; tcl_scan *myScan = tcl.scan.at(0); tcl_codify("keyword",*tcl.list_command.at(0)); tcl_codify(NULL,*tcl.list_command.at(1)); tcl_codify(NULL,*tcl.list_command.at(2)); tcl_codify(NULL,*tcl.list_command.at(3)); tcl_codify(NULL,*tcl.list_command.at(4)); tcl_codify(NULL,*tcl.list_command.at(5)); tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName); if (myNs.length()) { myEntryNs = tcl_entry_namespace(myNs); } else { myEntryNs = myScan->entry_ns; } tcl.entry_current->section = Entry::FUNCTION_SEC; tcl.entry_current->mtype = Method; tcl.entry_current->name = myName; tcl.entry_current->startLine = tcl.line_command; tcl.entry_current->bodyLine = tcl.line_body0; tcl.entry_current->endBodyLine = tcl.line_body1; tcl_protection(tcl.entry_current); tcl_command_ARGLIST(*tcl.list_command.at(4)); myEntryNs->addSubEntry(tcl.entry_current); myEntry = tcl.entry_current; tcl.fn.insert(myName,myEntry); myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(6),text); myScan->entry_ns = myEntryNs; myScan->entry_cl = NULL; myScan->entry_fn = myEntry; } //! Handle \c itcl::body statements. static void tcl_command_ITCL_BODY(const char *text) { QString myNs, myName; Entry *myEntryNs, *myEntryCl, *myEntry; tcl_scan *myScan = tcl.scan.at(0); tcl_codify("keyword",*tcl.list_command.at(0)); tcl_codify(NULL,*tcl.list_command.at(1)); tcl_codify(NULL,*tcl.list_command.at(2)); tcl_codify(NULL,*tcl.list_command.at(3)); tcl_codify(NULL,*tcl.list_command.at(4)); tcl_codify(NULL,*tcl.list_command.at(5)); tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName); if (myNs.length()) { myEntryNs = tcl_entry_namespace(myNs); myEntryCl = tcl_entry_class(myNs); } else { myEntryNs = myScan->entry_ns; myEntryCl = myScan->entry_cl; } tcl_command_ARGLIST(*tcl.list_command.at(4)); myEntry = tcl.fn.find(myName); if (myEntry != NULL) { tcl.entry_current->section = Entry::EMPTY_SEC; if (myEntry->args.isEmpty()) { myEntry->args = tcl.entry_current->args; myEntry->argList = tcl.entry_current->argList; } if (myEntry->brief.isEmpty()) { myEntry->brief = tcl.entry_current->brief; myEntry->briefFile = tcl.entry_current->briefFile; myEntry->briefLine = tcl.entry_current->briefLine; } else if (!tcl.entry_current->brief.isEmpty()) { myEntry->doc.append("\n

\n"); myEntry->doc.append(tcl.entry_current->brief); } if (myEntry->doc.isEmpty()) { myEntry->doc = tcl.entry_current->doc; myEntry->docFile = tcl.entry_current->docFile; myEntry->docLine = tcl.entry_current->docLine; } else if (!tcl.entry_current->doc.isEmpty()) { myEntry->doc.append("\n

\n"); myEntry->doc.append(tcl.entry_current->doc); } myEntry->bodyLine = tcl.line_body0; myEntry->endBodyLine = tcl.line_body1; } else {// should not happen, may be ignore? tcl.entry_current->section = Entry::FUNCTION_SEC; tcl.entry_current->mtype = Method; tcl.entry_current->name = myName; tcl.entry_current->startLine = tcl.line_command; tcl.entry_current->bodyLine = tcl.line_body0; tcl.entry_current->endBodyLine = tcl.line_body1; tcl_protection(tcl.entry_current); tcl.fn.insert(myName,tcl.entry_current); myEntryCl->addSubEntry(tcl.entry_current); myEntry = tcl.entry_current; } myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(6),text); myScan->entry_ns = myEntryNs; myScan->entry_cl = myEntryCl; myScan->entry_fn = myEntry; } //! Handle \c oo::define method and method inside \c itcl::class statements. static void tcl_command_METHOD(const char *text) { QString myNs, myName; Entry *myEntryNs, *myEntryCl, *myEntry; tcl_scan *myScan = tcl.scan.at(0); tcl_codify("keyword",*tcl.list_command.at(0)); tcl_codify(NULL,*tcl.list_command.at(1)); tcl_codify(NULL,*tcl.list_command.at(2)); tcl_codify(NULL,*tcl.list_command.at(3)); tcl_codify(NULL,*tcl.list_command.at(4)); tcl_codify(NULL,*tcl.list_command.at(5)); tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName); if (myNs.length()) { myEntryNs = tcl_entry_namespace(myNs); myEntryCl = tcl_entry_class(myNs); } else { myEntryNs = myScan->entry_ns; myEntryCl = myScan->entry_cl; } tcl.entry_current->section = Entry::FUNCTION_SEC; tcl.entry_current->mtype = Method; tcl.entry_current->name = myName; tcl.entry_current->startLine = tcl.line_command; tcl.entry_current->bodyLine = tcl.line_body0; tcl.entry_current->endBodyLine = tcl.line_body1; tcl_protection(tcl.entry_current); tcl_command_ARGLIST(*tcl.list_command.at(4)); myEntryCl->addSubEntry(tcl.entry_current); tcl.fn.insert(myName,tcl.entry_current); myEntry = tcl.entry_current; myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(6),text); myScan->entry_ns = myEntryNs; myScan->entry_cl = myEntryCl; myScan->entry_fn = myEntry; } //! Handle \c constructor statements inside class definitions. static void tcl_command_CONSTRUCTOR(const char *text) { QString myNs, myName; Entry *myEntryNs, *myEntryCl, *myEntry; tcl_scan *myScan = tcl.scan.at(0); tcl_codify("keyword",*tcl.list_command.at(0)); tcl_codify(NULL,*tcl.list_command.at(1)); tcl_codify(NULL,*tcl.list_command.at(2)); tcl_codify(NULL,*tcl.list_command.at(3)); tcl_name(myScan->entry_ns->name,*tcl.list_command.at(0),myNs,myName); if (myNs.length()) { myEntryNs = tcl_entry_namespace(myNs); myEntryCl = tcl_entry_class(myNs); } else { myEntryNs = myScan->entry_ns; myEntryCl = myScan->entry_cl; } tcl.entry_current->section = Entry::FUNCTION_SEC; tcl.entry_current->mtype = Method; tcl.entry_current->name = myName; tcl.entry_current->startLine = tcl.line_command; tcl.entry_current->bodyLine = tcl.line_body0; tcl.entry_current->endBodyLine = tcl.line_body1; tcl_protection(tcl.entry_current); tcl_command_ARGLIST(*tcl.list_command.at(2)); myEntryCl->addSubEntry(tcl.entry_current); myEntry = tcl.entry_current; tcl.fn.insert(myName,myEntry); myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(4),text); myScan->entry_ns = myEntryNs; myScan->entry_cl = myEntryCl; myScan->entry_fn = myEntry; } //! Handle \c destructor statements inside class definitions. static void tcl_command_DESTRUCTOR(const char *text) { QString myNs, myName; Entry *myEntryNs, *myEntryCl, *myEntry; tcl_scan *myScan = tcl.scan.at(0); tcl_codify("keyword",*tcl.list_command.at(0)); tcl_codify(NULL,*tcl.list_command.at(1)); tcl_name(myScan->entry_ns->name,*tcl.list_command.at(0),myNs,myName); if (myNs.length()) { myEntryNs = tcl_entry_namespace(myNs); myEntryCl = tcl_entry_class(myNs); } else { myEntryNs = myScan->entry_ns; myEntryCl = myScan->entry_cl; } tcl.entry_current->section = Entry::FUNCTION_SEC; tcl.entry_current->mtype = Method; tcl.entry_current->name = myName; tcl.entry_current->startLine = tcl.line_command; tcl.entry_current->bodyLine = tcl.line_body0; tcl.entry_current->endBodyLine = tcl.line_body1; tcl_protection(tcl.entry_current); myEntryCl->addSubEntry(tcl.entry_current); myEntry = tcl.entry_current; tcl.fn.insert(myName,myEntry); myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(2),text); myScan->entry_ns = myEntryNs; myScan->entry_cl = myEntryCl; myScan->entry_fn = myEntry; } //! Handle \c namespace statements. static void tcl_command_NAMESPACE(const char *text) { QString myNs, myName, myStr; Entry *myEntryNs=NULL; tcl_scan *myScan = tcl.scan.at(0); tcl_codify("keyword",*tcl.list_command.at(0)); tcl_codify(NULL,*tcl.list_command.at(1)); tcl_codify("keyword",*tcl.list_command.at(2)); tcl_codify(NULL,*tcl.list_command.at(3)); tcl_codify(NULL,*tcl.list_command.at(4)); tcl_codify(NULL,*tcl.list_command.at(5)); tcl_name(myScan->entry_ns->name,*tcl.list_command.at(4),myNs,myName); if (myNs.length()) { myName = myNs+"::"+myName; } tcl.entry_current->section = Entry::NAMESPACE_SEC; tcl.entry_current->name = myName; tcl.entry_current->startLine = tcl.line_command; tcl.entry_current->bodyLine = tcl.line_body0; tcl.entry_current->endBodyLine = tcl.line_body1; tcl.entry_main->addSubEntry(tcl.entry_current); tcl.ns.insert(myName,tcl.entry_current); myEntryNs = tcl.entry_current; myStr = *tcl.list_command.at(6); if (tcl.list_command.count() > 7) { for (uint i=7;ientry_ns = myEntryNs; myScan->entry_cl = NULL; myScan->entry_fn = NULL; } //! Handle \c itcl::class statements. static void tcl_command_ITCL_CLASS(const char *text) { QString myNs, myName, myStr; Entry *myEntryNs, *myEntryCl; tcl_scan *myScan = tcl.scan.at(0); tcl_codify("keyword",*tcl.list_command.at(0)); tcl_codify(NULL,*tcl.list_command.at(1)); tcl_codify("NULL",*tcl.list_command.at(2)); tcl_codify("NULL",*tcl.list_command.at(3)); tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName); if (myNs.length()) { myName = myNs+"::"+myName; } tcl.entry_current->section = Entry::CLASS_SEC; tcl.entry_current->name = myName; tcl.entry_current->startLine = tcl.line_command; tcl.entry_current->bodyLine = tcl.line_body0; tcl.entry_current->endBodyLine = tcl.line_body1; tcl.entry_main->addSubEntry(tcl.entry_current); myEntryNs = tcl_entry_namespace(myName); tcl.cl.insert(myName,tcl.entry_current); myEntryCl = tcl.entry_current; myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(4),text); myScan->entry_ns = myEntryNs; myScan->entry_cl = myEntryCl; myScan->entry_fn = NULL; } //! Handle \c oo::class statements. static void tcl_command_OO_CLASS(const char *text) { QString myNs, myName, myStr; Entry *myEntryNs, *myEntryCl; tcl_scan *myScan = tcl.scan.at(0); tcl_codify("keyword",*tcl.list_command.at(0)); tcl_codify(NULL,*tcl.list_command.at(1)); tcl_codify("NULL",*tcl.list_command.at(2)); tcl_codify("NULL",*tcl.list_command.at(3)); tcl_codify("NULL",*tcl.list_command.at(4)); tcl_codify("NULL",*tcl.list_command.at(5)); tcl_name(myScan->entry_ns->name,*tcl.list_command.at(4),myNs,myName); if (myNs.length()) { myName = myNs+"::"+myName; } tcl.entry_current->section = Entry::CLASS_SEC; tcl.entry_current->name = myName; tcl.entry_current->startLine = tcl.line_command; tcl.entry_current->bodyLine = tcl.line_body0; tcl.entry_current->endBodyLine = tcl.line_body1; tcl.entry_main->addSubEntry(tcl.entry_current); myEntryNs = tcl_entry_namespace(myName); tcl.cl.insert(myName,tcl.entry_current); myEntryCl = tcl.entry_current; myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(6),text); myScan->entry_ns = myEntryNs; myScan->entry_cl = myEntryCl; myScan->entry_fn = NULL; } //! Handle \c oo::define statements. static void tcl_command_OO_DEFINE(const char *text) { QString myNs, myName, myStr; Entry *myEntryNs, *myEntryCl; tcl_scan *myScan = tcl.scan.at(0); tcl_codify("keyword",*tcl.list_command.at(0)); tcl_codify(NULL,*tcl.list_command.at(1)); tcl_codify("NULL",*tcl.list_command.at(2)); tcl_codify("NULL",*tcl.list_command.at(3)); tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName); if (myNs.length()) { myName = myNs+"::"+myName; } myEntryNs = tcl_entry_namespace(myName); myEntryCl = tcl_entry_class(myName); myStr = *tcl.list_command.at(4); if (tcl.list_command.count() > 5) { for (uint i=5;ientry_ns = myEntryNs; myScan->entry_cl = myEntryCl; myScan->entry_fn = NULL; } //! Handle \c variable statements. static void tcl_command_VARIABLE(const char *text, int inclass) { QString myNs, myName; Entry *myEntry; tcl_scan *myScan = tcl.scan.at(0); tcl_codify("keyword",*tcl.list_command.at(0)); for (unsigned int i=1; i< tcl.list_command.count(); i++) { tcl_codify(NULL,*tcl.list_command.at(i)); } tcl_name(myScan->entry_ns->name,*tcl.list_command.at(2),myNs,myName); if (myNs.length()) {// qualified variables go into namespace myEntry = tcl_entry_namespace(myNs); tcl.entry_current->stat = true; } else { if (inclass) { myEntry = myScan->entry_cl; tcl.entry_current->stat = false; } else { myEntry = myScan->entry_ns; tcl.entry_current->stat = true; } } tcl.entry_current->section = Entry::VARIABLE_SEC; tcl.entry_current->name = myName; tcl.entry_current->startLine = tcl.line_command; tcl.entry_current->bodyLine = tcl.line_body0; tcl.entry_current->endBodyLine = tcl.line_body1; tcl_protection(tcl.entry_current); myEntry->addSubEntry(tcl.entry_current); tcl.entry_current = tcl_entry_new(); tcl_codify("comment",text); } //! Handling of command parsing. static void tcl_command(int what,const char *text) { if (what==0) { tcl.scan.at(0)->line1=yylineno;// current line in scan context tcl.line_body0=yylineno;// start line of command tcl_debug("+++%s",text); yy_push_state(COMMAND); tcl.list_command.clear(); tcl.string_command=""; tcl.string_last=""; tcl.command=1; return; } if (what==1) { if (tcl.string_last.length()) { tcl.list_command.append(tcl.string_last); tcl.string_last=""; } if (text) { tcl.list_command.append(text); } return; } if (what!=-1) {// should not happen tcl_abort("what %d",what); return; } tcl_debug("---"); if (tcl.command==0) { return;//TODO check on inside comment } if (tcl.string_last != "") {// get last word tcl.list_command.append(tcl.string_last); tcl.string_last=""; } yy_pop_state(); // check command QString myStr = *tcl.list_command.at(0); int myLevel = 0; Protection myProt = tcl.protection; if (tcl.list_command.count() < 3) { tcl_command_OTHER(text); goto command_end; } // remove leading "::" and apply TCL_SUBST if (myStr.left(2)=="::") myStr = myStr.mid(2); #if HAS_TCL_SUBST if (tcl.config_subst.contains(myStr)) {myStr=tcl.config_subst[myStr];} #endif if (strcmp("private",myStr)==0) { tcl.protection = Private; myLevel = 1; } else if (strcmp("protected",myStr)==0) { tcl.protection = Protected; myLevel = 1; } else if (strcmp("public",myStr)==0) { tcl.protection = Public; myLevel = 1; } if (myLevel) { tcl_codify("keyword",*tcl.list_command.at(0)); tcl_codify(NULL,*tcl.list_command.at(1)); tcl.list_command.remove(tcl.list_command.at(1)); tcl.list_command.remove(tcl.list_command.at(0)); if (tcl.list_command.count()==1) { tcl_scan *myScan = tcl.scan.at(0); myScan = tcl_scan_start(tcl.word_is,*tcl.list_command.at(0),text); myProt = tcl.protection; goto command_end; } myStr = *tcl.list_command.at(0); // remove leading "::" and apply TCL_SUBST if (myStr.left(2)=="::") myStr = myStr.mid(2); #if HAS_TCL_SUBST if (tcl.config_subst.contains(myStr)) {myStr=tcl.config_subst[myStr];} #endif } if (strcmp("proc",myStr)==0) { if (tcl.list_command.count() == 5) {// itcl::proc tcl.list_command.append(""); tcl.list_command.append(""); } if (tcl.list_command.count() != 7) {goto command_warn;} tcl_command_PROC(text); goto command_end; } if (strcmp("method",myStr)==0) { if (tcl.list_command.count() == 5) {// itcl::method tcl.list_command.append(""); tcl.list_command.append(""); } if (tcl.list_command.count() != 7) {goto command_warn;} tcl_command_METHOD(text); goto command_end; } if (strcmp("constructor",myStr)==0) { if (tcl.list_command.count() != 5) {goto command_warn;} tcl_command_CONSTRUCTOR(text); goto command_end; } if (strcmp("destructor",myStr)==0) { if (tcl.list_command.count() != 3) {goto command_warn;} tcl_command_DESTRUCTOR(text); goto command_end; } if (strcmp("namespace",myStr)==0) { if (strcmp("eval",*tcl.list_command.at(2))==0) { if (tcl.list_command.count() < 7) {goto command_warn;} tcl_command_NAMESPACE(text); goto command_end; } tcl_command_OTHER(text); goto command_end; } if (strcmp("itcl::class",myStr)==0) { if (tcl.list_command.count() != 5) {goto command_warn;} tcl_command_ITCL_CLASS(text); goto command_end; } if (strcmp("itcl::body",myStr)==0) { if (tcl.list_command.count() != 7) {goto command_warn;} tcl_command_ITCL_BODY(text); goto command_end; } if (strcmp("oo::class",myStr)==0) { if (strcmp("create",*tcl.list_command.at(2))==0) { if (tcl.list_command.count() != 7) {goto command_warn;} tcl_command_OO_CLASS(text); goto command_end; } tcl_command_OTHER(text); goto command_end; } if (strcmp("oo::define",myStr)==0) { if (tcl.list_command.count() < 5) {goto command_warn;} tcl_command_OO_DEFINE(text); goto command_end; } if (strcmp("variable",myStr)==0) { if (tcl.list_command.count() < 3) {goto command_warn;} if (tcl.scan.at(0)->entry_fn == NULL) {// only parsed outside functions tcl_command_VARIABLE(text,tcl.scan.at(0)->entry_cl!=NULL&&tcl.scan.at(0)->entry_cl->name!=""); goto command_end; } } if (strcmp("common",myStr)==0) { if (tcl.list_command.count() < 3) {goto command_warn;} if (tcl.scan.at(0)->entry_fn == NULL) {// only parsed outside functions tcl_command_VARIABLE(text,0); goto command_end; } } if (strcmp("inherit",myStr)==0 || strcmp("superclass",myStr)==0) { if (tcl.list_command.count() < 3) {goto command_warn;} if (tcl.scan.at(0)->entry_cl!=NULL&&tcl.scan.at(0)->entry_cl->name!="") { for (unsigned int i = 2; i < tcl.list_command.count(); i++) { tcl.scan.at(0)->entry_cl->extends->append(new BaseInfo(*tcl.list_command.at(i),Public,Normal)); } } } tcl_command_OTHER(text); goto command_end; command_warn: tcl_warn("count=%d: %s",tcl.list_command.count(),tcl.list_command.join(" ").ascii()); tcl_command_OTHER(text); command_end: tcl.list_command.clear(); tcl.command = 0; tcl.protection = myProt; } //---------------------------------------------------------------------------- //! Common initializations. static void tcl_init() { #if HAS_TCL_SUBST // Get values from option TCL_SUBST QStrList myStrLst = Config_getList("TCL_SUBST"); if (myStrLst.count()%2 != 0) { tcl.config_subst.clear(); } else { for (unsigned int i=0; i < myStrLst.count(); i=i+2) { tcl.config_subst[myStrLst.at(i)] = myStrLst.at(i+1); } } #endif tcl.code = NULL; tcl.code_font=NULL; tcl.code_line=1; tcl.code_linenumbers=1; tcl.config_autobrief = Config_getBool("JAVADOC_AUTOBRIEF"); tcl.input_string = NULL; tcl.input_position = 0; tcl.file_name = NULL; tcl.this_parser = NULL; tcl.command=0; tcl.comment=0; tcl.brace_level=0; tcl.bracket_level=0; tcl.bracket_quote=0; tcl.word_is=WORD; tcl.string_command=""; tcl.string_commentline=""; tcl.string_commentcodify=""; tcl.string_comment = ""; tcl.string_last = ""; tcl.entry_main = NULL; tcl.entry_file = NULL; tcl.entry_current = NULL; tcl.entry_inside = NULL; tcl.list_command.clear(); tcl.scan.clear(); tcl.ns.clear(); tcl.cl.clear(); tcl.fn.clear(); yylineno = 1; tcl.protection = Public; } //! Start parsing. static void tcl_parse() { tcl_scan *myScan; tcl.entry_file = tcl_entry_new(); tcl.entry_file->name = tcl.file_name; tcl.entry_file->section = Entry::SOURCE_SEC; tcl.entry_file->protection = Public; tcl.entry_main->addSubEntry(tcl.entry_file); tcl.entry_current = tcl_entry_new(); tclscanYYrestart( tclscanYYin ); BEGIN( TOP ); yylineno=1; myScan = new tcl_scan; myScan->type=STRING; myScan->string_after=""; myScan->line0=yylineno; myScan->line1=yylineno; myScan->start_stack_ptr=yy_start_stack_ptr; myScan->buffer_state=YY_CURRENT_BUFFER; myScan->entry_ns=tcl_entry_namespace(""); myScan->entry_cl=tcl_entry_class(""); myScan->entry_fn=NULL; tcl.entry_inside = myScan->entry_ns; tcl.entry_inside = tcl.entry_file; myScan->entry_scan = myScan->entry_ns; tcl.scan.insert(0,myScan); tclscanYYlex(); tcl.scan.clear(); tcl.ns.clear(); tcl.cl.clear(); tcl.fn.clear(); tcl.entry.clear(); } //! Parse text file and build up entry tree. void TclLanguageScanner::parseInput(const char *fileName,const char *input,Entry *root) { QFile myFile; myFile.setName(fileName); if (!myFile.open(IO_ReadOnly)) return; msg("Parsing '%s'...\n",fileName); groupEnterFile(fileName,yylineno); tcl_init(); tcl.code = NULL; tcl.input_string = input; tcl.file_name = fileName; tcl.this_parser = this; tcl.entry_main = root; /* toplevel entry */ tcl_parse(); groupLeaveFile(tcl.file_name,yylineno); root->program.resize(0); myFile.close(); } //! Parse file and codify. void TclLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf, const char * scopeName, const QCString & input, bool isExampleBlock, const char * exampleName, FileDef * fileDef, int startLine, int endLine, bool inlineFragment, MemberDef *memberDef, bool showLineNumbers ) { (void)scopeName; (void)exampleName; (void)fileDef; (void)endLine; (void)inlineFragment; (void)memberDef; if (input.isEmpty()) return; /* QString myStr="Codifying.."; if (scopeName) {myStr+=" scope=";myStr+=scopeName;} if (exampleName) {myStr+=" example=";myStr+=exampleName;} if (memberDef) {myStr+=" member=";myStr+=memberDef->memberTypeName(); myStr+=" ";myStr+=memberDef->qualifiedName();} if (fileDef) {myStr+=" file=";myStr+=fileDef->fileName();} printf("%s (%d,%d) %d %d\n====%s\n====\n",myStr.ascii(),startLine,endLine,isExampleBlock,inlineFragment,input.data()); */ QCString myInput = input; if (input.at(input.length()-1) != '\n') { myInput += "\n"; } if (isExampleBlock) {tcl_codify(NULL,input);return;} tcl_init(); tcl.code = &codeOutIntf; if (startLine<0) { startLine=1; } yylineno=startLine; tcl.code_linenumbers = showLineNumbers; tcl.code_line=yylineno; if (tcl.code_linenumbers) { tcl.code->writeLineNumber(0,0,0,tcl.code_line); } tcl.input_string = myInput.data(); tcl.file_name = ""; tcl.this_parser = NULL; tcl.entry_main = tcl_entry_new(); tcl_parse(); tcl.scan.clear(); tcl.ns.clear(); tcl.cl.clear(); tcl.fn.clear(); tcl.entry.clear(); } bool TclLanguageScanner::needsPreprocessing(const QCString &extension) { (void)extension; return FALSE; } void TclLanguageScanner::resetCodeParserState() { } void TclLanguageScanner::parsePrototype(const char *text) { (void)text; } static int yyread(char *buf,int max_size) { int c=0; *buf = '\0'; while ( c < max_size && tcl.input_string[tcl.input_position] ) { *buf = tcl.input_string[tcl.input_position++] ; c++; buf++; } //printf("Read from=%d size=%d max=%d c=%d\n",tcl.input_position,strlen(&tcl.input_string[tcl.input_position]),max_size,c); return c; } //---------------------------------------------------------------------------- // to avoid a warning void tclDummy() { yy_top_state(); } #if !defined(YY_FLEX_SUBMINOR_VERSION) //---------------------------------------------------------------------------- extern "C" { // some bogus code to keep the compiler happy void tclscannerYYdummy() { yy_flex_realloc(0,0); } } #endif