- moved most of the console code to 'common'.
The main console.cpp file cannot be done yet, but the rest is ready to go.
This commit is contained in:
parent
a712866219
commit
c3a381ed92
19 changed files with 16 additions and 12 deletions
812
src/common/console/c_expr.cpp
Normal file
812
src/common/console/c_expr.cpp
Normal file
|
|
@ -0,0 +1,812 @@
|
|||
/*
|
||||
** c_expr.cpp
|
||||
** Console commands dealing with mathematical expressions
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "c_dispatch.h"
|
||||
#include "c_cvars.h"
|
||||
#include "cmdlib.h"
|
||||
#include "printf.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
enum EProductionType
|
||||
{
|
||||
PROD_String, PROD_Double
|
||||
};
|
||||
|
||||
struct FProduction
|
||||
{
|
||||
EProductionType Type;
|
||||
};
|
||||
|
||||
struct FStringProd : public FProduction
|
||||
{
|
||||
char Value[1];
|
||||
};
|
||||
|
||||
struct FDoubleProd : public FProduction
|
||||
{
|
||||
double Value;
|
||||
};
|
||||
|
||||
struct FProducer
|
||||
{
|
||||
char Token[4];
|
||||
FProduction *(*DoubleProducer) (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *(*StringProducer) (FStringProd *prod1, FStringProd *prod2);
|
||||
};
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
bool IsFloat (const char *str);
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
static FProduction *ParseExpression (FCommandLine &argv, int &parsept);
|
||||
static const char *CIsNum (const char *str);
|
||||
static FStringProd *NewStringProd (const char *str);
|
||||
static FStringProd *NewStringProd (size_t len);
|
||||
static FDoubleProd *NewDoubleProd (double val);
|
||||
static FStringProd *DoubleToString (FProduction *prod);
|
||||
static FDoubleProd *StringToDouble (FProduction *prod);
|
||||
void MaybeStringCoerce (FProduction *&prod1, FProduction *&prod2);
|
||||
void MustStringCoerce (FProduction *&prod1, FProduction *&prod2);
|
||||
void DoubleCoerce (FProduction *&prod1, FProduction *&prod2);
|
||||
|
||||
FProduction *ProdAddDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdAddStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdSubDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdMulDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdDivDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdModDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdPowDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdLTDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdLTEDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdGTDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdGTEDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdEqDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdNeqDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdXorDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdAndDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdOrDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdLAndDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdLOrDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdLTStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdLTEStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdGTStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdGTEStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdEqStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdNeqStr (FStringProd *prod1, FStringProd *prod2);
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static FProducer Producers[] =
|
||||
{
|
||||
{ "+", ProdAddDbl, ProdAddStr },
|
||||
{ "-", ProdSubDbl, NULL },
|
||||
{ "*", ProdMulDbl, NULL },
|
||||
{ "/", ProdDivDbl, NULL },
|
||||
{ "%", ProdModDbl, NULL },
|
||||
{ "^", ProdPowDbl, NULL },
|
||||
{ "<", ProdLTDbl, ProdLTStr },
|
||||
{ "<=", ProdLTEDbl, ProdLTEStr },
|
||||
{ ">", ProdGTDbl, ProdGTStr },
|
||||
{ ">=", ProdGTEDbl, ProdGTEStr },
|
||||
{ "=", ProdEqDbl, ProdEqStr },
|
||||
{ "==", ProdEqDbl, ProdEqStr },
|
||||
{ "!=", ProdNeqDbl, ProdNeqStr },
|
||||
{ "<>", ProdNeqDbl, ProdNeqStr },
|
||||
{ "xor", ProdXorDbl, NULL },
|
||||
{ "&", ProdAndDbl, NULL },
|
||||
{ "|", ProdOrDbl, NULL },
|
||||
{ "&&", ProdLAndDbl, NULL },
|
||||
{ "||", ProdLOrDbl, NULL }
|
||||
};
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ParseExpression
|
||||
//
|
||||
// Builds a production from an expression. The supported syntax is LISP-like
|
||||
// but without parentheses.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FProduction *ParseExpression (FCommandLine &argv, int &parsept)
|
||||
{
|
||||
if (parsept >= argv.argc())
|
||||
return NULL;
|
||||
|
||||
const char *token = argv[parsept++];
|
||||
FProduction *prod1 = NULL, *prod2 = NULL, *prod3 = NULL;
|
||||
|
||||
if (IsFloat (token))
|
||||
{
|
||||
return NewDoubleProd (atof(token));
|
||||
}
|
||||
else if (stricmp (token, "true") == 0)
|
||||
{
|
||||
return NewDoubleProd (1.0);
|
||||
}
|
||||
else if (stricmp (token, "false") == 0)
|
||||
{
|
||||
return NewDoubleProd (0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < countof(Producers); ++i)
|
||||
{
|
||||
if (strcmp (Producers[i].Token, token) == 0)
|
||||
{
|
||||
prod1 = ParseExpression (argv, parsept);
|
||||
prod2 = ParseExpression (argv, parsept);
|
||||
if (prod1 == NULL || prod2 == NULL)
|
||||
{
|
||||
goto missing;
|
||||
}
|
||||
if (Producers[i].StringProducer == NULL)
|
||||
{
|
||||
DoubleCoerce (prod1, prod2);
|
||||
}
|
||||
else if (Producers[i].DoubleProducer == NULL)
|
||||
{
|
||||
MustStringCoerce (prod1, prod2);
|
||||
}
|
||||
else
|
||||
{
|
||||
MaybeStringCoerce (prod1, prod2);
|
||||
}
|
||||
if (prod1->Type == PROD_String)
|
||||
{
|
||||
prod3 = Producers[i].StringProducer ((FStringProd *)prod1, (FStringProd *)prod2);
|
||||
}
|
||||
else
|
||||
{
|
||||
prod3 = Producers[i].DoubleProducer ((FDoubleProd *)prod1, (FDoubleProd *)prod2);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (strcmp ("!", token) == 0)
|
||||
{
|
||||
prod1 = ParseExpression (argv, parsept);
|
||||
if (prod1 == NULL)
|
||||
{
|
||||
goto missing;
|
||||
}
|
||||
if (prod1->Type == PROD_String)
|
||||
{
|
||||
prod1 = StringToDouble (prod1);
|
||||
}
|
||||
prod3 = NewDoubleProd (!static_cast<FDoubleProd *>(prod1)->Value);
|
||||
goto done;
|
||||
}
|
||||
return NewStringProd (token);
|
||||
}
|
||||
|
||||
missing:
|
||||
Printf ("Missing argument to %s\n", token);
|
||||
|
||||
done:
|
||||
if (prod2 != NULL) M_Free (prod2);
|
||||
if (prod1 != NULL) M_Free (prod1);
|
||||
return prod3;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsFloat
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool IsFloat (const char *str)
|
||||
{
|
||||
const char *pt;
|
||||
|
||||
if (*str == '+' || *str == '-')
|
||||
str++;
|
||||
|
||||
if (*str == '.')
|
||||
{
|
||||
pt = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
pt = CIsNum (str);
|
||||
if (pt == NULL)
|
||||
return false;
|
||||
}
|
||||
if (*pt == '.')
|
||||
{
|
||||
pt = CIsNum (pt+1);
|
||||
if (pt == NULL)
|
||||
return false;
|
||||
}
|
||||
if (*pt == 'e' || *pt == 'E')
|
||||
{
|
||||
pt++;
|
||||
if (*pt == '+' || *pt == '-')
|
||||
pt++;
|
||||
pt = CIsNum (pt);
|
||||
}
|
||||
return pt != NULL && *pt == 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsNum
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static const char *CIsNum (const char *str)
|
||||
{
|
||||
const char *start = str;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
if (*str >= '0' && *str <= '9')
|
||||
str++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return (str > start) ? str : NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// NewStringProd (from a string)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FStringProd *NewStringProd (const char *str)
|
||||
{
|
||||
FStringProd *prod = (FStringProd *)M_Malloc (sizeof(FStringProd)+strlen(str));
|
||||
prod->Type = PROD_String;
|
||||
strcpy (prod->Value, str);
|
||||
return prod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// NewStringProd (from a length)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FStringProd *NewStringProd (size_t len)
|
||||
{
|
||||
FStringProd *prod = (FStringProd *)M_Malloc (sizeof(FStringProd)+len);
|
||||
prod->Type = PROD_String;
|
||||
prod->Value[0] = 0;
|
||||
return prod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// NewDoubleProd
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FDoubleProd *NewDoubleProd (double val)
|
||||
{
|
||||
FDoubleProd *prod = (FDoubleProd *)M_Malloc (sizeof(FDoubleProd));
|
||||
prod->Type = PROD_Double;
|
||||
prod->Value = val;
|
||||
return prod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DoubleToString
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FStringProd *DoubleToString (FProduction *prod)
|
||||
{
|
||||
char buf[128];
|
||||
FStringProd *newprod;
|
||||
|
||||
mysnprintf (buf, countof(buf), "%g", static_cast<FDoubleProd *>(prod)->Value);
|
||||
newprod = NewStringProd (buf);
|
||||
M_Free (prod);
|
||||
return newprod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// StringToDouble
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FDoubleProd *StringToDouble (FProduction *prod)
|
||||
{
|
||||
FDoubleProd *newprod;
|
||||
|
||||
newprod = NewDoubleProd (atof (static_cast<FStringProd *>(prod)->Value));
|
||||
M_Free (prod);
|
||||
return newprod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MaybeStringCoerce
|
||||
//
|
||||
// If one of the parameters is a string, convert the other to a string.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MaybeStringCoerce (FProduction *&prod1, FProduction *&prod2)
|
||||
{
|
||||
if (prod1->Type == PROD_String)
|
||||
{
|
||||
if (prod2->Type == PROD_Double)
|
||||
{
|
||||
prod2 = DoubleToString (prod2);
|
||||
}
|
||||
}
|
||||
else if (prod2->Type == PROD_String)
|
||||
{
|
||||
prod1 = DoubleToString (prod1);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MustStringCoerce
|
||||
//
|
||||
// Ensures that both parameters are strings
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MustStringCoerce (FProduction *&prod1, FProduction *&prod2)
|
||||
{
|
||||
if (prod1->Type == PROD_Double)
|
||||
{
|
||||
prod1 = DoubleToString (prod1);
|
||||
}
|
||||
if (prod2->Type == PROD_Double)
|
||||
{
|
||||
prod2 = DoubleToString (prod2);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DoubleCoerce
|
||||
//
|
||||
// Ensures that both parameters are doubles
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DoubleCoerce (FProduction *&prod1, FProduction *&prod2)
|
||||
{
|
||||
if (prod1->Type == PROD_String)
|
||||
{
|
||||
prod1 = StringToDouble (prod1);
|
||||
}
|
||||
if (prod2->Type == PROD_String)
|
||||
{
|
||||
prod2 = StringToDouble (prod2);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdAddDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdAddDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value + prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdAddStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdAddStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
size_t len = strlen (prod1->Value) + strlen (prod2->Value) + 1;
|
||||
FStringProd *prod = NewStringProd (len);
|
||||
strcpy (prod->Value, prod1->Value);
|
||||
strcat (prod->Value, prod2->Value);
|
||||
return prod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdSubDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdSubDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value - prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdMulDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdMulDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value * prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdDivDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdDivDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value / prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdModDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdModDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (fmod (prod1->Value, prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdPowDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdPowDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (pow (prod1->Value, prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLTDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLTDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value < prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLTEDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLTEDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value <= prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdGTDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdGTDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value > prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdGTEDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdGTEDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value >= prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdEqDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdEqDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value == prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdNeqDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdNeqDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value != prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLTStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLTStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) < 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLTEStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLTEStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) <= 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdGTStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdGTStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) > 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdGTEStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdGTEStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) >= 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdEqStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdEqStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) == 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdNeqStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdNeqStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) != 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdXorDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdXorDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd ((double)((int64_t)prod1->Value ^ (int64_t)prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdAndDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdAndDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd ((double)((int64_t)prod1->Value & (int64_t)prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdOrDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdOrDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd ((double)((int64_t)prod1->Value | (int64_t)prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLAndDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLAndDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd ((double)((int64_t)prod1->Value && (int64_t)prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLOrDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLOrDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd ((double)((int64_t)prod1->Value || (int64_t)prod2->Value));
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CCMD test
|
||||
//
|
||||
// If <expr> is non-zero, execute <true cmd>.
|
||||
// If <expr> is zero, execute [false cmd] if specified.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD (test)
|
||||
{
|
||||
int parsept = 1;
|
||||
FProduction *prod = ParseExpression (argv, parsept);
|
||||
|
||||
if (prod == NULL || parsept >= argv.argc())
|
||||
{
|
||||
Printf ("Usage: test <expr> <true cmd> [false cmd]\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prod->Type == PROD_String)
|
||||
{
|
||||
prod = StringToDouble (prod);
|
||||
}
|
||||
|
||||
if (static_cast<FDoubleProd *>(prod)->Value != 0.0)
|
||||
{
|
||||
AddCommandString (argv[parsept]);
|
||||
}
|
||||
else if (++parsept < argv.argc())
|
||||
{
|
||||
AddCommandString (argv[parsept]);
|
||||
}
|
||||
}
|
||||
if (prod != NULL)
|
||||
{
|
||||
M_Free (prod);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CCMD eval
|
||||
//
|
||||
// Evaluates an expression and either prints it to the console or stores
|
||||
// it in an existing cvar.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD (eval)
|
||||
{
|
||||
if (argv.argc() >= 2)
|
||||
{
|
||||
int parsept = 1;
|
||||
FProduction *prod = ParseExpression (argv, parsept);
|
||||
|
||||
if (prod != NULL)
|
||||
{
|
||||
if (parsept < argv.argc())
|
||||
{
|
||||
FBaseCVar *var = FindCVar (argv[parsept], NULL);
|
||||
if (var == NULL)
|
||||
{
|
||||
Printf ("Unknown variable %s\n", argv[parsept]);
|
||||
}
|
||||
else
|
||||
{
|
||||
UCVarValue val;
|
||||
|
||||
if (prod->Type == PROD_Double)
|
||||
{
|
||||
val.Float = (float)static_cast<FDoubleProd *>(prod)->Value;
|
||||
var->SetGenericRep (val, CVAR_Float);
|
||||
}
|
||||
else
|
||||
{
|
||||
val.String = static_cast<FStringProd *>(prod)->Value;
|
||||
var->SetGenericRep (val, CVAR_String);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prod->Type == PROD_Double)
|
||||
{
|
||||
Printf ("%g\n", static_cast<FDoubleProd *>(prod)->Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("%s\n", static_cast<FStringProd *>(prod)->Value);
|
||||
}
|
||||
}
|
||||
M_Free (prod);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Printf ("Usage: eval <expression> [variable]\n");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue