TinTin++ Mud Client The TinTin++ message board

 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
TinTin++ Mud Client

Alias Argument Stack with Switch Statements

 
Post new topic   Reply to topic    The TinTin++ message board Forum Index -> Bug Reports
View previous topic :: View next topic  
Author Message
atraeyu



Joined: 12 Dec 2007
Posts: 165

PostPosted: Sat Sep 27, 2014 1:43 pm    Post subject: Alias Argument Stack with Switch Statements Reply with quote

I believe that the argument stack for aliases is being broken when calling aliases from switch functions.

I stripped some relevant code from my codebase and globbed it into the following:

Code:
#nop VSOF;


#var COLORS.FG.BLACK  <aaa>;
#var COLORS.FG.WHITE  <fff>;
#var COLORS.FG.BLUE   <adf>;
#var COLORS.FG.GREEN  <afa>;
#var COLORS.FG.YELLOW <ffc>;
#var COLORS.FG.CYAN   <cff>;
#var COLORS.FG.ORANGE <fcc>;
#var COLORS.FG.PURPLE <cbf>;
#var COLORS.FG.PINK   <fae>;
#var COLORS.FG.RED    <faa>;

#var COLORS.BG.BLACK  <AAA>;
#var COLORS.BG.WHITE  <FFF>;
#var COLORS.BG.BLUE   <ADF>;
#var COLORS.BG.GREEN  <AFA>;
#var COLORS.BG.YELLOW <FFC>;
#var COLORS.BG.CYAN   <CFF>;
#var COLORS.BG.ORANGE <FCC>;
#var COLORS.BG.PURPLE <CBF>;
#var COLORS.BG.PINK   <FAE>;
#var COLORS.BG.RED    <FAA>;

#var COLORS.MSG.DEBUG    $COLORS.FG.YELLOW;
#var COLORS.MSG.INFO     $COLORS.FG.GREEN;
#var COLORS.MSG.WARNING  $COLORS.FG.ORANGE;
#var COLORS.MSG.ERROR    $COLORS.FG.RED;
#var COLORS.MSG.CRITICAL ${COLORS.FG.BLACK}${COLORS.BG.RED};

#var DEBUG      0;
#var INFO       1;
#var WARNING    2;
#var ERROR      3;
#var CRITICAL   4;

#alias msg {

    #if { $%1 >= $MSGLVL } {
        #format fmsglvl {%-10s} %1;
        #showme $COLORS[MSG][%1]MSG::${fmsglvl} %2;
        #unvar fmsglvl;
    };

};


#1 {
    #if {&MODULES} {
        msg {DEBUG} {MODULES already exists, skipping initialization.};

    };

    #else {
        msg {DEBUG} {MODULES does not exist, initializing MODULES.};

        #var MODULES {};

        #script {
            for mpath in $(find * -type f -name "__init__.tin"); do
                mname=$(dirname $(echo $mpath | cut -d'.' -f1));
                echo "#var MODULES[$mname][path]   {$mpath};";
                echo "#var MODULES[$mname][loaded] {0};";
            done
        };
    };
}


#tab module list;
#tab module load;
#tab module kill;
#tab module reload;

#alias module {

    msg {DEBUG} {%%1: %1};
    msg {DEBUG} {%%2: %2};

    #switch {%1} {

        #case {list}   {moduleList}
        #case {load}   {moduleLoad %2}
        #case {kill}   {moduleKill %2}
        #case {reload} {moduleReload %2}
        #default {
            msg {ERROR} {USAGE: module list | load <name | kill <name> | reload <name>};
        }

    }
}

#alias moduleList {

    #showme {${COLORS.FG.BLUE}Name                 Path                                     Loaded};
    #showme {${COLORS.FG.BLUE}-------------------- ---------------------------------------- ------};

    #foreach ${MODULES[]} {mname} {

        #format fmname   {%-20s} $mname;
        #format fmpath   {%-40s} $MODULES[$mname][path];
        #format fmloaded {%+6s}  $MODULES[$mname][loaded];

        #showme $fmname $fmpath $fmloaded;

    };

    #showme {${COLORS.FG.BLUE}--------------------------------------------------------------------};
}

#alias moduleLoad {

    msg {DEBUG} {IN moduleLoad};
    msg {DEBUG} {%%1: %1};
    msg {DEBUG} {%%2: %2};

    #if { "%1" == "" } {
        msg {ERROR} {Usage: module load <name>};
    };

    #elseif { "$MODULES[%1]" == "" } {
        msg {ERROR} {Module %1 does not exist.};
    };

    #else {
        msg {INFO} {Not yet implimented.};
    };
}

#alias moduleKill {
    msg {INFO} {Not yet implimented.};
}

#alias moduleReload {
    msg {INFO}
}



In my codebase, most of this code is in separate files, but for the sake of demonstration this should work.
Basically, the switch statement in module calls the correct alias based on it's arguments.

If you put this in a file and load it with tt++ -v -r test.tin, and then type "module list" you'll get good execution, and all the modules (any files the filesystem hierarchy named __init__.tin) are displayed.

You can also call it directly with: moduleList, again works as expected.

Similarly, if you use "moduleLoad <module>" you get good execution and see the "not yet implemented" message through the call to the msg alias.

However, if you attempt to use "module load <module>" you get output like this:

Quote:
module load api/cache
MSG::DEBUG %1: load
MSG::DEBUG %2: api/cache
#MATH EXP: UNKNOWN OPERATOR: =
#MATH EXP: UNKNOWN OPERATOR: =
#MATH EXP: UNKNOWN OPERATOR: =
#MATH EXP: UNKNOWN OPERATOR: =
MSG::ERROR USAGE: module list | load <name | kill <name> | reload <name>


The first two messages are generated by the module alias, not the moduleLoad alias, and it's got the correct alias arguments.
Then, we see several math errors. These are generated inside the msg alias, by:

Code:
#if { $%1 >= $MSGLVL } {


Then we finally see an error message from the default statement, which should only be called if none of the case statements were. We never see the messages from a call to "moduleLoad".

After playing around with this code, the only thing that makes sense to me is that the arguments being pushed onto the alias stack frame are somehow modifying the calling stack frame rather than their own.

It's likely I'm wrong, I'm prone to making giant mistakes (such as inserting quotes where they shouldn't be and being completely blind to it), but right now it does look like it may be a bug.
Back to top
View user's profile Send private message AIM Address
atraeyu



Joined: 12 Dec 2007
Posts: 165

PostPosted: Sat Sep 27, 2014 2:02 pm    Post subject: Reply with quote

If I swap out the switch statement for and if/elseif/else block:

Code:
#alias module {

    msg {DEBUG} {IN module};
    msg {DEBUG} {%%1: %1};
    msg {DEBUG} {%%2: %2};

    #switch {%1} {

        #if     {"%1" == "list"}   {moduleList};
        #elseif {"%1" == "load"}   {moduleLoad %2};
        #elseif {"%1" == "kill"}   {moduleKill %2};
        #elseif {"%1" == "reload"} {moduleReload %2};
        #else {
            msg {ERROR} {USAGE: module list | load <name | kill <name> | reload <name>};
        }

    }
}


Quote:
Then everything seems to work correctly:

module load api/cache
MSG::DEBUG IN module
MSG::DEBUG %1: load
MSG::DEBUG %2: api/cache
MSG::DEBUG IN moduleLoad
MSG::DEBUG %1: api/cache
MSG::DEBUG %2:
MSG::INFO Not yet implimented.
Back to top
View user's profile Send private message AIM Address
Scandum
Site Admin


Joined: 03 Dec 2004
Posts: 3857

PostPosted: Sat Sep 27, 2014 2:44 pm    Post subject: Reply with quote

Need to use #switch {"%1"} and #case "something" when working with strings.

It's a common mistake. Guess I'll mention it in in the help file.
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    The TinTin++ message board Forum Index -> Bug Reports All times are GMT - 5 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
Get TinTin++ Mud Client at SourceForge.net. Fast, secure and Free Open Source software downloads Get TinTin++ Mud Client at SourceForge.net. Fast, secure and Free Open Source software downloads
TinTin++ Homepage

Powered by phpBB © 2001, 2002 phpBB Group