/***************************************************************************** * 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. * */ %option never-interactive %option case-insensitive %option prefix="tclscannerYY" %{ #include #include #include #include #include #include #include #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 "arguments.h" #include "namespacedef.h" #include "filedef.h" #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 #define MAX_INCLUDE_DEPTH 10 static const char *stateToString(int state); //! Application error. #define tcl_err \ printf("Error %d %s() at line %d! ",__LINE__,tcl.file_name.data(),yylineno); \ yy_push_state(ERROR); \ yyless(0); \ printf //! Application warning. #define tcl_war \ printf("Warning %d %s() at line %d: ",__LINE__,tcl.file_name.data(),yylineno); \ printf //! Application message. #define tcl_inf \ if (0) printf("--- %.4d %d@%d: ",__LINE__,yylineno,yy_start_stack_ptr) && printf //! Debug message. #define D\ if (0) printf("--- %.4d %d@%d: %s\n",__LINE__,yylineno,yy_start_stack_ptr,yytext); // 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 == '{') /* } to keep vi happy */ { 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 = (int)(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 = (int)(p - elemStart); goto done; } break; /* * Double-quote: if element is in quotes then terminate it. */ case '"': if (inQuotes) { size = (int)(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 = (int)(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 = (int)(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 -= (int)(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(QCString &str, QCStringList &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 (!str.isEmpty()) { if (Tcl_SplitList(str,&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 { char type[2]; // type of scan context: "\"" "{" "[" "?" " " int line0; // start line of scan context int line1; // end line of scan context YY_BUFFER_STATE buffer_state; // value of scan context QCString 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 QCStringList after; // option/value list (options: NULL comment keyword script) } 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 QMap config_subst; // map of configuration option values QCString 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 scanned int brace_level; // bookkeeping of braces int bracket_level; // bookkeeping of brackets int bracket_quote; // bookkeeping of quotes (toggles) char 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 QCString string_command; // contain current command QCString string_commentline; // contain current comment after command QCString string_commentcodify; // current comment string used in codifying QCString string_comment; // contain current comment QCString string_last; // contain last read word or part of word QCString 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 QCStringList list_commandwords; // list of command words QList scan; // stack of scan contexts QAsciiDict ns; // all read namespace entries QAsciiDict cl; // all read class entries QAsciiDict fn; // all read function entries QList entry; // list of all created entries, will be deleted after codifying Protection protection; // current protections state const MemberDef *memberdef; // contain current MemberDef when codifying bool collectXRefs; } tcl; // scanner functions static int yyread(char *buf,int max_size); static tcl_scan *tcl_scan_start(char type, QCString content, QCString ns, Entry *entry_cls, Entry *entry_fn); 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 = Public; // myEntry->mtype = Method; // myEntry->virt = Normal; // myEntry->stat = FALSE; myEntry->fileName = tcl.file_name; myEntry->lang = SrcLangExt_Tcl; Doxygen::docGroup.initGroupInfo(myEntry); // collect entries if (!tcl.code) { 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 QCString &ns0, const QCString &name0, QCString &ns, QCString &name) { QCString myNm; int myStart; if (qstrncmp(name0.data(),"::",2)==0) { myNm = name0.mid(2); } else if (ns0.length() && ns0 != " ") { 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 name. Strip namespace qualifiers from name0 if inside inlined code segment. // @return 'ns' and 'name' of given current 'ns0' and 'name0' static void tcl_name_SnippetAware(const QCString &ns0, const QCString &name0, QCString &ns, QCString &name) { // If we are inside an inlined code snippet then ns0 // already contains the complete namespace path. // Any namespace qualifiers in name0 are redundant. int i = name0.findRev("::"); if (i>=0 && tcl.memberdef) { tcl_name(ns0, name0.mid(i+2), ns, name); } else { tcl_name(ns0, name0, ns, name); } } // Check and return namespace entry. // @return namespace entry Entry* tcl_entry_namespace(const QCString ns) { Entry *myEntry; if (ns.length()) { myEntry = tcl.ns.find(ns); } else { myEntry = tcl.ns.find("::"); } if (myEntry == NULL) { myEntry = tcl_entry_new(); myEntry->section = Entry::NAMESPACE_SEC; myEntry->name = ns; 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 QCString cl) { Entry *myEntry; if (!cl.length()) return(NULL); myEntry = tcl.cl.find(cl); if (myEntry == NULL) { myEntry = tcl_entry_new(); myEntry->section = Entry::CLASS_SEC; myEntry->name = cl; 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(QCString str) { static QCStringList 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"; myList <<"binary"; myList <<"catch"<<"cd"<<"close"<<"clock"<<"concat"; myList <<"eof"<<"eval"<<"exec"<<"exit"<<"expr"; myList <<"fblocked"<<"fconfigure"<<"file"<<"fileevent"<<"flush"<<"for"<<"foreach"<<"format"; myList <<"gets"<<"global"; myList <<"http"; myList <<"if"<<"incr"<<"info"<<"interp"; myList <<"join"; myList <<"lappend"<<"lassign"<<"lindex"<<"linsert"<<"llength"<<"load"<<"lrange"<<"lrepeat"<<"lreplace"<<"lreverse"<<"lset"; myList <<"namespace"; myList <<"package"<<"parray"<<"pid"<<"pkg_mkIndex"<<"proc"<<"puts"<<"pwd"; myList <<"registry"<<"rename"<<"return"; myList <<"scan"<<"set"<<"split"<<"string"<<"switch"; myList <<"tclLog"<<"tcl_endOfWord"<<"tcl_findLibrary"<<"tcl_startOfNextWord"<<"tcl_startOfPreviousWord"<<"tcl_wordBreakAfter"<<"tcl_wordBreakBefore"<<"tell"<<"time"; myList <<"unknown"<<"upvar"; myList <<"variable"<<"vwait"; // tk keywords myList <<"bell"<<"bind"<<"bindtags"; myList <<"clipboard"<<"console"<<"consoleinterp"; myList <<"destroy"; myList <<"event"; myList <<"focus"; myList <<"grid"; myList <<"lower"; myList <<"option"; myList <<"pack"<<"place"; myList <<"raise"; myList <<"send"; myList <<"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"; myList <<"winfo"<<"wm"; myList <<"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) 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,const char *str) { if (!tcl.code || !str) return; if (s && qstrcmp(s,"NULL")!=0) { tcl_font_end(); tcl.code->startFontClass(s); tcl.code_font=s; } char *tmp = (char *) malloc(strlen(str)+1); strcpy(tmp, str); char *p=tmp,*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'; // Dimitri: is this really needed? // wtschueller: As far as I can see: yes. // Deletes that \n that would produce ugly source listings otherwise. // However, there may exist more sophisticated solutions. tcl.code->codify(sp); if (tcl.code_font) { tcl.code->endFontClass(); } tcl.code->endCodeLine(); tcl.code->startCodeLine(tcl.code_linenumbers); if (tcl.code_linenumbers) { tcl.code->writeLineNumber(0,0,0,tcl.code_line); } if (tcl.code_font) { tcl.code->startFontClass(tcl.code_font); } } else { if (*(p-2)==0x1A) *(p-2) = '\0'; // remove ^Z tcl.code->codify(sp); done=TRUE; } } free(tmp); tcl_font_end(); } #if 0 //! 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,const QCString &str) { if (tcl.code==NULL) return; tcl_codify(s,str); } //! Codify 'str' with special font class 's'. static void tcl_codify(const char *s,const QCString &str) { if (!tcl.code) return; tcl_codify(s,str.data()); } #endif static void tcl_codify_cmd(const char *s,int i) { tcl_codify(s,(*tcl.list_commandwords.at(i))); } //! codify a string token // // codifies string according to type. // Starts a new scan context if needed (*myScan==0 and type == "script"). // Returns NULL or the created scan context. // static tcl_scan *tcl_codify_token(tcl_scan *myScan, const QCString type, const QCString string) { if (myScan != NULL) { if (type != NULL) { myScan->after << type << string; } else { myScan->after << "NULL" << string; } } else { if (qstrcmp(type, "script") == 0) { myScan = tcl.scan.at(0); myScan = tcl_scan_start('?', string, myScan->ns, myScan->entry_cl, myScan->entry_fn); } else { tcl_codify((const char*)type, string); } } return myScan; } //----------------------------------------------------------------------------- #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 %% . { D yyterminate(); } <> { D if (tcl.scan.count()<1) {// error D tcl_err("Tcl parser stack empty! Parser error in file '%s'.\n",tcl.file_name.data()); 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); tcl_comment(2,yytext+1); } "##".*\\\n { D tcl_codify("comment",yytext); QCString t=yytext; t = t.mid(2,t.length()-3); t.append("\n"); tcl_comment(1,t.data()); yy_push_state(COMMENT_NL); } "##".*\n { D tcl_codify("comment",yytext); tcl_comment(1,yytext+2); } "#"[@\\]"code"\n[ \t]*[^#] { D QCString t=yytext; tcl_codify("comment",t.left(7)); tcl_comment(2,"\n@code\n"); yyless(7); yy_push_state(COMMENT_CODE); } "#"[@\\]"verbatim"\n[ \t]*[^#] { D QCString t=yytext; tcl_codify("comment",t.left(11)); tcl_comment(2,"\n@verbatim\n"); yyless(11); yy_push_state(COMMENT_VERB); } "#".*\\\n { D tcl_codify("comment",yytext); QCString t=yytext; t = t.mid(1,t.length()-3); t.append("\n"); tcl_comment(2,t.data()); yy_push_state(COMMENT_NL); } "#".*\n { D tcl_codify("comment",yytext); tcl_comment(2,yytext+1); } "#".*\x1A { D QCString t=yytext; t = t.mid(0,t.length()-1); tcl_codify("comment",t.data()); t = t.mid(1,t.length()); tcl_comment(-2,t.data()); unput(0x1A); } \x1A { D tcl_comment(-2,""); unput(0x1A); } .|\n { D tcl_comment(-2,yytext); yyless(0); } "#"[@\\]"endcode"\n { D QCString t=yytext; t = t.left(t.length()-10); tcl_comment(2,t.data()); tcl_comment(2,"\n@endcode\n"); yy_pop_state(); yyless(0); } .*\n { D yymore(); } .*\x1A { D yy_pop_state(); yyless(0); } "#"[@\\]"endverbatim"\n { D QCString t=yytext; t = t.left(t.length()-14); tcl_comment(2,t.data()); tcl_comment(2,"\n@endverbatim\n"); yy_pop_state(); yyless(0); } .*\n { D yymore(); } .*\x1A { D yy_pop_state(); yyless(0); } .*\\\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 yy_pop_state(); yyless(0); } .*\x1A { D yy_pop_state(); yyless(0); } [ \t]* { D tcl.string_commentcodify += yytext; } "#<".*\\\n { D tcl.string_commentcodify += yytext; QCString 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 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.data()); tcl.string_commentline=""; tcl.string_commentcodify=""; } .*\\\n { D tcl.string_commentcodify += yytext; QCString 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 QCString t=yytext; t = t.left(t.length()-1); tcl.string_commentcodify += t; tcl.string_commentline += t; yy_pop_state(); unput(0x1A); } {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); } {ws}*\x1A { D tcl.string_commentcodify = ""; tcl.string_commentline = ""; tcl.line_body1=yylineno; tcl_command(-1,yytext); } {ws}*; { D tcl.string_commentcodify = ""; tcl.string_commentline = ""; tcl.line_body1=yylineno; tcl_command(-1,yytext); } {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 = ' '; tcl.string_last = "{*}"; tcl_word(0,&yytext[3]); } "\\"[\{\}\[\]\;\" \t] { D tcl.word_is=' '; tcl.string_last = ""; tcl_word(0,yytext); } . { D tcl.word_is=' '; if (yytext[0]=='{'||yytext[0]=='['||yytext[0]=='"') tcl.word_is = yytext[0]; 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. static tcl_scan *tcl_scan_start(char type, QCString content, QCString ns, Entry *entry_cl, Entry *entry_fn) { tcl_scan *myScan=tcl.scan.at(0); tcl_inf("line=%d type=%d '%s'\n",tcl.line_body0,type,content.data()); myScan->line1=yylineno; yy_push_state(TOP); myScan=new tcl_scan; myScan->type[0] =' '; myScan->type[1] = '\0'; switch (type) { case '"': case '{': case '[': myScan->type[0] = type; break; case '?': if (content[0]=='"' && content[content.length()-1]=='"') myScan->type[0]='"'; if (content[0]=='{' && content[content.length()-1]=='}') myScan->type[0]='{'; if (content[0]=='[' && content[content.length()-1]==']') myScan->type[0]='['; } if (myScan->type[0]!=' ') { tcl_codify(NULL,&myScan->type[0]); content = content.mid(1,content.length()-2); } content += (char)0x1A;// for detection end of scan context myScan->ns = ns; myScan->entry_cl = entry_cl; myScan->entry_fn = entry_fn; myScan->entry_scan = tcl.entry_current; myScan->buffer_state=yy_scan_string(content.data()); myScan->line0=tcl.line_body0; myScan->line1=tcl.line_body1; myScan->after.clear(); yylineno=myScan->line0; 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=tcl.scan.at(0); tcl_scan *myScan1=tcl.scan.at(1); tcl_inf("line=%d\n",myScan->line1); if (myScan->type[0]=='{') myScan->type[0]='}'; if (myScan->type[0]=='[') myScan->type[0]=']'; if (myScan->type[0]!=' ') tcl_codify(NULL,&myScan->type[0]); int myStart=-1; for (unsigned int i=0;iafter.count();i=i+2) { if (myScan->after[i]=="script") { myStart=i; break; } tcl_codify(myScan->after[i],myScan->after[i+1]); } yy_delete_buffer(myScan->buffer_state); yy_pop_state(); tcl.entry_inside = myScan1->entry_scan; yy_switch_to_buffer(myScan1->buffer_state); yylineno=myScan1->line1; tcl.protection = myScan1->protection; if (myStart>=0) { myScan1 = tcl_scan_start('?', myScan->after[myStart+1], myScan->ns, myScan->entry_cl, myScan->entry_fn); for (unsigned int i=myStart+2;iafter.count();i++) { myScan1->after.append(myScan->after[i]); } tcl.scan.remove(1); } else { tcl.scan.removeFirst(); } } //! 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_err("expected word separator: %s\n",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_inf("(\\\n) ?%s?\n",tcl.string_last.data()); return; } switch (myList[myLevel-1]) { case '{': case '[': case '"': break; case '.': if (myLevel==1) { myWord=' '; yy_pop_state(); yyless(0); tcl_inf("(\\\n) ?%s?\n",tcl.string_last.data()); return; } break; } myWhite=0; break; case 3:// { if (myWhite) {// {x}{ "x"{ tcl_err("expected word separator: %s\n",text); return; } switch (myList[myLevel-1]) { case '{': case '[': myList[myLevel++]='{'; break; case '"': case '.': break; } myWhite=0; break; case 4:// } if (myWhite) {// {x}{ "x"{ tcl_err("expected word separator: %s\n",text); return; } switch (myList[myLevel-1]) { case '{':// {{x}} myLevel--; if (myLevel==0 && !tcl.code) { myWhite=1; } break; case '[': case '"': case '.': break; } break; case 5:// [ if (myWhite) {// {x}[ tcl_err("expected word separator: %s\n",text); return; } switch (myList[myLevel-1]) { case '{': break; case '[': case '"': case '.': myList[myLevel++]='['; break; } myWhite=0; break; case 6:// ] if (myWhite) {// {x}] tcl_err("expected word separator: %s\n",text); return; } switch (myList[myLevel-1]) { case '{': break; case '[': myLevel--; break; case '"': case '.': break; } myWhite=0; break; case 7:// " if (myWhite) {// {x}" tcl_err("expected word separator: %s\n",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 if (myLevel==0) { myWord=' '; yy_pop_state(); yyless(0); tcl_inf("(%d) ?%s?\n",what,tcl.string_last.data()); return; } switch (myList[myLevel-1]) { case '{': case '[': case '"': break; case '.': if (myLevel==1) { myWord=' '; yy_pop_state(); yyless(0); tcl_inf("(.%d) ?%s?\n",what,tcl.string_last.data()); return; } else { myLevel--; } break; } myWhite=0; break; case 12:// \x1A if (myLevel==0) { myWord=' '; yy_pop_state(); yyless(0); tcl_inf("(%d) ?%s?\n",what,tcl.string_last.data()); return; } if (myLevel!=1 || myList[0] != '.') { tcl_war("level=%d expected=%c\n",myLevel,myList[myLevel-1]); } myWord=' '; yy_pop_state(); yyless(0); tcl_inf("(.%d) ?%s?\n",what,tcl.string_last.data()); return; break; default: tcl_err("wrong state: %d\n",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_err("comment in comment\n"); return; } yy_push_state(COMMENT); tcl_inf("<- %s\n",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_inf("-> %s\n",(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_inf("-> %s\n",(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.data(),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(); QCString processedDoc; if (what==99) { // inbody comment file or namespace or class or proc/method int myPos0; int myLine0; Entry myEntry0; // used to test parsing Entry *myEntry; Entry *myEntry1=NULL; 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; processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine); while (parseCommentBlock(tcl.this_parser, &myEntry0, processedDoc, 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(); processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); parseCommentBlock(tcl.this_parser, myEntry, processedDoc, 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 if (!myEntry1) { myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns); } processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); parseCommentBlock(tcl.this_parser, myEntry1, processedDoc, 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(); processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); parseCommentBlock(tcl.this_parser, myEntry, processedDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); tcl.entry_inside->addSubEntry(myEntry); } else { // we can add to current entry if (!myEntry1) { myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns); } processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); parseCommentBlock(tcl.this_parser, myEntry1, processedDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); } } else { // new entry tcl.entry_current = tcl_entry_new(); processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine); while (parseCommentBlock(tcl.this_parser, tcl.entry_current, processedDoc, 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_err("what %d\n",what); return; } } //! Parse given \c arglist . static void tcl_command_ARGLIST(QCString &arglist) { D Argument *myArg; QCStringList myArgs; QCString myArglist=""; if (!tcl.entry_current->argList) { 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 += "?" + QCString(myArg->name) + "? "; } else { myArg->name= (*myArgs.at(i)); myArglist += myArg->name + " "; } tcl.entry_current->argList->append(myArg); } arglist = myArglist; tcl.entry_current->args = arglist; } //! Create link. static void tcl_codify_link(QCString name) { if (tcl.code == NULL || name.isEmpty()) return; static int init=0; static QAsciiDict fn; if (init==0) { init=1; MemberNameSDict::Iterator mni(*Doxygen::memberNameSDict); MemberNameSDict::Iterator fni(*Doxygen::functionNameSDict); MemberName *mn=0; MemberDef *md; for (mni.toFirst();(mn=mni.current());++mni) { MemberNameIterator mi(*mn); for (mi.toFirst();(md=mi.current());++mi) { fn.insert(md->qualifiedName(),md); } } for (fni.toFirst();(mn=fni.current());++fni) { MemberNameIterator fi(*mn); for (fi.toFirst();(md=fi.current());++fi) { fn.insert(md->qualifiedName(),md); } } } MemberDef *myDef; QCString myName=name; if (name.mid(0,2)=="::") // fully qualified global command { myName = myName.mid(2); myDef = fn.find(myName); } else // not qualified name { QCString myName1=myName; myDef = NULL; myName1 = tcl.scan.at(0)->ns; if (myName1 == " " || myName1 == "") { myName1 = myName; } else { myName1 = myName1 + "::" + myName; } myDef = fn.find(myName1); // search namespace command if (myDef == NULL) { myDef = fn.find(myName); // search global command } } if (myDef != NULL) // documented command { tcl.code->writeCodeLink(myDef->getReference().data(), myDef->getOutputFileBase().data(), myDef->anchor().data(), name, myDef->qualifiedName().data()); if (tcl.memberdef) { myDef->addSourceReferencedBy(tcl.memberdef); //tcl.memberdef->addSourceReferences(myDef); } else { Entry* callerEntry; unsigned int i; // walk the stack of scan contexts and find the enclosing method or proc for (i=0;ientry_scan; if (callerEntry->mtype==Method && !callerEntry->name.isEmpty()) { break; } } if (iname; if (callerName.mid(0,2)=="::") // fully qualified global command { callerName = callerName.mid(2); } else { if (!(tcl.scan.at(0)->ns.stripWhiteSpace().isEmpty())) { callerName = tcl.scan.at(0)->ns + "::" + callerEntry->name; } } MemberDef *callerDef=NULL; callerDef = fn.find(callerName); if (callerDef!=NULL && myDef!= NULL && tcl.collectXRefs) { addDocCrossReference(callerDef,myDef); } } } } else if (tcl_keyword(myName)) // check keyword { tcl_codify("keyword",name); } else { tcl_codify(NULL,name); // something else } } //! scan general argument for brackets // // parses (*tcl.list_commandwords.at(i)) and checks for brackets. // Starts a new scan context if needed (*myScan==0 and brackets found). // Returns NULL or the created scan context. // static tcl_scan *tcl_command_ARG(tcl_scan *myScan, unsigned int i, bool ignoreOutermostBraces) { QCString myName; bool insideQuotes=false; unsigned int insideBrackets=0; unsigned int insideBraces=0; myName = (*tcl.list_commandwords.at(i)); if (i%2 != 0) { // handle white space myScan = tcl_codify_token(myScan, "NULL", myName); } else { QCString myStr = ""; unsigned int j; for (j=0;j0) { backslashed = myName[j-1]=='\\'; } // this is a state machine // input is c // internal state is myScan and insideXXX // these are the transitions: if (c=='[' && !backslashed && insideBraces==0) { insideBrackets++; } if (c==']' && !backslashed && insideBraces==0 && insideBrackets>0) { insideBrackets--; } if (c=='{' && !backslashed && !insideQuotes && !(ignoreOutermostBraces && j==0)) { insideBraces++; } if (c=='}' && !backslashed && !insideQuotes && insideBraces>0) { insideBraces--; } if (c=='"' && !backslashed && insideBraces==0) { insideQuotes=!insideQuotes; } // all output, depending on state and input if (c=='[' && !backslashed && insideBrackets==1 && insideBraces==0) { // the first opening bracket, output what we have so far myStr+=c; myScan = tcl_codify_token(myScan, "NULL", myStr); myStr=""; } else if (c==']' && !backslashed && insideBrackets==0 && insideBraces==0) { // the last closing bracket, start recursion, switch to deferred myScan = tcl_codify_token(myScan, "script", myStr); myStr=""; myStr+=c; } else { myStr+=c; } } if (i == 0 && myScan == NULL) { tcl_codify_link(myStr); } else { myScan = tcl_codify_token(myScan, "NULL", myStr); } } return (myScan); } //! Handle internal tcl commands. // "eval arg ?arg ...?" static void tcl_command_EVAL() { D tcl_codify_cmd("keyword", 0); tcl_scan *myScan = tcl.scan.at(0); QCString myString = ""; // we simply rescan the line without the eval // we include leading whitespace because tcl_scan_start will examine // the first char. If it finds a bracket it will assume one expression in brackets. // Example: eval [list set] [list NotInvoked] [Invoked NotInvoked] for (unsigned int i = 1; i < tcl.list_commandwords.count(); i++) { myString += (*tcl.list_commandwords.at(i)); } myScan = tcl_scan_start('?', myString, myScan->ns, myScan->entry_cl, myScan->entry_fn); } //! Handle internal tcl commands. // switch ?options? string pattern body ?pattern body ...? // switch ?options? string {pattern body ?pattern body ...?} static void tcl_command_SWITCH() { D tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_scan *myScan=NULL; unsigned int i; QCString token; // first: find the last option token unsigned int lastOptionIndex = 0; for (i = 2; i 0) { TclFindElement((const char*)token, token.length(), &elem, &next, &size, NULL); //printf("%s\nstart=%d, elem=%d, next=%d, size=%d, brace=%d\n", // (const char*) token, (const char*) token, elem, next, size, brace); // // handle leading whitespace/opening brace/double quotes if (elem - token > 0) { myScan = tcl_codify_token(myScan, "NULL", token.left(elem - token)); } // handle actual element without braces/double quotes if (nextIsPattern) { myScan = tcl_codify_token(myScan, "NULL", token.mid(elem - token,size)); //printf("pattern=%s\n",(const char*) token.mid(elem - token, size)); } else { myScan = tcl_codify_token(myScan, "script", token.mid(elem - token, size)); //printf("script =%s\n", (const char*) token.mid(elem - token, size)); } // handle trailing whitespace/closing brace/double quotes if (next - elem - size > 0) { myScan = tcl_codify_token(myScan, "NULL", token.mid(elem - token + size, next - elem - size)); } nextIsPattern = !nextIsPattern; token = token.mid(next - token); } if (inBraces) { myScan = tcl_codify_token(myScan, "NULL", QCString("}")); } if (!nextIsPattern) { tcl_war("Invalid switch syntax: last token is not a list of even elements.\n"); //tcl_war("%s\n", tcl.list_commandwords.join(" ").ascii()); } } else if ((tcl.list_commandwords.count() - lastOptionIndex > 6) && ((tcl.list_commandwords.count() - lastOptionIndex-3) % 4 == 0)) { //printf("detected: switch ?options? string pattern body ?pattern body ...?\n"); myScan = tcl_command_ARG(myScan, lastOptionIndex + 1, false); myScan = tcl_command_ARG(myScan, lastOptionIndex + 2, false); //printf("value=%s\n",(const char*) (*tcl.list_commandwords.at(lastOptionIndex + 2))); for (i = lastOptionIndex + 3; i < tcl.list_commandwords.count(); i += 4) { myScan = tcl_command_ARG(myScan, i + 0, false); // whitespace myScan = tcl_command_ARG(myScan, i + 1, false); // pattern myScan = tcl_command_ARG(myScan, i + 2, false); // whitespace myScan = tcl_codify_token(myScan, "script", (*tcl.list_commandwords.at(i+3))); // script //printf("pattern=%s\n",(const char*) (*tcl.list_commandwords.at(i+1)))); //printf("script=%s\n",(const char*) (*tcl.list_commandwords.at(i+3))); } } else { // not properly detected syntax tcl_war("Invalid switch syntax: %d options followed by %d tokens.\n", lastOptionIndex / 2, (tcl.list_commandwords.count() - 1) / 2 - lastOptionIndex / 2); for (i = lastOptionIndex + 1; i <= tcl.list_commandwords.count(); i++) { myScan = tcl_command_ARG(myScan, i, false); } } } //! Handle internal tcl commands. // "catch script ?resultVarName? ?optionsVarName?" static void tcl_command_CATCH() { D tcl_codify_cmd("keyword", 0); tcl_codify_cmd(NULL, 1); tcl_scan *myScan = tcl.scan.at(0); myScan = tcl_scan_start('?', *tcl.list_commandwords.at(2), myScan->ns, myScan->entry_cl, myScan->entry_fn); for (unsigned int i = 3; i < tcl.list_commandwords.count(); i++) { myScan = tcl_command_ARG(myScan, i, false); } } //! Handle internal tcl commands. // "if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?" static void tcl_command_IF(QCStringList type) { D tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_scan *myScan = NULL; myScan = tcl_command_ARG(myScan, 2, true); for (unsigned int i = 3;iafter << type[i] << tcl.list_commandwords[i]; } else { myScan=tcl.scan.at(0); myScan = tcl_scan_start('?',*tcl.list_commandwords.at(i), myScan->ns,myScan->entry_cl,myScan->entry_fn); } } } } //! Handle internal tcl commands. // "for start test next body" static void tcl_command_FOR() { D tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_scan *myScan=tcl.scan.at(0); myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2), myScan->ns,myScan->entry_cl,myScan->entry_fn); myScan->after << "NULL" << tcl.list_commandwords[3]; myScan = tcl_command_ARG(myScan, 4, true); myScan->after << "NULL" << tcl.list_commandwords[5]; myScan->after << "script" << tcl.list_commandwords[6]; myScan->after << "NULL" << tcl.list_commandwords[7]; myScan->after << "script" << tcl.list_commandwords[8]; } ///! Handle internal tcl commands. // "foreach varname list body" and // "foreach varlist1 list1 ?varlist2 list2 ...? body" static void tcl_command_FOREACH() { D unsigned int i; tcl_scan *myScan=NULL; tcl_codify_cmd("keyword",0); for (i = 1;iafter << "script" << tcl.list_commandwords[tcl.list_commandwords.count()-1]; } else { myScan=tcl.scan.at(0); myScan = tcl_scan_start('?',*tcl.list_commandwords.at(tcl.list_commandwords.count()-1), myScan->ns,myScan->entry_cl,myScan->entry_fn); } } ///! Handle internal tcl commands. // "while test body" static void tcl_command_WHILE() { D tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_scan *myScan = NULL; myScan = tcl_command_ARG(myScan, 2, true); myScan = tcl_command_ARG(myScan, 3, false); if (myScan!=0) { myScan->after << "script" << tcl.list_commandwords[4]; } else { myScan=tcl.scan.at(0); myScan = tcl_scan_start('?',*tcl.list_commandwords.at(4), myScan->ns,myScan->entry_cl,myScan->entry_fn); } } //! Handle all other commands. // Create links of first command word or first command word inside []. static void tcl_command_OTHER() { tcl_scan *myScan=NULL; for (unsigned int i=0; i< tcl.list_commandwords.count(); i++) { myScan = tcl_command_ARG(myScan, i, false); } } //! Handle \c proc statements. static void tcl_command_PROC() { D QCString myNs, myName; Entry *myEntryNs; Entry *myEntry; tcl_scan *myScan = tcl.scan.at(0); tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_codify_cmd(NULL,2); tcl_codify_cmd(NULL,3); tcl_codify_cmd(NULL,4); tcl_codify_cmd(NULL,5); tcl_name_SnippetAware(myScan->ns,(*tcl.list_commandwords.at(2)),myNs,myName); if (myNs.length()) { myEntryNs = tcl_entry_namespace(myNs); } else { myEntryNs = tcl_entry_namespace(myScan->ns); } //why not needed here? tcl.fn.remove(myName); 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_commandwords.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_commandwords.at(6), myEntryNs->name,NULL,myEntry); } //! Handle \c itcl::body statements and \c oo::define method and method inside \c itcl::class statements. static void tcl_command_METHOD() { D QCString myNs, myName; Entry *myEntryCl, *myEntry; tcl_scan *myScan = tcl.scan.at(0); tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_codify_cmd(NULL,2); tcl_codify_cmd(NULL,3); tcl_codify_cmd(NULL,4); tcl_codify_cmd(NULL,5); tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)),myNs,myName); if (myNs.length()) { myEntryCl = tcl_entry_class(myNs); } else { myNs = myScan->ns; myEntryCl = myScan->entry_cl; } // needed in case of more then one definition p.e. itcl::method and itcl::body // see also bug # tcl.fn.remove(myName); 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_commandwords.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_commandwords.at(6), myNs, myEntryCl, myEntry); } //! Handle \c constructor statements inside class definitions. static void tcl_command_CONSTRUCTOR() { D QCString myNs, myName; Entry *myEntryCl, *myEntry; tcl_scan *myScan = tcl.scan.at(0); tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_codify_cmd(NULL,2); tcl_codify_cmd(NULL,3); tcl_name(myScan->ns,(*tcl.list_commandwords.at(0)),myNs,myName); if (myNs.length()) { myEntryCl = tcl_entry_class(myNs); } else { myNs = myScan->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_commandwords.at(2)); if (myEntryCl) myEntryCl->addSubEntry(tcl.entry_current); myEntry = tcl.entry_current; tcl.fn.insert(myName,myEntry); myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(4), myNs, myEntryCl, myEntry); } //! Handle \c destructor statements inside class definitions. static void tcl_command_DESTRUCTOR() { D QCString myNs, myName; Entry *myEntryCl, *myEntry; tcl_scan *myScan = tcl.scan.at(0); tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_name(myScan->ns,(*tcl.list_commandwords.at(0)),myNs,myName); if (myNs.length()) { myEntryCl = tcl_entry_class(myNs); } else { myNs = myScan->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_commandwords.at(2), myNs, myEntryCl, myEntry); } //! Handle \c namespace statements. static bool tcl_command_NAMESPACE() { D QCString myNs, myName, myStr; //Entry *myEntryNs=NULL; tcl_scan *myScan = tcl.scan.at(0); tcl_name(myScan->ns,(*tcl.list_commandwords.at(4)),myNs,myName); if (myName.isEmpty()) return false; // not a namespace tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_codify_cmd("keyword",2); tcl_codify_cmd(NULL,3); tcl_codify_cmd(NULL,4); tcl_codify_cmd(NULL,5); if (!myNs.isEmpty()) { 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_commandwords.at(6)); if (tcl.list_commandwords.count() > 7) { for (uint i=7;ins,(*tcl.list_commandwords.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); tcl.cl.insert(myName,tcl.entry_current); myEntryCl = tcl.entry_current; myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(4), myName, myEntryCl, NULL); } //! Handle \c oo::class statements. static void tcl_command_OO_CLASS() { D QCString myNs, myName; //Entry *myEntryNs; Entry *myEntryCl; tcl_scan *myScan = tcl.scan.at(0); tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_codify_cmd("NULL",2); tcl_codify_cmd("NULL",3); tcl_codify_cmd("NULL",4); tcl_codify_cmd("NULL",5); tcl_name(myScan->ns,(*tcl.list_commandwords.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_commandwords.at(6), myName, myEntryCl, NULL); } //! Handle \c oo::define statements. static void tcl_command_OO_DEFINE() { D QCString myNs, myName, myStr; Entry *myEntryCl; tcl_scan *myScan = tcl.scan.at(0); tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl_codify_cmd("NULL",2); tcl_codify_cmd("NULL",3); tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)),myNs,myName); if (myNs.length()) { myName = myNs+"::"+myName; } myEntryCl = tcl_entry_class(myName); myStr = (*tcl.list_commandwords.at(4)); // // special cases first // oo::define classname method methodname args script // oo::define classname constructor argList bodyScript // oo::define classname destructor bodyScript unsigned int n =tcl.list_commandwords.count(); if ((myStr == "method" && n == 11) || (myStr == "constructor" && n == 9) || (myStr == "destructor" && n == 7)) { for (unsigned int i = 4; i < n-1; i++) { tcl_codify_cmd("NULL",i); } Entry *myEntry; QCString myMethod; tcl_name(myScan->ns,(*tcl.list_commandwords.at(n==11?6:4)),myNs,myMethod); // code snippet taken from tcl_command_METHOD()/tcl_command_CONSTRUCTOR tcl.fn.remove(myMethod); tcl.entry_current->section = Entry::FUNCTION_SEC; tcl.entry_current->mtype = Method; tcl.entry_current->name = myMethod; 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); if (n==11) { tcl_command_ARGLIST(*tcl.list_commandwords.at(8)); } else if (n==9) { tcl_command_ARGLIST(*tcl.list_commandwords.at(6)); } if (myEntryCl) myEntryCl->addSubEntry(tcl.entry_current); tcl.fn.insert(myMethod,tcl.entry_current); myEntry = tcl.entry_current; myScan = tcl_scan_start('?',*tcl.list_commandwords.at(n-1), myNs, myEntryCl, myEntry); } else { // The general case // Simply concat all arguments into a script. // Note: all documentation collected just before the // oo::define command is lost if (tcl.list_commandwords.count() > 5) { for (uint i=5;ins,(*tcl.list_commandwords.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 = tcl_entry_namespace(myScan->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(); } //! Handling of command parsing. //! what=0 -> ... //! what=1 -> ... //! what=-1 -> ... static void tcl_command(int what,const char *text) { int myLine=0; if (what==0) { tcl.scan.at(0)->line1=yylineno;// current line in scan context tcl.line_body0=yylineno;// start line of command tcl_inf("<- %s\n",text); yy_push_state(COMMAND); tcl.list_commandwords.clear(); tcl.string_command=""; tcl.string_last=""; tcl.command=1; return; } else if (what==1) { if (tcl.string_last.length()) { tcl.list_commandwords.append(tcl.string_last); tcl.string_last=""; } if (text) { tcl.list_commandwords.append(text); } return; } else if (what!=-1) {// should not happen tcl_err("what %d\n",what); return; } QCString myText = text; tcl_inf("->\n"); if (tcl.command==0) { return; //TODO check on inside comment } if (tcl.string_last != "") {// get last word tcl.list_commandwords.append(tcl.string_last); tcl.string_last=""; } yy_pop_state(); // check command QCString myStr = (*tcl.list_commandwords.at(0)); tcl_scan *myScanBackup=tcl.scan.at(0); int myLevel = 0; Protection myProt = tcl.protection; if (tcl.list_commandwords.count() < 3) { tcl_command_OTHER(); goto command_end; } // remove leading "::" and apply TCL_SUBST if (myStr.left(2)=="::") myStr = myStr.mid(2); if (tcl.config_subst.contains(myStr)) { myStr=tcl.config_subst[myStr]; } if (myStr=="private") { tcl.protection = Private; myLevel = 1; } else if (myStr=="protected") { tcl.protection = Protected; myLevel = 1; } else if (myStr=="public") { tcl.protection = Public; myLevel = 1; } if (myLevel) { tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); tcl.list_commandwords.remove(tcl.list_commandwords.at(1)); tcl.list_commandwords.remove(tcl.list_commandwords.at(0)); if (tcl.list_commandwords.count()==1) { tcl_scan *myScan = tcl.scan.at(0); myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(0), myScan->ns,myScan->entry_cl,myScan->entry_fn); myProt = tcl.protection; goto command_end; } myStr = (*tcl.list_commandwords.at(0)); // remove leading "::" and apply TCL_SUBST if (myStr.left(2)=="::") myStr = myStr.mid(2); if (tcl.config_subst.contains(myStr)) { myStr=tcl.config_subst[myStr]; } } if (myStr=="proc") { if (tcl.list_commandwords.count() == 5) {// itcl::proc tcl.list_commandwords.append(""); tcl.list_commandwords.append(""); } if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;} tcl_command_PROC(); goto command_end; } if (myStr=="method") { if (tcl.list_commandwords.count() == 5) {// itcl::method tcl.list_commandwords.append(""); tcl.list_commandwords.append(""); } if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;} tcl_command_METHOD(); goto command_end; } if (myStr=="constructor") { if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;} tcl_command_CONSTRUCTOR(); goto command_end; } if (myStr=="destructor") { if (tcl.list_commandwords.count() != 3) {myLine=__LINE__;goto command_warn;} tcl_command_DESTRUCTOR(); goto command_end; } if (myStr=="namespace") { if ((*tcl.list_commandwords.at(2))=="eval") { if (tcl.list_commandwords.count() < 7) {myLine=__LINE__;goto command_warn;} if (tcl_command_NAMESPACE()) { goto command_end; } } else { tcl_command_OTHER(); goto command_end; } } if (myStr=="itcl::class") { if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;} tcl_command_ITCL_CLASS(); goto command_end; } if (myStr=="itcl::body") { if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;} tcl_command_METHOD(); goto command_end; } if (myStr=="oo::class") { if ((*tcl.list_commandwords.at(2))=="create") { if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;} tcl_command_OO_CLASS(); goto command_end; } tcl_command_OTHER(); goto command_end; } if (myStr=="oo::define") { if (tcl.list_commandwords.count() < 5) {myLine=__LINE__;goto command_warn;} tcl_command_OO_DEFINE(); goto command_end; } if (myStr=="variable") { if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;} if (tcl.scan.at(0)->entry_fn == NULL) {// only parsed outside functions tcl_command_VARIABLE(tcl.scan.at(0)->entry_cl && tcl.scan.at(0)->entry_cl->name!=""); goto command_end; } } if (myStr=="common") { if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;} if (tcl.scan.at(0)->entry_fn == NULL) {// only parsed outside functions tcl_command_VARIABLE(0); goto command_end; } } if (myStr=="inherit" || myStr=="superclass") { if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;} if (tcl.scan.at(0)->entry_cl && tcl.scan.at(0)->entry_cl->name!="") { for (unsigned int i = 2; i < tcl.list_commandwords.count(); i = i + 2) { tcl.scan.at(0)->entry_cl->extends->append(new BaseInfo((*tcl.list_commandwords.at(i)),Public,Normal)); } } goto command_end; } /* * Start of internal tcl keywords * Ready: switch, eval, catch, if, for, foreach, while */ if (myStr=="switch") { if (tcl.list_commandwords.count() < 5) {myLine=__LINE__;goto command_warn;} tcl_command_SWITCH(); goto command_end; } if (myStr=="eval") { if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;} tcl_command_EVAL(); goto command_end; } if (myStr=="catch") { if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;} tcl_command_CATCH(); goto command_end; } if (myStr=="for") { if (tcl.list_commandwords.count() != 9) {myLine=__LINE__;goto command_warn;} tcl_command_FOR(); goto command_end; } if (myStr=="foreach") { if (tcl.list_commandwords.count() < 7 || tcl.list_commandwords.count()%2==0) {myLine=__LINE__;goto command_warn;} tcl_command_FOREACH(); goto command_end; } /* if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN? */ if (myStr=="if" && tcl.list_commandwords.count() > 4) { QCStringList myType; myType << "keyword" << "NULL" << "expr" << "NULL"; char myState='x';// last word: e'x'pr 't'hen 'b'ody 'e'lse else'i'f.. for (unsigned int i = 4; i < tcl.list_commandwords.count(); i = i + 2) { QCString myStr=(*tcl.list_commandwords.at(i)); if (myState=='x') { if (myStr=="then") { myState='t'; myType << "keyword" << "NULL"; } else { myState='b'; myType << "script" << "NULL"; } } else if (myState=='t') { myState='b'; myType << "script" << "NULL"; } else if (myState=='b') { if (myStr=="elseif") { myState='i'; myType << "keyword" << "NULL"; } else if (myStr=="else" && i==tcl.list_commandwords.count()-3) { myState = 'b'; myType << "keyword" << "NULL" << "script"; i = tcl.list_commandwords.count(); } else if (i==tcl.list_commandwords.count()-1) { myState = 'b'; myType << "script"; i = tcl.list_commandwords.count(); } else { myLine=__LINE__;goto command_warn; } } else if (myState=='i') { myState='x'; myType << "expr" << "NULL"; } } if (myState != 'b') {myLine=__LINE__;goto command_warn;} tcl_command_IF(myType); goto command_end; } if (myStr=="while") { if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;} tcl_command_WHILE(); goto command_end; } tcl_command_OTHER(); goto command_end; command_warn:// print warning message because of wrong used syntax tcl_war("%d count=%d: %s\n",myLine,tcl.list_commandwords.count(),tcl.list_commandwords.join(" ").data()); tcl_command_OTHER(); command_end:// add remaining text to current context if (!myText.isEmpty()) { if(myScanBackup==tcl.scan.at(0)) { tcl_codify("comment",myText); } else { tcl.scan.at(0)->after << "comment" << myText; } } tcl.list_commandwords.clear(); tcl.command = 0; tcl.protection = myProt; } //---------------------------------------------------------------------------- //! Common initializations. static void tcl_init() { // Get values from option TCL_SUBST tcl.config_subst.clear(); QStrList myStrList = Config_getList(TCL_SUBST); const char *s=myStrList.first(); while (s) { QCString myStr=s; int i=myStr.find('='); if (i>0) { QCString myName=myStr.left(i).stripWhiteSpace(); QCString myValue=myStr.right(myStr.length()-i-1).stripWhiteSpace(); if (!myName.isEmpty() && !myValue.isEmpty()) tcl_inf("TCL_SUBST: use '%s'\n",s); tcl.config_subst[myName] = myValue; } s = myStrList.next(); } if (tcl.input_string.at(tcl.input_string.length()-1) == 0x1A) { } else if (tcl.input_string.at(tcl.input_string.length()-1) == '\n') { tcl.input_string[tcl.input_string.length()-1] = 0x1A; } else { tcl.input_string += 0x1A; } tcl.code = NULL; tcl.code_font=NULL; tcl.code_line=1; tcl.code_linenumbers=1; tcl.config_autobrief = Config_getBool(JAVADOC_AUTOBRIEF); 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=' '; 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_commandwords.clear(); tcl.scan.clear(); tcl.ns.clear(); tcl.cl.clear(); tcl.fn.clear(); yylineno = 1; tcl.protection = Public; tcl.memberdef = NULL; } //! Start parsing. static void tcl_parse(const QCString ns, const QCString cls) { 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); Entry *myEntry=tcl_entry_new(); myEntry->name=""; tcl.entry_main->addSubEntry(myEntry); tcl.ns.insert("::",myEntry); tcl.entry_current = tcl_entry_new(); tclscannerYYrestart( tclscannerYYin ); BEGIN( TOP ); yylineno=1; myScan = new tcl_scan; myScan->type[0]=' ';myScan->type[1]='\n'; myScan->after.clear(); myScan->line0=yylineno; myScan->line1=yylineno; myScan->buffer_state=YY_CURRENT_BUFFER; myScan->ns=ns; myScan->entry_cl=tcl_entry_class(cls); myScan->entry_fn=NULL; tcl.entry_inside = tcl.entry_file; myScan->entry_scan = tcl.entry_inside; tcl.scan.insert(0,myScan); tclscannerYYlex(); 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, bool /*sameTranslationUnit*/, QStrList & /*filesInSameTranslationUnit*/) { QFile myFile; tcl_inf("%s\n",fileName); myFile.setName(fileName); if (!myFile.open(IO_ReadOnly)) return; if (strlen(input)<1) return; tcl.input_string = input; if (tcl.input_string.length()<1) return; printlex(yy_flex_debug, TRUE, __FILE__, fileName); msg("Parsing %s...\n",fileName); Doxygen::docGroup.enterFile(fileName,yylineno); tcl_init(); tcl.code = NULL; tcl.file_name = fileName; tcl.this_parser = this; tcl.entry_main = root; /* toplevel entry */ tcl_parse("",""); Doxygen::docGroup.leaveFile(tcl.file_name,yylineno); root->program.resize(0); myFile.close(); printlex(yy_flex_debug, FALSE, __FILE__, fileName); } //! Parse file and codify. void TclLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf, const char * scopeName, const QCString & input, SrcLangExt lang, bool isExampleBlock, const char * exampleName, FileDef * fileDef, int startLine, int endLine, bool inlineFragment, const MemberDef *memberDef, bool showLineNumbers, const Definition *searchCtx, bool collectXRefs ) { (void)scopeName; (void)lang; (void)exampleName; (void)fileDef; (void)endLine; (void)inlineFragment; (void)searchCtx; (void)collectXRefs; if (input.length()<1) return; printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); tcl.input_string = input; QCString myNs=""; QCString myCls=""; if (memberDef) { if (memberDef->getClassDef()) { myCls = memberDef->getClassDef()->displayName(); myNs = myCls; } else if (memberDef->getNamespaceDef()) { myNs = memberDef->getNamespaceDef()->displayName(); } } QCString 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(); } tcl_inf("%s (%d,%d) %d %d\n",myStr.data(),startLine,endLine,isExampleBlock,inlineFragment); //tcl_inf("%s\n"input.data()); tcl_init(); tcl.collectXRefs = collectXRefs; tcl.memberdef = memberDef; tcl.code = &codeOutIntf; if (startLine<0) { startLine=1; } yylineno=startLine; tcl.code_linenumbers = showLineNumbers; tcl.code_line=yylineno; tcl.code->startCodeLine(tcl.code_linenumbers); if (tcl.code_linenumbers) { tcl.code->writeLineNumber(0,0,0,tcl.code_line); } tcl.file_name = ""; tcl.this_parser = NULL; if (isExampleBlock) { tcl_codify(NULL,input); } else { tcl.entry_main = tcl_entry_new(); tcl_parse(myNs,myCls); } tcl.code->endCodeLine(); tcl.scan.clear(); tcl.ns.clear(); tcl.cl.clear(); tcl.fn.clear(); tcl.entry.clear(); printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } 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.at(tcl.input_position) ) { *buf = tcl.input_string.at(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 #include "tclscanner.l.h"