## Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

# XyCalc v1.0

Xylor Baysklef
Join date: 4 May 2003
Posts: 109
02-12-2004 01:57
Here is an in-game calculator designed to be put on an attachment. It temporarily renames your attachment while giving output.

To use it, put the following scripts on an object/attachement, and give commands like this:

xc 1+1
XyCalc v1.0: 2

You can also use parenthesis to input more complex commands:

xc sqrt(3^2 + 4^2)
XyCalc v1.0: 5.0

XyCalc handles variables, and has a few constants of its own. You can assign a variable using the '=' operator:

xc W = 5.0
XyCalc v1.0: 5.0
xc L = 4.0
XyCalc v1.0: 4.0
xc A = W * L
XyCalc v1.0: 20.0

You can list which variables are set, by using the "xc vars" command:

xc vars
XyCalc v1.0: a = 20.0
XyCalc v1.0: w = 5.0
XyCalc v1.0: l = 4.0

Note: XyCalc is not case sensitive. It converts all input to lowercase before processing.

You can also look at the constants available with "xc constants":

xc constants
XyCalc v1.0: pi = 3.141593
XyCalc v1.0: e = 2.718282
XyCalc v1.0: ans = 20.0

Notice the constant 'ans'. This is updated to the previous result each time you enter a command. This can be used to chain commands together:

xc sin(45)
XyCalc v1.0: 0.707107
xc asin(ans)
XyCalc v1.0: 45.000019

You can also assign a variable embedded in your command:

xc sin( theta=asin( sqrt(2) / 2) )
XyCalc v1.0: 0.707107
xc theta
XyCalc v1.0: 45.000019

You can switch between Radian and Degree mode for trig commands by saying:

XyCalc v1.0: Trig is now in radian mode.
or
xc degrees
XyCalc v1.0: Trig is now in degree mode.

XyCalc understands the following operations:

+, -, /, *, ^, %, &, |,
abs, rand, sqrt, round, floor, ceil,
sin, cos, tan, asin, acos, atan,
sinh, cosh, tanh, asinh, acosh, atanh,
ln, log

Future versions may include vector types, to handle vector manipulation.

Here is the code (Split into different posts since it is too large... check the replies):

XyCalc v1.0
CODE
`////////////////////////////////////////////// XyCalc Script//// Written by Xylor Baysklef/////////////////////////////////////////////////////////// CONSTANTS ///////////////////// Channels to communicate with the processor.integer NEW_COMMAND         = 14000;integer PUSH_OPERAND        = 14001;integer EXECUTE_OPERATOR    = 14002;integer DISPLAY_RESULTS     = 14003;integer XYCALC_SAY          = 14004;integer XYCALC_RESULTS      = 14005;// OpHandler channels.integer OP_HANDLER_REQUEST  = 14100;integer OP_HANDLER_RETURN   = 14101;// Bit-wise operand types.integer OP_INTEGER      = 1;integer OP_FLOAT        = 2;integer OP_NUMBER       = 3;integer OP_VECTOR       = 4;integer OP_ROTATION     = 8;integer OP_STRING       = 16;integer OP_PARAMS       = 32;//integer OP_RESERVED     = 64;integer OP_ANY          = 127;integer OP_MULTIPLIER   = 128;integer TOKEN_OPERATOR  = 0;integer TOKEN_OPERAND   = 1;// Number of operands and types each operator uses.list    OPERAND_INFO;            // Used for error handling.integer NO_ERROR    = FALSE;integer ERROR       = TRUE;                // Number of ops in operand info list.integer OP_KNOWN        = 13;// Value to assume for the rest.list OP_UNKNOWN_INFO    = [1, OP_FLOAT];                ///////////// END CONSTANTS ///////////////////////////// GLOBAL VARIABLES ///////////////// This is the post-fix stacklist    gStack;integer gStackSize;// This is whether or not an error was encountered.integer gHadError;// This whether or not we are currently waiting// for an op handler return.integer gWaitingForOpHandler;// These are tokens  waiting to be// processed once the current op handler is done.list    gPendingTokens;// This is whether or not to display results// once we are done waiting for the op handler.integer gPendingDisplayResults;/////////// END GLOBAL VARIABLES ////////////Say(string mesg) {    // Switch names temporarily.    string OldName = llGetObjectName();    llSetObjectName(llGetScriptName());    llSay(0, llGetSubString(mesg, 0, 254));    llSetObjectName(OldName);}Error(string operator, string mesg) {    // Report the error.    Say("Error executing '" + operator + "' operator: " + mesg + ".");}//////////// STACK FUNCTIONS //////////////////ClearStack() {    // This clears the stack, and stack size.    gStack      = [];    gStackSize  = 0;}Push(string operand, integer type) {        // Just put this on the end of the list.    gStack += [operand, type];    gStackSize++;}PushList(list operand) {        // Just put this on the end of the list.    gStack += operand;    gStackSize++;}list Pop() {    // Remove the last item from the list.    list Operand  = llList2List(gStack, -2, -1);    gStack   = llDeleteSubList(gStack, -2, -1);    gStackSize--;    return Operand;}integer IsStackEmpty() {    // Check the stack size.    if (gStackSize)        return FALSE;    else        return TRUE;}////////// END STACK FUNCTIONS ///////////////string TypeToString(integer type) {        if (type == OP_NUMBER)        return "number";    if (type == OP_INTEGER)        return "integer";    if (type == OP_FLOAT)        return "float";    if (type == OP_VECTOR)        return "vector";    if (type == OP_ROTATION)        return "rotation";    if (type == OP_STRING)        return "string";    if (type == OP_PARAMS)        return "params";            return "unknown";}integer ExecuteOperator(string operator, integer operator_index) {    // See how many operatand to extract, and what    // types they should be.    integer NumOperands;    integer OperandTypes;         // Check if this operator is in the operand info list.    if (operator_index > OP_KNOWN) {        NumOperands     = llList2Integer(OP_UNKNOWN_INFO, 0);         OperandTypes    = llList2Integer(OP_UNKNOWN_INFO, 1);    }    else {        NumOperands     = llList2Integer(OPERAND_INFO, operator_index * 2);         OperandTypes    = llList2Integer(OPERAND_INFO, operator_index * 2 + 1);    }            // Make sure there are enough operands.    if (gStackSize < NumOperands) {        Error(operator, "Not enough operands");        return ERROR;    }            // Build the operand list, and check types.    list OperandList = [];    integer i;    list Operand;    integer TypeMultiplier = 1;    string OpToken;    integer OpType;    integer ExpectedType;    for (i = 0; i < NumOperands; i++) {        // Extract the operand from the post fix stack.        Operand = Pop();                        // Figure out the expected operand type.        ExpectedType = (OperandTypes / TypeMultiplier) & OP_ANY;                // Check type info.        OpToken = llList2String (Operand, 0);        OpType  = llList2Integer(Operand, 1);                //Say("types: " + llList2CSV([OperandTypes,         //                  TypeMultiplier, ExpectedType, OpType]));                // First check for the case this is unknown.        if (OpType == OP_STRING) {            // See if we need to determine if this is a float or            // an integer.            if (ExpectedType == OP_NUMBER) {                // If there is a '.' in the string, assume                // it is a float.                if (llSubStringIndex(OpToken, ".") != -1)                    // Convert to a float.                    Operand = [(float) OpToken, OP_FLOAT];                else                    // Convert to an integer.                    Operand = [(integer) OpToken, OP_INTEGER];            }            // Otherwise convert to the expected type.            else if (ExpectedType == OP_INTEGER)                Operand = [(integer) OpToken, OP_INTEGER];            else if (ExpectedType == OP_FLOAT)                Operand = [(float) OpToken, OP_FLOAT];            else if (ExpectedType == OP_VECTOR)                Operand = [(float) OpToken, OP_VECTOR];            else if (ExpectedType == OP_ROTATION)                Operand = [(float) OpToken, OP_ROTATION];        }                // Now check if casting is needed.        else if (OpType == OP_INTEGER && ExpectedType == OP_FLOAT)            // Convert to float.            Operand = [(float) OpToken, OP_FLOAT];        else if (OpType == OP_FLOAT && ExpectedType == OP_INTEGER)            // Convert to integer.            Operand = [(integer) OpToken, OP_INTEGER];                            // Otherwise, compare type info (OpType != OP_UNKNOWN)        else  if ( OpType & ExpectedType == 0) {            Error(operator, "Invalid type; Cannot cast from (" +                     TypeToString(OpType) + ") to (" +                    TypeToString(ExpectedType) + ")");            return ERROR;        }                // Add the operand and update the type multiplier.        OperandList += Operand;        TypeMultiplier *= OP_MULTIPLIER;    }        //llSay(0, llList2CSV([operator, operator_index] + OperandList));            // Send this off the the op handler.    llMessageLinked(LINK_SET, OP_HANDLER_REQUEST,                     llList2CSV([operator] + OperandList), "");    // Set this flag while we wait for the op handler.    gWaitingForOpHandler = TRUE;                    return NO_ERROR;}ShowResults() {    // Send the results off for processing.    llMessageLinked(LINK_SET, XYCALC_RESULTS, llList2CSV(gStack), "");}default {    state_entry() {        // Number of operands and types each operator uses.        OPERAND_INFO  = [                        1,  OP_INTEGER,                                // ~                         2,  OP_NUMBER   + OP_NUMBER  * OP_MULTIPLIER,  // +                        2,  OP_NUMBER   + OP_NUMBER  * OP_MULTIPLIER,  // -                        2,  OP_NUMBER   + OP_NUMBER  * OP_MULTIPLIER,  // /                        2,  OP_NUMBER   + OP_NUMBER  * OP_MULTIPLIER,  // *                        -1, 0, // ( --  special                        -1, 0, // ) -- special                        2,  OP_STRING   + OP_ANY     * OP_MULTIPLIER,  // =                        2,  OP_NUMBER   + OP_NUMBER  * OP_MULTIPLIER,  // ^                        2,  OP_INTEGER  + OP_INTEGER * OP_MULTIPLIER,  // %                        2,  OP_INTEGER  + OP_INTEGER * OP_MULTIPLIER,  // &                        2,  OP_INTEGER  + OP_INTEGER * OP_MULTIPLIER,  // |                        1,  OP_NUMBER,                                 // abs                        1,  OP_NUMBER,                                 // rand                        //1,  OP_FLOAT,                       // sqrt                        //1,  OP_FLOAT,                       // round                        //1,  OP_FLOAT,                       // asinh                        //1,  OP_FLOAT,                       // acosh                        //1,  OP_FLOAT,                       // atanh                        //1,  OP_FLOAT,                       // sinh                        //1,  OP_FLOAT,                       // cosh                        //1,  OP_FLOAT,                       // tanh                        //1,  OP_FLOAT,                       // asin                        //1,  OP_FLOAT,                       // acos                        //1,  OP_FLOAT,                       // atan                        //1,  OP_FLOAT,                       // sin                        //1,  OP_FLOAT,                       // cos                        //1,  OP_FLOAT,                       // tan                        //1,  OP_FLOAT,                       // ln                        //1,  OP_FLOAT,                       // log                        //1,  OP_FLOAT,                       // floor                        //1,  OP_FLOAT,                       // ceil                        -1];                                Say("Free Memory: " + (string) llGetFreeMemory());    }        link_message(integer sender, integer channel, string data, key id) {        if (channel == NEW_COMMAND) {            // Clear the stack.            ClearStack();            // Clear the error flag.            gHadError = FALSE;            // Clear the pending tokens list.            gPendingTokens = [];            // Clear the waiting for op handler flag.            gWaitingForOpHandler = FALSE;            // Clear the pending display results flag.            gPendingDisplayResults = FALSE;            return;        }                // Check for a previous error.        if (gHadError)            return;                if (channel == PUSH_OPERAND) {            // If we are waiting for an op handler, add this            // to the pending tokens list.            list Operand = llCSV2List(data);            if (gWaitingForOpHandler)                gPendingTokens += Operand + [TOKEN_OPERAND];            else                // Just push this onto the stack.                PushList(Operand);            return;        }        if (channel == DISPLAY_RESULTS) {                   // If we are waiting for an op handler, set the            // pending display results flags for now.            if (gWaitingForOpHandler) {                gPendingDisplayResults = TRUE;            }            else                 // Otherwise show the results now.                ShowResults();                            return;        }        if (channel == EXECUTE_OPERATOR) {                    list Parsed = llCSV2List(data);                                    // If we are waiting for an op handler, just            // add this to the pending tokens list.            if (gWaitingForOpHandler) {                gPendingTokens += Parsed + [TOKEN_OPERATOR];            }            else                // Otherwise execute the operator now.                gHadError = ExecuteOperator(llList2String(Parsed, 0),                                 (integer)llList2String(Parsed, 1));                                            return;        }        if (channel == OP_HANDLER_RETURN) {            // Unset the wait flag.            gWaitingForOpHandler = FALSE;                        // Check the results for an error.            list Parsed = llCSV2List(data);            if (llList2String(Parsed, 0) == "ERROR") {                // Display the error.                string Operator = llList2String(Parsed, 1);                string ErrorMsg = llList2String(Parsed, 2);                Error(Operator, ErrorMsg);                                // Throw the error flag, and quit.                gHadError = TRUE;                return;            }                                    // Push the results onto the stack.            PushList(Parsed);                        // If there are no more pending tokens, and we            // are waiting to display results, do it now.            if (gPendingDisplayResults &&                llGetListLength(gPendingTokens) == 0) {                ShowResults();                return;            }                        // If there are pending tokens, push all operands until            // we get to an operator to execute.            integer Found = FALSE;            list Token;            while (llGetListLength(gPendingTokens) > 0 && !Found) {                Token = llList2List(gPendingTokens, 0, 2);                gPendingTokens = llDeleteSubList(gPendingTokens, 0, 2);                                // See if this is an operand.                if (llList2Integer(Token, 2) != TOKEN_OPERATOR) {                    // Just push this onto the stack.                    PushList(llList2List(Token, 0, 1));                }                else {                    // Execute this operator.                    Found = TRUE;                    gHadError = ExecuteOperator(llList2String(Token, 0),                                     (integer)llList2String(Token, 1));                }            }            return;        }        if (channel == XYCALC_SAY) {            // Used to re-route output through the xy calc script.            Say(data);            return;        }    }}`

Since only 20,000 characters can be sent per post, I will post the rest of the scripts once this post shows up in the script library.

Xylor
Xylor Baysklef
Join date: 4 May 2003
Posts: 109
02-14-2004 17:01
XyCalc Parser
CODE
`////////////////////////////////////////////// XyCalc Parser Script//// Written by Xylor Baysklef/////////////////////////////////////////////////////////// CONSTANTS ///////////////////// Channels to communicate with the processor.integer NEW_COMMAND      = 14000;integer PUSH_OPERAND     = 14001;integer EXECUTE_OPERATOR = 14002;integer DISPLAY_RESULTS  = 14003;// Channels to send mode info.integer MODE_DEGREE      = 14200;integer MODE_RADIAN      = 14201;// Variable Handler.integer VARIABLE_LOOKUP  = 14300;integer PIPE_RESULTS     = 14301;integer PIPE_OPERAND     = 14302;integer CMD_LIST_VARS    = 14303;integer CMD_CLEAR_VARS   = 14304;integer CMD_LIST_CONST   = 14305;// Prefix before all calculation commands.string  INFIX_PREFIX = "xc ";string  RPN_PREFIX   = "rpn ";// Command names.list    COMMAND_NAMES   = [ "degrees", "radians" ,                             "vars", "clear", "constants"];// Command channels.list    COMMAND_CHANS   = [ MODE_DEGREE, MODE_RADIAN,                             CMD_LIST_VARS, CMD_CLEAR_VARS, CMD_LIST_CONST];// Bit-wise operand types.//integer OP_OPERATOR     = 0;//integer OP_INTEGER      = 1;//integer OP_FLOAT        = 2;//integer OP_NUMBER       = 3;//integer OP_VECTOR       = 4;//integer OP_ROTATION     = 8;integer OP_STRING       = 16;//integer OP_PARAMS       = 32;//integer OP_RESERVED     = 64;//integer OP_ANY          = 127;//integer OP_MULTIPLIER   = 128;// Seperators used while tokenizing.list    OPERATORS    =                [ "~", "+", "-", "/", "*", "(", ")", "=",                   "^", "%", "&", "|",                 "abs", "rand", "sqrt", "round",                 "asinh", "acosh", "atanh", "sinh", "cosh", "tanh",                  "asin", "acos", "atan", "sin", "cos", "tan",                  "ln", "log", "floor", "ceil"];// Operator precedence levels.list    OPERATOR_PRECEDENCE = [                6,  // ~                3,  // +                3,  // -                4,  // /                4,  // *                -1, // ( -- special                -1, // ) -- special                1,  // =                7,  // ^                5,  // %                2,  // &                2,  // |                // Assume everything higher than                // this is '6' to save memory.                //6,  // abs                //6,  // rand                //6,  // sqrt                //6,  // round                //6,  // sin                //6,  // cos                //6,  // tan                //6,  // asin                //6,  // acos                //6,  // atan                //6,  // sinh                //6,  // cosh                //6,  // tanh                //6,  // asinh                //6,  // acosh                //6,  // atanh                //6,  // ln                //6,  // log                //6,  // floor                //6,  // ceil                -1];                // Number of ops in precedence list.integer OP_KNOWN        = 11;// Precedence to assume for the rest.integer OP_UNKNOWN_VAL  = 6;///////////// END CONSTANTS ///////////////////////////// GLOBAL VARIABLES ///////////////// Current object owner.key gOwner;// Used to pre-calculate the prefix lengths.integer gInfixPrefixLen;integer gRpnPrefixLen;// This is the operator stacklist    gStack;integer gStackSize;// Whether or not the previous token was// an operator.integer gLastWasOperator;/////////// END GLOBAL VARIABLES ////////////Say(string mesg) {    // Switch names temporarily.    string OldName = llGetObjectName();    llSetObjectName(llGetScriptName());    llSay(0, llGetSubString(mesg, 0, 254));    llSetObjectName(OldName);}integer IsOperand(string token) {    // Check if this is an operator.  If it isn't    // then it is an operand.    if (llListFindList(OPERATORS, [token]) == -1)        return TRUE;    else        return FALSE;}list ParseTokens(string data) {    // This repeatedly calls llParseString2List, since    // doing it in one call will not work (LSL bug).    integer MaxOperatorsPerCall = 8;        // Do this loop until we have processed all operators.    integer Block;    integer NumOperands = llGetListLength(OPERATORS);    list Previous = [data];    list Next;    for (Block = 0; Block < NumOperands; Block += MaxOperatorsPerCall) {        // Parse each entry currently in the previous list.        integer i;        for (i = 0; i < llGetListLength(Previous); i++) {            string Entry = llList2String(Previous, i);            // Don't process this entry if it is an operator.            if (IsOperand(Entry))                // Parse this entry, and put it in the Next list.                Next += llParseString2List(Entry, [" "],                             llList2List(OPERATORS, Block, Block + MaxOperatorsPerCall - 1));            else                Next += [Entry];        }        // Update previous.        Previous = Next;        Next = [];    }    // Return the results.    return Previous;}//////////// STACK FUNCTIONS //////////////////ClearStack() {    // This clears the stack, and stack size.    gStack        = [];    gStackSize    = 0;}Push(string operator) {    // Just put this on the end of the list.    gStack += [operator];    gStackSize++;}string Pop() {    if (gStackSize) {        // Remove the last item from the list.        string Operator = llList2String(gStack, -1);        gStack   = llDeleteSubList(gStack, -1, -1);        gStackSize--;        return Operator;    }    else        return "";}string StackTop() {    // If the stack is empty, return nothing.    if (gStackSize == 0)        return "";    else        // Return the top of the stack.        return llList2String(gStack, -1);    }integer IsStackEmpty() {    // Check the stack size.    if (gStackSize)        return FALSE;    else        return TRUE;}////////// END STACK FUNCTIONS ///////////////integer Precedence(string oper1, string oper2) {    // This returns TRUE if oper1 has precedence     // over oper2 when oper1 appears to the left    // of oper2 in an infix expression without    // parentheses.        // First check for parentheses.    if (oper1 == "(" || oper2 == "(")        return FALSE;            // oper1 should never == ")"        if (oper2 == ")")        return TRUE;            integer Oper1Index = llListFindList(OPERATORS, [oper1]);    integer Oper2Index = llListFindList(OPERATORS, [oper2]);        integer Oper1Precedence;    if (Oper1Index > OP_KNOWN)        Oper1Precedence = OP_UNKNOWN_VAL;    else        Oper1Precedence = llList2Integer(OPERATOR_PRECEDENCE, Oper1Index);            integer Oper2Precedence;    if (Oper2Index > OP_KNOWN)        Oper2Precedence = OP_UNKNOWN_VAL;    else        Oper2Precedence = llList2Integer(OPERATOR_PRECEDENCE, Oper2Index);        // See if oper1 higher or equal precedence than oper2.    if (Oper1Precedence >= Oper2Precedence)        return TRUE;    else        return FALSE;}integer CheckForCommand(string mesg) {    // Check for command.    integer i;    string CommandName;    integer CommandNameLen;    for (i = 0; i < llGetListLength(COMMAND_NAMES); i++) {        CommandName = llList2String(COMMAND_NAMES, i);        CommandNameLen = llStringLength(CommandName);                if (llGetSubString(mesg, 0, CommandNameLen - 1) == CommandName) {                        // Convert the command into a message.            integer CommandChannel = llList2Integer(COMMAND_CHANS, i);            // Send the command.            llMessageLinked(LINK_SET, CommandChannel,                 llGetSubString(mesg, CommandNameLen, -1), "");                  // Command found.                  return TRUE;        }    }    // No command.    return FALSE;}ExecuteOperator(string operator) {        if (operator == "(")        Say("Warning: Mismatched parenthesis.");    else                  llMessageLinked(LINK_SET, EXECUTE_OPERATOR, llList2CSV(                [operator, (string) llListFindList(OPERATORS, [operator])]), "");}default {    state_entry() {              gOwner = llGetOwner();        llListen(0, "", gOwner, "");                                // Pre-calculate these to save processing time.        gInfixPrefixLen = llStringLength(INFIX_PREFIX);        gRpnPrefixLen   = llStringLength(RPN_PREFIX);                Say("Free Memory: " + (string) llGetFreeMemory());    }        on_rez(integer param) {        // See if owner changed.        if (gOwner != llGetOwner())            llResetScript();    }        listen(integer channel, string name, key id, string mesg) {        // Go lowercase.        mesg = llToLower(mesg);        // Check for a command prefix.        if (llGetSubString(mesg, 0, gInfixPrefixLen - 1) == INFIX_PREFIX) {                        // Strip off the prefix.            string Command = llGetSubString(mesg, gInfixPrefixLen, -1);                            // Check for a special command.            if (CheckForCommand(Command))                return;                            // Parse the command into tokens, discarding spaces.            list Parsed = ParseTokens(Command);                                // Convert from in-fix to post-fix form.            ClearStack();            // Tell the processor a new command is starting.            llMessageLinked(LINK_SET, NEW_COMMAND, "", "");            // Set the last was operator flag for '-' processing.            gLastWasOperator = TRUE;                                    integer i;            string Token;            for (i = 0; i < llGetListLength(Parsed); i++) {                Token = llList2String(Parsed, i);                                            // Check for negative numbers.                if (Token == "-" && gLastWasOperator) {                    // Concatenate this with the next token.                           i++;                    Token = "-" + llList2String(Parsed, i);                }                                       if (IsOperand(Token)) {                    // Check for the special case that the next token is                    // the '=' operator, in which case we do not do a lookup.                    if (llList2String(Parsed, i + 1) == "=")                        // Bypass the variable handler.                        llMessageLinked(LINK_SET, PIPE_OPERAND,                             llList2CSV([Token, OP_STRING]), "");                      else                        // Send this to the variable handler for possible varable lookup.                        llMessageLinked(LINK_SET, VARIABLE_LOOKUP, Token, "");                    // Set the last was operator flag.                    gLastWasOperator = FALSE;                }                else {                    // Execute operators until there are none left, or                     // precedence takes over.                    while (!IsStackEmpty() && Precedence(StackTop(), Token))                        // Execute the operator.                        ExecuteOperator(Pop());                                            if (IsStackEmpty() || Token != ")")                        Push(Token);                    else // Pop the open paranthesis and discard it.                        Pop();                                            // Set the last was operator flag.                    gLastWasOperator = TRUE;                }            }                        // Add any remaining operators.            while (!IsStackEmpty())                // Execute the operator.                ExecuteOperator(Pop());                                // Tell the processor to display results.            // Pipe this through the variable lookup script,            // so that message timing is correct.            llMessageLinked(LINK_SET, PIPE_RESULTS, "", "");            return;        }        if (llGetSubString(mesg, 0, gRpnPrefixLen - 1) == RPN_PREFIX) {              // Strip off the prefix.            string Command = llGetSubString(mesg, gRpnPrefixLen, -1);                            // Check for a special command.            if (CheckForCommand(Command))                return;                            // Parse the command into tokens.            list Parsed = llParseString2List(Command, [" "], OPERATORS);                        // Tell the processor a new command is starting.            llMessageLinked(LINK_SET, NEW_COMMAND, "", "");                        integer i;            string Token;            for (i = 0; i < llGetListLength(Parsed); i++) {                Token = llList2String(Parsed, i);                                if (IsOperand(Token)) {                    // Send this to the variable handler for possible varable lookup.                    llMessageLinked(LINK_SET, VARIABLE_LOOKUP, Token, "");                   }                else {                    // Execute this operator.                    llMessageLinked(LINK_SET, EXECUTE_OPERATOR, llList2CSV(                                [Token, (string) llListFindList(OPERATORS, [Token])]), "");                }            }                                        // Tell the processor to display results.            // Pipe this through the variable lookup script,            // so that message timing is correct.            llMessageLinked(LINK_SET, PIPE_RESULTS, "", "");            return;        }    }}`
Xylor Baysklef
Join date: 4 May 2003
Posts: 109
02-14-2004 17:03
[edit: added patch by Francis Chung]

XyCalc Variables
CODE
`////////////////////////////////////////////// XyCalc Variables Script//// Written by Xylor Baysklef/////////////////////////////////////////////////////////// CONSTANTS ///////////////////// Channels to communicate with the processor.integer NEW_COMMAND      = 14000;integer PUSH_OPERAND     = 14001;integer EXECUTE_OPERATOR = 14002;integer DISPLAY_RESULTS  = 14003;integer XYCALC_SAY       = 14004;integer XYCALC_RESULTS   = 14005;// Variable Handler.integer VARIABLE_LOOKUP  = 14300;integer PIPE_RESULTS     = 14301;integer PIPE_OPERAND     = 14302;integer CMD_LIST_VARS    = 14303;integer CMD_CLEAR_VARS   = 14304;integer CMD_LIST_CONST   = 14305;// Bit-wise operand types.integer OP_OPERATOR     = 0;integer OP_INTEGER      = 1;integer OP_FLOAT        = 2;integer OP_NUMBER       = 3;integer OP_VECTOR       = 4;integer OP_ROTATION     = 8;integer OP_STRING       = 16;integer OP_PARAMS       = 32;//integer OP_RESERVED     = 64;integer OP_ANY          = 127;integer OP_MULTIPLIER   = 128;// OpHandler channels.integer OP_HANDLER_REQUEST  = 14100;integer OP_HANDLER_RETURN   = 14101;// These are invalid characters, that a // variable name cannot start with.string  INVALID_CHARS   = "0123456789.";// Math constant.float   e       = 2.71828182845904523536;// These are constants, always present.list    CONSTANT_NAMES    = ["pi", "e", "ans"];list    CONSTANT_VALUES   = [ PI, OP_FLOAT,                              e,  OP_FLOAT,                              0,  0         // Special                              ];///////////// END CONSTANTS ///////////////////////////// GLOBAL VARIABLES ///////////////// These hold the variable names.list    gVarNames   = CONSTANT_NAMES;// These hold the variable values.list    gVarValues  = CONSTANT_VALUES;// These are the number of constants in// the variables list, which we should not change.integer gNumConstants;// This is the last result info.string  gLastResult     = "0";integer gLastResultType = OP_INTEGER;// These are the operands we are working on.list    gOperandList;/////////// END GLOBAL VARIABLES ////////////Say(string mesg) {    // Send this to the xy calc script for output.    llMessageLinked(LINK_SET, XYCALC_SAY, mesg, "");}SendResults(string result, integer type) {    // Send back the results.    llMessageLinked(LINK_SET, OP_HANDLER_RETURN, llList2CSV(                    [result, type]), "");}Error(string operator, string mesg) {    // Send back the results as an error.    llMessageLinked(LINK_SET, OP_HANDLER_RETURN, llList2CSV(                    ["ERROR", operator, mesg]), "");}string FormatFloat(float num) {    string Float = (string) num;    // Remove trailing 0's.    integer i = llStringLength(Float) - 1;    integer NonZero = FALSE;    string Char;    integer NumZeroes = 0;    while( !NonZero && i >= 0) {        Char = llGetSubString(Float, i, i);        if (Char == "0")            NumZeroes++;        else if (Char == ".") {            // Back up one zero.            NumZeroes--;            NonZero = TRUE;        }        else            NonZero = TRUE;             i--;    }        return llGetSubString(Float, 0, -NumZeroes - 1);}string FormatData(string value, integer type) {    // Format this value based on its type.    if (type == OP_INTEGER)        return (string) ((integer) value);              else if (type == OP_FLOAT)        return FormatFloat((float) value);         else if (type == OP_VECTOR)        return (string) ((vector) value);          else if (type == OP_ROTATION)        return (string) ((rotation) value);          else if (type == OP_STRING)        return value;    else        return value + ", " + (string) type;}DisplayVariable(string name, string value, integer type) {    // Format the value, and display it.    Say(name + " = " + FormatData(value, type));}////////// OPERATOR LIST FUNCTIONS ///////////integer GetOpType(integer op_number) {    return llList2Integer(gOperandList, op_number * -2 + 1);}integer OpToInteger(integer op_number) {    return llList2Integer(gOperandList, op_number * -2);}float OpToFloat(integer op_number) {    return llList2Float(gOperandList, op_number * -2);}vector OpToVector(integer op_number) {    return llList2Vector(gOperandList, op_number * -2);}rotation OpToRotation(integer op_number) {    return llList2Rot(gOperandList, op_number * -2);}string OpToString(integer op_number) {    return llList2String(gOperandList, op_number * -2);}//////// END OPERATOR LIST FUNCTIONS ////////default {    state_entry() {             // Set the number of constants.        gNumConstants = llGetListLength(CONSTANT_NAMES);    }        link_message(integer sender, integer channel, string data, key id) {        if (channel == VARIABLE_LOOKUP) {            // Check if this operand is known.            integer VarIndex = llListFindList(gVarNames, [data]);                        // Just pass this on as unknown if we couldn't find it.            if (VarIndex == -1) {                llMessageLinked(LINK_SET, PUSH_OPERAND,                             llList2CSV([data, OP_STRING]), "");                return;            }                        // "ans" is special, check for that first.            if (data == "ans") {                llMessageLinked(LINK_SET, PUSH_OPERAND,                            llList2CSV([gLastResult, gLastResultType]), "");                return;            }                        // Otherwise replace this operand with our recorded            // value/type, and send that instead.            string VarValue     = llList2String (gVarValues, VarIndex * 2);            integer VarType     = llList2Integer(gVarValues, VarIndex * 2 + 1);                        llMessageLinked(LINK_SET, PUSH_OPERAND,                            llList2CSV([VarValue, VarType]), "");                                 return;        }        if (channel == XYCALC_RESULTS) {            // Record these results, and display them.            list Results = llCSV2List(data);                        gLastResult     = llList2String(Results, 0);            gLastResultType = llList2Integer(Results, 1);                           // Show results.            Say(FormatData(gLastResult, gLastResultType));                            return;        }        if (channel == OP_HANDLER_REQUEST) {                        // Split up the data.            list Parsed = llCSV2List(data);                        // See if this an assignment operator.            string Operator = llList2String(Parsed, 0);            if (Operator != "=")                // No,  Ignore it.                return;                            // Extract the operands.            gOperandList = llList2List(Parsed, 1, -1);                                            // Otherwise lets check the first operand for a valid name.            string VarName = OpToString(1);                        if (llSubStringIndex(INVALID_CHARS,                     llGetSubString(VarName, 0, 0)) != -1) {                Error(Operator, "Invalid variable name '" + VarName + "'");                return;            }                        // Valid variable name.  See if this variable is already known.            integer VarIndex = llListFindList(gVarNames, [VarName]);                        string  VarValue = OpToString(2);            integer VarType  = GetOpType(2);                                    if (VarIndex != -1) {                // See if this is a constant.                if (VarIndex < gNumConstants) {                    // Trigger error.                    Error("=", "Cannot assign to the constant '" + VarName + "'");                    SendResults(VarValue, VarType);                    return;                }                // Remove the old one.                gVarNames   = llDeleteSubList(gVarNames, VarIndex, VarIndex);                gVarValues  = llDeleteSubList(gVarValues, VarIndex * 2, VarIndex * 2 + 1);            }                                    // Add this variable.                        gVarNames   += [VarName];            gVarValues  += [VarValue, VarType];                        SendResults(VarValue, VarType);            return;                       }        if (channel == PIPE_RESULTS) {            // Just pass this on to the main processor.  It is only            // sent here to make sure message timings are syncronized.            llMessageLinked(LINK_SET, DISPLAY_RESULTS, "", "");            return;        }        if (channel == PIPE_OPERAND) {            // Pass this through unfiltered.  This keeps messages            // syncronized.            llMessageLinked(LINK_SET, PUSH_OPERAND, data, "");            return;        }        if (channel == CMD_LIST_VARS) {            // List all variables.            // First see if there are any variables to show.            integer NumVars = llGetListLength(gVarNames);            if (NumVars <= gNumConstants) {                Say("No variables.");            }            else {                // Go through the variables list, and display them.                integer i;                for (i = gNumConstants; i < NumVars; i++) {                    string VarName      = llList2String(gVarNames, i);                    string VarValue     = llList2String (gVarValues, i * 2);                    integer VarType     = llList2Integer(gVarValues, i * 2 + 1);                                        DisplayVariable(VarName, VarValue, VarType);                }            }            return;        }        if (channel == CMD_CLEAR_VARS) {            // Clear all variables.            gVarNames   = CONSTANT_NAMES;            gVarValues  = CONSTANT_VALUES;               Say("Variables cleared.");                     return;        }        if (channel == CMD_LIST_CONST) {            // Go through the constants in the variable list, and display them.            integer i;            // Don't show the last one (ans), we will handle this seperately.            for (i = 0; i < gNumConstants - 1; i++) {                string VarName      = llList2String(gVarNames, i);                string VarValue     = llList2String (gVarValues, i * 2);                integer VarType     = llList2Integer(gVarValues, i * 2 + 1);                                DisplayVariable(VarName, VarValue, VarType);            }            // Show 'ans'.            DisplayVariable("ans", gLastResult, gLastResultType);            return;        }    }}`

XyCalc OpHandler +-*/^%&|~
CODE
`////////////////////////////////////////////// XyCalc OpHandler +-*/^%&|~ Script//// Written by Xylor Baysklef/////////////////////////////////////////////////////////// CONSTANTS ///////////////////// These are the operators this script handles.list    HANDLED_OPERATORS   = [ "+", "-", "*", "/",                                 "^", "%", "&", "|", "~"];// OpHandler channels.integer OP_HANDLER_REQUEST  = 14100;integer OP_HANDLER_RETURN   = 14101;// Bit-wise operand types.integer OP_OPERATOR     = 0;integer OP_INTEGER      = 1;integer OP_FLOAT        = 2;integer OP_NUMBER       = 3;integer OP_VECTOR       = 4;integer OP_ROTATION     = 8;integer OP_STRING       = 16;integer OP_PARAMS       = 32;//integer OP_RESERVED     = 64;integer OP_ANY          = 127;integer OP_MULTIPLIER   = 128;///////////// END CONSTANTS ///////////////////////////// GLOBAL VARIABLES ///////////////// These are the operands we are working on.list    gOperandList;/////////// END GLOBAL VARIABLES ////////////////////// OPERATOR LIST FUNCTIONS ///////////integer GetOpType(integer op_number) {    return llList2Integer(gOperandList, op_number * -2 + 1);}integer OpToInteger(integer op_number) {    return llList2Integer(gOperandList, op_number * -2);}float OpToFloat(integer op_number) {    return llList2Float(gOperandList, op_number * -2);}vector OpToVector(integer op_number) {    return llList2Vector(gOperandList, op_number * -2);}rotation OpToRotation(integer op_number) {    return llList2Rot(gOperandList, op_number * -2);}//////// END OPERATOR LIST FUNCTIONS ////////SendResults(string result, integer type) {    // Send back the results.    llMessageLinked(LINK_SET, OP_HANDLER_RETURN, llList2CSV(                    [result, type]), "");}Error(string operator, string mesg) {    // Send back the results as an error.    llMessageLinked(LINK_SET, OP_HANDLER_RETURN, llList2CSV(                    ["ERROR", operator, mesg]), "");}DivideByZero(string operator) {    Error(operator, "Divide by zero");}///// Start Patch by Francis Chung// Fran wuz here//// The `fmod' function  returns  the  value  X-I*Y,  for  the// largest  integer  I such that, if Y is nonzero, the result// has the same sign as X and magnitude less than the  magni-// tude of Y.// Raises divide by zero when y = 0, but as far as I know, LSL// doesn't allow me to specify NaN, soo...float fmod( float x, float y ) {    float sign = 1;    float maxI = 1;    float k;    if ( x ) {        sign = x/llFabs(x);        x = llFabs(x);     }            if ( y )        y = llFabs(y);    else {        DivideByZero("%");        return 0;    }        while ( x > maxI * y )        maxI *= 2;    for( k = maxI/2; k >= 1; k/=2 ) {        if ( k*y < x )            x -= k*y;    }        return x * sign;}////// End Patch by Francis Chungdefault {    state_entry() {         }            link_message(integer sender, integer channel, string data, key id) {        if (channel == OP_HANDLER_REQUEST) {            // Split up the data.            list Parsed = llCSV2List(data);                                    // See if we need to handle this request.            string Operator = llList2String(Parsed, 0);                        if (llListFindList(HANDLED_OPERATORS, [Operator]) == -1)                // No, ignore it.                return;                            // Extract the operands.            gOperandList = llList2List(Parsed, 1, -1);                            // Check the operator, and execute it.            if (Operator == "+") {                // If both operands are integers, keep the result                // an integer.                if (GetOpType(1) == OP_INTEGER &&                    GetOpType(2) == OP_INTEGER)                    // Stay in integer form.                    SendResults((string) ( OpToInteger(1) + OpToInteger(2) ), OP_INTEGER);                else                    // Go to float form.                    SendResults((string) ( OpToFloat(1) + OpToFloat(2) ), OP_FLOAT);            }            else if (Operator == "-") {                // If both operands are integers, keep the result                // an integer.                if (GetOpType(1) == OP_INTEGER &&                    GetOpType(2) == OP_INTEGER)                    // Stay in integer form.                    SendResults((string) ( OpToInteger(1) - OpToInteger(2) ), OP_INTEGER);                else                    // Go to float form.                    SendResults((string) ( OpToFloat(1) - OpToFloat(2) ), OP_FLOAT);            }            else if (Operator == "*") {                // If both operands are integers, keep the result                // an integer.                if (GetOpType(1) == OP_INTEGER &&                    GetOpType(2) == OP_INTEGER)                    // Stay in integer form.                    SendResults((string) ( OpToInteger(1) * OpToInteger(2) ), OP_INTEGER);                else                    // Go to float form.                    SendResults((string) ( OpToFloat(1) * OpToFloat(2) ), OP_FLOAT);            }            else if (Operator == "/") {                // Check for divide by 0.                if ( llFabs(OpToFloat(2)) < 0.00001 ) {                    DivideByZero(Operator);                    return;                }                                // If both operands are integers, keep the result                // an integer (if possible).                if (GetOpType(1) == OP_INTEGER &&                    GetOpType(2) == OP_INTEGER) {                    // Try to stay in integer form.                    integer OpInt1 = OpToInteger(1);                    integer OpInt2 = OpToInteger(2);                                        if ( OpInt1 % OpInt2 == 0)                        // We can stay integer.                                            SendResults((string) ( OpInt1 / OpInt2 ), OP_INTEGER);                    else                        // There is a remainder, go float.                        SendResults((string) ( OpToFloat(1) / OpToFloat(2) ), OP_FLOAT);                }                else                    // Go to float form.                    SendResults((string) ( OpToFloat(1) / OpToFloat(2) ), OP_FLOAT);            }            else if (Operator == "^") {                // Check for divide by 0.                float Op1 = OpToFloat(1);                float Op2 = OpToFloat(2);                                if (Op1 == 0 && Op2 <= 0) {                    DivideByZero(Operator);                    return;                }                                // If both operands are integers, keep the result                // an integer.                float Result = llPow(Op1, Op2);                                if (GetOpType(1) == OP_INTEGER &&                    GetOpType(2) == OP_INTEGER &&                    Op2 > 0)                    // Stay in integer form.                    SendResults((string) Result, OP_INTEGER);                else                    // Go to float form.                    SendResults((string) Result, OP_FLOAT);            }            else if (Operator == "%") {                ///// Start Patch by Francis Chung                if ( GetOpType(1) == OP_INTEGER && GetOpType(2) == OP_INTEGER ) {                    SendResults((string) (OpToInteger(1) % OpToInteger(2)), OP_INTEGER);                }                else {                    float x = 0;                    float y = 1;                    if ( GetOpType(1) == OP_INTEGER )                        x = OpToInteger(1);                    if ( GetOpType(1) == OP_FLOAT )                        x = OpToFloat(1);                    if ( GetOpType(2) == OP_INTEGER )                        y = OpToInteger(2);                    if ( GetOpType(2) == OP_FLOAT )                        y = OpToFloat(2);                                            SendResults((string) fmod(x,y), OP_FLOAT);                }                ////// End Patch by Francis Chung             }            else if (Operator == "&") {                SendResults((string) (OpToInteger(1) & OpToInteger(2)), OP_INTEGER);            }            else if (Operator == "|") {                SendResults((string) (OpToInteger(1) | OpToInteger(2)), OP_INTEGER);            }            else if (Operator == "~") {                SendResults((string) (~OpToInteger(1)), OP_INTEGER);            }                        return;        }    }}`
Xylor Baysklef
Join date: 4 May 2003
Posts: 109
02-14-2004 17:04
XyCalc OpHandler Transcendental
CODE
`////////////////////////////////////////////// XyCalc OpHandler Transcendental Script//// Written by Xylor Baysklef/////////////////////////////////////////////////////////// CONSTANTS ///////////////////// These are the operators this script handles.list    HANDLED_OPERATORS   = [ "sin", "cos", "tan",                                "asin", "acos", "atan",                                "sinh", "cosh", "tanh",                                "asinh", "acosh", "atanh",                                "ln", "log", "sqrt"];// Used to re-route output.integer XYCALC_SAY          = 14004;// OpHandler channels.integer OP_HANDLER_REQUEST  = 14100;integer OP_HANDLER_RETURN   = 14101;// Channels to listen for mode info.integer MODE_DEGREE      = 14200;integer MODE_RADIAN      = 14201;// Bit-wise operand types.integer OP_OPERATOR     = 0;integer OP_INTEGER      = 1;integer OP_FLOAT        = 2;integer OP_NUMBER       = 3;integer OP_VECTOR       = 4;integer OP_ROTATION     = 8;integer OP_STRING       = 16;integer OP_PARAMS       = 32;//integer OP_RESERVED     = 64;integer OP_ANY          = 127;integer OP_MULTIPLIER   = 128;// Math Constants.float   e       = 2.71828182845904523536;float   LOG_10  = 2.302585092994;float   LN_ERROR_MARGIN = 0.01;// How long before timing out.float   LN_CALC_TIMEOUT = 15.0;///////////// END CONSTANTS ///////////////////////////// GLOBAL VARIABLES ///////////////// These are the operands we are working on.list    gOperandList;// This is used to convert from deg to rad,// if needed.// Note: We start in DEGREE mode by default.float   gModeMultiplier = DEG_TO_RAD;/////////// END GLOBAL VARIABLES ////////////Say(string mesg) {    // Send this to the xy calc script for output.    llMessageLinked(LINK_SET, XYCALC_SAY, mesg, "");}/////////////// MATH FUNCTIONS /////////////////////float Ln(float x) {        // Use the power series:    // ln(x) = 2 * Sum{n=0, n=Inf} [ ([(x-1)/(x+1)]^(2n+1)) / 2n+1 ]    // Keep interating until the current term is less    // than LN_ERROR_MARGIN.            // Scale this to match the individual term magnitude.    float ErrorMargin = LN_ERROR_MARGIN * LN_ERROR_MARGIN / 2.0;        // Precalculate (x-1)/(x+1), and [(x-1)/(x+1)]^2 (so we    // avoid repeatedly calling llPow), and initialize variables    // used for lookup of previous term results    float X_Term = (x - 1) / (x + 1);    float X_Term_Squared = X_Term * X_Term;        float Result = X_Term;        float This_X_Term = X_Term;    float ThisFullTerm;        // (Start on n=2*1+1=3)    integer n = 3;        // Keep track of how long we are trying this, and just    // use whatever we came up with at the timeout point.      llResetTime();    do {        This_X_Term *= X_Term_Squared;        ThisFullTerm = This_X_Term / n;        Result += ThisFullTerm;        n += 2;    } while (llFabs(ThisFullTerm) > ErrorMargin &&             llGetTime() < LN_CALC_TIMEOUT);    // Give a warning if we timed out.    if (llFabs(ThisFullTerm) > ErrorMargin) {        Say("Warning: Ln(x) calculation timed out.");    }        return Result * 2;}float Log(float x) {    // This returns the log, base 10, of x.    return Ln(x) / LOG_10;}float Cosh(float x) {    return (llPow(e, x) + llPow(e, -x)) / 2.0;}float Sinh(float x) {    return (llPow(e, x) - llPow(e, -x)) / 2.0;}float Tanh(float x) {    return Sinh(x) / Cosh(x);}float Asinh(float x) {    return Ln(x + llSqrt(x * x + 1));}float Acosh(float x) {    return Ln(x + llSqrt(x * x - 1));}float Atanh(float x) {    return Ln( (1 + x) / (1 - x) ) / 2;}///////////// END MATH FUNCTIONS //////////////////////////// OPERATOR LIST FUNCTIONS ///////////integer GetOpType(integer op_number) {    return llList2Integer(gOperandList, op_number * -2 + 1);}integer OpToInteger(integer op_number) {    return llList2Integer(gOperandList, op_number * -2);}float OpToFloat(integer op_number) {    return llList2Float(gOperandList, op_number * -2);}vector OpToVector(integer op_number) {    return llList2Vector(gOperandList, op_number * -2);}rotation OpToRotation(integer op_number) {    return llList2Rot(gOperandList, op_number * -2);}//////// END OPERATOR LIST FUNCTIONS ////////SendResults(string result, integer type) {    // Send back the results.    llMessageLinked(LINK_SET, OP_HANDLER_RETURN, llList2CSV(                    [result, type]), "");}Error(string operator, string mesg) {    // Send back the results as an error.    llMessageLinked(LINK_SET, OP_HANDLER_RETURN, llList2CSV(                    ["ERROR", operator, mesg]), "");}DomainError(string operator) {    Error(operator, "Invalid domain");}DivideByZero(string operator) {    Error(operator, "Divide by zero");}default {    state_entry() {    }            link_message(integer sender, integer channel, string data, key id) {        if (channel == OP_HANDLER_REQUEST) {            // Split up the data.            list Parsed = llCSV2List(data);                                    // See if we need to handle this request.            string Operator = llList2String(Parsed, 0);                        if (llListFindList(HANDLED_OPERATORS, [Operator]) == -1)                // No, ignore it.                return;                            // Extract the operands.            gOperandList = llList2List(Parsed, 1, -1);                            // Check the operator, and execute it.            if (Operator == "sqrt") {                // Bounds check.                float Operand = OpToFloat(1);                if (Operand < 0) {                    DomainError(Operator);                    return;                }                                           SendResults((string) (llSqrt(Operand)), OP_FLOAT);                     }            else if (Operator == "sin") {                SendResults((string) llSin(OpToFloat(1) * gModeMultiplier), OP_FLOAT);            }            else if (Operator == "cos") {                SendResults((string) llCos(OpToFloat(1) * gModeMultiplier), OP_FLOAT);            }            else if (Operator == "tan") {                SendResults((string) llTan(OpToFloat(1) * gModeMultiplier), OP_FLOAT);            }            else if (Operator == "asin") {                // Bounds check.                float Operand = OpToFloat(1);                if (Operand < -1.0)                    Operand = -1.0;                                    if (Operand > 1.0)                    Operand = 1.0;                                    SendResults((string) (llAsin(Operand) / gModeMultiplier), OP_FLOAT);            }            else if (Operator == "acos") {                // Bounds check.                float Operand = OpToFloat(1);                if (Operand < -1.0)                    Operand = -1.0;                                    if (Operand > 1.0)                    Operand = 1.0;                                    SendResults((string) (llAcos(Operand) / gModeMultiplier), OP_FLOAT);            }            else if (Operator == "atan") {                                    SendResults((string) (llAtan2(OpToFloat(1), 1) / gModeMultiplier), OP_FLOAT);            }                                    else if (Operator == "sinh") {                SendResults((string) Sinh(OpToFloat(1)), OP_FLOAT);            }            else if (Operator == "cosh") {                SendResults((string) Cosh(OpToFloat(1)), OP_FLOAT);            }            else if (Operator == "tanh") {                SendResults((string) Tanh(OpToFloat(1)), OP_FLOAT);            }                        else if (Operator == "asinh") {                SendResults((string) Asinh(OpToFloat(1)), OP_FLOAT);            }            else if (Operator == "acosh") {                // Check domain.                float Operand = OpToFloat(1);                if (Operand < 1.0) {                    DomainError(Operator);                    return;                }                SendResults((string) Acosh(Operand), OP_FLOAT);            }            else if (Operator == "atanh") {                // Check domain.                float Operand = OpToFloat(1);                if (Operand <= -1.0 ||                    Operand >= 1.0) {                    DomainError(Operator);                    return;                }                SendResults((string) Atanh(Operand), OP_FLOAT);            }            else if (Operator == "ln") {                // Check domain.                float Operand = OpToFloat(1);                if (Operand <= 0.0) {                    DomainError(Operator);                    return;                }                SendResults((string) Ln(Operand), OP_FLOAT);            }            else if (Operator == "log") {                // Check domain.                float Operand = OpToFloat(1);                if (Operand <= 0.0) {                    DomainError(Operator);                    return;                }                SendResults((string) (Ln(Operand) / LOG_10), OP_FLOAT);            }                        return;        }        if (channel == MODE_DEGREE) {            // Set the mode multiplier.            gModeMultiplier = DEG_TO_RAD;            Say("Trig is now in degree mode.");            return;        }        if (channel == MODE_RADIAN) {            // Set the mode multiplier.            gModeMultiplier = 1.0;            Say("Trig is now in radian mode.");            return;        }    }}`

XyCalc OpHandler Misc
CODE
`////////////////////////////////////////////// XyCalc OpHandler Misc Script//// Written by Xylor Baysklef/////////////////////////////////////////////////////////// CONSTANTS ///////////////////// These are the operators this script handles.list    HANDLED_OPERATORS   = [ "abs", "rand", "round",                                 "floor", "ceil"];// OpHandler channels.integer OP_HANDLER_REQUEST  = 14100;integer OP_HANDLER_RETURN   = 14101;// Bit-wise operand types.integer OP_OPERATOR     = 0;integer OP_INTEGER      = 1;integer OP_FLOAT        = 2;integer OP_NUMBER       = 3;integer OP_VECTOR       = 4;integer OP_ROTATION     = 8;integer OP_STRING       = 16;integer OP_PARAMS       = 32;//integer OP_RESERVED     = 64;integer OP_ANY          = 127;integer OP_MULTIPLIER   = 128;///////////// END CONSTANTS ///////////////////////////// GLOBAL VARIABLES ///////////////// These are the operands we are working on.list    gOperandList;/////////// END GLOBAL VARIABLES ////////////////////// OPERATOR LIST FUNCTIONS ///////////integer GetOpType(integer op_number) {    return llList2Integer(gOperandList, op_number * -2 + 1);}integer OpToInteger(integer op_number) {    return llList2Integer(gOperandList, op_number * -2);}float OpToFloat(integer op_number) {    return llList2Float(gOperandList, op_number * -2);}vector OpToVector(integer op_number) {    return llList2Vector(gOperandList, op_number * -2);}rotation OpToRotation(integer op_number) {    return llList2Rot(gOperandList, op_number * -2);}//////// END OPERATOR LIST FUNCTIONS ////////SendResults(string result, integer type) {    // Send back the results.    llMessageLinked(LINK_SET, OP_HANDLER_RETURN, llList2CSV(                    [result, type]), "");}Error(string operator, string mesg) {    // Send back the results as an error.    llMessageLinked(LINK_SET, OP_HANDLER_RETURN, llList2CSV(                    ["ERROR", operator, mesg]), "");}DivideByZero(string operator) {    Error(operator, "Divide by zero");}default {    state_entry() {         }            link_message(integer sender, integer channel, string data, key id) {        if (channel == OP_HANDLER_REQUEST) {            // Split up the data.            list Parsed = llCSV2List(data);                                    // See if we need to handle this request.            string Operator = llList2String(Parsed, 0);                        if (llListFindList(HANDLED_OPERATORS, [Operator]) == -1)                // No, ignore it.                return;                            // Extract the operands.            gOperandList = llList2List(Parsed, 1, -1);                            // Check the operator, and execute it.            if (Operator == "abs") {                // If operands is an integer, keep the result                // an integer.                if (GetOpType(1) == OP_INTEGER)                    // Stay in integer form.                    SendResults((string) llAbs(OpToInteger(1)), OP_INTEGER);                else                    // Go to float form.                    SendResults((string) llFabs(OpToFloat(1)), OP_FLOAT);            }            else if (Operator == "rand") {                // If operands is an integer, keep the result                // an integer.                if (GetOpType(1) == OP_INTEGER) {                    // Stay in integer form.  Return 1 to Operand                    integer Operand = OpToInteger(1);                                                 integer Result;                    // Check for 0.                    if (Operand == 0)                        Result = 0;                    // Otherwise check sign, and send back results.                    else if (Operand < 0) {                        Result = llFloor(llFrand(Operand));                        // This is a very small possibility, but...                        if (Result == 0)                            Result = -1;                                                                      }                    else { // Operand > 0                        Result = llCeil(llFrand(Operand));                        // This is a very small possibility, but...                        if (Result == 0)                            Result = 1;                                                }                           // Send back the results.                    SendResults((string) Result, OP_INTEGER);                                   }                else                    // Go to float form.                    SendResults((string) llFrand(OpToFloat(1)), OP_FLOAT);            }            else if (Operator == "round") {                SendResults((string) llRound(OpToFloat(1)), OP_INTEGER);            }            else if (Operator == "floor") {                SendResults((string) llFloor(OpToFloat(1)), OP_INTEGER);            }            else if (Operator == "ceil") {                SendResults((string) llCeil(OpToFloat(1)), OP_INTEGER);            }            return;        }    }}`
Xylor Baysklef
`...DivideByZero(string operator) {    Error(operator, "Divide by zero");}///// Start Patch by Francis Chung /////////////////////////////////////// Fran wuz here//// The `fmod' function  returns  the  value  X-I*Y,  for  the// largest  integer  I such that, if Y is nonzero, the result// has the same sign as X and magnitude less than the  magni-// tude of Y.// Raises divide by zero when y = 0, but as far as I know, LSL// doesn't allow me to specify NaN, soo...float fmod( float x, float y ) {    float sign = 1;    float maxI = 1;    float k;    if ( x ) {        sign = x/llFabs(x);        x = llFabs(x);     }            if ( y )        y = llFabs(y);    else {        DivideByZero("%");        return 0;    }        while ( x > maxI * y )        maxI *= 2;    for( k = maxI/2; k >= 1; k/=2 ) {        if ( k*y < x )            x -= k*y;    }        return x * sign;}////// End Patch by Francis Chung //////////////////////////////////////default {    state_entry() {         }.....                    // Go to float form.                    SendResults((string) Result, OP_FLOAT);            }            else if (Operator == "%") {                ///// Start Patch by Francis Chung /////////////////////////////////////                if ( GetOpType(1) == OP_INTEGER && GetOpType(2) == OP_INTEGER ) {                    SendResults((string) (OpToInteger(1) % OpToInteger(2)), OP_INTEGER);                }                else {                    float x = 0;                    float y = 1;                    if ( GetOpType(1) == OP_INTEGER )                        x = OpToInteger(1);                    if ( GetOpType(1) == OP_FLOAT )                        x = OpToFloat(1);                    if ( GetOpType(2) == OP_INTEGER )                        y = OpToInteger(2);                    if ( GetOpType(2) == OP_FLOAT )                        y = OpToFloat(2);                                            SendResults((string) fmod(x,y), OP_FLOAT);                }                ////// End Patch by Francis Chung //////////////////////////////////////            }            else if (Operator == "&") {                SendResults((string) (OpToInteger(1) & OpToInteger(2)), OP_INTEGER);            }...`