egghelp.org community Forum Index
[ egghelp.org home | forum home ]
egghelp.org community
Discussion of eggdrop bots, shell accounts and tcl scripts.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Strange issues in TCL

 
Post new topic   Reply to topic    egghelp.org community Forum Index -> Scripting Help
View previous topic :: View next topic  
Author Message
dj-zath
Op


Joined: 15 Nov 2008
Posts: 134

PostPosted: Sat Nov 15, 2008 7:31 am    Post subject: Strange issues in TCL Reply with quote

Recently, I upgraded from a hosted box running FreeBSD.. to a CoLocation box running Linux.

I was running an older version of eggdrop on the bsd box, but opted to run the latest TCL and eggdrop on this new box..

everything compiled and installed without any problems.. untill...

I went to load a custom script I wrote to manage my radio station interface..

BZZZZT! the script COMPLETELY FAILS!

okay, I thought, I figured I'd probably have to change things and would begin rewriting the script from scratch..

then I discovered WHY the script failed... and I'd like to know if this was intentional or whatnot... and how to FIX it...


I didn't get very far- in fact, right on the first piece of code/procs..

I have discovered the following:

1 timers will NOT run, period.
2 a proc will NOT load another proc... (list does NOTHING)
3 can't have a 'if{}' statement outside a proc (such as in the eggdrop.conf file)

an 'if' statement will run inside a proc, but ONLY if a GLOBAL varable is set; "local" varables don't work in 'if' statements- in or out of procs

so, the following piece of code:
Code:

if {![info exists StartLoop]} {
       utimer 5 [list RunLoop]
       set StartLoop 1
}

proc RunLoop {} {
       utimer 5 [list Action]
       return 1
}



does NOT work at all! this piece of code has THREE failures in it (mentioned above) and thats as far as I got!

I'm SURE there are more and more "odd failures" but the bot itself seems to run just FINE.. its as if the failures are INTENTIONAL or as if the bot was designed to no longer allow the use of the internal TCL scripting to run external functions...

I have tried reinstalling Eggdrop and TCL but nothing has improved

I have tried clean installs, clean uninstalls, YUM and manual installs- make static.. you name it!

I am totally STUMPED on this one!

anyone offer some help?? thanks!

DjZ
Smile Smile
Back to top
View user's profile Send private message Visit poster's website
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Sat Nov 15, 2008 12:30 pm    Post subject: Reply with quote

Could you provide some additional information, such as version of eggdrop, version of tcl, the full source of your custom script, any generated/logged errors?

  1. Odd, do you get any errors logged or such?

  2. The list command does not call another proc, it simply generates a tcl-list. It is used with timers to prevent code injection and remote exploits, such as command substitutions ([command]) and variable evaluation.
    This would rather be a side-effect of your first problem.

  3. This is very odd. Tcl should not make any difference to what commands are available simply by changing the command execution context. Did you get any errors when trying this?

  4. Variable context must be considered. A globalspace variable is not implicitly made available to the environment of a proc, but must explicitly be made available using the upvar or global commands. A local variable within a proc will only persist through the execution of the proc, and is wiped once the proc ends. Any variable already created within the current instance of the proc should be usable with if, aswell as any other command, without having to link it to a globalspace variable.


Personally, I can not see any reason for the posted code not working (I am assuming there is a proc named Action aswell somewhere in your script). I also assume the pasted code is executed at global context, and StartLoop has not been set prior running this code.
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
dj-zath
Op


Joined: 15 Nov 2008
Posts: 134

PostPosted: Sat Nov 15, 2008 9:23 pm    Post subject: Reply with quote

hi and thanks for your prompt reply!

a couple things to explain reguarding your inquiry.

1.. the "code" I provided above was just an example- it assumes a proc named "Action" exists.

2.. the actual code I have for the radio interface is rather lengthy.. and I'd rather not post it since it contains sensitive information (of course, I could "bleep out" that info.. but I might miss something... and that will bite me in the ass later on Smile)

3. I think the code itself would work once the "base" parts are figured out..

I have began to use "debug mode".. and now I see the error messages ( call it a brain fart or what!) The error messages still don't make sense, however, but at least I see whats happening...

the args/flags for called procs are being dropped and/or ignored

note the following example:

heres a example piece of code I put in:

Code:

bind pub -n !test Test

proc   Test {} {
    utimer 5 [list Go]
}


proc     Go {nick uhost hand chan arg} {
     putserv "PRIVMSG #Test : Operation Complete."
}



then I type !test in the chatroom:

I receive the error in debug:

Tcl error [Test]: wrong # args: should be "Go nick uhost hand chan arg"

and, of course, the operation fails.


This suggests that flags/args from the "called" proc are simply being ignored and, of course, then "error out" and fail...

thats basically all I have at this time.. I'm still "debugging" this and trying out other ideas to see if I can figure it out.. the MOST LIKELY thing is I probably am forgetting something that which USED to work when omitted- but now REQUIRED and I just don't know what it is!

again, thanks for your time, help and input!

DjZ
Smile Smile
Back to top
View user's profile Send private message Visit poster's website
speechles
Revered One


Joined: 26 Aug 2006
Posts: 1398
Location: emerald triangle, california (coastal redwoods)

PostPosted: Sat Nov 15, 2008 10:38 pm    Post subject: Reply with quote

Your problem is painfully obvious and the error given to you clearly spells it out.
Code:
    utimer 5 [list Go]

You are invoking the procedure go, with no parameters. Yet in your procedure declartion below:
Code:
proc     Go {nick uhost hand chan arg} {

You are expecting there to be 5 passed: nick, uhost, hand, chan, arg

You need to include these arguments when invoking the timer passing them to the go procedure, or eliminate them from the go procedure as I have done below.
Code:
bind pub n !test Test

proc   Test {nick uhost hand chan arg} {
    utimer 5 [list Go]
}


proc     Go { } {
     putserv "PRIVMSG #Test : Operation Complete."
}

When you use a bind, it will expect to pass a set amount of parameters (in your case: nick, uhost, hand, chan and the remaining user text given). Your procedure header parameters must match this amount as well. If you invoke the go procedure without passing arguments you must also leave the parameter field empty within the procedure header.
_________________
speechles' eggdrop tcl archive
Back to top
View user's profile Send private message
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Sat Nov 15, 2008 10:55 pm    Post subject: Reply with quote

As speechles pointed out, you must always make sure function calls have the right number of arguments. Different bindings will call the associated function with a set of arguments depending on the type of the binding, and hence your proc must match that. Also, keep in mind that there is no automatic variable injection or such when calling a function from another function..

Since your problems started when you upgraded your eggdrop, I would guess it is related to one of a few binding types that has been altered in a non-backwards compatible manner. These are notc, part, and mode (pre 1.3.18 ); see the tcl-commands.doc document for further information on compability with these commands, including portable code.
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
dj-zath
Op


Joined: 15 Nov 2008
Posts: 134

PostPosted: Mon Nov 17, 2008 11:52 pm    Post subject: Reply with quote

DING!

okay okay! I get cha!

yeah, the old code didn't require sending the args/flags along with a run/list command... (though I DID include them in the "controlled" proc..)

since the writing of the previous post, I have "worked around" as many issues as I could... mainly sticking all the "timer-controlled" procs (updates) into a SINGLE proc and then binding that to "time" (the number of globals is SCARY!)

I still noticed that NO expressions or if/else works unless I set those particular varables as a global even if the if statment is still inside the SAME proc as the varable! setting the varable as a global works- even though that varable will NEVER be used outside the proc (isn't that a whaste of resources??) for this reason, I'm cirrently at 46 "global" varables and expect to climb to over 100! (I hope there isn't a LIMIT!)

because it was requested: and now I can access the web at this terminal)

heres the ACTUAL code, from the OLD Bot, reguarding the timers..

Code:


##### Run Timers #####

if      {![info exists loop]} {
        utimer 5 [list RunLoop1]
        utimer 6 [list RunLoop2]
        utimer 97 [list RunLoop3]
        utimer 98 [list RunLoop4]
        set loop 1
}

proc    RunLoop1 {} {
        [list GetInfo]
        utimer 5 [list RunLoop1]
        return 1
}

proc    RunLoop2 {} {
        [list OtsSwitch]
        utimer 5 [list RunLoop2]
        return 1
}


proc    RunLoop3 {} {
        [list UpteTitle]
        utimer 5 [list RunLoop3]
        return 1
}

proc    RunLoop4 {} {
        [list UpteSong]
        utimer 5 [list RunLoop4]
        return 1
}



this code WORKED in the old Bot FLAWLESSLY..

but, as it was pointed out.. I was WAY beihind and I know I misssed a LOT of upgrades.. I'm "re"learning TCL now so I could figure out the NEW limits on what I can and can't do...

the NEW code for the "timers" section has been changed to:

Code:

### Get Server Info ###

bind time - "* * * * *" ServInfo


"GetInfo" (sockets), "OtsSwitch" (auto playout control), "UpteTitle" (updates the current cast title) and "UpteSong" (updates the current song name) have all been combined to a single proc called "ServInfo" and, though its now SLOWED to updating once a minute.. (old code did it once every 5 seconds) it was the best I could do!

Now, with Speechless's suggestions, I will try reworking the timers section once again.. I surely didn't catch the concept of including the arg/flasg on the end of the exec/list section (I tried everything ELSE)

One thins I see going wrong... is will I have to pass the args all the way down to the end procs and will that be an issue? I guess I'll find out!

in the meantime, thanks everyone for your help! I appreciate it.. I'm working hard to redesign all of this.. and.. perhaps, with all your help, I'll not only get the NEW Bot up and running, but I plan to ELIMINATE the old Bot's reliance on PHP for the web-side of things.. I think the new Bot could do a BETTER job than running php in a shell!

more exciting details to come! if you want to find out more, I invite you to my chat network at this link (the website is still down as the BOT will be generating it DYNAMICALLY!) see? eggdrop in action!

Using Flash: http://www.warp-radio.com/warp-chat-flash.html

you can join via your favorite IRC client too:

server irc.warp-radio.com:6667

channel #WARP-Radio

come by and say hi Smile (sorry if this seemed poachy- but I am writing the bot in realtime and it does make progress in that chat netowrk!)

again, thanks for all your help.. I believe it will be resolved soon enough

-DjZ-
Smile Smile
Back to top
View user's profile Send private message Visit poster's website
dj-zath
Op


Joined: 15 Nov 2008
Posts: 134

PostPosted: Tue Nov 18, 2008 9:39 am    Post subject: Reply with quote

okay.. I think I got it working...

heres the NEW code..

Code:

if      {![info exists loop]} {
        utimer 5 [list RunLoop1 (args)]
        set loop 1
}

proc    RunLoop1 {args} {
        ServInfo (args)
        utimer 5 [list RunLoop1 (args)]
        return 1
}


I still have to varify if, indeed, the first part is only running once or if it is looping on its own...


and now.... I got a different but [somewhat] simular issue..

I need to do the following:

1.. Strip ASCII/web codes(not html) from incoming "winamp" title strings

2.. Then need to put them back in (after the strings were minpolated)

this sounds strange, I need to explain...

I'm actually pulling in from one server- and passing to another.. I need to strip all the "&nb#23"'s and stuff from the incoming shoutcast titles.. then after I rearrange, add new tags, etc.. (including displaying in PLAIN text to irc) I need to import them BACK to the stream title (spaces becomes _'s for example)

I tried hunting for command sets and the like- but I never DID get this one figured out.. but since I'm "in the neighborhood" (so to speak) I thought I'd toss it out to you, the experts!

any input or suggestions would be appreciated!

and, again, thanks in advance for your help and support!

DjZ
Smile Smile
Back to top
View user's profile Send private message Visit poster's website
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Tue Nov 18, 2008 3:29 pm    Post subject: Reply with quote

A few thoughts comes into mind reading your last two posts.

Quote:
I still noticed that NO expressions or if/else works unless I set those particular varables as a global even if the if statment is still inside the SAME proc as the varable! setting the varable as a global works- even though that varable will NEVER be used outside the proc (isn't that a whaste of resources??) for this reason, I'm cirrently at 46 "global" varables and expect to climb to over 100! (I hope there isn't a LIMIT!)

Could you post just one example of this. As long as a variable exists within the same instance of a proc before it is read, there should be no problem. If/else constructs should work independent of variables, as these would be expanded as the whole conditional is simply run through expr and the result tested for true/false. Hence if/else really doesn't care what's within the conditional as long as expr don't complain.

Global variables have the only limit of available names and memory. If you are afraid you'll get overrun with that many global variables, consider using a separate namespace.


Quote:
heres the ACTUAL code, from the OLD Bot, reguarding the timers..

Code:
if      {![info exists loop]} {
        utimer 5 [list RunLoop1]
        utimer 6 [list RunLoop2]
        utimer 97 [list RunLoop3]
        utimer 98 [list RunLoop4]
        set loop 1
}

proc    RunLoop1 {} {
        [list GetInfo]
        utimer 5 [list RunLoop1]
        return 1
}
...

I am very puzzled why you're using [list GetInfo] rather than just GetInfo. Same with the other procs in your script.. Otherwize, there is nothing that sticks out that would stop it from working on a current eggdrop. As long as there exists no variable named "loop" at the current context, the timers would be started, and loops kept running.

Quote:
heres the NEW code..

Code:
if      {![info exists loop]} {
        utimer 5 [list RunLoop1 (args)]
        set loop 1
}

proc    RunLoop1 {args} {
        ServInfo (args)
        utimer 5 [list RunLoop1 (args)]
        return 1
}

Did you intentionally use "args" as an argument name here, fully knowing it's special properties? If not, I would strongly suggest against using that name, and suggest you go for anything else but that.
"utimer 5 [list RunLoop1 (args)]" most likely will not produce the result you expect. Once the timer triggers, RunLoop will be called with one single parameter, being literally "(args)". To actually do the variable substitution, you'll have to use $varname.
Same goes within your RunLoop1 proc when you call ServInfo...

Quote:
I need to do the following:

1.. Strip ASCII/web codes(not html) from incoming "winamp" title strings

2.. Then need to put them back in (after the strings were minpolated)

Your best tool for data mining would probably be regexp/regsub, using regular expressions. In some simpler cases, some of the subcommands of string may be helpful as well.
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    egghelp.org community Forum Index -> Scripting Help All times are GMT - 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Forum hosting provided by Reverse.net

Powered by phpBB © 2001, 2005 phpBB Group
subGreen style by ktauber