From 6245ef410358f332330195f9f2bfa458cfb6a2b8 Mon Sep 17 00:00:00 2001 From: wtschueller Date: Tue, 10 Jun 2014 21:41:33 +0200 Subject: Tcl: collect XRefs also if INLINE_SOURCES = no --- src/tclscanner.l | 36 +++++++ testing/057/057__caller__graphs_8tcl.xml | 64 ++++++++++++ testing/057/namespace1.xml | 113 ++++++++++++++++++++ testing/057/namespace1_1_11.xml | 28 +++++ testing/057/namespace1_1_11_1_11.xml | 26 +++++ testing/057/namespace2.xml | 30 ++++++ testing/057/namespace2_1_12.xml | 29 ++++++ testing/057/namespace2_1_12_1_12.xml | 29 ++++++ testing/057/namespace2_1_12_1_12_1_12.xml | 29 ++++++ testing/057/namespace2_1_12_1_12_1_12_1_12.xml | 28 +++++ testing/057/namespacebar.xml | 57 ++++++++++ testing/057/namespacefoo.xml | 27 +++++ testing/057_caller_graphs.tcl | 138 +++++++++++++++++++++++++ 13 files changed, 634 insertions(+) create mode 100644 testing/057/057__caller__graphs_8tcl.xml create mode 100644 testing/057/namespace1.xml create mode 100644 testing/057/namespace1_1_11.xml create mode 100644 testing/057/namespace1_1_11_1_11.xml create mode 100644 testing/057/namespace2.xml create mode 100644 testing/057/namespace2_1_12.xml create mode 100644 testing/057/namespace2_1_12_1_12.xml create mode 100644 testing/057/namespace2_1_12_1_12_1_12.xml create mode 100644 testing/057/namespace2_1_12_1_12_1_12_1_12.xml create mode 100644 testing/057/namespacebar.xml create mode 100644 testing/057/namespacefoo.xml create mode 100644 testing/057_caller_graphs.tcl diff --git a/src/tclscanner.l b/src/tclscanner.l index 1fd20cd..7201088 100644 --- a/src/tclscanner.l +++ b/src/tclscanner.l @@ -451,6 +451,7 @@ static struct QList entry; // list of all created entries, will be deleted after codifying Protection protection; // current protections state MemberDef *memberdef; // contain current MemberDef when codifying + bool collectXRefs; } tcl; // scanner functions @@ -1652,6 +1653,40 @@ static void tcl_codify_link(QCString name) { myDef->addSourceReferencedBy(tcl.memberdef); tcl.memberdef->addSourceReferences(myDef); + } else { + Entry* callerEntry; + unsigned int i; + // walk the stack of scan contexts and find the enclosing method or proc + for (i=0;ientry_scan; + if (callerEntry->mtype==Method && !callerEntry->name.isEmpty()) + { + break; + } + } + if (iname; + if (callerName.mid(0,2)=="::") // fully qualified global command + { + callerName = callerName.mid(2); + } + else + { + if (!(tcl.scan.at(0)->ns.stripWhiteSpace().isEmpty())) + { + callerName = tcl.scan.at(0)->ns + "::" + callerEntry->name; + } + } + MemberDef *callerDef=NULL; + callerDef = fn.find(callerName); + if (callerDef!=NULL && myDef!= NULL && tcl.collectXRefs) + { + addDocCrossReference(callerDef,myDef); + } + } } } else if (tcl_keyword(myName)) // check keyword @@ -2634,6 +2669,7 @@ tcl_inf("%s (%d,%d) %d %d\n",myStr.ascii(),startLine,endLine,isExampleBlock,inli return; } tcl_init(); + tcl.collectXRefs = collectXRefs; tcl.memberdef = memberDef; tcl.code = &codeOutIntf; if (startLine<0) diff --git a/testing/057/057__caller__graphs_8tcl.xml b/testing/057/057__caller__graphs_8tcl.xml new file mode 100644 index 0000000..d2e3d84 --- /dev/null +++ b/testing/057/057__caller__graphs_8tcl.xml @@ -0,0 +1,64 @@ + + + + 057_caller_graphs.tcl + bar + foo + 1::1::1 + 1 + 1::1 + 2::2::2::2::2 + 2 + 2::2 + 2::2::2 + 2::2::2::2 + + + + baz + args + baz + + + + + + + + + + + bar + args + bar + + + + + + + + 1::test3 + + + + next + args + next + + + + + + + + 2::next + + + + + + + + + diff --git a/testing/057/namespace1.xml b/testing/057/namespace1.xml new file mode 100644 index 0000000..e40300d --- /dev/null +++ b/testing/057/namespace1.xml @@ -0,0 +1,113 @@ + + + + 1 + 1::1 + + + + 1::baz + args + baz + + + + + + + + test1 + test5 + + + + 1::bar + args + bar + + + + + + + + test2 + + + + 1::test1 + args + test1 + + + + + + + + baz + + + + 1::test2 + args + test2 + + + + + + + + bar + + + + 1::test3 + args + test3 + + + + + + + + bar + + + + 1::test4 + args + test4 + + + + + + + + 1::1::bar + + + + 1::test5 + args + test5 + + + + + + + + baz + + + + + + + + + diff --git a/testing/057/namespace1_1_11.xml b/testing/057/namespace1_1_11.xml new file mode 100644 index 0000000..157ab5e --- /dev/null +++ b/testing/057/namespace1_1_11.xml @@ -0,0 +1,28 @@ + + + + 1::1 + 1::1::1 + + + + 1::1::bar + args + bar + + + + + + + + 1::test4 + + + + + + + + + diff --git a/testing/057/namespace1_1_11_1_11.xml b/testing/057/namespace1_1_11_1_11.xml new file mode 100644 index 0000000..2f5a685 --- /dev/null +++ b/testing/057/namespace1_1_11_1_11.xml @@ -0,0 +1,26 @@ + + + + 1::1::1 + + + + 1::1::1::bar + args + bar + + + + + + + + + + + + + + + + diff --git a/testing/057/namespace2.xml b/testing/057/namespace2.xml new file mode 100644 index 0000000..47a9fcf --- /dev/null +++ b/testing/057/namespace2.xml @@ -0,0 +1,30 @@ + + + + 2 + 2::2 + + + + 2::next + args + next + + + + + + + + 2::2::next + next + 2::2::2::2::2::next + + + + + + + + + diff --git a/testing/057/namespace2_1_12.xml b/testing/057/namespace2_1_12.xml new file mode 100644 index 0000000..3338473 --- /dev/null +++ b/testing/057/namespace2_1_12.xml @@ -0,0 +1,29 @@ + + + + 2::2 + 2::2::2 + + + + 2::2::next + args + next + + + + + + + + 2::2::2::next + 2::next + + + + + + + + + diff --git a/testing/057/namespace2_1_12_1_12.xml b/testing/057/namespace2_1_12_1_12.xml new file mode 100644 index 0000000..259ef25 --- /dev/null +++ b/testing/057/namespace2_1_12_1_12.xml @@ -0,0 +1,29 @@ + + + + 2::2::2 + 2::2::2::2 + + + + 2::2::2::next + args + next + + + + + + + + 2::2::2::2::next + 2::2::next + + + + + + + + + diff --git a/testing/057/namespace2_1_12_1_12_1_12.xml b/testing/057/namespace2_1_12_1_12_1_12.xml new file mode 100644 index 0000000..cea3062 --- /dev/null +++ b/testing/057/namespace2_1_12_1_12_1_12.xml @@ -0,0 +1,29 @@ + + + + 2::2::2::2 + 2::2::2::2::2 + + + + 2::2::2::2::next + args + next + + + + + + + + 2::2::2::2::2::next + 2::2::2::next + + + + + + + + + diff --git a/testing/057/namespace2_1_12_1_12_1_12_1_12.xml b/testing/057/namespace2_1_12_1_12_1_12_1_12.xml new file mode 100644 index 0000000..65bfa00 --- /dev/null +++ b/testing/057/namespace2_1_12_1_12_1_12_1_12.xml @@ -0,0 +1,28 @@ + + + + 2::2::2::2::2 + + + + 2::2::2::2::2::next + args + next + + + + + + + + 2::next + 2::2::2::2::next + + + + + + + + + diff --git a/testing/057/namespacebar.xml b/testing/057/namespacebar.xml new file mode 100644 index 0000000..642986b --- /dev/null +++ b/testing/057/namespacebar.xml @@ -0,0 +1,57 @@ + + + + bar + + + + bar::slave + + slave + + + + + + + + baz + foo::master + + + + bar::baz + + baz + + + + + + + + bazbaz + slave + + + + bar::bazbaz + + bazbaz + + + + + + + + baz + + + + + + + + + diff --git a/testing/057/namespacefoo.xml b/testing/057/namespacefoo.xml new file mode 100644 index 0000000..11f8053 --- /dev/null +++ b/testing/057/namespacefoo.xml @@ -0,0 +1,27 @@ + + + + foo + + + + foo::master + + master + + + + + + + + bar::slave + + + + + + + + + diff --git a/testing/057_caller_graphs.tcl b/testing/057_caller_graphs.tcl new file mode 100644 index 0000000..25bf1e7 --- /dev/null +++ b/testing/057_caller_graphs.tcl @@ -0,0 +1,138 @@ +#// objective: test for completeness and correctness of references/referencedby relations +#// check: 057__caller__graphs_8tcl.xml +#// check: namespacebar.xml +#// check: namespacefoo.xml +#// check: namespace1.xml +#// check: namespace1_1_11.xml +#// check: namespace1_1_11_1_11.xml +#// check: namespace2.xml +#// check: namespace2_1_12.xml +#// check: namespace2_1_12_1_12.xml +#// check: namespace2_1_12_1_12_1_12.xml +#// check: namespace2_1_12_1_12_1_12_1_12.xml +#// config: EXTRACT_ALL = yes +#// config: INLINE_SOURCES = no +#// config: REFERENCED_BY_RELATION = yes +#// config: REFERENCES_RELATION = yes +# config: HAVE_DOT = yes +# config: CALLER_GRAPH = yes +# config: CALL_GRAPH = yes +# config: GENERATE_HTML = yes + +# This is a stripped down example from my code. +# Doxygen 1.8.7 generates the correct relations (xml) +# but caller graphs will be incomplete. +# It does not generate any relations at all if INLINE_SOURCES = no. +namespace eval bar {} +proc bar::slave { } { + array set info [info frame 0]; puts -nonewline ->$info(proc) + if {1} then { + bar::baz + } + return +} +proc bar::baz {} { + array set info [info frame 0]; puts -nonewline ->$info(proc) + bar::bazbaz +} +proc bar::bazbaz {} { + array set info [info frame 0]; puts -nonewline ->$info(proc) +} +namespace eval foo {} +proc foo::master { } { + array set info [info frame 0]; puts -nonewline $info(proc) + bar::slave + return +} +# +# now we check tcl's rules: from the help +# NAME RESOLUTION +#... Command names are also always resolved by looking in the current +#namespace first. If not found there, they are searched for in every namespace on +#the current namespace's command path (which is empty by default). If not found +#there, command names are looked up in the global namespace (or, failing that, +#are processed by the unknown command.) ... +# +namespace eval ::1::1::1 {} +proc ::baz args { + array set info [info frame 0]; puts -nonewline ->$info(proc) +} +proc ::1::baz args { + array set info [info frame 0]; puts -nonewline ->$info(proc) +} +proc ::bar args { + array set info [info frame 0]; puts -nonewline ->$info(proc) +} +proc ::1::bar args { + array set info [info frame 0]; puts -nonewline ->$info(proc) +} +proc ::1::1::bar args { + array set info [info frame 0]; puts -nonewline ->$info(proc) +} +proc ::1::1::1::bar args { + array set info [info frame 0]; puts -nonewline ->$info(proc) +} +proc ::1::test1 args { + array set info [info frame 0]; puts -nonewline $info(proc) + baz +} +proc ::1::test2 args { + array set info [info frame 0]; puts -nonewline $info(proc) + bar +} +proc ::1::test3 args { + array set info [info frame 0]; puts -nonewline $info(proc) + ::bar +} +proc ::1::test4 args { + array set info [info frame 0]; puts -nonewline $info(proc) + 1::bar +} +proc ::1::test5 args { + array set info [info frame 0]; puts -nonewline $info(proc) + 1::baz +} +# +# funny example, do you see the infinite loop? +# we stop before the interpreter crashes +set ::countdown 10 +namespace eval ::2::2::2::2::2 {} +proc ::next args { + array set info [info frame 0]; puts $info(proc) + 2::next +} +proc ::2::next args { + array set info [info frame 0]; puts $info(proc) + incr ::countdown -1 + if {$::countdown>0} then { + 2::next + } else { + puts "stop after 10 rounds." + } +} +proc ::2::2::next args { + array set info [info frame 0]; puts $info(proc) + 2::next +} +proc ::2::2::2::next args { + array set info [info frame 0]; puts $info(proc) + 2::next +} +proc ::2::2::2::2::next args { + array set info [info frame 0]; puts $info(proc) + 2::next +} +proc ::2::2::2::2::2::next args { + array set info [info frame 0]; puts $info(proc) + 2::next +} +# now, check with tcl what is called +foo::master +puts "" +foreach proc [lsort [info procs ::1::test?]] { + $proc + puts "" +} +::next +exit + -- cgit v0.12 From 9d315a987d7d0ea2f38809aa74e36c92281910df Mon Sep 17 00:00:00 2001 From: wtschueller Date: Wed, 11 Jun 2014 22:02:02 +0200 Subject: Tcl: recurse for [] --- src/tclscanner.l | 256 +++++++++++++------ testing/058/058__bracket__recursion_8tcl.xml | 354 +++++++++++++++++++++++++++ testing/058_bracket_recursion.tcl | 141 +++++++++++ 3 files changed, 677 insertions(+), 74 deletions(-) create mode 100644 testing/058/058__bracket__recursion_8tcl.xml create mode 100644 testing/058_bracket_recursion.tcl diff --git a/src/tclscanner.l b/src/tclscanner.l index 7201088..48e8214 100644 --- a/src/tclscanner.l +++ b/src/tclscanner.l @@ -1700,6 +1700,122 @@ static void tcl_codify_link(QCString name) } +//! scan general argument for brackets +// +// parses (*tcl.list_commandwords.at(i)).utf8() and checks for brackets. +// Starts a new scan context if needed (*myScan==0 and brackets found). +// Returns NULL or the created scan context. +// +static tcl_scan *tcl_command_ARG(tcl_scan *myScan, unsigned int i, bool ignoreOutermostBraces) +{ + QCString myName; + bool insideQuotes=false; + unsigned int insideBrackets=0; + unsigned int insideBraces=0; + myName = (*tcl.list_commandwords.at(i)).utf8(); + if (i%2 != 0) + { + // handle white space + if (myScan!=NULL) + { + myScan->after << "NULL" << myName; + } + else + { + tcl_codify(NULL,myName); + } + } + else + { + QCString myStr = ""; + unsigned int j; + for (j=0;j0) + { + backslashed = myName[j-1]=='\\'; + } + // this is a state machine + // input is c + // internal state is myScan and insideXXX + // these are the transitions: + if (c=='[' && !backslashed && insideBraces==0) + { + insideBrackets++; + } + if (c==']' && !backslashed && insideBraces==0 && insideBrackets>0) + { + insideBrackets--; + } + if (c=='{' && !backslashed && !insideQuotes && !(ignoreOutermostBraces && j==0)) + { + insideBraces++; + } + if (c=='}' && !backslashed && !insideQuotes && insideBraces>0) + { + insideBraces--; + } + if (c=='"' && !backslashed && insideBraces==0) + { + insideQuotes=!insideQuotes; + } + // all output, depending on state and input + if (c=='[' && !backslashed && insideBrackets==1 && insideBraces==0) + { + // the first opening bracket, output what we have so far + myStr+=c; + if (myScan!=NULL) + { + myScan->after << "NULL" << myStr; + } + else + { + tcl_codify(NULL,myStr); + } + myStr=""; + } + else if (c==']' && !backslashed && insideBrackets==0 && insideBraces==0) + { + // the last closing bracket, start recursion, switch to deferred + if (myScan!=NULL) + { + myScan->after << "script" << myStr; + } + else + { + myScan=tcl.scan.at(0); + myScan = tcl_scan_start('?',myStr, + myScan->ns,myScan->entry_cl,myScan->entry_fn); + } + myStr=""; + myStr+=c; + } + else + { + myStr+=c; + } + } + if (myScan!=NULL) + { + myScan->after << "NULL" << myStr; + } + else + { + if (i==0) + { + tcl_codify_link(myStr); + } + else + { + tcl_codify(NULL,myStr); + } + } + } + return (myScan); +} + //! Handle internal tcl commands. // "if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?" static void tcl_command_IF(QStringList type) @@ -1707,12 +1823,27 @@ static void tcl_command_IF(QStringList type) D tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); - tcl_scan *myScan=tcl.scan.at(0); - myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2), - myScan->ns,myScan->entry_cl,myScan->entry_fn); + tcl_scan *myScan = NULL; + myScan = tcl_command_ARG(myScan, 2, true); for (unsigned int i = 3;iafter << type[i] << tcl.list_commandwords[i]; + if (type[i] == "expr") + { + myScan = tcl_command_ARG(myScan, i, true); + } + else + { + if (myScan!=0) + { + myScan->after << type[i] << tcl.list_commandwords[i]; + } + else + { + myScan=tcl.scan.at(0); + myScan = tcl_scan_start('?',*tcl.list_commandwords.at(i), + myScan->ns,myScan->entry_cl,myScan->entry_fn); + } + } } } //! Handle internal tcl commands. @@ -1726,7 +1857,7 @@ D myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2), myScan->ns,myScan->entry_cl,myScan->entry_fn); myScan->after << "NULL" << tcl.list_commandwords[3]; - myScan->after << "script" << tcl.list_commandwords[4]; + myScan = tcl_command_ARG(myScan, 4, true); myScan->after << "NULL" << tcl.list_commandwords[5]; myScan->after << "script" << tcl.list_commandwords[6]; myScan->after << "NULL" << tcl.list_commandwords[7]; @@ -1740,14 +1871,22 @@ static void tcl_command_FOREACH() { D unsigned int i; + tcl_scan *myScan=NULL; tcl_codify_cmd("keyword",0); for (i = 1;iafter << "script" << tcl.list_commandwords[tcl.list_commandwords.count()-1]; + } + else + { + myScan=tcl.scan.at(0); + myScan = tcl_scan_start('?',*tcl.list_commandwords.at(tcl.list_commandwords.count()-1), + myScan->ns,myScan->entry_cl,myScan->entry_fn); } - tcl_scan *myScan=tcl.scan.at(0); - myScan = tcl_scan_start('?',*tcl.list_commandwords.at(tcl.list_commandwords.count()-1), - myScan->ns,myScan->entry_cl,myScan->entry_fn); } ///! Handle internal tcl commands. @@ -1757,68 +1896,29 @@ static void tcl_command_WHILE() D tcl_codify_cmd("keyword",0); tcl_codify_cmd(NULL,1); - tcl_scan *myScan=tcl.scan.at(0); - myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2), + tcl_scan *myScan = NULL; + myScan = tcl_command_ARG(myScan, 2, true); + myScan = tcl_command_ARG(myScan, 3, false); + if (myScan!=0) + { + myScan->after << "script" << tcl.list_commandwords[4]; + } + else + { + myScan=tcl.scan.at(0); + myScan = tcl_scan_start('?',*tcl.list_commandwords.at(4), myScan->ns,myScan->entry_cl,myScan->entry_fn); - myScan->after << "NULL" << tcl.list_commandwords[3]; - myScan->after << "script" << tcl.list_commandwords[4]; + } } //! Handle all other commands. // Create links of first command word or first command word inside []. static void tcl_command_OTHER() { - if (tcl.code == NULL) return; -D - QCString myName; + tcl_scan *myScan=NULL; for (unsigned int i=0; i< tcl.list_commandwords.count(); i++) { - myName = (*tcl.list_commandwords.at(i)).utf8(); - if (i==0) - { - tcl_codify_link(myName); - } - else if (i%2 != 0) - { - tcl_codify(NULL,myName); - } - else - { - QCString myStr=""; - int myCmd=0; - unsigned int i; - for (i=0;i\n"); // check command QCString myStr = (*tcl.list_commandwords.at(0)).utf8(); + tcl_scan *myScanBackup=tcl.scan.at(0); int myLevel = 0; Protection myProt = tcl.protection; if (tcl.list_commandwords.count() < 3) { tcl_command_OTHER(); - goto command_text; + goto command_end; } // remove leading "::" and apply TCL_SUBST if (myStr.left(2)=="::") myStr = myStr.mid(2); @@ -2294,7 +2395,7 @@ tcl_inf("->\n"); goto command_end; } tcl_command_OTHER(); - goto command_text; + goto command_end; } if (myStr=="itcl::class") { @@ -2317,7 +2418,7 @@ tcl_inf("->\n"); goto command_end; } tcl_command_OTHER(); - goto command_text; + goto command_end; } if (myStr=="oo::define") { @@ -2331,7 +2432,7 @@ tcl_inf("->\n"); if (tcl.scan.at(0)->entry_fn == NULL) {// only parsed outside functions tcl_command_VARIABLE(tcl.scan.at(0)->entry_cl && tcl.scan.at(0)->entry_cl->name!=""); - goto command_text; + goto command_end; } } if (myStr=="common") @@ -2340,7 +2441,7 @@ tcl_inf("->\n"); if (tcl.scan.at(0)->entry_fn == NULL) {// only parsed outside functions tcl_command_VARIABLE(0); - goto command_text; + goto command_end; } } if (myStr=="inherit" || myStr=="superclass") @@ -2378,7 +2479,7 @@ if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN? if (myStr=="if" && tcl.list_commandwords.count() > 4) { QStringList myType; - myType << "keyword" << "NULL" << "script" << "NULL"; + myType << "keyword" << "NULL" << "expr" << "NULL"; char myState='x';// last word: e'x'pr 't'hen 'b'ody 'e'lse else'i'f.. for (unsigned int i = 4; i < tcl.list_commandwords.count(); i = i + 2) { @@ -2427,7 +2528,7 @@ if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN? else if (myState=='i') { myState='x'; - myType << "script" << "NULL"; + myType << "expr" << "NULL"; } } if (myState != 'b') {myLine=__LINE__;goto command_warn;} @@ -2441,15 +2542,22 @@ if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN? goto command_end; } tcl_command_OTHER(); - goto command_text; + goto command_end; command_warn:// print warning message because of wrong used syntax tcl_war("%d count=%d: %s\n",myLine,tcl.list_commandwords.count(),tcl.list_commandwords.join(" ").ascii()); tcl_command_OTHER(); - command_text:// print remaining text as comment - if (!myText.isEmpty()) tcl_codify("comment",myText); - myText = ""; command_end:// add remaining text to current context - if (!myText.isEmpty()) tcl.scan.at(0)->after << "comment" << myText; + if (!myText.isEmpty()) + { + if(myScanBackup==tcl.scan.at(0)) + { + tcl_codify("comment",myText); + } + else + { + tcl.scan.at(0)->after << "comment" << myText; + } + } tcl.list_commandwords.clear(); tcl.command = 0; tcl.protection = myProt; diff --git a/testing/058/058__bracket__recursion_8tcl.xml b/testing/058/058__bracket__recursion_8tcl.xml new file mode 100644 index 0000000..da0168d --- /dev/null +++ b/testing/058/058__bracket__recursion_8tcl.xml @@ -0,0 +1,354 @@ + + + + 058_bracket_recursion.tcl + + + + Invoked + args + Invoked + + should be reference by every proc below + + + + + + + a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t + + + + NotInvoked + args + NotInvoked + + must not be reference by every proc below + + + + + + + + + + a + args + a + + + + + + + + Invoked + + + + b + args + b + + + + + + + + Invoked + + + + c + args + c + + + + + + + + Invoked + + + + d + args + d + + + + + + + + Invoked + + + + e + args + e + + + + + + + + Invoked + + + + f + args + f + + + + + + + + Invoked + + + + g + args + g + + + + + + + + Invoked + + + + h + args + h + + + + + + + + Invoked + + + + i + args + i + + + + + + + + Invoked + + + + j + args + j + + + + + + + + Invoked + + + + k + args + k + + + + + + + + Invoked + + + + l + args + l + + + + + + + + Invoked + + + + m + args + m + + + + + + + + Invoked + + + + n + args + n + + + + + + + + Invoked + + + + o + args + o + + + + + + + + Invoked + + + + $NotInvoked + args + $NotInvoked + + + + + + + + + + + p + args + p + + + + + + + + Invoked + + + + q + args + q + + + + + + + + Invoked + + + + r + args + r + + + + + + + + Invoked + + + + s + args + s + + + + + + + + Invoked + + + + t + args + t + + + + + + + + Invoked + + + + + + + + + diff --git a/testing/058_bracket_recursion.tcl b/testing/058_bracket_recursion.tcl new file mode 100644 index 0000000..0a07087 --- /dev/null +++ b/testing/058_bracket_recursion.tcl @@ -0,0 +1,141 @@ +#// objective: tests processing of commands inside brackets [], only references/referencedby relations are relevant +#// check: 058__bracket__recursion_8tcl.xml +#// config: REFERENCED_BY_RELATION = yes +#// config: REFERENCES_RELATION = yes +#// config: EXTRACT_ALL = yes +#// config: INLINE_SOURCES = yes + +## +# \brief should be reference by every proc below +proc Invoked args { + puts "Procedure \"Invoked\" is invoked indeed. Ok." + return $args +} +## +# \brief must not be reference by every proc below +proc NotInvoked args { + puts "Procedure \"NotInvoked\" is invoked. Not Ok!" + return $args +} +# +# check if call references work at all +proc a args { + Invoked NotInvoked + return +} +# +# check brackets with various quoting, bracing +proc b args { + set r [Invoked] + set r [list \[NotInvoked \]] + return +} +proc c args { + set r \{[Invoked]\} + set r {[NotInvoked]} + return +} +proc d args { + set r "[Invoked]" + set r "\[NotInvoked \]" + return +} +proc e args { + set r [list \[NotInvoked [Invoked]\]] + return +} +proc f args { + set r [list [Invoked \[NotInvoked \]]] + return +} +proc g args { + set r "{[Invoked]}" + set r "{\[NotInvoked \]}" + return +} +proc h args { + [Invoked set] r {[NotInvoked]} + return +} +# check brackets in tcl commands containing script arguments +# +# example generated according to +# https://groups.google.com/d/msg/comp.lang.tcl/G5-mc3GiIyY/e-AVD9t7xMkJ +proc i args { + foreach item [Invoked] { + return + } +} +proc j args { + foreach [Invoked item] [list one two three] { + } + return +} +proc k args { + while {[Invoked 0]} { + } +} +proc l args { + for {} {[Invoked 0]} {} { + } +} +proc m args { + if {[Invoked 1]} { + } +} +proc n args { + if [Invoked 1] { + } +} +proc o args { + if {0} { + } elseif {[Invoked 0]} { + } +} +# these are really nasty examples +# they shows, that the condition argument may not be parsed as a script +set NotInvoked \$NotInvoked +proc $NotInvoked args { + puts "Procedure \"\$NotInvoked\" is invoked. Not Ok!" + return $args +} +proc p args { + set NotInvoked \$NotInvoked + if {$NotInvoked eq [Invoked 1]} { + } + return +} +proc q args { + set NotInvoked \$NotInvoked + if {0} { + } elseif {$NotInvoked eq [Invoked 1]} { + } + return +} +proc r args { + set NotInvoked \$NotInvoked + while {$NotInvoked eq [Invoked 1]} { + } + return +} +proc s args { + set NotInvoked \$NotInvoked + for {} {$NotInvoked eq [Invoked 1]} {} { + } + return +} +# dangling open brackets should not confuse the scanner +proc t args { + set foo ]]]][Invoked] + return +} + +# +# call all single letter procs +# let tcl check what is called and what is not called +foreach p [info procs ?] { + puts "Check procedure \"$p\"" + $p +} +exit + -- cgit v0.12