1 /*****************************************************************************
2 * Parser for Tcl subset
4 * Copyright (C) 2010 by Rene Zaumseil
5 * based on the work of Dimitri van Heesch.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation under the terms of the GNU General Public License is hereby
9 * granted. No representations are made about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
11 * See the GNU General Public License for more details.
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
25 #include <qstringlist.h>
41 #include "commentscan.h"
43 #include "tclscanner.h"
44 #include "outputlist.h"
45 #include "membername.h"
46 #include "searchindex.h"
47 #include "commentcnv.h"
50 #include "arguments.h"
51 #include "namespacedef.h"
54 #define YY_NEVER_INTERACTIVE 1
57 #define MAX_INCLUDE_DEPTH 10
59 //! Application error.
61 printf("Error %d %s() at line %d! ",__LINE__,tcl.file_name.data(),yylineno); \
62 yy_push_state(ERROR); \
66 //! Application warning.
68 printf("Warning %d %s() at line %d: ",__LINE__,tcl.file_name.data(),yylineno); \
71 //! Application message.
73 if (0) printf("--- %.4d %d@%d: ",__LINE__,yylineno,yy_start_stack_ptr) && printf
77 if (0) printf("--- %.4d %d@%d: %s\n",__LINE__,yylineno,yy_start_stack_ptr,yytext);
79 // BEGIN of copy from tclUtil.c
80 // - Tcl_Interp removed
81 // - changes are marked with RZ
82 // #define's to adapt the code:
84 #define UCHAR (unsigned char)
87 #define ckalloc malloc
89 #define TclCopyAndCollapse(size,src,dest) memcpy(dest,src,size); *(dest+size)=0
91 CONST char *list, /* Points to the first byte of a string
92 * containing a Tcl list with zero or more
93 * elements (possibly in braces). */
94 int listLength, /* Number of bytes in the list's string. */
95 CONST char **elementPtr, /* Where to put address of first significant
96 * character in first element of list. */
97 CONST char **nextPtr, /* Fill in with location of character just
98 * after all white space following end of
99 * argument (next arg or end of list). */
100 int *sizePtr, /* If non-zero, fill in with size of
102 int *bracePtr) /* If non-zero, fill in with non-zero/zero to
103 * indicate that arg was/wasn't in braces. */
105 CONST char *p = list;
106 CONST char *elemStart; /* Points to first byte of first element. */
107 CONST char *limit; /* Points just after list's last byte. */
108 int openBraces = 0; /* Brace nesting level during parse. */
110 int size = 0; /* lint. */
114 * Skim off leading white space and check for an opening brace or quote.
115 * We treat embedded NULLs in the list as bytes belonging to a list
119 limit = (list + listLength);
120 while ((p < limit) && (isspace(UCHAR(*p))))
121 { /* INTL: ISO space. */
125 { /* no element found */
130 if (*p == '{') /* } to keep vi happy */
143 *bracePtr = openBraces;
147 * Find element's end (a space, close brace, or the end of the string).
155 * Open brace: don't treat specially unless the element is in
156 * braces. In this case, keep a nesting count.
167 * Close brace: if element is in braces, keep nesting count and
168 * quit when the last close brace is seen.
176 else if (openBraces == 1)
178 size = (int)(p - elemStart);
180 if ((p >= limit) || isspace(UCHAR(*p)))
181 { /* INTL: ISO space. */
186 * Garbage after the closing brace; return an error.
194 * Backslash: skip over everything up to the end of the backslash
199 //RZ Tcl_UtfBackslash(p, &numChars, NULL);
200 //RZ p += (numChars - 1);
205 * Space: ignore if element is in braces or quotes; otherwise
215 if ((openBraces == 0) && !inQuotes)
217 size = (int)(p - elemStart);
223 * Double-quote: if element is in quotes then terminate it.
229 size = (int)(p - elemStart);
231 if ((p >= limit) || isspace(UCHAR(*p)))
232 { /* INTL: ISO space */
237 * Garbage after the closing quote; return an error.
247 * End of list: terminate element.
260 size = (int)(p - elemStart);
264 while ((p < limit) && (isspace(UCHAR(*p))))
265 { /* INTL: ISO space. */
268 *elementPtr = elemStart;
278 CONST char *list, /* Pointer to string with list structure. */
279 int *argcPtr, /* Pointer to location to fill in with the
280 * number of elements in the list. */
281 CONST char ***argvPtr) /* Pointer to place to store pointer to array
282 * of pointers to list elements. */
284 CONST char **argv, *l, *element;
286 int length, size, i, result, elSize, brace;
289 * Figure out how much space to allocate. There must be enough space for
290 * both the array of pointers and also for a copy of the list. To estimate
291 * the number of pointers needed, count the number of space characters in
295 for (size = 2, l = list; *l != 0; l++)
297 if (isspace(UCHAR(*l)))
298 { /* INTL: ISO space. */
302 * Consecutive space can only count as a single list delimiter.
307 char next = *(l + 1);
314 if (isspace(UCHAR(next)))
315 { /* INTL: ISO space. */
322 length = (int)(l - list);
323 argv = (CONST char **) ckalloc((unsigned)
324 ((size * sizeof(char *)) + length + 1));
325 for (i = 0, p = ((char *) argv) + size*sizeof(char *);
328 CONST char *prevList = list;
330 result = TclFindElement(list, length, &element, &list,
332 length -= (int)(list - prevList);
333 if (result != TCL_OK)
335 ckfree((char *) argv);
344 ckfree((char *) argv);
350 memcpy(p, element, (size_t) elSize);
357 TclCopyAndCollapse(elSize, element, p);
369 void tcl_split_list(QString &str, QStringList &list)
375 if (str.left(1)=="{" && str.right(1)=="}")
377 str=str.mid(1,str.length()-2);
379 else if (str.left(1)=="\"" && str.right(1)=="\"")
381 str=str.mid(1,str.length()-2);
383 if (Tcl_SplitList(str.ascii(),&argc,&argv) != TCL_OK)
389 for (int i = 0; i < argc; i++)
391 list.append(argv[i]);
393 ckfree((char *) argv);
397 //! Structure containing information about current scan context.
400 char type[2]; // type of scan context: "\"" "{" "[" "?" " "
401 int line0; // start line of scan context
402 int line1; // end line of scan context
403 YY_BUFFER_STATE buffer_state; // value of scan context
404 QCString ns; // current namespace
405 Entry *entry_fn; // if set contains the current proc/method/constructor/destructor
406 Entry *entry_cl; // if set contain the current class
407 Entry *entry_scan; // current scan entry
408 Protection protection; // current protections state
409 QStringList after; // option/value list (options: NULL comment keyword script)
412 //* Structure containing all internal global variables.
415 CodeOutputInterface * code; // if set then we are codifying the file
416 int code_line; // current line of code
417 int code_linenumbers; // if true create line numbers in code
418 const char *code_font; // used font to codify
419 bool config_autobrief; // value of configuration option
420 QMap<QString,QString> config_subst; // map of configuration option values
421 QCString input_string; // file contents
422 int input_position; // position in file
423 QCString file_name; // name of used file
424 ParserInterface *this_parser; // myself
425 int command; // true if command was found
426 int comment; // set true if comment was scaned
427 int brace_level; // bookkeeping of braces
428 int bracket_level; // bookkeeping of brackets
429 int bracket_quote; // bookkeeping of quotes (toggles)
430 char word_is; // type of current word: "\"" "{" "[" "?" " "
431 int line_comment; // line number of comment
432 int line_commentline; // line number of comment after command
433 int line_command; // line number of command
434 int line_body0; // start line of body
435 int line_body1; // end line of body
436 QCString string_command; // contain current command
437 QCString string_commentline; // contain current comment after command
438 QCString string_commentcodify; // current comment string used in codifying
439 QCString string_comment; // contain current comment
440 QCString string_last; // contain last read word or part of word
441 QCString string; // temporary string value
442 Entry* entry_main; // top level entry
443 Entry* entry_file; // entry of current file
444 Entry* entry_current; // currently used entry
445 Entry* entry_inside; // contain entry of current scan context
446 QStringList list_commandwords; // list of command words
447 QList<tcl_scan> scan; // stack of scan contexts
448 QAsciiDict<Entry> ns; // all read namespace entries
449 QAsciiDict<Entry> cl; // all read class entries
450 QAsciiDict<Entry> fn; // all read function entries
451 QList<Entry> entry; // list of all created entries, will be deleted after codifying
452 Protection protection; // current protections state
453 MemberDef *memberdef; // contain current MemberDef when codifying
457 static int yyread(char *buf,int max_size);
458 static tcl_scan *tcl_scan_start(char type, QString content, QCString ns, Entry *entry_cls, Entry *entry_fn);
459 static void tcl_scan_end();
460 static void tcl_comment(int what,const char *text);
461 static void tcl_word(int what,const char *text);
462 static void tcl_command(int what,const char *text);
466 //! Create new entry.
467 // @return new initialised entry
468 Entry* tcl_entry_new()
470 Entry *myEntry = new Entry;
471 myEntry->section = Entry::EMPTY_SEC;
473 // myEntry->type = "";
475 // myEntry->doc = "";
476 myEntry->protection = Public;
477 // myEntry->mtype = Method;
478 // myEntry->virt = Normal;
479 // myEntry->stat = FALSE;
480 myEntry->fileName = tcl.file_name;
481 myEntry->lang = SrcLangExt_Tcl;
482 initGroupInfo(myEntry);
486 tcl.entry.insert(0,myEntry);
491 //! Set protection level.
492 void tcl_protection(Entry *entry)
494 if (entry->protection!=Public&&entry->protection!=Protected&&entry->protection!=Private)
496 entry->protection = tcl.protection;
498 if (entry->protection!=Protected&&entry->protection!=Private)
500 entry->protection = Public;
505 // @return 'ns' and 'name' of given current 'ns0' and 'name0'
506 static void tcl_name(const QCString &ns0, const QCString &name0, QCString &ns, QCString &name)
511 if (qstrncmp(name0.data(),"::",2)==0)
515 else if (ns0.length() && ns0 != " ")
517 myNm = ns0 + "::" + name0;
523 myStart = myNm.findRev("::");
531 ns = myNm.mid(0,myStart);
532 name = myNm.mid(myStart+2);
536 // Check and return namespace entry.
537 // @return namespace entry
538 Entry* tcl_entry_namespace(const QCString ns)
543 myEntry = tcl.ns.find(ns);
547 myEntry = tcl.ns.find("::");
551 myEntry = tcl_entry_new();
552 myEntry->section = Entry::NAMESPACE_SEC;
554 tcl.entry_main->addSubEntry(myEntry);
555 tcl.ns.insert(ns,myEntry);
560 // Check and return class entry.
561 // @return class entry
562 Entry* tcl_entry_class(const QCString cl)
565 if (!cl.length()) return(NULL);
567 myEntry = tcl.cl.find(cl);
570 myEntry = tcl_entry_new();
571 myEntry->section = Entry::CLASS_SEC;
573 tcl.entry_main->addSubEntry(myEntry);
574 tcl.cl.insert(cl,myEntry);
579 //! Check for keywords.
580 // @return 1 if keyword and 0 otherwise
581 static int tcl_keyword(QCString str)
583 static QStringList myList;
588 myList <<"append"<<"apply"<<"array"<<"auto_execok"<<"auto_import"<<"auto_load"<<"auto_mkindex"<<"auto_qualify"<<"auto_reset";
590 myList <<"catch"<<"cd"<<"close"<<"clock"<<"concat";
591 myList <<"eof"<<"eval"<<"exec"<<"exit"<<"expr";
592 myList <<"fblocked"<<"fconfigure"<<"file"<<"fileevent"<<"flush"<<"for"<<"foreach"<<"format";
593 myList <<"gets"<<"global";
595 myList <<"if"<<"incr"<<"info"<<"interp";
597 myList <<"lappend"<<"lassign"<<"lindex"<<"linsert"<<"llength"<<"load"<<"lrange"<<"lrepeat"<<"lreplace"<<"lreverse"<<"lset";
598 myList <<"namespace";
599 myList <<"package"<<"parray"<<"pid"<<"pkg_mkIndex"<<"proc"<<"puts"<<"pwd";
600 myList <<"registry"<<"rename"<<"return";
601 myList <<"scan"<<"set"<<"split"<<"string"<<"switch";
602 myList <<"tclLog"<<"tcl_endOfWord"<<"tcl_findLibrary"<<"tcl_startOfNextWord"<<"tcl_startOfPreviousWord"<<"tcl_wordBreakAfter"<<"tcl_wordBreakBefore"<<"tell"<<"time";
603 myList <<"unknown"<<"upvar";
604 myList <<"variable"<<"vwait";
606 myList <<"bell"<<"bind"<<"bindtags";
607 myList <<"clipboard"<<"console"<<"consoleinterp";
614 myList <<"pack"<<"place";
617 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";
618 myList <<"winfo"<<"wm";
619 myList <<"button"<<"canvas"<<"checkbutton"<<"entry"<<"frame"<<"image"<<"label"<<"labelframe"<<"listbox"<<"menu"<<"menubutton"<<"message"<<"panedwindow"<<"radiobutton"<<"scale"<<"scrollbar"<<"spinbox"<<"toplevel";
623 str=str.stripWhiteSpace();
624 if (str.left(2)=="::") {str=str.mid(2);}
625 if (myList.findIndex(str) != -1) return(1);
629 //! End codifying with special font class.
630 static void tcl_font_end()
632 if (!tcl.code) return;
635 tcl.code->endFontClass();
640 //! Codify 'str' with special font class 's'.
641 static void tcl_codify(const char *s,char *str)
643 if (!tcl.code || !str) return;
644 if (s && qstrcmp(s,"NULL")!=0)
647 tcl.code->startFontClass(s);
656 while ((c=*p++) && c!='\n') {}
661 tcl.code->codify(sp);
664 tcl.code->endFontClass();
666 tcl.code->endCodeLine();
667 tcl.code->startCodeLine(tcl.code_linenumbers);
668 if (tcl.code_linenumbers)
670 tcl.code->writeLineNumber(0,0,0,tcl.code_line);
674 tcl.code->startFontClass(tcl.code_font);
679 tcl.code->codify(sp);
687 //! Codify 'str' with special font class 's'.
688 static void tcl_codify(const char *s,const char *str)
690 if (tcl.code==NULL) return;
691 char *tmp= (char *) malloc(strlen(str)+1);
697 //! Codify 'str' with special font class 's'.
698 static void tcl_codify(const char *s,const QString &str)
700 if (tcl.code==NULL) return;
701 tcl_codify(s,str.utf8());
705 //! Codify 'str' with special font class 's'.
706 static void tcl_codify(const char *s,const QCString &str)
708 if (!tcl.code) return;
709 tcl_codify(s,str.data());
712 static void tcl_codify_cmd(const char *s,int i)
714 tcl_codify(s,(*tcl.list_commandwords.at(i)).utf8());
717 //-----------------------------------------------------------------------------
719 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
720 //-----------------------------------------------------------------------------
745 if (tcl.scan.count()<1)
748 tcl_err("Tcl parser stack empty! Parser error in file '%s'.\n",tcl.file_name.data());
751 else if (tcl.scan.count()==1)
752 {// exit, check on input?
766 tcl.line_comment=yylineno;
769 <TOP>({ws}|[\;\n])+ {
771 tcl_codify(NULL,yytext);
776 tcl.line_command=yylineno;
782 tcl_codify("comment",yytext);
786 tcl_codify("comment",yytext);
787 tcl_comment(2,yytext+1);
789 <COMMENT>"##".*\\\n {
791 tcl_codify("comment",yytext);
793 t = t.mid(2,t.length()-3);
795 tcl_comment(1,t.data());
796 yy_push_state(COMMENT_NL);
800 tcl_codify("comment",yytext);
801 tcl_comment(1,yytext+2);
803 <COMMENT>"#"[@\\]"code"\n[ \t]*[^#] {
806 tcl_codify("comment",t.left(7));
807 tcl_comment(2,"\n@code\n");
809 yy_push_state(COMMENT_CODE);
811 <COMMENT>"#"[@\\]"verbatim"\n[ \t]*[^#] {
814 tcl_codify("comment",t.left(11));
815 tcl_comment(2,"\n@verbatim\n");
817 yy_push_state(COMMENT_VERB);
821 tcl_codify("comment",yytext);
823 t = t.mid(1,t.length()-3);
825 tcl_comment(2,t.data());
826 yy_push_state(COMMENT_NL);
830 tcl_codify("comment",yytext);
831 tcl_comment(2,yytext+1);
836 t = t.mid(0,t.length()-1);
837 tcl_codify("comment",t.data());
838 t = t.mid(1,t.length());
839 tcl_comment(-2,t.data());
849 tcl_comment(-2,yytext);
853 <COMMENT_CODE>"#"[@\\]"endcode"\n {
856 t = t.left(t.length()-10);
857 tcl_comment(2,t.data());
858 tcl_comment(2,"\n@endcode\n");
866 <COMMENT_CODE>.*\x1A {
872 <COMMENT_VERB>"#"[@\\]"endverbatim"\n {
875 t = t.left(t.length()-14);
876 tcl_comment(2,t.data());
877 tcl_comment(2,"\n@endverbatim\n");
885 <COMMENT_VERB>.*\x1A {
893 tcl_codify("comment",yytext);
894 tcl_comment(2,yytext);
898 tcl_codify("comment",yytext);
899 tcl_comment(2,yytext);
908 <COMMENTLINE>.*\x1A {
913 <COMMENTLINE>[ \t]* {
915 tcl.string_commentcodify += yytext;
917 <COMMENTLINE>"#<".*\\\n {
919 tcl.string_commentcodify += yytext;
921 t = t.mid(2,t.length()-4);
923 tcl.string_commentline += t;
924 yy_push_state(COMMENTLINE_NL);
926 <COMMENTLINE>"#<".*\n {
928 tcl.string_commentcodify += yytext;
929 tcl.string_commentline += (yytext+2);
934 if (tcl.string_commentline.length())
936 tcl.entry_current->brief = tcl.string_commentline;
937 tcl.entry_current->briefLine = tcl.line_commentline;
938 tcl.entry_current->briefFile = tcl.file_name;
941 tcl_command(-1,tcl.string_commentcodify.data());
942 tcl.string_commentline="";
943 tcl.string_commentcodify="";
946 <COMMENTLINE_NL>.*\\\n {
948 tcl.string_commentcodify += yytext;
950 t = t.left(t.length()-3);
952 tcl.string_commentline += t;
954 <COMMENTLINE_NL>.*\n {
956 tcl.string_commentcodify += yytext;
957 tcl.string_commentline += yytext;
960 <COMMENTLINE_NL>.*\x1A {
963 t = t.left(t.length()-1);
964 tcl.string_commentcodify += t;
965 tcl.string_commentline += t;
970 <COMMAND>{ws}*[\;]{ws}*"#<" {
972 tcl.string_commentcodify = yytext;
973 tcl.string_commentcodify = tcl.string_commentcodify.left(tcl.string_commentcodify.length()-2);
974 tcl.string_commentline = "";
975 tcl.line_commentline = yylineno;
976 tcl.line_body1=yylineno;
979 yy_push_state(COMMENTLINE);
983 tcl.string_commentcodify = "";
984 tcl.string_commentline = "";
985 tcl.line_body1=yylineno;
990 tcl.string_commentcodify = "";
991 tcl.string_commentline = "";
992 tcl.line_body1=yylineno;
993 tcl_command(-1,yytext);
997 tcl.string_commentcodify = "";
998 tcl.string_commentline = "";
999 tcl.line_body1=yylineno-1;
1000 tcl_command(-1,yytext);
1004 tcl_command(1,yytext);
1009 tcl.string_last = "{*}";
1010 tcl_word(0,&yytext[3]);
1012 <COMMAND>"\\"[\{\}\[\]\;\" \t] {
1015 tcl.string_last = "";
1021 if (yytext[0]=='{'||yytext[0]=='['||yytext[0]=='"') tcl.word_is = yytext[0];
1022 tcl.string_last = "";
1027 <WORD>"\\"[\{\}\[\]\;\" \t] {
1055 tcl_word(10,yytext);
1058 tcl_word(11,yytext);
1061 tcl_word(12,yytext);
1068 //! Start new scan context for given 'content'.
1069 // @return created new scan context.
1070 static tcl_scan *tcl_scan_start(char type, QString content, QCString ns, Entry *entry_cl, Entry *entry_fn)
1072 tcl_scan *myScan=tcl.scan.at(0);
1074 tcl_inf("line=%d type=%d '%s'\n",tcl.line_body0,type,content.ascii());
1076 myScan->line1=yylineno;
1079 myScan=new tcl_scan;
1080 myScan->type[0] =' ';
1081 myScan->type[1] = '\0';
1086 myScan->type[0] = type;
1089 if (content[0]=='"' && content[content.length()-1]=='"') myScan->type[0]='"';
1090 if (content[0]=='{' && content[content.length()-1]=='}') myScan->type[0]='{';
1091 if (content[0]=='[' && content[content.length()-1]==']') myScan->type[0]='[';
1093 if (myScan->type[0]!=' ')
1095 tcl_codify(NULL,&myScan->type[0]);
1096 content = content.mid(1,content.length()-2);
1098 content += (char)0x1A;// for detection end of scan context
1100 myScan->entry_cl = entry_cl;
1101 myScan->entry_fn = entry_fn;
1102 myScan->entry_scan = tcl.entry_current;
1103 myScan->buffer_state=yy_scan_string(content.ascii());
1104 myScan->line0=tcl.line_body0;
1105 myScan->line1=tcl.line_body1;
1106 myScan->after.clear();
1107 yylineno=myScan->line0;
1108 myScan->protection = tcl.protection;
1110 tcl.entry_inside = myScan->entry_scan;
1111 tcl.entry_current = tcl_entry_new();
1112 tcl.scan.insert(0,myScan);
1113 yy_switch_to_buffer(myScan->buffer_state);
1117 //! Close current scan context.
1118 static void tcl_scan_end()
1120 tcl_scan *myScan=tcl.scan.at(0);
1121 tcl_scan *myScan1=tcl.scan.at(1);
1122 tcl_inf("line=%d\n",myScan->line1);
1124 if (myScan->type[0]=='{') myScan->type[0]='}';
1125 if (myScan->type[0]=='[') myScan->type[0]=']';
1126 if (myScan->type[0]!=' ') tcl_codify(NULL,&myScan->type[0]);
1128 for (unsigned int i=0;i<myScan->after.count();i=i+2)
1130 if (myScan->after[i]=="script") {
1134 tcl_codify(myScan->after[i].utf8(),myScan->after[i+1].utf8());
1136 yy_delete_buffer(myScan->buffer_state);
1138 tcl.entry_inside = myScan1->entry_scan;
1139 yy_switch_to_buffer(myScan1->buffer_state);
1140 yylineno=myScan1->line1;
1141 tcl.protection = myScan1->protection;
1144 myScan1 = tcl_scan_start('?', myScan->after[myStart+1], myScan->ns, myScan->entry_cl, myScan->entry_fn);
1145 for (unsigned int i=myStart+2;i<myScan->after.count();i++)
1147 myScan1->after.append(myScan->after[i]);
1153 tcl.scan.removeFirst();
1157 //! Handling of word parsing.
1158 static void tcl_word(int what,const char *text)
1160 static char myList[1024]="";// nesting level list
1161 static int myLevel=0;// number of current nesting level
1162 static int myWhite=0;// set true when next char should be whitespace
1163 static char myWord;// internal state
1168 yy_push_state(WORD);
1173 case '"': myWord = text[0]; break;
1174 default: myWord = '.';
1180 case 1:// all other chars
1183 tcl_err("expected word separator: %s\n",text);
1199 tcl_inf("(\\\n) ?%s?\n",tcl.string_last.data());
1202 switch (myList[myLevel-1])
1214 tcl_inf("(\\\n) ?%s?\n",tcl.string_last.data());
1224 tcl_err("expected word separator: %s\n",text);
1227 switch (myList[myLevel-1])
1231 myList[myLevel++]='{';
1242 tcl_err("expected word separator: %s\n",text);
1245 switch (myList[myLevel-1])
1249 if (myLevel==0 && !tcl.code)
1263 tcl_err("expected word separator: %s\n",text);
1266 switch (myList[myLevel-1])
1273 myList[myLevel++]='[';
1281 tcl_err("expected word separator: %s\n",text);
1284 switch (myList[myLevel-1])
1300 tcl_err("expected word separator: %s\n",text);
1303 switch (myList[myLevel-1])
1308 myList[myLevel++]='"';
1325 tcl_inf("(%d) ?%s?\n",what,tcl.string_last.data());
1328 switch (myList[myLevel-1])
1340 tcl_inf("(.%d) ?%s?\n",what,tcl.string_last.data());
1357 tcl_inf("(%d) ?%s?\n",what,tcl.string_last.data());
1360 if (myLevel!=1 || myList[0] != '.')
1362 tcl_war("level=%d expected=%c\n",myLevel,myList[myLevel-1]);
1367 tcl_inf("(.%d) ?%s?\n",what,tcl.string_last.data());
1372 tcl_err("wrong state: %d\n",what);
1375 tcl.string_last += text;
1378 //! Handling of comment parsing.
1379 static void tcl_comment(int what,const char *text)
1382 { // begin of comment
1385 tcl_err("comment in comment\n");
1388 yy_push_state(COMMENT);
1389 tcl_inf("<- %s\n",text);
1390 tcl.string_comment="";
1394 { // start new comment
1397 tcl_comment(99,""); // inbody
1399 tcl.string_comment=text;
1406 tcl.string_comment+=text;
1409 else if (what==-1 || what == -2)
1410 { // end of comment without/with command
1413 tcl.string_last=tcl.string_comment;
1414 tcl_comment(100+what,"");
1418 tcl.string_last = "";
1419 tcl_inf("-> %s\n",(const char *)tcl.string_comment);
1422 tcl.string_comment="";
1425 else if (what==98 || what==99)
1426 { // 98=new 99=inbody
1427 if (tcl.this_parser && tcl.string_comment.length())
1429 tcl_inf("-> %s\n",(const char *)tcl.string_comment);
1432 int myLine=tcl.line_comment;
1435 Protection myProt=tcl.protection;
1438 myI.addArray("/*!",3);
1439 myI.addArray(tcl.string_comment.data(),tcl.string_comment.length());
1440 myI.addArray("*/",2);
1441 convertCppComments(&myI,&myO,tcl.file_name);
1442 myO.dropFromStart(3);
1443 myO.shrink(myO.curPos()-2);
1445 QCString myDoc = myO.data();
1447 { // inbody comment file or namespace or class or proc/method
1450 Entry myEntry0; // used to test parsing
1453 Entry *myEntry1=NULL;
1454 if (tcl.scan.at(0)->entry_fn)
1456 myEntry1=tcl.scan.at(0)->entry_fn;
1458 else if (tcl.scan.at(0)->entry_cl)
1460 myEntry1=tcl.scan.at(0)->entry_cl;
1465 while (parseCommentBlock(tcl.this_parser, &myEntry0, myDoc, tcl.file_name,
1466 myLine, FALSE, tcl.config_autobrief, FALSE, myProt, myPos, myNew))
1469 { // we need a new entry in this case
1471 myEntry = tcl_entry_new();
1472 parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name,
1473 myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
1474 tcl.entry_inside->addSubEntry(myEntry);
1477 { // we can add to current entry in this case
1480 myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns);
1482 parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name,
1483 myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
1489 { // we need a new entry
1491 myEntry = tcl_entry_new();
1492 parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name,
1493 myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
1494 tcl.entry_inside->addSubEntry(myEntry);
1497 { // we can add to current entry
1500 myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns);
1502 parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name,
1503 myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
1508 tcl.entry_current = tcl_entry_new();
1509 while (parseCommentBlock(tcl.this_parser, tcl.entry_current, myDoc,
1510 tcl.file_name, myLine, FALSE, tcl.config_autobrief, FALSE,
1511 myProt, myPos, myNew))
1515 tcl.entry_inside->addSubEntry(tcl.entry_current);
1516 tcl.entry_current = tcl_entry_new();
1520 tcl.entry_current->section = tcl.entry_inside->section;
1521 tcl.entry_current->name = tcl.entry_inside->name;
1526 tcl.entry_inside->addSubEntry(tcl.entry_current);
1527 tcl.entry_current = tcl_entry_new();
1531 tcl.entry_current->section = tcl.entry_inside->section;
1532 tcl.entry_current->name = tcl.entry_inside->name;
1535 if (tcl.protection != myProt)
1537 tcl.scan.at(0)->protection = tcl.protection = myProt;
1543 tcl_err("what %d\n",what);
1548 //! Parse given \c arglist .
1549 static void tcl_command_ARGLIST(QString &arglist)
1554 QString myArglist="";
1556 if (!tcl.entry_current->argList)
1558 tcl.entry_current->argList=new ArgumentList;
1560 tcl_split_list(arglist,myArgs);
1561 for (uint i=0;i<myArgs.count();i++)
1563 QStringList myArgs1;
1566 tcl_split_list(*myArgs.at(i),myArgs1);
1567 if (myArgs1.count()==2)
1569 myArg->name= (*myArgs1.at(0)).utf8();
1570 myArg->defval= (*myArgs1.at(1)).utf8();
1571 if (myArg->defval.isEmpty())
1573 myArg->defval = " ";
1575 myArglist += "?" + QCString(myArg->name) + "? ";
1579 myArg->name= (*myArgs.at(i)).utf8();
1580 myArglist += QString(myArg->name) + " ";
1582 tcl.entry_current->argList->append(myArg);
1584 arglist = myArglist;
1585 tcl.entry_current->args = arglist.utf8();
1589 static void tcl_codify_link(QCString name)
1591 if (tcl.code == NULL || name.isEmpty()) return;
1593 static QAsciiDict<MemberDef> fn;
1597 MemberNameSDict::Iterator mni(*Doxygen::memberNameSDict);
1598 MemberNameSDict::Iterator fni(*Doxygen::functionNameSDict);
1601 for (mni.toFirst();(mn=mni.current());++mni)
1603 MemberNameIterator mi(*mn);
1604 for (mi.toFirst();(md=mi.current());++mi)
1606 fn.insert(md->qualifiedName(),md);
1609 for (fni.toFirst();(mn=fni.current());++fni)
1611 MemberNameIterator fi(*mn);
1612 for (fi.toFirst();(md=fi.current());++fi)
1614 fn.insert(md->qualifiedName(),md);
1619 QCString myName=name;
1620 if (name.mid(0,2)=="::") // fully qualified global command
1622 myName = myName.mid(2);
1623 myDef = fn.find(myName);
1625 else // not qualified name
1627 QCString myName1=myName;
1629 myName1 = tcl.scan.at(0)->ns;
1630 if (myName1 == " " || myName1 == "")
1636 myName1 = myName1 + "::" + myName;
1638 myDef = fn.find(myName1); // search namespace command
1641 myDef = fn.find(myName); // search global command
1644 if (myDef != NULL) // documented command
1646 tcl.code->writeCodeLink(myDef->getReference().data(),
1647 myDef->getOutputFileBase().data(),
1648 myDef->anchor().data(),
1650 myDef->qualifiedName().data());
1653 myDef->addSourceReferencedBy(tcl.memberdef);
1654 tcl.memberdef->addSourceReferences(myDef);
1657 else if (tcl_keyword(myName)) // check keyword
1659 tcl_codify("keyword",name);
1663 tcl_codify(NULL,name); // something else
1668 //! Handle internal tcl commands.
1669 // "if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?"
1670 static void tcl_command_IF(QStringList type)
1673 tcl_codify_cmd("keyword",0);
1674 tcl_codify_cmd(NULL,1);
1675 tcl_scan *myScan=tcl.scan.at(0);
1676 myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2),
1677 myScan->ns,myScan->entry_cl,myScan->entry_fn);
1678 for (unsigned int i = 3;i<tcl.list_commandwords.count();i++)
1680 myScan->after << type[i] << tcl.list_commandwords[i];
1683 //! Handle internal tcl commands.
1684 // "for start test next body"
1685 static void tcl_command_FOR()
1688 tcl_codify_cmd("keyword",0);
1689 tcl_codify_cmd(NULL,1);
1690 tcl_scan *myScan=tcl.scan.at(0);
1691 myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2),
1692 myScan->ns,myScan->entry_cl,myScan->entry_fn);
1693 myScan->after << "NULL" << tcl.list_commandwords[3];
1694 myScan->after << "script" << tcl.list_commandwords[4];
1695 myScan->after << "NULL" << tcl.list_commandwords[5];
1696 myScan->after << "script" << tcl.list_commandwords[6];
1697 myScan->after << "NULL" << tcl.list_commandwords[7];
1698 myScan->after << "script" << tcl.list_commandwords[8];
1701 ///! Handle internal tcl commands.
1702 // "foreach varname list body" and
1703 // "foreach varlist1 list1 ?varlist2 list2 ...? body"
1704 static void tcl_command_FOREACH()
1708 tcl_codify_cmd("keyword",0);
1709 for (i = 1;i<tcl.list_commandwords.count()-1;i++)
1711 tcl_codify_cmd(NULL,i);
1713 tcl_scan *myScan=tcl.scan.at(0);
1714 myScan = tcl_scan_start('?',*tcl.list_commandwords.at(tcl.list_commandwords.count()-1),
1715 myScan->ns,myScan->entry_cl,myScan->entry_fn);
1718 ///! Handle internal tcl commands.
1719 // "while test body"
1720 static void tcl_command_WHILE()
1723 tcl_codify_cmd("keyword",0);
1724 tcl_codify_cmd(NULL,1);
1725 tcl_scan *myScan=tcl.scan.at(0);
1726 myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2),
1727 myScan->ns,myScan->entry_cl,myScan->entry_fn);
1728 myScan->after << "NULL" << tcl.list_commandwords[3];
1729 myScan->after << "script" << tcl.list_commandwords[4];
1732 //! Handle all other commands.
1733 // Create links of first command word or first command word inside [].
1734 static void tcl_command_OTHER()
1736 if (tcl.code == NULL) return;
1739 for (unsigned int i=0; i< tcl.list_commandwords.count(); i++)
1741 myName = (*tcl.list_commandwords.at(i)).utf8();
1744 tcl_codify_link(myName);
1748 tcl_codify(NULL,myName);
1755 for (i=0;i<myName.length();i++)
1757 QChar c = myName[i];
1760 if (c==' '||c=='\t'||c=='\n'||c==']')
1762 tcl_codify_link(myStr);
1773 for (;i<myName.length();i++)
1776 if (c!=' ' && c!='\t' && c!='\n') break;
1779 tcl_codify(NULL,myStr);
1785 tcl_codify(NULL,myStr);
1790 //! Handle \c proc statements.
1791 static void tcl_command_PROC()
1794 QCString myNs, myName;
1797 tcl_scan *myScan = tcl.scan.at(0);
1799 tcl_codify_cmd("keyword",0);
1800 tcl_codify_cmd(NULL,1);
1801 tcl_codify_cmd(NULL,2);
1802 tcl_codify_cmd(NULL,3);
1803 tcl_codify_cmd(NULL,4);
1804 tcl_codify_cmd(NULL,5);
1805 tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)).utf8(),myNs,myName);
1808 myEntryNs = tcl_entry_namespace(myNs);
1812 myEntryNs = tcl_entry_namespace(myScan->ns);
1814 //why not needed here? tcl.fn.remove(myName);
1815 tcl.entry_current->section = Entry::FUNCTION_SEC;
1816 tcl.entry_current->mtype = Method;
1817 tcl.entry_current->name = myName;
1818 tcl.entry_current->startLine = tcl.line_command;
1819 tcl.entry_current->bodyLine = tcl.line_body0;
1820 tcl.entry_current->endBodyLine = tcl.line_body1;
1821 tcl_protection(tcl.entry_current);
1822 tcl_command_ARGLIST(*tcl.list_commandwords.at(4));
1823 myEntryNs->addSubEntry(tcl.entry_current);
1824 myEntry = tcl.entry_current;
1825 tcl.fn.insert(myName,myEntry);
1826 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(6),
1827 myEntryNs->name,NULL,myEntry);
1830 //! Handle \c itcl::body statements and \c oo::define method and method inside \c itcl::class statements.
1831 static void tcl_command_METHOD()
1834 QCString myNs, myName;
1835 Entry *myEntryCl, *myEntry;
1836 tcl_scan *myScan = tcl.scan.at(0);
1838 tcl_codify_cmd("keyword",0);
1839 tcl_codify_cmd(NULL,1);
1840 tcl_codify_cmd(NULL,2);
1841 tcl_codify_cmd(NULL,3);
1842 tcl_codify_cmd(NULL,4);
1843 tcl_codify_cmd(NULL,5);
1844 tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)).utf8(),myNs,myName);
1847 myEntryCl = tcl_entry_class(myNs);
1852 myEntryCl = myScan->entry_cl;
1854 // needed in case of more then one definition p.e. itcl::method and itcl::body
1856 tcl.fn.remove(myName);
1857 tcl.entry_current->section = Entry::FUNCTION_SEC;
1858 tcl.entry_current->mtype = Method;
1859 tcl.entry_current->name = myName;
1860 tcl.entry_current->startLine = tcl.line_command;
1861 tcl.entry_current->bodyLine = tcl.line_body0;
1862 tcl.entry_current->endBodyLine = tcl.line_body1;
1863 tcl_protection(tcl.entry_current);
1864 tcl_command_ARGLIST(*tcl.list_commandwords.at(4));
1865 myEntryCl->addSubEntry(tcl.entry_current);
1866 tcl.fn.insert(myName,tcl.entry_current);
1867 myEntry = tcl.entry_current;
1868 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(6),
1869 myNs, myEntryCl, myEntry);
1872 //! Handle \c constructor statements inside class definitions.
1873 static void tcl_command_CONSTRUCTOR()
1876 QCString myNs, myName;
1877 Entry *myEntryCl, *myEntry;
1878 tcl_scan *myScan = tcl.scan.at(0);
1880 tcl_codify_cmd("keyword",0);
1881 tcl_codify_cmd(NULL,1);
1882 tcl_codify_cmd(NULL,2);
1883 tcl_codify_cmd(NULL,3);
1884 tcl_name(myScan->ns,(*tcl.list_commandwords.at(0)).utf8(),myNs,myName);
1887 myEntryCl = tcl_entry_class(myNs);
1892 myEntryCl = myScan->entry_cl;
1894 tcl.entry_current->section = Entry::FUNCTION_SEC;
1895 tcl.entry_current->mtype = Method;
1896 tcl.entry_current->name = myName;
1897 tcl.entry_current->startLine = tcl.line_command;
1898 tcl.entry_current->bodyLine = tcl.line_body0;
1899 tcl.entry_current->endBodyLine = tcl.line_body1;
1900 tcl_protection(tcl.entry_current);
1901 tcl_command_ARGLIST(*tcl.list_commandwords.at(2));
1902 if (myEntryCl) myEntryCl->addSubEntry(tcl.entry_current);
1903 myEntry = tcl.entry_current;
1904 tcl.fn.insert(myName,myEntry);
1905 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(4),
1906 myNs, myEntryCl, myEntry);
1909 //! Handle \c destructor statements inside class definitions.
1910 static void tcl_command_DESTRUCTOR()
1913 QCString myNs, myName;
1914 Entry *myEntryCl, *myEntry;
1915 tcl_scan *myScan = tcl.scan.at(0);
1917 tcl_codify_cmd("keyword",0);
1918 tcl_codify_cmd(NULL,1);
1919 tcl_name(myScan->ns,(*tcl.list_commandwords.at(0)).utf8(),myNs,myName);
1922 myEntryCl = tcl_entry_class(myNs);
1927 myEntryCl = myScan->entry_cl;
1929 tcl.entry_current->section = Entry::FUNCTION_SEC;
1930 tcl.entry_current->mtype = Method;
1931 tcl.entry_current->name = myName;
1932 tcl.entry_current->startLine = tcl.line_command;
1933 tcl.entry_current->bodyLine = tcl.line_body0;
1934 tcl.entry_current->endBodyLine = tcl.line_body1;
1935 tcl_protection(tcl.entry_current);
1936 myEntryCl->addSubEntry(tcl.entry_current);
1937 myEntry = tcl.entry_current;
1938 tcl.fn.insert(myName,myEntry);
1939 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(2),
1940 myNs, myEntryCl, myEntry);
1943 //! Handle \c namespace statements.
1944 static void tcl_command_NAMESPACE()
1947 QCString myNs, myName, myStr;
1948 //Entry *myEntryNs=NULL;
1949 tcl_scan *myScan = tcl.scan.at(0);
1951 tcl_codify_cmd("keyword",0);
1952 tcl_codify_cmd(NULL,1);
1953 tcl_codify_cmd("keyword",2);
1954 tcl_codify_cmd(NULL,3);
1955 tcl_codify_cmd(NULL,4);
1956 tcl_codify_cmd(NULL,5);
1957 tcl_name(myScan->ns,(*tcl.list_commandwords.at(4)).utf8(),myNs,myName);
1960 myName = myNs+"::"+myName;
1962 tcl.entry_current->section = Entry::NAMESPACE_SEC;
1963 tcl.entry_current->name = myName;
1964 tcl.entry_current->startLine = tcl.line_command;
1965 tcl.entry_current->bodyLine = tcl.line_body0;
1966 tcl.entry_current->endBodyLine = tcl.line_body1;
1967 tcl.entry_main->addSubEntry(tcl.entry_current);
1968 tcl.ns.insert(myName,tcl.entry_current);
1969 //myEntryNs = tcl.entry_current;
1970 myStr = (*tcl.list_commandwords.at(6)).utf8();
1971 if (tcl.list_commandwords.count() > 7)
1973 for (uint i=7;i<tcl.list_commandwords.count();i++)
1975 myStr.append((*tcl.list_commandwords.at(i)).utf8());
1979 myScan = tcl_scan_start(tcl.word_is,myStr, myName, NULL, NULL);
1982 //! Handle \c itcl::class statements.
1983 static void tcl_command_ITCL_CLASS()
1986 QCString myNs, myName, myStr;
1988 tcl_scan *myScan = tcl.scan.at(0);
1990 tcl_codify_cmd("keyword",0);
1991 tcl_codify_cmd(NULL,1);
1992 tcl_codify_cmd("NULL",2);
1993 tcl_codify_cmd("NULL",3);
1994 tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)).utf8(),myNs,myName);
1997 myName = myNs+"::"+myName;
1999 tcl.entry_current->section = Entry::CLASS_SEC;
2000 tcl.entry_current->name = myName;
2001 tcl.entry_current->startLine = tcl.line_command;
2002 tcl.entry_current->bodyLine = tcl.line_body0;
2003 tcl.entry_current->endBodyLine = tcl.line_body1;
2004 tcl.entry_main->addSubEntry(tcl.entry_current);
2005 tcl.cl.insert(myName,tcl.entry_current);
2006 myEntryCl = tcl.entry_current;
2007 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(4),
2008 myName, myEntryCl, NULL);
2011 //! Handle \c oo::class statements.
2012 static void tcl_command_OO_CLASS()
2015 QCString myNs, myName, myStr;
2018 tcl_scan *myScan = tcl.scan.at(0);
2020 tcl_codify_cmd("keyword",0);
2021 tcl_codify_cmd(NULL,1);
2022 tcl_codify_cmd("NULL",2);
2023 tcl_codify_cmd("NULL",3);
2024 tcl_codify_cmd("NULL",4);
2025 tcl_codify_cmd("NULL",5);
2026 tcl_name(myScan->ns,(*tcl.list_commandwords.at(4)).utf8(),myNs,myName);
2029 myName = myNs+"::"+myName;
2031 tcl.entry_current->section = Entry::CLASS_SEC;
2032 tcl.entry_current->name = myName;
2033 tcl.entry_current->startLine = tcl.line_command;
2034 tcl.entry_current->bodyLine = tcl.line_body0;
2035 tcl.entry_current->endBodyLine = tcl.line_body1;
2036 tcl.entry_main->addSubEntry(tcl.entry_current);
2037 //myEntryNs = tcl_entry_namespace(myName);
2038 tcl.cl.insert(myName,tcl.entry_current);
2039 myEntryCl = tcl.entry_current;
2040 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(6),
2041 myName, myEntryCl, NULL);
2044 //! Handle \c oo::define statements.
2045 static void tcl_command_OO_DEFINE()
2048 QCString myNs, myName, myStr;
2050 tcl_scan *myScan = tcl.scan.at(0);
2052 tcl_codify_cmd("keyword",0);
2053 tcl_codify_cmd(NULL,1);
2054 tcl_codify_cmd("NULL",2);
2055 tcl_codify_cmd("NULL",3);
2056 tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)).utf8(),myNs,myName);
2059 myName = myNs+"::"+myName;
2061 myEntryCl = tcl_entry_class(myName);
2062 myStr = (*tcl.list_commandwords.at(4)).utf8();
2063 if (tcl.list_commandwords.count() > 5)
2065 for (uint i=5;i<tcl.list_commandwords.count();i++)
2067 myStr.append((*tcl.list_commandwords.at(i)).utf8());
2071 myScan = tcl_scan_start(tcl.word_is,myStr,myName,myEntryCl,NULL);
2074 //! Handle \c variable statements.
2075 static void tcl_command_VARIABLE(int inclass)
2078 QCString myNs, myName;
2080 tcl_scan *myScan = tcl.scan.at(0);
2082 tcl_codify_cmd("keyword",0);
2083 for (unsigned int i=1; i< tcl.list_commandwords.count(); i++)
2085 tcl_codify_cmd(NULL,i);
2087 tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)).utf8(),myNs,myName);
2089 {// qualified variables go into namespace
2090 myEntry = tcl_entry_namespace(myNs);
2091 tcl.entry_current->stat = true;
2097 myEntry = myScan->entry_cl;
2098 tcl.entry_current->stat = false;
2102 myEntry = tcl_entry_namespace(myScan->ns);
2103 tcl.entry_current->stat = true;
2106 tcl.entry_current->section = Entry::VARIABLE_SEC;
2107 tcl.entry_current->name = myName;
2108 tcl.entry_current->startLine = tcl.line_command;
2109 tcl.entry_current->bodyLine = tcl.line_body0;
2110 tcl.entry_current->endBodyLine = tcl.line_body1;
2111 tcl_protection(tcl.entry_current);
2112 myEntry->addSubEntry(tcl.entry_current);
2113 tcl.entry_current = tcl_entry_new();
2116 //! Handling of command parsing.
2120 static void tcl_command(int what,const char *text)
2125 tcl.scan.at(0)->line1=yylineno;// current line in scan context
2126 tcl.line_body0=yylineno;// start line of command
2127 tcl_inf("<- %s\n",text);
2128 yy_push_state(COMMAND);
2129 tcl.list_commandwords.clear();
2130 tcl.string_command="";
2137 if (tcl.string_last.length())
2139 tcl.list_commandwords.append(tcl.string_last);
2144 tcl.list_commandwords.append(text);
2149 {// should not happen
2150 tcl_err("what %d\n",what);
2153 QCString myText = text;
2157 return; //TODO check on inside comment
2159 if (tcl.string_last != "")
2161 tcl.list_commandwords.append(tcl.string_last);
2167 QCString myStr = (*tcl.list_commandwords.at(0)).utf8();
2169 Protection myProt = tcl.protection;
2171 if (tcl.list_commandwords.count() < 3)
2173 tcl_command_OTHER();
2176 // remove leading "::" and apply TCL_SUBST
2177 if (myStr.left(2)=="::") myStr = myStr.mid(2);
2178 if (tcl.config_subst.contains(myStr))
2180 myStr=tcl.config_subst[myStr].utf8();
2182 if (myStr=="private")
2184 tcl.protection = Private;
2187 else if (myStr=="protected")
2189 tcl.protection = Protected;
2192 else if (myStr=="public")
2194 tcl.protection = Public;
2199 tcl_codify_cmd("keyword",0);
2200 tcl_codify_cmd(NULL,1);
2201 tcl.list_commandwords.remove(tcl.list_commandwords.at(1));
2202 tcl.list_commandwords.remove(tcl.list_commandwords.at(0));
2203 if (tcl.list_commandwords.count()==1)
2205 tcl_scan *myScan = tcl.scan.at(0);
2206 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(0),
2207 myScan->ns,myScan->entry_cl,myScan->entry_fn);
2208 myProt = tcl.protection;
2211 myStr = (*tcl.list_commandwords.at(0)).utf8();
2212 // remove leading "::" and apply TCL_SUBST
2213 if (myStr.left(2)=="::") myStr = myStr.mid(2);
2214 if (tcl.config_subst.contains(myStr))
2216 myStr=tcl.config_subst[myStr].utf8();
2221 if (tcl.list_commandwords.count() == 5)
2223 tcl.list_commandwords.append("");
2224 tcl.list_commandwords.append("");
2226 if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;}
2230 if (myStr=="method")
2232 if (tcl.list_commandwords.count() == 5)
2234 tcl.list_commandwords.append("");
2235 tcl.list_commandwords.append("");
2237 if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;}
2238 tcl_command_METHOD();
2241 if (myStr=="constructor")
2243 if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;}
2244 tcl_command_CONSTRUCTOR();
2247 if (myStr=="destructor")
2249 if (tcl.list_commandwords.count() != 3) {myLine=__LINE__;goto command_warn;}
2250 tcl_command_DESTRUCTOR();
2253 if (myStr=="namespace")
2255 if ((*tcl.list_commandwords.at(2)).utf8()=="eval")
2257 if (tcl.list_commandwords.count() < 7) {myLine=__LINE__;goto command_warn;}
2258 tcl_command_NAMESPACE();
2261 tcl_command_OTHER();
2264 if (myStr=="itcl::class")
2266 if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;}
2267 tcl_command_ITCL_CLASS();
2270 if (myStr=="itcl::body")
2272 if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;}
2273 tcl_command_METHOD();
2276 if (myStr=="oo::class")
2278 if ((*tcl.list_commandwords.at(2)).utf8()=="create")
2280 if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;}
2281 tcl_command_OO_CLASS();
2284 tcl_command_OTHER();
2287 if (myStr=="oo::define")
2289 if (tcl.list_commandwords.count() < 5) {myLine=__LINE__;goto command_warn;}
2290 tcl_command_OO_DEFINE();
2293 if (myStr=="variable")
2295 if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;}
2296 if (tcl.scan.at(0)->entry_fn == NULL)
2297 {// only parsed outside functions
2298 tcl_command_VARIABLE(tcl.scan.at(0)->entry_cl && tcl.scan.at(0)->entry_cl->name!="");
2302 if (myStr=="common")
2304 if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;}
2305 if (tcl.scan.at(0)->entry_fn == NULL)
2306 {// only parsed outside functions
2307 tcl_command_VARIABLE(0);
2311 if (myStr=="inherit" || myStr=="superclass")
2313 if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;}
2314 if (tcl.scan.at(0)->entry_cl && tcl.scan.at(0)->entry_cl->name!="")
2316 for (unsigned int i = 2; i < tcl.list_commandwords.count(); i = i + 2)
2318 tcl.scan.at(0)->entry_cl->extends->append(new BaseInfo((*tcl.list_commandwords.at(i)).utf8(),Public,Normal));
2324 * Start of internal tcl keywords
2325 * Ready: if, for, foreach, while
2326 * TODO: switch, eval, ?
2330 if (tcl.list_commandwords.count() != 9) {myLine=__LINE__;goto command_warn;}
2334 if (myStr=="foreach")
2336 if (tcl.list_commandwords.count() < 7 || tcl.list_commandwords.count()%2==0) {myLine=__LINE__;goto command_warn;}
2337 tcl_command_FOREACH();
2341 if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
2343 if (myStr=="if" && tcl.list_commandwords.count() > 4)
2346 myType << "keyword" << "NULL" << "script" << "NULL";
2347 char myState='x';// last word: e'x'pr 't'hen 'b'ody 'e'lse else'i'f..
2348 for (unsigned int i = 4; i < tcl.list_commandwords.count(); i = i + 2)
2350 QCString myStr=(*tcl.list_commandwords.at(i)).utf8();
2356 myType << "keyword" << "NULL";
2361 myType << "script" << "NULL";
2364 else if (myState=='t')
2367 myType << "script" << "NULL";
2369 else if (myState=='b')
2371 if (myStr=="elseif") {
2373 myType << "keyword" << "NULL";
2375 else if (myStr=="else" && i==tcl.list_commandwords.count()-3)
2378 myType << "keyword" << "NULL" << "script";
2379 i = tcl.list_commandwords.count();
2381 else if (i==tcl.list_commandwords.count()-1)
2385 i = tcl.list_commandwords.count();
2389 myLine=__LINE__;goto command_warn;
2392 else if (myState=='i')
2395 myType << "script" << "NULL";
2398 if (myState != 'b') {myLine=__LINE__;goto command_warn;}
2399 tcl_command_IF(myType);
2404 if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;}
2405 tcl_command_WHILE();
2408 tcl_command_OTHER();
2410 command_warn:// print warning message because of wrong used syntax
2411 tcl_war("%d count=%d: %s\n",myLine,tcl.list_commandwords.count(),tcl.list_commandwords.join(" ").ascii());
2412 tcl_command_OTHER();
2413 command_text:// print remaining text as comment
2414 if (!myText.isEmpty()) tcl_codify("comment",myText);
2416 command_end:// add remaining text to current context
2417 if (!myText.isEmpty()) tcl.scan.at(0)->after << "comment" << myText;
2418 tcl.list_commandwords.clear();
2420 tcl.protection = myProt;
2423 //----------------------------------------------------------------------------
2424 //! Common initializations.
2425 static void tcl_init()
2427 // Get values from option TCL_SUBST
2428 tcl.config_subst.clear();
2429 if (Config::instance()->get("TCL_SUBST"))
2431 QStrList myStrList = Config_getList("TCL_SUBST");
2432 const char *s=myStrList.first();
2436 int i=myStr.find('=');
2439 QCString myName=myStr.left(i).stripWhiteSpace();
2440 QCString myValue=myStr.right(myStr.length()-i-1).stripWhiteSpace();
2441 if (!myName.isEmpty() && !myValue.isEmpty())
2442 tcl_inf("TCL_SUBST: use '%s'\n",s);
2443 tcl.config_subst[myName] = myValue;
2445 s = myStrList.next();
2449 if (tcl.input_string.at(tcl.input_string.length()-1) == '\n')
2451 tcl.input_string[tcl.input_string.length()-1] = 0x1A;
2455 tcl.input_string += 0x1A;
2460 tcl.code_linenumbers=1;
2461 tcl.config_autobrief = Config_getBool("JAVADOC_AUTOBRIEF");
2462 tcl.input_position = 0;
2463 tcl.file_name = NULL;
2464 tcl.this_parser = NULL;
2468 tcl.bracket_level=0;
2469 tcl.bracket_quote=0;
2471 tcl.string_command="";
2472 tcl.string_commentline="";
2473 tcl.string_commentcodify="";
2474 tcl.string_comment = "";
2475 tcl.string_last = "";
2476 tcl.entry_main = NULL;
2477 tcl.entry_file = NULL;
2478 tcl.entry_current = NULL;
2479 tcl.entry_inside = NULL;
2480 tcl.list_commandwords.clear();
2486 tcl.protection = Public;
2487 tcl.memberdef = NULL;
2491 static void tcl_parse(const QCString ns, const QCString cls)
2495 tcl.entry_file = tcl_entry_new();
2496 tcl.entry_file->name = tcl.file_name;
2497 tcl.entry_file->section = Entry::SOURCE_SEC;
2498 tcl.entry_file->protection = Public;
2499 tcl.entry_main->addSubEntry(tcl.entry_file);
2500 Entry *myEntry=tcl_entry_new();
2502 tcl.entry_main->addSubEntry(myEntry);
2503 tcl.ns.insert("::",myEntry);
2504 tcl.entry_current = tcl_entry_new();
2506 tclscannerYYrestart( tclscannerYYin );
2509 myScan = new tcl_scan;
2510 myScan->type[0]=' ';myScan->type[1]='\n';
2511 myScan->after.clear();
2512 myScan->line0=yylineno;
2513 myScan->line1=yylineno;
2514 myScan->buffer_state=YY_CURRENT_BUFFER;
2516 myScan->entry_cl=tcl_entry_class(cls);
2517 myScan->entry_fn=NULL;
2518 tcl.entry_inside = tcl.entry_file;
2519 myScan->entry_scan = tcl.entry_inside;
2520 tcl.scan.insert(0,myScan);
2529 //! Parse text file and build up entry tree.
2530 void TclLanguageScanner::parseInput(const char *fileName,
2533 bool /*sameTranslationUnit*/,
2534 QStrList & /*filesInSameTranslationUnit*/)
2537 tcl_inf("%s\n",fileName);
2538 myFile.setName(fileName);
2539 if (!myFile.open(IO_ReadOnly)) return;
2540 if (strlen(input)<1) return;
2542 tcl.input_string = input;
2543 if (tcl.input_string.length()<1) return;
2544 printlex(yy_flex_debug, TRUE, __FILE__, fileName);
2546 msg("Parsing %s...\n",fileName);
2547 groupEnterFile(fileName,yylineno);
2551 tcl.file_name = fileName;
2552 tcl.this_parser = this;
2553 tcl.entry_main = root; /* toplevel entry */
2555 groupLeaveFile(tcl.file_name,yylineno);
2556 root->program.resize(0);
2558 printlex(yy_flex_debug, FALSE, __FILE__, fileName);
2561 //! Parse file and codify.
2562 void TclLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf,
2563 const char * scopeName,
2564 const QCString & input,
2566 bool isExampleBlock,
2567 const char * exampleName,
2571 bool inlineFragment,
2572 MemberDef *memberDef,
2573 bool showLineNumbers,
2574 Definition *searchCtx,
2583 (void)inlineFragment;
2587 if (input.length()<1) return;
2588 printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? fileDef->fileName().data(): NULL);
2589 tcl.input_string = input;
2595 if (memberDef->getClassDef())
2597 myCls = memberDef->getClassDef()->displayName();
2600 else if (memberDef->getNamespaceDef())
2602 myNs = memberDef->getNamespaceDef()->displayName();
2606 QString myStr="Codifying..";
2620 myStr+=memberDef->memberTypeName();
2622 myStr+=memberDef->qualifiedName();
2627 myStr+=fileDef->fileName();
2629 tcl_inf("%s (%d,%d) %d %d\n",myStr.ascii(),startLine,endLine,isExampleBlock,inlineFragment);
2630 //tcl_inf("%s\n"input.data());
2633 tcl_codify(NULL,input);
2637 tcl.memberdef = memberDef;
2638 tcl.code = &codeOutIntf;
2644 tcl.code_linenumbers = showLineNumbers;
2645 tcl.code_line=yylineno;
2646 tcl.code->startCodeLine(tcl.code_linenumbers);
2647 if (tcl.code_linenumbers)
2649 tcl.code->writeLineNumber(0,0,0,tcl.code_line);
2652 tcl.this_parser = NULL;
2653 tcl.entry_main = tcl_entry_new();
2654 tcl_parse(myNs,myCls);
2655 tcl.code->endCodeLine();
2661 printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL);
2664 bool TclLanguageScanner::needsPreprocessing(const QCString &extension)
2670 void TclLanguageScanner::resetCodeParserState()
2674 void TclLanguageScanner::parsePrototype(const char *text)
2679 static int yyread(char *buf,int max_size)
2684 while ( c < max_size && tcl.input_string.at(tcl.input_position) )
2686 *buf = tcl.input_string.at(tcl.input_position++) ;
2689 //printf("Read from=%d size=%d max=%d c=%d\n",tcl.input_position,strlen(&tcl.input_string[tcl.input_position]),max_size,c);
2693 //----------------------------------------------------------------------------
2695 // to avoid a warning
2701 #if !defined(YY_FLEX_SUBMINOR_VERSION)
2702 //----------------------------------------------------------------------------
2703 extern "C" { // some bogus code to keep the compiler happy
2704 void tclscannerYYdummy() { yy_flex_realloc(0,0); }