Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How do you convert a TCL list into a string that PHP can read?

23 views
Skip to first unread message

comp.lang.tcl

unread,
Apr 20, 2006, 8:25:46 PM4/20/06
to
I have a TCL proc that needs to convert what might be a list into a
string to read

consider this:

[set string [PROPER_CASE {hello world}]]; # OUTPUTS Hello World which
is fine for PHP

[set string [PROPER_CASE {-hello world}]]; # OUTPUT {{-Hello}}
World, which PHP will print literally as {{-Hello}} World, instead of
-Hello World

Is there an easy way for TCL to brute-force a list into a
strictly-string-only format to prevent this potentially ugly display
from being displayed by PHP/etc.?

Thanx
Phil

Robert Heller

unread,
Apr 20, 2006, 8:50:09 PM4/20/06
to
"comp.lang.tcl" <phillip....@gmail.com>,

In a message on 20 Apr 2006 17:25:46 -0700, wrote :

"> I have a TCL proc that needs to convert what might be a list into a
"> string to read
">
"> consider this:
">
"> [set string [PROPER_CASE {hello world}]]; # OUTPUTS Hello World which
"> is fine for PHP
">
"> [set string [PROPER_CASE {&#045;hello world}]]; # OUTPUT {{-Hello}}
"> World, which PHP will print literally as {{-Hello}} World, instead of
"> -Hello World

What is 'PROPER_CASE'?

">
"> Is there an easy way for TCL to brute-force a list into a
"> strictly-string-only format to prevent this potentially ugly display
"> from being displayed by PHP/etc.?
">
"> Thanx
"> Phil
">
">

Robert Heller -- 978-544-6933
Deepwoods Software -- Linux Installation and Administration
http://www.deepsoft.com/ -- Web Hosting, with CGI and Database
hel...@deepsoft.com -- Contract Programming: C/C++, Tcl/Tk



MH

unread,
Apr 20, 2006, 9:03:09 PM4/20/06
to
In article <1145579146.2...@e56g2000cwe.googlegroups.com>,

Not sure what "PROPER_CASE" does..

However, I think you want to look at the "join" command (you may need to call
it multiple times).

% set s "{{-Hello}} World"
{{-Hello}} World
% join $s
{-Hello} World
% join [join $s]
-Hello World

MH

Bryan Oakley

unread,
Apr 20, 2006, 9:12:32 PM4/20/06
to

To convert a list to a string with a space between each list element:

join $someList " "

So maybe you want:

[set string [join [PROPER_CASE ...] " "]


--
Bryan Oakley
http://www.tclscripting.com

sleb...@gmail.com

unread,
Apr 20, 2006, 10:46:04 PM4/20/06
to

The other replies here are right you may want to use join to "flatten"
your list. But I also think your [PROPER_CASE] proc is written wrongly
in that you intend it to return a string but instead it returns a list,
worse still a double nested list:

{
{
{
-Hello
}
}
World
}

which requires you to do [join] twice to flatten it out. I'd strongly
recommend that you look at the PROPER_CASE proc and correct the bug
there if it is under your control.

Of course, [join] only flattens a list by 1 level and since your list
is double nested you need to call [join] twice. But if you're not sure
how many levels deep your list is nested here's a small proc to
recursively flatten an arbitrarily nested list:

proc flatten {ls} {
set ret ""
foreach x $ls {
if {$x == "\{" || $x == "\}"} {
# handle braces:
lappend ret $x
} elseif {[llength $x] > 1} {
# recursively flatten sublist:
set ret [concat $ret [flatten $x]]
} else {
lappend ret $x
}
}
return $ret
}

So you can use it like:

set string [flatten [PROPER_CASE {&#045;hello world}]]

comp.lang.tcl

unread,
Apr 21, 2006, 10:01:12 AM4/21/06
to

sleb...@yahoo.com wrote:
> comp.lang.tcl wrote:
> > I have a TCL proc that needs to convert what might be a list into a
> > string to read
> >
> > consider this:
> >
> > [set string [PROPER_CASE {hello world}]]; # OUTPUTS Hello World which
> > is fine for PHP
> >
> > [set string [PROPER_CASE {-hello world}]]; # OUTPUT {{-Hello}}
> set string [flatten [PROPER_CASE {-hello world}]]


Thanx for the proc, however, tclsh locks up tight, bringing down PHP
and Apache and all web services in the process, if you try this:

set string [flatten [PROPER_CASE {{-hello} {world}}]]

If you have a string with curly braces and a dash, it blows up. Take
one or the other away, all is well.

Phil

Bryan Oakley

unread,
Apr 21, 2006, 11:16:52 AM4/21/06
to
comp.lang.tcl wrote:
> Thanx for the proc, however, tclsh locks up tight, bringing down PHP
> and Apache and all web services in the process, if you try this:
>
> set string [flatten [PROPER_CASE {{-hello} {world}}]]
>
> If you have a string with curly braces and a dash, it blows up. Take
> one or the other away, all is well.

"it blows up" does nothing to help us figure out the problem. Do you get
any sort of tcl error you can show us, either on the web page or in a
log? It really sounds like your problem is that PROPER_CASE is buggy,
and/or it is improperly documented.

Would it be possible for you to show us the result of the following command?

[list PROPER_CASE [info args PROPER_CASE] [info body PROPER_CASE]]

comp.lang.tcl

unread,
Apr 21, 2006, 11:52:11 AM4/21/06
to

Bryan Oakley wrote:
> comp.lang.tcl wrote:
> > Thanx for the proc, however, tclsh locks up tight, bringing down PHP
> > and Apache and all web services in the process, if you try this:
> >
> > set string [flatten [PROPER_CASE {{-hello} {world}}]]
> >
> > If you have a string with curly braces and a dash, it blows up. Take
> > one or the other away, all is well.
>
> "it blows up" does nothing to help us figure out the problem.

Sorry, there is no further description I can give you. tclsh locks,
produces 100% CPU usage when you view via top, no error logs of any
kind.

Here is PROPER_CASE:

[TCL]
#######################################################################################
#

# Proc PROPER_CASE - this proc will convert string text into "marquee"
style
# by displaying its "proper case" (or in this case: "Proper Case").
The
# first letter of each word is capitalized except for small words
(yet,
# small words are capitalized if they are the first word in the text).

# Special capitalization consideration is taken for common ethnic
words,
# hyphenated words, and words adjoined by underscores. Also
consideration is
# taken for words surrounded by non-alphabetic characters (updated
7/10/2000)
#

# UPDATE 11/21/00: Exemptions within the phrase are now accepted
within
# PROPER_CASE to allow for words within phrases to not be capitalized.

#

# SYNTAX: set myPhrase [PROPER_CASE $myPhrase] {for all words}

# set myPhrase [PROPER_CASE -exempt [list of exempted words]
-- $myPhrase]
#
# IMPORTANT: If you include a list of words to be exempted you MUST
include the
# following:
#
# -exempt : This flag indicates an exemption list is to
follow
# -- : End of exemption list
#
# Without including "-exempt" before your exemption list
there will be no
# words to exempt; without including "--" it cannot deduce
the end of the
# exemption list and this proc will return an empty string.
#

# Written by Phil Powell. All rights reserved. on 2/14/00, updated
7/10/00, 11/21/00
#
######################################################################################
proc PROPER_CASE {args} {
set lb [format %c 91]; set rb [format %c 93]; set bslash [format %c
92]
lappend statesList AL AK AR AZ CA CO CT DE DC FL GA HI ID IL IN IA KS
KY LA ME MD MA
lappend statesList MI MN MS MO MT NE NV NH NJ NM NY NC ND OH OK OR PA
RI SC SD TN TX
lappend statesList UT VT VA WA WV WI WY PR GU VI
lappend directionsList NE NW SE SW N.E. S.E. S.W. N.W.
set exemptFlag {}; set exemptHash {}; set phrase {}
if {[regexp -nocase -- "-exempt" [lindex $args 0]]} {
set exemptFlag [lindex $args 0]
set i 1
if {[lsearch -exact $args "--"] < 0} {set exemptFlag {}}
if {[string length $exemptFlag] > 0} {
while {![regexp -- "--" [lindex $args $i]]} {
lappend exemptList "[lindex $args $i]"
incr i
}
set exemptHash [lindex $args $i]
set phrase [lindex $args [expr {$i + 1}]]
}
} else {
set phrase [lindex $args 0]
}
regsub -all {"} $phrase "%1%" phrase
regsub -all "$bslash[set lb](.*)$bslash$rb" $phrase "%2%[set
bslash]1%2%" phrase
lappend smallWords a an in of
lappend exemptionVars statesList directionsList
if {[string length $exemptFlag] > 0 && [string length $exemptHash] > 0
&& [info exists exemptList]} {
lappend exemptionVars exemptList
}
for {set i 0} {$i < [llength $phrase]} {incr i} {
set word [lindex $phrase $i]
set isExempted 0
foreach smallWord $smallWords {
if {$smallWord == $word && $i > 0} { set isExempted 1 }
}
if {$word == [string toupper $word] && !$isExempted} {set isExempted
1}
if {!$isExempted} {
foreach exemptionVar $exemptionVars {
if {[lsearch -exact [set $exemptionVar] "$word"] >=0} {set
isExempted 1}
}
}

if {!$isExempted} {

foreach char "- _" {

set foundChar 0
if {[regexp -- "$char" $word]} {
set word [split $word "$char"]
set foundChar 1
}

for {set j 0} {$j < [llength $word]} {incr j} {
set wordlet [lindex $word $j]
set beginIndx 0; set nonWord {}
while {![regexp -nocase {[a-z]} [string index $wordlet $beginIndx]]}
{
append nonWord [string index $wordlet $beginIndx]
incr beginIndx
}
### Check to see if word is "Scots/Irish" but > 2 chars
set tinyWord 0; set letter {}
if {[expr [string length $wordlet] - [string length $nonWord]] <
3} {
### Avoid setting of string range > 1 if word < 2 chars
set tinyWord 1
set endIndx [expr [string length $wordlet] - 1]
} else {
set endIndx [expr [string length $nonWord] + 1]
}
set snippet [string tolower [string range $wordlet $beginIndx
$endIndx]]
if {!$tinyWord} {
set letter [string index $wordlet [expr 2 + [string length
$nonWord]]]
if {($snippet == "mc" || $snippet == "o'")} {
set letter [string toupper $letter]
}
}

set tempsnippet "$nonWord[string toupper [string index $snippet
0]]"
if {$endIndx > 0} {
append tempsnippet [string index $snippet 1]
}
set snippet $tempsnippet

set tempwordlet $snippet$letter
if {!$tinyWord} {
append tempwordlet [string range $wordlet [expr 3 + [string
length $nonWord]] end]
}
set wordlet $tempwordlet

set word [lreplace $word $j $j $wordlet]
}; # end of "j" for loop

if {$foundChar} {
set word [join $word "$char"]
}
}; # End of foreach

set phrase [lreplace $phrase $i $i $word]
}; # end of "if {!$isExempted}"

}; # end of outer for loop
regsub -all "%1%" $phrase {"} phrase
regsub -all "%2%(.*)%2%" $phrase "$lb[set bslash]1$rb" phrase
return $phrase
}
[/TCL]

Bryan Oakley

unread,
Apr 21, 2006, 12:42:22 PM4/21/06
to
comp.lang.tcl wrote:
> Sorry, there is no further description I can give you. tclsh locks,
> produces 100% CPU usage when you view via top, no error logs of any
> kind.
>
> Here is PROPER_CASE:
> <snip>

Holy cow! All that just to change the case of words in a string?

The proc is a bit buggy at first glance. It's amazing it works at all.
It takes a string, does some string operations on it, then iterates over
it as if it were a list and performs list operations on it. Then, it
takes the list, performs string operations on it and returns a string.

Indeed, testing it out by copying it into a tclsh session, it _is_
buggy. If the first char is "-" it gets in an infinite loop.

Maybe you should file a bug with whomever wrote PROPER_CASE instead of
trying to work around its limitations.

Gerald W. Lester

unread,
Apr 21, 2006, 12:48:29 PM4/21/06
to

It does a *little* more than [string totitle $string] -- it ignores two
letter state "names" -- but not much.

My guess is this is a "translation" of a procedure from another language by
someone who does not have a good knowledge of Tcl.

--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+

comp.lang.tcl

unread,
Apr 21, 2006, 1:03:55 PM4/21/06
to

Gerald W. Lester wrote:
> Bryan Oakley wrote:
> > comp.lang.tcl wrote:
> >> Sorry, there is no further description I can give you. tclsh locks,
> >> produces 100% CPU usage when you view via top, no error logs of any
> >> kind.
> >>
> >> Here is PROPER_CASE:
> >> <snip>
> >
> > Holy cow! All that just to change the case of words in a string?
> >
> > The proc is a bit buggy at first glance. It's amazing it works at all.
> > It takes a string, does some string operations on it, then iterates over
> > it as if it were a list and performs list operations on it. Then, it
> > takes the list, performs string operations on it and returns a string.
> >
> > Indeed, testing it out by copying it into a tclsh session, it _is_
> > buggy. If the first char is "-" it gets in an infinite loop.
> >
> > Maybe you should file a bug with whomever wrote PROPER_CASE instead of
> > trying to work around its limitations.
> >
>
> It does a *little* more than [string totitle $string] -- it ignores two
> letter state "names" -- but not much.
>

Last I checked [string totitle] doesn't capitalize hyphenated names,
Scots/Irish/Dutch names, etc. I wrote it back in 2000, when I only had
about a year's knowledge of TCL at the time, I'm sure it needs a bit of
fine-tuning, but it does the job it's supposed to do.

Phil

Bryan Oakley

unread,
Apr 21, 2006, 1:04:55 PM4/21/06
to
Bryan Oakley wrote:

> Maybe you should file a bug with whomever wrote PROPER_CASE instead of
> trying to work around its limitations.
>

FWIW, the culprit is this infinite loop:

while {![regexp -nocase {[a-z]} [string index $wordlet $beginIndx]]} {
append nonWord [string index $wordlet $beginIndx]
incr beginIndx
}

Under the right conditions (such as a word beginning or ending with "-"
or "_"), $wordlet will be null. When wordlet is null, [string index
$wordlet $beginIndx] will be null for all values of $beginIndx, the
regexp will never match, and the loop will never terminate.

Bryan Oakley

unread,
Apr 21, 2006, 1:22:17 PM4/21/06
to
comp.lang.tcl wrote:

> Last I checked [string totitle] doesn't capitalize hyphenated names,
> Scots/Irish/Dutch names, etc. I wrote it back in 2000, when I only had
> about a year's knowledge of TCL at the time, I'm sure it needs a bit of
> fine-tuning, but it does the job it's supposed to do.
>
> Phil

It's pretty fragile though. As I pointed out in another message in this
thread, it can get into an infinite loop if a word begins or ends with
"-" or "_". It also will yield unexpected results for other types of
input as well. So, it really only works for a small set of well behaved
inputs.

We can help you with those problems if you like.

Not sure what to do about the OP, other than to suggest perhaps writing
their own PROPER_CASE proc or help to debug this one. There appears to
be no good way to solve his/her problem other than to fix PROPER_CASE.

comp.lang.tcl

unread,
Apr 21, 2006, 1:45:26 PM4/21/06
to

Bryan Oakley wrote:
> Bryan Oakley wrote:
>
> > Maybe you should file a bug with whomever wrote PROPER_CASE instead of
> > trying to work around its limitations.
> >
>
> FWIW, the culprit is this infinite loop:
>
> while {![regexp -nocase {[a-z]} [string index $wordlet $beginIndx]]} {
> append nonWord [string index $wordlet $beginIndx]
> incr beginIndx
> }

WOW! I would never have found that one, you are truly one of the TCL
gurus out there (you came highly recommended by those I know)

this seemed to have fixed the problem (probably overkill but it was the
best I could think up at the moment:

while {[info exists wordlet] && [string length $wordlet] > 0 &&


![regexp -nocase {[a-z]} [string index $wordlet $beginIndx]]} {
append nonWord [string index $wordlet $beginIndx]
incr beginIndx
}

Phil

Bryan Oakley

unread,
Apr 21, 2006, 1:57:29 PM4/21/06
to
comp.lang.tcl wrote:
>
> WOW! I would never have found that one, you are truly one of the TCL
> gurus out there (you came highly recommended by those I know)

Thanks for the compliment but finding it took two minutes. I simply put
a print statement at the top of every loop, then tried a couple of very
obvious tests.

> this seemed to have fixed the problem (probably overkill but it was the
> best I could think up at the moment:
>
> while {[info exists wordlet] && [string length $wordlet] > 0 &&
> ![regexp -nocase {[a-z]} [string index $wordlet $beginIndx]]} {
> append nonWord [string index $wordlet $beginIndx]
> incr beginIndx
> }

Yeah, that definitely helps that particular problem but it doesn't fix
all problems in the code.

Since you seem new to programming, you might want to look at tcltest.
Once you are up to speed on it (which doesn't take long), it would take
about 5-10 minutes to craft a couple dozen tests to validate the proc
against a whole range of inputs. That would have uncovered many bugs.

http://mini.net/tcl/tcltest

sleb...@gmail.com

unread,
Apr 21, 2006, 3:15:26 PM4/21/06
to
comp.lang.tcl wrote:
> Gerald W. Lester wrote:
> > Bryan Oakley wrote:
> > > comp.lang.tcl wrote:
> > >> Sorry, there is no further description I can give you. tclsh locks,
> > >> produces 100% CPU usage when you view via top, no error logs of any
> > >> kind.
> > >>
> > >> Here is PROPER_CASE:
> > >> <snip>
> > >
> > > Holy cow! All that just to change the case of words in a string?
> > >
> > > The proc is a bit buggy at first glance. It's amazing it works at all.
> > > It takes a string, does some string operations on it, then iterates over
> > > it as if it were a list and performs list operations on it. Then, it
> > > takes the list, performs string operations on it and returns a string.
> > >
> > > Indeed, testing it out by copying it into a tclsh session, it _is_
> > > buggy. If the first char is "-" it gets in an infinite loop.
> > >
> > > Maybe you should file a bug with whomever wrote PROPER_CASE instead of
> > > trying to work around its limitations.
> > >
> >
> > It does a *little* more than [string totitle $string] -- it ignores two
> > letter state "names" -- but not much.
> >
>
> Last I checked [string totitle] doesn't capitalize hyphenated names,
> Scots/Irish/Dutch names, etc. I wrote it back in 2000, when I only had
> about a year's knowledge of TCL at the time, I'm sure it needs a bit of
> fine-tuning, but it does the job it's supposed to do.

You should factor out some of the code in there. Not because it is
faster, or to make the code re-usable or even to save memory but simply
to make it easier to understand. Here's a work-alike version I whipped
up in about 2 minutes:

######
# Reformats a string to have proper case
######
proc properCase {str} {
set ret ""
foreach x [split $str " \t\n\r"] {
append ret "[caseFormat [string trim $x]]"
append ret " "
}
return $ret
}

########
# Applies case formatting rule to a word
########
proc caseFormat {word} {
if {[set ret [irishScotFormat $word]] != ""} {
return $ret
}
if {[set ret [smallWordFormat $word]] != ""} {
return $ret
}
if {[set ret [statesFormat $word]] != ""} {
return $ret
}
return [string totitle $word [firstAlpha $word] end]
}

# Returns first alpha char in a word
proc firstAlpha {word} {
for {set i 0} {$i < [string length $word]} {incr i} {
if {[string is alpha [string index $word $i]]} {
return $i
}
}
return end
}

################ Formatting rules:

proc smallWordFormat {word} {
if {[lsearch -exact {
a an in of and at is
} $word] != -1} {
return $word
}
return ""
}

proc irishScotFormat {word} {
return ""
}

proc statesFormat {word} {
set word [string toupper $word]
if {[lsearch -exact {


AL AK AR AZ CA CO CT DE DC FL GA
HI ID IL IN IA KS KY LA ME MD MA

MI MN MS MO MT NE NV NH NJ NM NY
NC ND OH OK OR PA RI SC SD TN TX

UT VT VA WA WV WI WY PR GU VI NE


NW SE SW N.E. S.E. S.W. N.W.

} $word] != -1} {
return $word
}
return ""
}


I haven't implemented the irishScotFormat proc partly because I'm not
sure what you want and partly because I'm too lazy to do it. Notice
that the bulk of the processing happens in caseFormat which only have
to handle a single word at a time. This simplifies the properCase proc
to simply parse the string a word at a time without having to worry
about the processing. It's also very easy to add in more formatting
checks in the caseFormat proc.

Hope this helps you a little, I just had to re-implement it, the
[PROPER_CASE] proc was too ugly for me to resist.

sleb...@gmail.com

unread,
Apr 21, 2006, 3:22:29 PM4/21/06
to
sleb...@yahoo.com wrote:
> comp.lang.tcl wrote:
> > Gerald W. Lester wrote:
> > > Bryan Oakley wrote:
> > > > comp.lang.tcl wrote:
> > > >> Sorry, there is no further description I can give you. tclsh locks,
> > > >> produces 100% CPU usage when you view via top, no error logs of any
> > > >> kind.
> > > >>
> > > >> Here is PROPER_CASE:
> > > >> <snip>
> > > >
> > >
> > > It does a *little* more than [string totitle $string] -- it ignores two
> > > letter state "names" -- but not much.
> > >
> >
> > Last I checked [string totitle] doesn't capitalize hyphenated names,
> > Scots/Irish/Dutch names, etc.

Oops, forgot about another thing the original code did. Add this rule
to the code I previously submitted:

proc uppercaseFormat {word} {
if {[string toupper $word] == $word} {return $word}
return ""
}

comp.lang.tcl

unread,
Apr 21, 2006, 5:56:23 PM4/21/06
to

Bryan Oakley wrote:
> comp.lang.tcl wrote:
> >
> > WOW! I would never have found that one, you are truly one of the TCL
> > gurus out there (you came highly recommended by those I know)
>
> Thanks for the compliment but finding it took two minutes. I simply put
> a print statement at the top of every loop, then tried a couple of very
> obvious tests.
>

Right, I do the same with PHP, using print_r() everywhere I go, but I
don't know how to do that with TCL especially in the environment I have
here at work (RHEL4)

> > this seemed to have fixed the problem (probably overkill but it was the
> > best I could think up at the moment:
> >
> > while {[info exists wordlet] && [string length $wordlet] > 0 &&
> > ![regexp -nocase {[a-z]} [string index $wordlet $beginIndx]]} {
> > append nonWord [string index $wordlet $beginIndx]
> > incr beginIndx
> > }
>
> Yeah, that definitely helps that particular problem but it doesn't fix
> all problems in the code.
>
> Since you seem new to programming,

Sorry, I'm not new, I've been at it since 1996. Web programming that
is. Done TCL since 1999. I just don't have the means of testing my
TCL procs apart from using Wish on my very slow home PC (I use Linux at
work, haven't yet found an environment I can use to test TCL procs at
work and don't have root access to my machine even if I were to find
something).

Bryan Oakley

unread,
Apr 21, 2006, 6:10:20 PM4/21/06
to
comp.lang.tcl wrote:
> Sorry, I'm not new, I've been at it since 1996. Web programming that
> is. Done TCL since 1999. I just don't have the means of testing my
> TCL procs apart from using Wish on my very slow home PC (I use Linux at
> work, haven't yet found an environment I can use to test TCL procs at
> work and don't have root access to my machine even if I were to find
> something).

That's an odd statement. If you have the ability to edit and run them,
you can test them. tcltest is 100% pure tcl. In fact, if you can run
them via your web server, you can run tests *in* your webserver. Just
drop the tcltest source code wherever you can access it (read: in the
same file or directory where PROPER_CASE is defined) and off you go. Of
course, you can also test them via tclsh if you have that available.

As for testing them at home, I bet even the slowest PC you can find that
is still running is sufficient to run tcltest for a modest number of tests.

I don't mean to be telling you how to work. It's just that these errors
were so trivial to reproduce that it seemed like a beginners mistake. No
offense. I just didn't think you were aware of some of the options
available to you.

MH

unread,
Apr 21, 2006, 6:36:12 PM4/21/06
to
In article <1145656583.5...@u72g2000cwu.googlegroups.com>,

comp.lang.tcl <phillip....@gmail.com> wrote:
>
>Bryan Oakley wrote:
>> comp.lang.tcl wrote:
>> >
>> > WOW! I would never have found that one, you are truly one of the TCL
>> > gurus out there (you came highly recommended by those I know)
>>
>> Thanks for the compliment but finding it took two minutes. I simply put
>> a print statement at the top of every loop, then tried a couple of very
>> obvious tests.
>>
>
>Right, I do the same with PHP, using print_r() everywhere I go, but I
>don't know how to do that with TCL especially in the environment I have
>here at work (RHEL4)

Hmm.. Shouldn't "tclsh" be standard in that environment?

[cut]

>Sorry, I'm not new, I've been at it since 1996. Web programming that
>is. Done TCL since 1999. I just don't have the means of testing my
>TCL procs apart from using Wish on my very slow home PC (I use Linux at
>work, haven't yet found an environment I can use to test TCL procs at
>work and don't have root access to my machine even if I were to find
>something).

I downloaded and compiled tcl on my work machine (even though we use Tcl
extensively and already have several copies of tclsh installed) and intalled
it on my user account. Took all of 30 seconds of configuration to tell it to
install to my home directory, instead of the system directory..

./configure --prefix=/home/mydir/apps
make
make install

MH

comp.lang.tcl

unread,
Apr 21, 2006, 7:10:13 PM4/21/06
to

I have tclsh already on my machine here at work (Linux) so I don't have
to install it.

I read the man pages for tcltest but it's beyond me, sorry. I don't
know how to download it, where to find it (yes did a Google search,
didn't help whatsoever for me), what to do, etc.

I need a "3rd grade" step-by-step instruction to what to do.

Phil

MH

unread,
Apr 21, 2006, 7:47:52 PM4/21/06
to
In article <1145661013.5...@g10g2000cwb.googlegroups.com>,

Sorry 'bout that. You said you didn't have the environment to test your TCL
procs, so I read that you mean you didn't have tclsh..

I've never used tcltest, so I'm no help there..

MH

Cameron Laird

unread,
Apr 21, 2006, 9:08:04 PM4/21/06
to
In article <gLc2g.18464$tN3....@newssvr27.news.prodigy.net>,
.
.
.
Phil, I strongly advise you to start by going over every word
Bryan has written here. It's not just that he's right, or
that he's a senior sort of Tcl person, although both of those
are true. The point is that what he writes here will make all
the difference in your future with Tcl. If you acquire a few
straightforward techniques, it will be like staying up on a
bicycle--you'll soon be traveling smoothly all the way to the
horizon. The alternative, frankly, is that you're going to be
stuck with your feet on the ground, pushing the bicycle (Tcl)
around, instead of having it carry *you*.

With your home PC, you should have a Tcl interpreter that you
can launch and with which you can usefully interact in under
ten seconds; I have a 100 MHz Pentium beside me that's so
equipped (actually better). We'll help you get there, right
away. If you continue to believe that Tcl procs are as dif-
ficult as they appear from your descriptions, though, there's
no way we can prevent you from *years* of misery trying to
wrestle such an awful language into submission.

Let us help you install (or locate) an appropriate interpreter
on your chosen hosts, and soon you can be launching your own
sessions and studying such dialogues as
% set mystring aabbbbcc
aabbbbcc
% string x
bad option "x": must be bytelength, compare, equal, first, index, is,
last, length, map, match, range, repeat, replace, tolower, toupper,
totitle, trim, trimleft, trimright, wordend, or wordstart
% string toupper $mystring
AABBBBCC
% split $mystring
aabbbbcc
% split $mystring {}
a a b b b b c c
% string trimright
wrong # args: should be "string trimright string ?chars?"
% string trimright $mystring c
aabbbb
Does that interest you?

While PHP has much to recommend it, I've removed comp.lang.php
from follow-ups. Please be assured that PHP and Tcl can play
together quite nicely; there's really nothing more to say in
this thread that's specific to the former.

Donal K. Fellows

unread,
Apr 22, 2006, 12:35:07 PM4/22/06
to
comp.lang.tcl wrote:
> I read the man pages for tcltest but it's beyond me, sorry. I don't
> know how to download it, where to find it (yes did a Google search,
> didn't help whatsoever for me), what to do, etc.
>
> I need a "3rd grade" step-by-step instruction to what to do.

Well, although tcltest has lots (and lots) of features, you can get
going pretty simply. Here's an example:

# Set things up
package require tcltest 2
namespace import tcltest::*

# You probably want to [source] the procedures to test here...

# Run some tests
test example-1.1 {an example test of expr} -body {
expr 1+2
} -result 3
test example-1.2 {another example test of expr} -body {
expr 1+2+3
} -result 6

# Good practice splits up tests by "functional area"
test example-2.1 {a test of incr} -body {
set x 0
list $x [incr x] [incr x] [incr x] $x
} -result {0 1 2 3 3}
# And so on...

# Now print out the test report
cleanupTests
return

That's it. Now I just put that code in a file and run the tests using
tclsh, like this, to get a short report:

$ tclsh example.test
example.test: Total 3 Passed 3 Skipped 0 Failed 0

Now, it's going to be hard to get much easier than that, isn't it? :-)

Donal.

Cameron Laird

unread,
Apr 22, 2006, 3:08:04 PM4/22/06
to
In article <%Ws2g.4372$xt....@fe3.news.blueyonder.co.uk>,

Donal K. Fellows <donal.k...@manchester.ac.uk> wrote:
>comp.lang.tcl wrote:
>> I read the man pages for tcltest but it's beyond me, sorry. I don't
>> know how to download it, where to find it (yes did a Google search,
>> didn't help whatsoever for me), what to do, etc.
>>
>> I need a "3rd grade" step-by-step instruction to what to do.
>
>Well, although tcltest has lots (and lots) of features, you can get
>going pretty simply. Here's an example:
>
> # Set things up
> package require tcltest 2
.
.
.

> $ tclsh example.test
> example.test: Total 3 Passed 3 Skipped 0 Failed 0
>
>Now, it's going to be hard to get much easier than that, isn't it? :-)
>
>Donal.

Donal, my guess is that the very first command,
package require tcltest ...
might be a stumbling block. If that's true, Phil, please
let us know in what environment you're working at the time,
and what version of Tcl you have.

Gerald W. Lester

unread,
Apr 22, 2006, 5:27:53 PM4/22/06
to
comp.lang.tcl wrote:
> ... I just don't have the means of testing my

> TCL procs apart from using Wish on my very slow home PC (I use Linux at
> work, haven't yet found an environment I can use to test TCL procs at
> work and don't have root access to my machine even if I were to find
> something).

Go to: http://www.equi4.com/pub/tk/downloads.html

And download the appropriate TclKit. It does not need to be installed, it
will run as a user program.

BTW, Tcl (like most Linux/Unix programs) does not need to be installed by an
administrator -- you can compile and "install" it under your home directory
and just add to your PATH the directory where tclsh and wish are.

It is also rather surprising that the Linux at work does not already have
Tcl on it, I thought almost all distros came with Tcl/Tk.

comp.lang.tcl

unread,
Apr 24, 2006, 10:27:26 AM4/24/06
to

Sure. It'd be easier to explain the concept of 2 + 2 to me from an
auto-solipsist standpoint.

Dude, that was utter UTTER Hungarian! :(

I understood NONE of what you just did. Absolutely NOTHING.

This might be a great time to mention that I learned TCL via..
VIGNETTE. http://www.vignette.com. Does that help?

Phil

>
> Donal.

Bryan Oakley

unread,
Apr 24, 2006, 10:28:18 AM4/24/06
to
comp.lang.tcl wrote:
> I have tclsh already on my machine here at work (Linux) so I don't have
> to install it.
>
> I read the man pages for tcltest but it's beyond me, sorry. I don't
> know how to download it, where to find it (yes did a Google search,
> didn't help whatsoever for me), what to do, etc.
>
> I need a "3rd grade" step-by-step instruction to what to do.

Does this help?

http://www.tclscripting.com/articles/apr06/article1.html
http://www.tclscripting.com/articles/apr06/article2.html

Bryan Oakley

unread,
Apr 24, 2006, 10:53:06 AM4/24/06
to
comp.lang.tcl wrote:

> Dude, that was utter UTTER Hungarian! :(
>
> I understood NONE of what you just did. Absolutely NOTHING.
>
> This might be a great time to mention that I learned TCL via..
> VIGNETTE. http://www.vignette.com. Does that help?

I suspected as much. I used to work at Vignette and I know first hand
that they did an absolutely terrible job teaching Tcl. Because of their
rather questionable design choices they magnified quoting problems
ten-fold and encouraged bad habits. Pity, because tcl is just absolutely
perfect for scripting web pages; much better than any other language IMHO.

The simple answer, Phil, is that tcltest is just a file you can "source"
like any other file. It may already exist as a package in which case you
can do "package require tcltest" instead of "source". Once you've done
either of those, you have at your disposal a new tcl command named
"test" (or "tcltest::test") that you can use to build up suites of
automated tests. You actually get a lot more than just the test command,
but that's beside the point.

So, much like you can create a web page with something like this (I'm
guessing; I don't know exactly how you embed tcl in your php scripts):

<html>
<some tag to embed tcl>
PROPER_CASE "Hello, world"
</some tag>

... you can create test scripts with something that may look like this :

<html>
<some tag to embed tcl>
source tcltest.tcl ;# or "package require tcltest 2"
source yourCodeToBeTested.tcl
test example-1 {a simple test} -body ... -result ...
test example-2 {another test} -body ... -result ...
cleanupTests
</some tag>

Visit the web page, et voila!, you've just written and run a regression
test. Now, I can't guarantee it is truly that easy for you because I
don't know what environment you are using. Generally speaking though, if
you are able to source your own tcl files you can source tcltest.tcl and
write regression tests with the "test" command.

My suggestion: where you have one file now that defines the proc
PROPER_CASE, create two files. Assuming the first file is named
"library.tcl", name the second file "library.test". Put your test
scripts in the second file, then source "library.test" (or do "tclsh
library.test") whenever you want to run the tests.

I hope this helps.

comp.lang.tcl

unread,
Apr 24, 2006, 12:09:37 PM4/24/06
to

Bryan Oakley wrote:
> comp.lang.tcl wrote:
>
> > Dude, that was utter UTTER Hungarian! :(
> >
> > I understood NONE of what you just did. Absolutely NOTHING.
> >
> > This might be a great time to mention that I learned TCL via..
> > VIGNETTE. http://www.vignette.com. Does that help?
>
> I suspected as much. I used to work at Vignette and I know first hand
> that they did an absolutely terrible job teaching Tcl. Because of their
> rather questionable design choices they magnified quoting problems
> ten-fold and encouraged bad habits. Pity, because tcl is just absolutely
> perfect for scripting web pages; much better than any other language IMHO.
>

The abject irony is that Vignette no longer uses TCL in newer versions
of its content management platform; it's all J2EE now.

> The simple answer, Phil, is that tcltest is just a file you can "source"
> like any other file. It may already exist as a package in which case you
> can do "package require tcltest" instead of "source". Once you've done
> either of those, you have at your disposal a new tcl command named
> "test" (or "tcltest::test") that you can use to build up suites of
> automated tests. You actually get a lot more than just the test command,
> but that's beside the point.
>
> So, much like you can create a web page with something like this (I'm
> guessing; I don't know exactly how you embed tcl in your php scripts):
>
> <html>
> <some tag to embed tcl>
> PROPER_CASE "Hello, world"
> </some tag>

Don't have anything that can do that, sorry. My TCL code is called
command-line only:

[PHP]
<?
$msg = exec("tclsh \"$pathToTclFile\" 2>&1");
?>
[/PHP]

Only way I can do it since Apache is not set up to handle embedded TCL
(and I don't have root privileges to change Apache were I to know how
to do it and it's also not a requirement so no one will OK such a
change)

>
> ... you can create test scripts with something that may look like this :
>
> <html>
> <some tag to embed tcl>
> source tcltest.tcl ;# or "package require tcltest 2"
> source yourCodeToBeTested.tcl
> test example-1 {a simple test} -body ... -result ...
> test example-2 {another test} -body ... -result ...
> cleanupTests
> </some tag>
>

I am probably still doing this wrong but I at this point don't know if
I'll ever get this right, so here goes:

[phillip@here ~]$ tclsh << eof
> package require tcltest 2
> source {/var/www/html/tcl/lib/tcl_string_tools.tcl}
> test PROPER_CASE {_hello world} -body
> cleanupTests
> eof
invalid command name "test"
invalid command name "cleanupTests"
[phillip@here ~]$ tclsh << eof
> source tcltest 2
> source {/var/www/html/tcl/lib/tcl_string_tools.tcl}
> test PROPER_CASE {_hello world} -body
> cleanupTests
> eof
wrong # args: should be "source fileName"
invalid command name "test"
invalid command name "cleanupTests"

> Visit the web page, et voila!, you've just written and run a regression
> test. Now, I can't guarantee it is truly that easy for you because I
> don't know what environment you are using. Generally speaking though, if
> you are able to source your own tcl files you can source tcltest.tcl and
> write regression tests with the "test" command.

Environment: RHEL4 with Apache 2.0.53, PHP 4.3.9 and MySQL 4.1.17

>
> My suggestion: where you have one file now that defines the proc
> PROPER_CASE, create two files. Assuming the first file is named
> "library.tcl", name the second file "library.test". Put your test
> scripts in the second file, then source "library.test" (or do "tclsh
> library.test") whenever you want to run the tests.
>
> I hope this helps.
>

It does to a point, but I still don't understand, I'm sorry.

Phil

Bryan Oakley

unread,
Apr 24, 2006, 12:28:57 PM4/24/06
to
comp.lang.tcl wrote:
> The abject irony is that Vignette no longer uses TCL in newer versions
> of its content management platform; it's all J2EE now.

Yeah, that's been true for many years. There are still customers using
Tcl with storyserver but they are few and far between.

Pity.

>>So, much like you can create a web page with something like this (I'm
>>guessing; I don't know exactly how you embed tcl in your php scripts):
>>
>><html>
>><some tag to embed tcl>
>> PROPER_CASE "Hello, world"
>></some tag>
>
>
> Don't have anything that can do that, sorry. My TCL code is called
> command-line only:
>
> [PHP]
> <?
> $msg = exec("tclsh \"$pathToTclFile\" 2>&1");
> ?>
> [/PHP]
>
> Only way I can do it since Apache is not set up to handle embedded TCL
> (and I don't have root privileges to change Apache were I to know how
> to do it and it's also not a requirement so no one will OK such a
> change)

In such a case, executing a script with tests is equally trivial:

<?
$msg = exec("tclsh \"$pathToTestFile\" 2>&1");
?>

>
>
>>... you can create test scripts with something that may look like this :
>>
>><html>
>><some tag to embed tcl>
>> source tcltest.tcl ;# or "package require tcltest 2"
>> source yourCodeToBeTested.tcl
>> test example-1 {a simple test} -body ... -result ...
>> test example-2 {another test} -body ... -result ...
>> cleanupTests
>></some tag>
>>
>
> I am probably still doing this wrong but I at this point don't know if
> I'll ever get this right, so here goes:
>
> [phillip@here ~]$ tclsh << eof
>
>>package require tcltest 2
>>source {/var/www/html/tcl/lib/tcl_string_tools.tcl}
>>test PROPER_CASE {_hello world} -body
>>cleanupTests
>>eof
>
> invalid command name "test"
> invalid command name "cleanupTests"
> [phillip@here ~]$ tclsh << eof

My mistake. You need "namespace import tcltest::*" in order to use the
commands without fully qualifying them.

>
>>source tcltest 2

That is incorrect. "package require tcltest 2" or 'source tcltest.tcl'.
Pick one.

Try putting the following in a file (e.g. propercase.test) and running
it with tclsh (e.g.: tclsh propercase.test)

# uncomment the following line if the package require doesn't
# work or the tcltest.tcl you want to use is in the current
# directory.
# source tcltest.tcl
package require tcltest 2

# import the commands so we don't have to fully qualify them:
namespace import ::tcltest::*

# load in the code to be tested
source propercase.tcl

# run a couple of tests:
test PROPER_CASE-1 {a simple test of PROPER_CASE} -body {
PROPER_CASE {hello world}
} -result {Hello World}

test PROPER_CASE-2 {leading underscore} -body {
PROPER_CASE {_hello world}
} -result {_Hello World}

test PROPER_CASE-3 {leading dash} -body {
PROPER_CASE {-hello world}
} -result {-Hello World}

test PROPER_CASE-4 {unbalanced braces} -body {
PROPER_CASE "hello world\}"
} -result "Hello World\}"

# clean up and print the results
cleanupTests

Neil Madden

unread,
Apr 24, 2006, 12:47:32 PM4/24/06
to
comp.lang.tcl wrote:
[...]

>
> I am probably still doing this wrong but I at this point don't know if
> I'll ever get this right, so here goes:
>
> [phillip@here ~]$ tclsh << eof
>
>>package require tcltest 2
>>source {/var/www/html/tcl/lib/tcl_string_tools.tcl}
>>test PROPER_CASE {_hello world} -body
>>cleanupTests
>>eof
>
> invalid command name "test"
> invalid command name "cleanupTests"


OK, you're almost there. You can leave off the << eof stuff, as tclsh
will present you with an interactive shell:

$ tclsh
% package require tcltest 2
2.2.1
% namespace import tcltest::*
% test expr-1.1 {description of test...} -body {
expr 1+2
} -result 3
% cleanupTests
: Total 1 Passed 1 Skipped 0 Failed 0
%

Once you get this working (the namespace import seems to be what you are
missing), then you can put all this in a file:

package require tcltest 2
namespace import tcltest::*

source /var/www/html/tcl/lib/tcl_string_tools.tcl ;# or whatever

test proper_case-1.1 {describe the test ...} -body {
# test some part of proper-case here


PROPER_CASE {-hello world}
} -result {-Hello World}

cleanupTests

Then to run this you just do:

$ tclsh nameOfFile.test
nameOfFile.test: Total 1 Passed 1 Skipped 0
Failed 0

Hope that helps,

-- Neil

comp.lang.tcl

unread,
Apr 24, 2006, 1:43:40 PM4/24/06
to

Results (after cleaning up pathing structure):

[phillip@here ~]$ tclsh /home/me/test.tcl

==== PROPER_CASE-4 unbalanced braces FAILED
==== Contents of test case:

PROPER_CASE "hello world\}"


---- Result was:
Hello {World\}}
---- Result should have been (exact matching):
Hello World}
==== PROPER_CASE-4 FAILED

test.tcl: Total 4 Passed 3 Skipped 0 Failed
1
[phillip@here ~]$


I hope that's what I am supposed to get

Phil

Bryan Oakley

unread,
Apr 24, 2006, 2:40:38 PM4/24/06
to
comp.lang.tcl wrote:
> Results (after cleaning up pathing structure):
>
> [phillip@here ~]$ tclsh /home/me/test.tcl
>
> ==== PROPER_CASE-4 unbalanced braces FAILED
> ==== Contents of test case:
>
> PROPER_CASE "hello world\}"
>
>
> ---- Result was:
> Hello {World\}}
> ---- Result should have been (exact matching):
> Hello World}
> ==== PROPER_CASE-4 FAILED
>
> test.tcl: Total 4 Passed 3 Skipped 0 Failed
> 1
> [phillip@here ~]$
>
>
> I hope that's what I am supposed to get

You're going to have to tell us. Do you think the proper case should be
'Hello World}' or should it be 'Hello {World\}}'?

My guess is it should return what the test case says it should return.
If so, your regression test found its first bug!

You now have two choices: decide that the test case is wrong and correct
it to expect the proper result, or decide that your test case is correct
and the code is wrong, in which case you need to fix the code so it will
return the expected result. My guess is, you need to fix the code.

Cameron Laird

unread,
Apr 24, 2006, 5:07:58 PM4/24/06
to
In article <1145894977.8...@i40g2000cwc.googlegroups.com>,
comp.lang.tcl <phillip....@gmail.com> wrote:
.
.
.

>Don't have anything that can do that, sorry. My TCL code is called
>command-line only:
>
>[PHP]
><?
> $msg = exec("tclsh \"$pathToTclFile\" 2>&1");
>?>
>[/PHP]
.
.
.
While I think working with Bryan and the others so you have a
minimal useful Tcl development environment is the right thing
to do, I should mention that, if your only goal is to get your
few Web pages working, I'd personally just recode them in PHP.
PHP can implement the relatively straightforward functionality
you've described to this point.
0 new messages