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.
36 #include "commentscan.h"
38 #include "tclscanner.h"
39 #include "outputlist.h"
40 #include "membername.h"
41 #include "searchindex.h"
42 #include "commentcnv.h"
46 #include <qstringlist.h>
49 #include "arguments.h"
51 #define YY_NEVER_INTERACTIVE 1
54 #define MAX_INCLUDE_DEPTH 10
56 //! Application error.
58 printf("Error %d %s() at line %d! ",__LINE__,tcl.file_name.data(),yylineno); \
59 yy_push_state(ERROR); \
63 //! Application warning.
65 printf("Warning %d %s() at line %d: ",__LINE__,tcl.file_name.data(),yylineno); \
68 //! Application message.
70 if (0) printf("--- %.4d %d@%d: ",__LINE__,yylineno,yy_start_stack_ptr) && printf
74 if (0) printf("--- %.4d %d@%d: %s\n",__LINE__,yylineno,yy_start_stack_ptr,yytext);
76 // BEGIN of copy from tclUtil.c
77 // - Tcl_Interp removed
78 // - changes are marked with RZ
79 // #define's to adapt the code:
81 #define UCHAR (unsigned char)
84 #define ckalloc malloc
86 #define TclCopyAndCollapse(size,src,dest) memcpy(dest,src,size); *(dest+size)=0
88 CONST char *list, /* Points to the first byte of a string
89 * containing a Tcl list with zero or more
90 * elements (possibly in braces). */
91 int listLength, /* Number of bytes in the list's string. */
92 CONST char **elementPtr, /* Where to put address of first significant
93 * character in first element of list. */
94 CONST char **nextPtr, /* Fill in with location of character just
95 * after all white space following end of
96 * argument (next arg or end of list). */
97 int *sizePtr, /* If non-zero, fill in with size of
99 int *bracePtr) /* If non-zero, fill in with non-zero/zero to
100 * indicate that arg was/wasn't in braces. */
102 CONST char *p = list;
103 CONST char *elemStart; /* Points to first byte of first element. */
104 CONST char *limit; /* Points just after list's last byte. */
105 int openBraces = 0; /* Brace nesting level during parse. */
107 int size = 0; /* lint. */
111 * Skim off leading white space and check for an opening brace or quote.
112 * We treat embedded NULLs in the list as bytes belonging to a list
116 limit = (list + listLength);
117 while ((p < limit) && (isspace(UCHAR(*p))))
118 { /* INTL: ISO space. */
122 { /* no element found */
140 *bracePtr = openBraces;
144 * Find element's end (a space, close brace, or the end of the string).
152 * Open brace: don't treat specially unless the element is in
153 * braces. In this case, keep a nesting count.
164 * Close brace: if element is in braces, keep nesting count and
165 * quit when the last close brace is seen.
173 else if (openBraces == 1)
175 size = (p - elemStart);
177 if ((p >= limit) || isspace(UCHAR(*p)))
178 { /* INTL: ISO space. */
183 * Garbage after the closing brace; return an error.
191 * Backslash: skip over everything up to the end of the backslash
196 //RZ Tcl_UtfBackslash(p, &numChars, NULL);
197 //RZ p += (numChars - 1);
202 * Space: ignore if element is in braces or quotes; otherwise
212 if ((openBraces == 0) && !inQuotes)
214 size = (p - elemStart);
220 * Double-quote: if element is in quotes then terminate it.
226 size = (p - elemStart);
228 if ((p >= limit) || isspace(UCHAR(*p)))
229 { /* INTL: ISO space */
234 * Garbage after the closing quote; return an error.
244 * End of list: terminate element.
257 size = (p - elemStart);
261 while ((p < limit) && (isspace(UCHAR(*p))))
262 { /* INTL: ISO space. */
265 *elementPtr = elemStart;
275 CONST char *list, /* Pointer to string with list structure. */
276 int *argcPtr, /* Pointer to location to fill in with the
277 * number of elements in the list. */
278 CONST char ***argvPtr) /* Pointer to place to store pointer to array
279 * of pointers to list elements. */
281 CONST char **argv, *l, *element;
283 int length, size, i, result, elSize, brace;
286 * Figure out how much space to allocate. There must be enough space for
287 * both the array of pointers and also for a copy of the list. To estimate
288 * the number of pointers needed, count the number of space characters in
292 for (size = 2, l = list; *l != 0; l++)
294 if (isspace(UCHAR(*l)))
295 { /* INTL: ISO space. */
299 * Consecutive space can only count as a single list delimiter.
304 char next = *(l + 1);
311 if (isspace(UCHAR(next)))
312 { /* INTL: ISO space. */
320 argv = (CONST char **) ckalloc((unsigned)
321 ((size * sizeof(char *)) + length + 1));
322 for (i = 0, p = ((char *) argv) + size*sizeof(char *);
325 CONST char *prevList = list;
327 result = TclFindElement(list, length, &element, &list,
329 length -= (list - prevList);
330 if (result != TCL_OK)
332 ckfree((char *) argv);
341 ckfree((char *) argv);
347 memcpy(p, element, (size_t) elSize);
354 TclCopyAndCollapse(elSize, element, p);
366 void tcl_split_list(QString &str, QStringList &list)
372 if (str.left(1)=="{" && str.right(1)=="}")
374 str=str.mid(1,str.length()-2);
376 else if (str.left(1)=="\"" && str.right(1)=="\"")
378 str=str.mid(1,str.length()-2);
380 if (Tcl_SplitList(str.ascii(),&argc,&argv) != TCL_OK)
386 for (int i = 0; i < argc; i++)
388 list.append(argv[i]);
390 ckfree((char *) argv);
394 //! Structure containing information about current scan context.
397 char type[2]; // type of scan context: "\"" "{" "[" "?" " "
398 int line0; // start line of scan context
399 int line1; // end line of scan context
400 YY_BUFFER_STATE buffer_state; // value of scan context
401 QCString ns; // current namespace
402 Entry *entry_fn; // if set contains the current proc/method/constructor/destructor
403 Entry *entry_cl; // if set contain the current class
404 Entry *entry_scan; // current scan entry
405 Protection protection; // current protections state
406 QStringList after; // option/value list (options: NULL comment keyword script)
409 //* Structure containing all internal global variables.
412 CodeOutputInterface * code; // if set then we are codifying the file
413 int code_line; // current line of code
414 int code_linenumbers; // if true create line numbers in code
415 const char *code_font; // used font to codify
416 bool config_autobrief; // value of configuration option
417 QMap<QString,QString> config_subst; // map of configuration option values
418 QCString input_string; // file contents
419 int input_position; // position in file
420 QCString file_name; // name of used file
421 ParserInterface *this_parser; // myself
422 int command; // true if command was found
423 int comment; // set true if comment was scaned
424 int brace_level; // bookkeeping of braces
425 int bracket_level; // bookkeeping of brackets
426 int bracket_quote; // bookkeeping of quotes (toggles)
427 char word_is; // type of current word: "\"" "{" "[" "?" " "
428 int line_comment; // line number of comment
429 int line_commentline; // line number of comment after command
430 int line_command; // line number of command
431 int line_body0; // start line of body
432 int line_body1; // end line of body
433 QCString string_command; // contain current command
434 QCString string_commentline; // contain current comment after command
435 QCString string_commentcodify; // current comment string used in codifying
436 QCString string_comment; // contain current comment
437 QCString string_last; // contain last read word or part of word
438 QCString string; // temporary string value
439 Entry* entry_main; // top level entry
440 Entry* entry_file; // entry of current file
441 Entry* entry_current; // currently used entry
442 Entry* entry_inside; // contain entry of current scan context
443 QStringList list_commandwords; // list of command words
444 QList<tcl_scan> scan; // stack of scan contexts
445 QAsciiDict<Entry> ns; // all read namespace entries
446 QAsciiDict<Entry> cl; // all read class entries
447 QAsciiDict<Entry> fn; // all read function entries
448 QList<Entry> entry; // list of all created entries, will be deleted after codifying
449 Protection protection; // current protections state
450 MemberDef *memberdef; // contain current MemberDef when codifying
454 static int yyread(char *buf,int max_size);
455 static tcl_scan *tcl_scan_start(char type, QString content, QCString ns, Entry *entry_cls, Entry *entry_fn);
456 static void tcl_scan_end();
457 static void tcl_comment(int what,const char *text);
458 static void tcl_word(int what,const char *text);
459 static void tcl_command(int what,const char *text);
463 //! Create new entry.
464 // @return new initialised entry
465 Entry* tcl_entry_new()
467 Entry *myEntry = new Entry;
468 myEntry->section = Entry::EMPTY_SEC;
470 // myEntry->type = "";
472 // myEntry->doc = "";
473 myEntry->protection = Public;
474 // myEntry->mtype = Method;
475 // myEntry->virt = Normal;
476 // myEntry->stat = FALSE;
477 myEntry->fileName = tcl.file_name;
478 myEntry->lang = SrcLangExt_Tcl;
479 initGroupInfo(myEntry);
483 tcl.entry.insert(0,myEntry);
488 //! Set protection level.
489 void tcl_protection(Entry *entry)
491 if (entry->protection!=Public&&entry->protection!=Protected&&entry->protection!=Private)
493 entry->protection = tcl.protection;
495 if (entry->protection!=Protected&&entry->protection!=Private)
497 entry->protection = Public;
502 // @return 'ns' and 'name' of given current 'ns0' and 'name0'
503 static void tcl_name(const QCString &ns0, const QCString &name0, QCString &ns, QCString &name)
508 if (strncmp(name0.data(),"::",2)==0)
512 else if (ns0.length() && ns0 != " ")
514 myNm = ns0 + "::" + name0;
520 myStart = myNm.findRev("::");
528 ns = myNm.mid(0,myStart);
529 name = myNm.mid(myStart+2);
533 // Check and return namespace entry.
534 // @return namespace entry
535 Entry* tcl_entry_namespace(const QCString ns)
540 myEntry = tcl.ns.find(ns);
544 myEntry = tcl.ns.find("::");
548 myEntry = tcl_entry_new();
549 myEntry->section = Entry::NAMESPACE_SEC;
551 tcl.entry_main->addSubEntry(myEntry);
552 tcl.ns.insert(ns,myEntry);
557 // Check and return class entry.
558 // @return class entry
559 Entry* tcl_entry_class(const QCString cl)
562 if (!cl.length()) return(NULL);
564 myEntry = tcl.cl.find(cl);
567 myEntry = tcl_entry_new();
568 myEntry->section = Entry::CLASS_SEC;
570 tcl.entry_main->addSubEntry(myEntry);
571 tcl.cl.insert(cl,myEntry);
576 //! Check for keywords.
577 // @return 1 if keyword and 0 otherwise
578 static int tcl_keyword(QCString str)
580 static QStringList myList;
585 myList <<"append"<<"apply"<<"array"<<"auto_execok"<<"auto_import"<<"auto_load"<<"auto_mkindex"<<"auto_qualify"<<"auto_reset";
587 myList <<"catch"<<"cd"<<"close"<<"clock"<<"concat";
588 myList <<"eof"<<"eval"<<"exec"<<"exit"<<"expr";
589 myList <<"fblocked"<<"fconfigure"<<"file"<<"fileevent"<<"flush"<<"for"<<"foreach"<<"format";
590 myList <<"gets"<<"global";
592 myList <<"if"<<"incr"<<"info"<<"interp";
594 myList <<"lappend"<<"lassign"<<"lindex"<<"linsert"<<"llength"<<"load"<<"lrange"<<"lrepeat"<<"lreplace"<<"lreverse"<<"lset";
595 myList <<"namespace";
596 myList <<"package"<<"parray"<<"pid"<<"pkg_mkIndex"<<"proc"<<"puts"<<"pwd";
597 myList <<"registry"<<"rename"<<"return";
598 myList <<"scan"<<"set"<<"split"<<"string"<<"switch";
599 myList <<"tclLog"<<"tcl_endOfWord"<<"tcl_findLibrary"<<"tcl_startOfNextWord"<<"tcl_startOfPreviousWord"<<"tcl_wordBreakAfter"<<"tcl_wordBreakBefore"<<"tell"<<"time";
600 myList <<"unknown"<<"upvar";
601 myList <<"variable"<<"vwait";
603 myList <<"bell"<<"bind"<<"bindtags";
604 myList <<"clipboard"<<"console"<<"consoleinterp";
611 myList <<"pack"<<"place";
614 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";
615 myList <<"winfo"<<"wm";
616 myList <<"button"<<"canvas"<<"checkbutton"<<"entry"<<"frame"<<"image"<<"label"<<"labelframe"<<"listbox"<<"menu"<<"menubutton"<<"message"<<"panedwindow"<<"radiobutton"<<"scale"<<"scrollbar"<<"spinbox"<<"toplevel";
620 str=str.stripWhiteSpace();
621 if (str.left(2)=="::") {str=str.mid(2);}
622 if (myList.findIndex(str) != -1) return(1);
626 //! End codifying with special font class.
627 static void tcl_font_end()
629 if (tcl.code==NULL) return;
632 tcl.code->endFontClass();
637 //! Codify 'str' with special font class 's'.
638 static void tcl_codify(const char *s,char *str)
640 if (tcl.code==NULL||str==NULL) return;
641 if (s && strcmp(s,"NULL")!=0)
644 tcl.code->startFontClass(s);
653 while ((c=*p++) && c!='\n') {}
658 tcl.code->codify(sp);
660 tcl.code->endCodeLine();
661 if (tcl.code_linenumbers)
663 if (tcl.code_font!=NULL)
665 tcl.code->endFontClass();
666 tcl.code->writeLineNumber(0,0,0,tcl.code_line);
667 tcl.code->startFontClass(tcl.code_font);
671 tcl.code->writeLineNumber(0,0,0,tcl.code_line);
677 tcl.code->codify(sp);
685 //! Codify 'str' with special font class 's'.
686 static void tcl_codify(const char *s,const char *str)
688 if (tcl.code==NULL) return;
689 char *tmp= (char *) malloc(strlen(str)+1);
695 //! Codify 'str' with special font class 's'.
696 static void tcl_codify(const char *s,const QString &str)
698 if (tcl.code==NULL) return;
699 tcl_codify(s,str.utf8());
703 //! Codify 'str' with special font class 's'.
704 static void tcl_codify(const char *s,const QCString &str)
706 if (tcl.code==NULL) return;
707 tcl_codify(s,str.data());
710 static void tcl_codify_cmd(const char *s,int i)
712 tcl_codify(s,(*tcl.list_commandwords.at(i)).utf8());
715 //-----------------------------------------------------------------------------
717 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
718 //-----------------------------------------------------------------------------
743 if (tcl.scan.count()<1)
746 tcl_err("Tcl parser stack empty! Parser error in file '%s'.\n",tcl.file_name.data());
749 else if (tcl.scan.count()==1)
750 {// exit, check on input?
764 tcl.line_comment=yylineno;
767 <TOP>({ws}|[\;\n])+ {
769 tcl_codify(NULL,yytext);
774 tcl.line_command=yylineno;
780 tcl_codify("comment",yytext);
784 tcl_codify("comment",yytext);
785 tcl_comment(2,yytext+1);
787 <COMMENT>"##".*\\\n {
789 tcl_codify("comment",yytext);
791 t = t.mid(2,t.length()-3);
793 tcl_comment(1,t.data());
794 yy_push_state(COMMENT_NL);
798 tcl_codify("comment",yytext);
799 tcl_comment(1,yytext+2);
801 <COMMENT>"#"[@\\]"code"\n[ \t]*[^#] {
804 tcl_codify("comment",t.left(7));
805 tcl_comment(2,"\n@code\n");
807 yy_push_state(COMMENT_CODE);
809 <COMMENT>"#"[@\\]"verbatim"\n[ \t]*[^#] {
812 tcl_codify("comment",t.left(11));
813 tcl_comment(2,"\n@verbatim\n");
815 yy_push_state(COMMENT_VERB);
819 tcl_codify("comment",yytext);
821 t = t.mid(1,t.length()-3);
823 tcl_comment(2,t.data());
824 yy_push_state(COMMENT_NL);
828 tcl_codify("comment",yytext);
829 tcl_comment(2,yytext+1);
834 t = t.mid(0,t.length()-1);
835 tcl_codify("comment",t.data());
836 t = t.mid(1,t.length());
837 tcl_comment(-2,t.data());
847 tcl_comment(-2,yytext);
851 <COMMENT_CODE>"#"[@\\]"endcode"\n {
854 t = t.left(t.length()-10);
855 tcl_comment(2,t.data());
856 tcl_comment(2,"\n@endcode\n");
864 <COMMENT_CODE>.*\x1A {
870 <COMMENT_VERB>"#"[@\\]"endverbatim"\n {
873 t = t.left(t.length()-14);
874 tcl_comment(2,t.data());
875 tcl_comment(2,"\n@endverbatim\n");
883 <COMMENT_VERB>.*\x1A {
891 tcl_codify("comment",yytext);
892 tcl_comment(2,yytext);
896 tcl_codify("comment",yytext);
897 tcl_comment(2,yytext);
906 <COMMENTLINE>.*\x1A {
911 <COMMENTLINE>[ \t]* {
913 tcl.string_commentcodify += yytext;
915 <COMMENTLINE>"#<".*\\\n {
917 tcl.string_commentcodify += yytext;
919 t = t.mid(2,t.length()-4);
921 tcl.string_commentline += t;
922 yy_push_state(COMMENTLINE_NL);
924 <COMMENTLINE>"#<".*\n {
926 tcl.string_commentcodify += yytext;
927 tcl.string_commentline += (yytext+2);
932 if (tcl.string_commentline.length())
934 tcl.entry_current->brief = tcl.string_commentline;
935 tcl.entry_current->briefLine = tcl.line_commentline;
936 tcl.entry_current->briefFile = tcl.file_name;
939 tcl_command(-1,tcl.string_commentcodify.data());
940 tcl.string_commentline="";
941 tcl.string_commentcodify="";
944 <COMMENTLINE_NL>.*\\\n {
946 tcl.string_commentcodify += yytext;
948 t = t.left(t.length()-3);
950 tcl.string_commentline += t;
952 <COMMENTLINE_NL>.*\n {
954 tcl.string_commentcodify += yytext;
955 tcl.string_commentline += yytext;
958 <COMMENTLINE_NL>.*\x1A {
961 t = t.left(t.length()-1);
962 tcl.string_commentcodify += t;
963 tcl.string_commentline += t;
968 <COMMAND>{ws}*[\;]{ws}*"#<" {
970 tcl.string_commentcodify = yytext;
971 tcl.string_commentcodify = tcl.string_commentcodify.left(tcl.string_commentcodify.length()-2);
972 tcl.string_commentline = "";
973 tcl.line_commentline = yylineno;
974 tcl.line_body1=yylineno;
977 yy_push_state(COMMENTLINE);
981 tcl.string_commentcodify = "";
982 tcl.string_commentline = "";
983 tcl.line_body1=yylineno;
988 tcl.string_commentcodify = "";
989 tcl.string_commentline = "";
990 tcl.line_body1=yylineno;
991 tcl_command(-1,yytext);
995 tcl.string_commentcodify = "";
996 tcl.string_commentline = "";
997 tcl.line_body1=yylineno-1;
998 tcl_command(-1,yytext);
1002 tcl_command(1,yytext);
1007 tcl.string_last = "{*}";
1008 tcl_word(0,&yytext[3]);
1010 <COMMAND>"\\"[\{\}\[\]\;\" \t] {
1013 tcl.string_last = "";
1019 if (yytext[0]=='{'||yytext[0]=='['||yytext[0]=='"') tcl.word_is = yytext[0];
1020 tcl.string_last = "";
1025 <WORD>"\\"[\{\}\[\]\;\" \t] {
1053 tcl_word(10,yytext);
1056 tcl_word(11,yytext);
1059 tcl_word(12,yytext);
1066 //! Start new scan context for given 'content'.
1067 // @return created new scan context.
1068 static tcl_scan *tcl_scan_start(char type, QString content, QCString ns, Entry *entry_cl, Entry *entry_fn)
1070 tcl_scan *myScan=tcl.scan.at(0);
1072 tcl_inf("line=%d type=%d '%s'\n",tcl.line_body0,type,content.ascii());
1074 myScan->line1=yylineno;
1077 myScan=new tcl_scan;
1078 myScan->type[0] =' ';
1079 myScan->type[1] = '\0';
1084 myScan->type[0] = type;
1087 if (content[0]=='"' && content[content.length()-1]=='"') myScan->type[0]='"';
1088 if (content[0]=='{' && content[content.length()-1]=='}') myScan->type[0]='{';
1089 if (content[0]=='[' && content[content.length()-1]==']') myScan->type[0]='[';
1091 if (myScan->type[0]!=' ')
1093 tcl_codify(NULL,&myScan->type[0]);
1094 content = content.mid(1,content.length()-2);
1096 content += (char)0x1A;// for detection end of scan context
1098 myScan->entry_cl = entry_cl;
1099 myScan->entry_fn = entry_fn;
1100 myScan->entry_scan = tcl.entry_current;
1101 myScan->buffer_state=yy_scan_string(content.ascii());
1102 myScan->line0=tcl.line_body0;
1103 myScan->line1=tcl.line_body1;
1104 myScan->after.clear();
1105 yylineno=myScan->line0;
1106 myScan->protection = tcl.protection;
1108 tcl.entry_inside = myScan->entry_scan;
1109 tcl.entry_current = tcl_entry_new();
1110 tcl.scan.insert(0,myScan);
1111 yy_switch_to_buffer(myScan->buffer_state);
1115 //! Close current scan context.
1116 static void tcl_scan_end()
1118 tcl_scan *myScan=tcl.scan.at(0);
1119 tcl_scan *myScan1=tcl.scan.at(1);
1120 tcl_inf("line=%d\n",myScan->line1);
1122 if (myScan->type[0]=='{') myScan->type[0]='}';
1123 if (myScan->type[0]=='[') myScan->type[0]=']';
1124 if (myScan->type[0]!=' ') tcl_codify(NULL,&myScan->type[0]);
1126 for (unsigned int i=0;i<myScan->after.count();i=i+2)
1128 if (myScan->after[i]=="script") {
1132 tcl_codify(myScan->after[i].utf8(),myScan->after[i+1].utf8());
1134 yy_delete_buffer(myScan->buffer_state);
1136 tcl.entry_inside = myScan1->entry_scan;
1137 yy_switch_to_buffer(myScan1->buffer_state);
1138 yylineno=myScan1->line1;
1139 tcl.protection = myScan1->protection;
1142 myScan1 = tcl_scan_start('?', myScan->after[myStart+1], myScan->ns, myScan->entry_cl, myScan->entry_fn);
1143 for (unsigned int i=myStart+2;i<myScan->after.count();i++)
1145 myScan1->after.append(myScan->after[i]);
1151 tcl.scan.removeFirst();
1155 //! Handling of word parsing.
1156 static void tcl_word(int what,const char *text)
1158 static char myList[1024]="";// nesting level list
1159 static int myLevel=0;// number of current nesting level
1160 static int myWhite=0;// set true when next char should be whitespace
1161 static char myWord;// internal state
1166 yy_push_state(WORD);
1171 case '"': myWord = text[0]; break;
1172 default: myWord = '.';
1178 case 1:// all other chars
1181 tcl_err("expected word separator: %s\n",text);
1197 tcl_inf("(\\\n) ?%s?\n",tcl.string_last.data());
1200 switch (myList[myLevel-1])
1212 tcl_inf("(\\\n) ?%s?\n",tcl.string_last.data());
1222 tcl_err("expected word separator: %s\n",text);
1225 switch (myList[myLevel-1])
1229 myList[myLevel++]='{';
1240 tcl_err("expected word separator: %s\n",text);
1243 switch (myList[myLevel-1])
1247 if (myLevel==0 && tcl.code==NULL)
1261 tcl_err("expected word separator: %s\n",text);
1264 switch (myList[myLevel-1])
1271 myList[myLevel++]='[';
1279 tcl_err("expected word separator: %s\n",text);
1282 switch (myList[myLevel-1])
1298 tcl_err("expected word separator: %s\n",text);
1301 switch (myList[myLevel-1])
1306 myList[myLevel++]='"';
1323 tcl_inf("(%d) ?%s?\n",what,tcl.string_last.data());
1326 switch (myList[myLevel-1])
1338 tcl_inf("(.%d) ?%s?\n",what,tcl.string_last.data());
1355 tcl_inf("(%d) ?%s?\n",what,tcl.string_last.data());
1358 if (myLevel!=1 || myList[0] != '.')
1360 tcl_war("level=%d expected=%c\n",myLevel,myList[myLevel-1]);
1365 tcl_inf("(.%d) ?%s?\n",what,tcl.string_last.data());
1370 tcl_err("wrong state: %d\n",what);
1373 tcl.string_last += text;
1376 //! Handling of comment parsing.
1377 static void tcl_comment(int what,const char *text)
1380 { // begin of comment
1383 tcl_err("comment in comment\n");
1386 yy_push_state(COMMENT);
1387 tcl_inf("<- %s\n",text);
1388 tcl.string_comment="";
1392 { // start new comment
1395 tcl_comment(99,""); // inbody
1397 tcl.string_comment=text;
1404 tcl.string_comment+=text;
1407 else if (what==-1 || what == -2)
1408 { // end of comment without/with command
1411 tcl.string_last=tcl.string_comment;
1412 tcl_comment(100+what,"");
1416 tcl.string_last = "";
1417 tcl_inf("-> %s\n",(const char *)tcl.string_comment);
1420 tcl.string_comment="";
1423 else if (what==98 || what==99)
1424 { // 98=new 99=inbody
1425 if (tcl.this_parser && tcl.string_comment.length())
1427 tcl_inf("-> %s\n",(const char *)tcl.string_comment);
1430 int myLine=tcl.line_comment;
1433 Protection myProt=tcl.protection;
1436 myI.addArray("/*!",3);
1437 myI.addArray(tcl.string_comment.data(),tcl.string_comment.length());
1438 myI.addArray("*/",2);
1439 convertCppComments(&myI,&myO,tcl.file_name);
1440 myO.dropFromStart(3);
1441 myO.shrink(myO.curPos()-2);
1443 QCString myDoc = myO.data();
1445 { // inbody comment file or namespace or class or proc/method
1448 Entry myEntry0; // used to test parsing
1451 Entry *myEntry1=NULL;
1452 if (tcl.scan.at(0)->entry_fn)
1454 myEntry1=tcl.scan.at(0)->entry_fn;
1456 else if (tcl.scan.at(0)->entry_cl)
1458 myEntry1=tcl.scan.at(0)->entry_cl;
1463 while (parseCommentBlock(tcl.this_parser, &myEntry0, myDoc, tcl.file_name,
1464 myLine, FALSE, tcl.config_autobrief, FALSE, myProt, myPos, myNew))
1467 { // we need a new entry in this case
1469 myEntry = tcl_entry_new();
1470 parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name,
1471 myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
1472 tcl.entry_inside->addSubEntry(myEntry);
1475 { // we can add to current entry in this case
1478 myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns);
1480 parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name,
1481 myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
1487 { // we need a new entry
1489 myEntry = tcl_entry_new();
1490 parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name,
1491 myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
1492 tcl.entry_inside->addSubEntry(myEntry);
1495 { // we can add to current entry
1498 myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns);
1500 parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name,
1501 myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew);
1506 tcl.entry_current = tcl_entry_new();
1507 while (parseCommentBlock(tcl.this_parser, tcl.entry_current, myDoc,
1508 tcl.file_name, myLine, FALSE, tcl.config_autobrief, FALSE,
1509 myProt, myPos, myNew))
1513 tcl.entry_inside->addSubEntry(tcl.entry_current);
1514 tcl.entry_current = tcl_entry_new();
1518 tcl.entry_current->section = tcl.entry_inside->section;
1519 tcl.entry_current->name = tcl.entry_inside->name;
1524 tcl.entry_inside->addSubEntry(tcl.entry_current);
1525 tcl.entry_current = tcl_entry_new();
1529 tcl.entry_current->section = tcl.entry_inside->section;
1530 tcl.entry_current->name = tcl.entry_inside->name;
1533 if (tcl.protection != myProt)
1535 tcl.scan.at(0)->protection = tcl.protection = myProt;
1541 tcl_err("what %d\n",what);
1546 //! Parse given \c arglist .
1547 static void tcl_command_ARGLIST(QString &arglist)
1552 QString myArglist="";
1554 if (tcl.entry_current->argList==NULL)
1556 tcl.entry_current->argList=new ArgumentList;
1558 tcl_split_list(arglist,myArgs);
1559 for (uint i=0;i<myArgs.count();i++)
1561 QStringList myArgs1;
1564 tcl_split_list(*myArgs.at(i),myArgs1);
1565 if (myArgs1.count()==2)
1567 myArg->name= (*myArgs1.at(0)).utf8();
1568 myArg->defval= (*myArgs1.at(1)).utf8();
1569 if (myArg->defval.isEmpty())
1571 myArg->defval = " ";
1573 myArglist += "?" + QCString(myArg->name) + "? ";
1577 myArg->name= (*myArgs.at(i)).utf8();
1578 myArglist += QString(myArg->name) + " ";
1580 tcl.entry_current->argList->append(myArg);
1582 arglist = myArglist;
1583 tcl.entry_current->args = arglist.utf8();
1587 static void tcl_codify_link(QCString name)
1589 if (tcl.code == NULL || name.isEmpty()) return;
1591 static QAsciiDict<MemberDef> fn;
1595 MemberNameSDict::Iterator mni(*Doxygen::memberNameSDict);
1596 MemberNameSDict::Iterator fni(*Doxygen::functionNameSDict);
1599 for (mni.toFirst();(mn=mni.current());++mni)
1601 MemberNameIterator mi(*mn);
1602 for (mi.toFirst();(md=mi.current());++mi)
1604 fn.insert(md->qualifiedName(),md);
1607 for (fni.toFirst();(mn=fni.current());++fni)
1609 MemberNameIterator fi(*mn);
1610 for (fi.toFirst();(md=fi.current());++fi)
1612 fn.insert(md->qualifiedName(),md);
1617 QCString myName=name;
1618 if (name.mid(0,2)=="::") // fully qualified global command
1620 myName = myName.mid(2);
1621 myDef = fn.find(myName);
1623 else // not qualified name
1625 QCString myName1=myName;
1627 myName1 = tcl.scan.at(0)->ns;
1628 if (myName1 == " " || myName1 == "")
1634 myName1 = myName1 + "::" + myName;
1636 myDef = fn.find(myName1); // search namespace command
1639 myDef = fn.find(myName); // search global command
1642 if (myDef != NULL) // documented command
1644 tcl.code->writeCodeLink(myDef->getReference().data(),
1645 myDef->getOutputFileBase().data(),
1646 myDef->anchor().data(),
1648 myDef->qualifiedName().data());
1651 myDef->addSourceReferencedBy(tcl.memberdef);
1652 tcl.memberdef->addSourceReferences(myDef);
1655 else if (tcl_keyword(myName)) // check keyword
1657 tcl_codify("keyword",name);
1661 tcl_codify(NULL,name); // something else
1666 //! Handle internal tcl commands.
1667 // "if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?"
1668 static void tcl_command_IF(QStringList type)
1671 tcl_codify_cmd("keyword",0);
1672 tcl_codify_cmd(NULL,1);
1673 tcl_scan *myScan=tcl.scan.at(0);
1674 myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2),
1675 myScan->ns,myScan->entry_cl,myScan->entry_fn);
1676 for (unsigned int i = 3;i<tcl.list_commandwords.count();i++)
1678 myScan->after << type[i] << tcl.list_commandwords[i];
1681 //! Handle internal tcl commands.
1682 // "for start test next body"
1683 static void tcl_command_FOR()
1686 tcl_codify_cmd("keyword",0);
1687 tcl_codify_cmd(NULL,1);
1688 tcl_scan *myScan=tcl.scan.at(0);
1689 myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2),
1690 myScan->ns,myScan->entry_cl,myScan->entry_fn);
1691 myScan->after << "NULL" << tcl.list_commandwords[3];
1692 myScan->after << "script" << tcl.list_commandwords[4];
1693 myScan->after << "NULL" << tcl.list_commandwords[5];
1694 myScan->after << "script" << tcl.list_commandwords[6];
1695 myScan->after << "NULL" << tcl.list_commandwords[7];
1696 myScan->after << "script" << tcl.list_commandwords[8];
1699 ///! Handle internal tcl commands.
1700 // "foreach varname list body" and
1701 // "foreach varlist1 list1 ?varlist2 list2 ...? body"
1702 static void tcl_command_FOREACH()
1706 tcl_codify_cmd("keyword",0);
1707 for (i = 1;i<tcl.list_commandwords.count()-1;i++)
1709 tcl_codify_cmd(NULL,i);
1711 tcl_scan *myScan=tcl.scan.at(0);
1712 myScan = tcl_scan_start('?',*tcl.list_commandwords.at(tcl.list_commandwords.count()-1),
1713 myScan->ns,myScan->entry_cl,myScan->entry_fn);
1716 ///! Handle internal tcl commands.
1717 // "while test body"
1718 static void tcl_command_WHILE()
1721 tcl_codify_cmd("keyword",0);
1722 tcl_codify_cmd(NULL,1);
1723 tcl_scan *myScan=tcl.scan.at(0);
1724 myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2),
1725 myScan->ns,myScan->entry_cl,myScan->entry_fn);
1726 myScan->after << "NULL" << tcl.list_commandwords[3];
1727 myScan->after << "script" << tcl.list_commandwords[4];
1730 //! Handle all other commands.
1731 // Create links of first command word or first command word inside [].
1732 static void tcl_command_OTHER()
1734 if (tcl.code == NULL) return;
1737 for (unsigned int i=0; i< tcl.list_commandwords.count(); i++)
1739 myName = (*tcl.list_commandwords.at(i)).utf8();
1742 tcl_codify_link(myName);
1746 tcl_codify(NULL,myName);
1753 for (i=0;i<myName.length();i++)
1755 QChar c = myName[i];
1758 if (c==' '||c=='\t'||c=='\n'||c==']')
1760 tcl_codify_link(myStr);
1771 for (;i<myName.length();i++)
1774 if (c!=' ' && c!='\t' && c!='\n') break;
1777 tcl_codify(NULL,myStr);
1783 tcl_codify(NULL,myStr);
1788 //! Handle \c proc statements.
1789 static void tcl_command_PROC()
1792 QCString myNs, myName;
1795 tcl_scan *myScan = tcl.scan.at(0);
1797 tcl_codify_cmd("keyword",0);
1798 tcl_codify_cmd(NULL,1);
1799 tcl_codify_cmd(NULL,2);
1800 tcl_codify_cmd(NULL,3);
1801 tcl_codify_cmd(NULL,4);
1802 tcl_codify_cmd(NULL,5);
1803 tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)).utf8(),myNs,myName);
1806 myEntryNs = tcl_entry_namespace(myNs);
1810 myEntryNs = tcl_entry_namespace(myScan->ns);
1812 //why not needed here? tcl.fn.remove(myName);
1813 tcl.entry_current->section = Entry::FUNCTION_SEC;
1814 tcl.entry_current->mtype = Method;
1815 tcl.entry_current->name = myName;
1816 tcl.entry_current->startLine = tcl.line_command;
1817 tcl.entry_current->bodyLine = tcl.line_body0;
1818 tcl.entry_current->endBodyLine = tcl.line_body1;
1819 tcl_protection(tcl.entry_current);
1820 tcl_command_ARGLIST(*tcl.list_commandwords.at(4));
1821 myEntryNs->addSubEntry(tcl.entry_current);
1822 myEntry = tcl.entry_current;
1823 tcl.fn.insert(myName,myEntry);
1824 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(6),
1825 myEntryNs->name,NULL,myEntry);
1828 //! Handle \c itcl::body statements and \c oo::define method and method inside \c itcl::class statements.
1829 static void tcl_command_METHOD()
1832 QCString myNs, myName;
1833 Entry *myEntryCl, *myEntry;
1834 tcl_scan *myScan = tcl.scan.at(0);
1836 tcl_codify_cmd("keyword",0);
1837 tcl_codify_cmd(NULL,1);
1838 tcl_codify_cmd(NULL,2);
1839 tcl_codify_cmd(NULL,3);
1840 tcl_codify_cmd(NULL,4);
1841 tcl_codify_cmd(NULL,5);
1842 tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)).utf8(),myNs,myName);
1845 myEntryCl = tcl_entry_class(myNs);
1850 myEntryCl = myScan->entry_cl;
1852 // needed in case of more then one definition p.e. itcl::method and itcl::body
1854 tcl.fn.remove(myName);
1855 tcl.entry_current->section = Entry::FUNCTION_SEC;
1856 tcl.entry_current->mtype = Method;
1857 tcl.entry_current->name = myName;
1858 tcl.entry_current->startLine = tcl.line_command;
1859 tcl.entry_current->bodyLine = tcl.line_body0;
1860 tcl.entry_current->endBodyLine = tcl.line_body1;
1861 tcl_protection(tcl.entry_current);
1862 tcl_command_ARGLIST(*tcl.list_commandwords.at(4));
1863 myEntryCl->addSubEntry(tcl.entry_current);
1864 tcl.fn.insert(myName,tcl.entry_current);
1865 myEntry = tcl.entry_current;
1866 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(6),
1867 myNs, myEntryCl, myEntry);
1870 //! Handle \c constructor statements inside class definitions.
1871 static void tcl_command_CONSTRUCTOR()
1874 QCString myNs, myName;
1875 Entry *myEntryCl, *myEntry;
1876 tcl_scan *myScan = tcl.scan.at(0);
1878 tcl_codify_cmd("keyword",0);
1879 tcl_codify_cmd(NULL,1);
1880 tcl_codify_cmd(NULL,2);
1881 tcl_codify_cmd(NULL,3);
1882 tcl_name(myScan->ns,(*tcl.list_commandwords.at(0)).utf8(),myNs,myName);
1885 myEntryCl = tcl_entry_class(myNs);
1890 myEntryCl = myScan->entry_cl;
1892 tcl.entry_current->section = Entry::FUNCTION_SEC;
1893 tcl.entry_current->mtype = Method;
1894 tcl.entry_current->name = myName;
1895 tcl.entry_current->startLine = tcl.line_command;
1896 tcl.entry_current->bodyLine = tcl.line_body0;
1897 tcl.entry_current->endBodyLine = tcl.line_body1;
1898 tcl_protection(tcl.entry_current);
1899 tcl_command_ARGLIST(*tcl.list_commandwords.at(2));
1900 myEntryCl->addSubEntry(tcl.entry_current);
1901 myEntry = tcl.entry_current;
1902 tcl.fn.insert(myName,myEntry);
1903 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(4),
1904 myNs, myEntryCl, myEntry);
1907 //! Handle \c destructor statements inside class definitions.
1908 static void tcl_command_DESTRUCTOR()
1911 QCString myNs, myName;
1912 Entry *myEntryCl, *myEntry;
1913 tcl_scan *myScan = tcl.scan.at(0);
1915 tcl_codify_cmd("keyword",0);
1916 tcl_codify_cmd(NULL,1);
1917 tcl_name(myScan->ns,(*tcl.list_commandwords.at(0)).utf8(),myNs,myName);
1920 myEntryCl = tcl_entry_class(myNs);
1925 myEntryCl = myScan->entry_cl;
1927 tcl.entry_current->section = Entry::FUNCTION_SEC;
1928 tcl.entry_current->mtype = Method;
1929 tcl.entry_current->name = myName;
1930 tcl.entry_current->startLine = tcl.line_command;
1931 tcl.entry_current->bodyLine = tcl.line_body0;
1932 tcl.entry_current->endBodyLine = tcl.line_body1;
1933 tcl_protection(tcl.entry_current);
1934 myEntryCl->addSubEntry(tcl.entry_current);
1935 myEntry = tcl.entry_current;
1936 tcl.fn.insert(myName,myEntry);
1937 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(2),
1938 myNs, myEntryCl, myEntry);
1941 //! Handle \c namespace statements.
1942 static void tcl_command_NAMESPACE()
1945 QCString myNs, myName, myStr;
1946 Entry *myEntryNs=NULL;
1947 tcl_scan *myScan = tcl.scan.at(0);
1949 tcl_codify_cmd("keyword",0);
1950 tcl_codify_cmd(NULL,1);
1951 tcl_codify_cmd("keyword",2);
1952 tcl_codify_cmd(NULL,3);
1953 tcl_codify_cmd(NULL,4);
1954 tcl_codify_cmd(NULL,5);
1955 tcl_name(myScan->ns,(*tcl.list_commandwords.at(4)).utf8(),myNs,myName);
1958 myName = myNs+"::"+myName;
1960 tcl.entry_current->section = Entry::NAMESPACE_SEC;
1961 tcl.entry_current->name = myName;
1962 tcl.entry_current->startLine = tcl.line_command;
1963 tcl.entry_current->bodyLine = tcl.line_body0;
1964 tcl.entry_current->endBodyLine = tcl.line_body1;
1965 tcl.entry_main->addSubEntry(tcl.entry_current);
1966 tcl.ns.insert(myName,tcl.entry_current);
1967 myEntryNs = tcl.entry_current;
1968 myStr = (*tcl.list_commandwords.at(6)).utf8();
1969 if (tcl.list_commandwords.count() > 7)
1971 for (uint i=7;i<tcl.list_commandwords.count();i++)
1973 myStr.append((*tcl.list_commandwords.at(i)).utf8());
1977 myScan = tcl_scan_start(tcl.word_is,myStr, myName, NULL, NULL);
1980 //! Handle \c itcl::class statements.
1981 static void tcl_command_ITCL_CLASS()
1984 QCString myNs, myName, myStr;
1986 tcl_scan *myScan = tcl.scan.at(0);
1988 tcl_codify_cmd("keyword",0);
1989 tcl_codify_cmd(NULL,1);
1990 tcl_codify_cmd("NULL",2);
1991 tcl_codify_cmd("NULL",3);
1992 tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)).utf8(),myNs,myName);
1995 myName = myNs+"::"+myName;
1997 tcl.entry_current->section = Entry::CLASS_SEC;
1998 tcl.entry_current->name = myName;
1999 tcl.entry_current->startLine = tcl.line_command;
2000 tcl.entry_current->bodyLine = tcl.line_body0;
2001 tcl.entry_current->endBodyLine = tcl.line_body1;
2002 tcl.entry_main->addSubEntry(tcl.entry_current);
2003 tcl.cl.insert(myName,tcl.entry_current);
2004 myEntryCl = tcl.entry_current;
2005 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(4),
2006 myName, myEntryCl, NULL);
2009 //! Handle \c oo::class statements.
2010 static void tcl_command_OO_CLASS()
2013 QCString myNs, myName, myStr;
2016 tcl_scan *myScan = tcl.scan.at(0);
2018 tcl_codify_cmd("keyword",0);
2019 tcl_codify_cmd(NULL,1);
2020 tcl_codify_cmd("NULL",2);
2021 tcl_codify_cmd("NULL",3);
2022 tcl_codify_cmd("NULL",4);
2023 tcl_codify_cmd("NULL",5);
2024 tcl_name(myScan->ns,(*tcl.list_commandwords.at(4)).utf8(),myNs,myName);
2027 myName = myNs+"::"+myName;
2029 tcl.entry_current->section = Entry::CLASS_SEC;
2030 tcl.entry_current->name = myName;
2031 tcl.entry_current->startLine = tcl.line_command;
2032 tcl.entry_current->bodyLine = tcl.line_body0;
2033 tcl.entry_current->endBodyLine = tcl.line_body1;
2034 tcl.entry_main->addSubEntry(tcl.entry_current);
2035 //myEntryNs = tcl_entry_namespace(myName);
2036 tcl.cl.insert(myName,tcl.entry_current);
2037 myEntryCl = tcl.entry_current;
2038 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(6),
2039 myName, myEntryCl, NULL);
2042 //! Handle \c oo::define statements.
2043 static void tcl_command_OO_DEFINE()
2046 QCString myNs, myName, myStr;
2048 tcl_scan *myScan = tcl.scan.at(0);
2050 tcl_codify_cmd("keyword",0);
2051 tcl_codify_cmd(NULL,1);
2052 tcl_codify_cmd("NULL",2);
2053 tcl_codify_cmd("NULL",3);
2054 tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)).utf8(),myNs,myName);
2057 myName = myNs+"::"+myName;
2059 myEntryCl = tcl_entry_class(myName);
2060 myStr = (*tcl.list_commandwords.at(4)).utf8();
2061 if (tcl.list_commandwords.count() > 5)
2063 for (uint i=5;i<tcl.list_commandwords.count();i++)
2065 myStr.append((*tcl.list_commandwords.at(i)).utf8());
2069 myScan = tcl_scan_start(tcl.word_is,myStr,myName,myEntryCl,NULL);
2072 //! Handle \c variable statements.
2073 static void tcl_command_VARIABLE(int inclass)
2076 QCString myNs, myName;
2078 tcl_scan *myScan = tcl.scan.at(0);
2080 tcl_codify_cmd("keyword",0);
2081 for (unsigned int i=1; i< tcl.list_commandwords.count(); i++)
2083 tcl_codify_cmd(NULL,i);
2085 tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)).utf8(),myNs,myName);
2087 {// qualified variables go into namespace
2088 myEntry = tcl_entry_namespace(myNs);
2089 tcl.entry_current->stat = true;
2095 myEntry = myScan->entry_cl;
2096 tcl.entry_current->stat = false;
2100 myEntry = tcl_entry_namespace(myScan->ns);
2101 tcl.entry_current->stat = true;
2104 tcl.entry_current->section = Entry::VARIABLE_SEC;
2105 tcl.entry_current->name = myName;
2106 tcl.entry_current->startLine = tcl.line_command;
2107 tcl.entry_current->bodyLine = tcl.line_body0;
2108 tcl.entry_current->endBodyLine = tcl.line_body1;
2109 tcl_protection(tcl.entry_current);
2110 myEntry->addSubEntry(tcl.entry_current);
2111 tcl.entry_current = tcl_entry_new();
2114 //! Handling of command parsing.
2118 static void tcl_command(int what,const char *text)
2123 tcl.scan.at(0)->line1=yylineno;// current line in scan context
2124 tcl.line_body0=yylineno;// start line of command
2125 tcl_inf("<- %s\n",text);
2126 yy_push_state(COMMAND);
2127 tcl.list_commandwords.clear();
2128 tcl.string_command="";
2135 if (tcl.string_last.length())
2137 tcl.list_commandwords.append(tcl.string_last);
2142 tcl.list_commandwords.append(text);
2147 {// should not happen
2148 tcl_err("what %d\n",what);
2151 QCString myText = text;
2155 return; //TODO check on inside comment
2157 if (tcl.string_last != "")
2159 tcl.list_commandwords.append(tcl.string_last);
2165 QCString myStr = (*tcl.list_commandwords.at(0)).utf8();
2167 Protection myProt = tcl.protection;
2169 if (tcl.list_commandwords.count() < 3)
2171 tcl_command_OTHER();
2174 // remove leading "::" and apply TCL_SUBST
2175 if (myStr.left(2)=="::") myStr = myStr.mid(2);
2176 if (tcl.config_subst.contains(myStr))
2178 myStr=tcl.config_subst[myStr].utf8();
2180 if (myStr=="private")
2182 tcl.protection = Private;
2185 else if (myStr=="protected")
2187 tcl.protection = Protected;
2190 else if (myStr=="public")
2192 tcl.protection = Public;
2197 tcl_codify_cmd("keyword",0);
2198 tcl_codify_cmd(NULL,1);
2199 tcl.list_commandwords.remove(tcl.list_commandwords.at(1));
2200 tcl.list_commandwords.remove(tcl.list_commandwords.at(0));
2201 if (tcl.list_commandwords.count()==1)
2203 tcl_scan *myScan = tcl.scan.at(0);
2204 myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(0),
2205 myScan->ns,myScan->entry_cl,myScan->entry_fn);
2206 myProt = tcl.protection;
2209 myStr = (*tcl.list_commandwords.at(0)).utf8();
2210 // remove leading "::" and apply TCL_SUBST
2211 if (myStr.left(2)=="::") myStr = myStr.mid(2);
2212 if (tcl.config_subst.contains(myStr))
2214 myStr=tcl.config_subst[myStr].utf8();
2219 if (tcl.list_commandwords.count() == 5)
2221 tcl.list_commandwords.append("");
2222 tcl.list_commandwords.append("");
2224 if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;}
2228 if (myStr=="method")
2230 if (tcl.list_commandwords.count() == 5)
2232 tcl.list_commandwords.append("");
2233 tcl.list_commandwords.append("");
2235 if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;}
2236 tcl_command_METHOD();
2239 if (myStr=="constructor")
2241 if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;}
2242 tcl_command_CONSTRUCTOR();
2245 if (myStr=="destructor")
2247 if (tcl.list_commandwords.count() != 3) {myLine=__LINE__;goto command_warn;}
2248 tcl_command_DESTRUCTOR();
2251 if (myStr=="namespace")
2253 if ((*tcl.list_commandwords.at(2)).utf8()=="eval")
2255 if (tcl.list_commandwords.count() < 7) {myLine=__LINE__;goto command_warn;}
2256 tcl_command_NAMESPACE();
2259 tcl_command_OTHER();
2262 if (myStr=="itcl::class")
2264 if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;}
2265 tcl_command_ITCL_CLASS();
2268 if (myStr=="itcl::body")
2270 if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;}
2271 tcl_command_METHOD();
2274 if (myStr=="oo::class")
2276 if ((*tcl.list_commandwords.at(2)).utf8()=="create")
2278 if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;}
2279 tcl_command_OO_CLASS();
2282 tcl_command_OTHER();
2285 if (myStr=="oo::define")
2287 if (tcl.list_commandwords.count() < 5) {myLine=__LINE__;goto command_warn;}
2288 tcl_command_OO_DEFINE();
2291 if (myStr=="variable")
2293 if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;}
2294 if (tcl.scan.at(0)->entry_fn == NULL)
2295 {// only parsed outside functions
2296 tcl_command_VARIABLE(tcl.scan.at(0)->entry_cl!=NULL&&tcl.scan.at(0)->entry_cl->name!="");
2300 if (myStr=="common")
2302 if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;}
2303 if (tcl.scan.at(0)->entry_fn == NULL)
2304 {// only parsed outside functions
2305 tcl_command_VARIABLE(0);
2309 if (myStr=="inherit" || myStr=="superclass")
2311 if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;}
2312 if (tcl.scan.at(0)->entry_cl!=NULL&&tcl.scan.at(0)->entry_cl->name!="")
2314 for (unsigned int i = 2; i < tcl.list_commandwords.count(); i = i + 2)
2316 tcl.scan.at(0)->entry_cl->extends->append(new BaseInfo((*tcl.list_commandwords.at(i)).utf8(),Public,Normal));
2322 * Start of internal tcl keywords
2323 * Ready: if, for, foreach, while
2324 * TODO: switch, eval, ?
2328 if (tcl.list_commandwords.count() != 9) {myLine=__LINE__;goto command_warn;}
2332 if (myStr=="foreach")
2334 if (tcl.list_commandwords.count() < 7 || tcl.list_commandwords.count()%2==0) {myLine=__LINE__;goto command_warn;}
2335 tcl_command_FOREACH();
2339 if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
2341 if (myStr=="if" && tcl.list_commandwords.count() > 4)
2344 myType << "keyword" << "NULL" << "script" << "NULL";
2345 char myState='x';// last word: e'x'pr 't'hen 'b'ody 'e'lse else'i'f..
2346 for (unsigned int i = 4; i < tcl.list_commandwords.count(); i = i + 2)
2348 QCString myStr=(*tcl.list_commandwords.at(i)).utf8();
2354 myType << "keyword" << "NULL";
2359 myType << "script" << "NULL";
2362 else if (myState=='t')
2365 myType << "script" << "NULL";
2367 else if (myState=='b')
2369 if (myStr=="elseif") {
2371 myType << "keyword" << "NULL";
2373 else if (myStr=="else" && i==tcl.list_commandwords.count()-3)
2376 myType << "keyword" << "NULL" << "script";
2377 i = tcl.list_commandwords.count();
2379 else if (i==tcl.list_commandwords.count()-1)
2383 i = tcl.list_commandwords.count();
2387 myLine=__LINE__;goto command_warn;
2390 else if (myState=='i')
2393 myType << "script" << "NULL";
2396 if (myState != 'b') {myLine=__LINE__;goto command_warn;}
2397 tcl_command_IF(myType);
2402 if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;}
2403 tcl_command_WHILE();
2406 tcl_command_OTHER();
2408 command_warn:// print warning message because of wrong used syntax
2409 tcl_war("%d count=%d: %s\n",myLine,tcl.list_commandwords.count(),tcl.list_commandwords.join(" ").ascii());
2410 tcl_command_OTHER();
2411 command_text:// print remaining text as comment
2412 if (!myText.isEmpty()) tcl_codify("comment",myText);
2414 command_end:// add remaining text to current context
2415 if (!myText.isEmpty()) tcl.scan.at(0)->after << "comment" << myText;
2416 tcl.list_commandwords.clear();
2418 tcl.protection = myProt;
2421 //----------------------------------------------------------------------------
2422 //! Common initializations.
2423 static void tcl_init()
2425 // Get values from option TCL_SUBST
2426 tcl.config_subst.clear();
2427 if (Config::instance()->get("TCL_SUBST"))
2429 QStrList myStrList = Config_getList("TCL_SUBST");
2430 const char *s=myStrList.first();
2434 int i=myStr.find('=');
2437 QCString myName=myStr.left(i).stripWhiteSpace();
2438 QCString myValue=myStr.right(myStr.length()-i-1).stripWhiteSpace();
2439 if (!myName.isEmpty() && !myValue.isEmpty())
2440 tcl_inf("TCL_SUBST: use '%s'\n",s);
2441 tcl.config_subst[myName] = myValue;
2443 s = myStrList.next();
2447 if (tcl.input_string.at(tcl.input_string.length()-1) == '\n')
2449 tcl.input_string[tcl.input_string.length()-1] = 0x1A;
2453 tcl.input_string += 0x1A;
2458 tcl.code_linenumbers=1;
2459 tcl.config_autobrief = Config_getBool("JAVADOC_AUTOBRIEF");
2460 tcl.input_position = 0;
2461 tcl.file_name = NULL;
2462 tcl.this_parser = NULL;
2466 tcl.bracket_level=0;
2467 tcl.bracket_quote=0;
2469 tcl.string_command="";
2470 tcl.string_commentline="";
2471 tcl.string_commentcodify="";
2472 tcl.string_comment = "";
2473 tcl.string_last = "";
2474 tcl.entry_main = NULL;
2475 tcl.entry_file = NULL;
2476 tcl.entry_current = NULL;
2477 tcl.entry_inside = NULL;
2478 tcl.list_commandwords.clear();
2484 tcl.protection = Public;
2485 tcl.memberdef = NULL;
2489 static void tcl_parse(const QCString ns, const QCString cls)
2493 tcl.entry_file = tcl_entry_new();
2494 tcl.entry_file->name = tcl.file_name;
2495 tcl.entry_file->section = Entry::SOURCE_SEC;
2496 tcl.entry_file->protection = Public;
2497 tcl.entry_main->addSubEntry(tcl.entry_file);
2498 Entry *myEntry=tcl_entry_new();
2500 tcl.entry_main->addSubEntry(myEntry);
2501 tcl.ns.insert("::",myEntry);
2502 tcl.entry_current = tcl_entry_new();
2504 tclscanYYrestart( tclscanYYin );
2507 myScan = new tcl_scan;
2508 myScan->type[0]=' ';myScan->type[1]='\n';
2509 myScan->after.clear();
2510 myScan->line0=yylineno;
2511 myScan->line1=yylineno;
2512 myScan->buffer_state=YY_CURRENT_BUFFER;
2514 myScan->entry_cl=tcl_entry_class(cls);
2515 myScan->entry_fn=NULL;
2516 tcl.entry_inside = tcl.entry_file;
2517 myScan->entry_scan = tcl.entry_inside;
2518 tcl.scan.insert(0,myScan);
2527 //! Parse text file and build up entry tree.
2528 void TclLanguageScanner::parseInput(const char *fileName,const char *input,Entry *root)
2531 tcl_inf("%s\n",fileName);
2532 myFile.setName(fileName);
2533 if (!myFile.open(IO_ReadOnly)) return;
2534 if (strlen(input)<1) return;
2536 tcl.input_string = input;
2537 if (tcl.input_string.length()<1) return;
2539 msg("Parsing %s...\n",fileName);
2540 groupEnterFile(fileName,yylineno);
2544 tcl.file_name = fileName;
2545 tcl.this_parser = this;
2546 tcl.entry_main = root; /* toplevel entry */
2548 groupLeaveFile(tcl.file_name,yylineno);
2549 root->program.resize(0);
2553 //! Parse file and codify.
2554 void TclLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf,
2555 const char * scopeName,
2556 const QCString & input,
2557 bool isExampleBlock,
2558 const char * exampleName,
2562 bool inlineFragment,
2563 MemberDef *memberDef,
2564 bool showLineNumbers,
2565 Definition *searchCtx
2572 (void)inlineFragment;
2575 if (input.length()<1) return;
2576 tcl.input_string = input;
2582 if (memberDef->getClassDef())
2584 myCls = memberDef->getClassDef()->displayName();
2587 else if (memberDef->getNamespaceDef())
2589 myNs = memberDef->getNamespaceDef()->displayName();
2593 QString myStr="Codifying..";
2607 myStr+=memberDef->memberTypeName();
2609 myStr+=memberDef->qualifiedName();
2614 myStr+=fileDef->fileName();
2616 tcl_inf("%s (%d,%d) %d %d\n",myStr.ascii(),startLine,endLine,isExampleBlock,inlineFragment);
2617 //tcl_inf("%s\n"input.data());
2620 tcl_codify(NULL,input);
2624 tcl.memberdef = memberDef;
2625 tcl.code = &codeOutIntf;
2631 tcl.code_linenumbers = showLineNumbers;
2632 tcl.code_line=yylineno;
2633 if (tcl.code_linenumbers)
2635 tcl.code->writeLineNumber(0,0,0,tcl.code_line);
2638 tcl.this_parser = NULL;
2639 tcl.entry_main = tcl_entry_new();
2640 tcl_parse(myNs,myCls);
2648 bool TclLanguageScanner::needsPreprocessing(const QCString &extension)
2654 void TclLanguageScanner::resetCodeParserState()
2658 void TclLanguageScanner::parsePrototype(const char *text)
2663 static int yyread(char *buf,int max_size)
2668 while ( c < max_size && tcl.input_string.at(tcl.input_position) )
2670 *buf = tcl.input_string.at(tcl.input_position++) ;
2673 //printf("Read from=%d size=%d max=%d c=%d\n",tcl.input_position,strlen(&tcl.input_string[tcl.input_position]),max_size,c);
2677 //----------------------------------------------------------------------------
2679 // to avoid a warning
2685 #if !defined(YY_FLEX_SUBMINOR_VERSION)
2686 //----------------------------------------------------------------------------
2687 extern "C" { // some bogus code to keep the compiler happy
2688 void tclscannerYYdummy() { yy_flex_realloc(0,0); }