Пример #1
0
/****************************************************************************\
*
*  GetUserNumber
*
\****************************************************************************/
int Console::GetUserNumber( int minInput, int maxInput ) const
{
   char pInput[100];
   int  result;
   int  numberFound;
   int  negativeNumber;

   do
   {
      // Set a string   
      GetUserString(pInput, 100);
   
      // Initialize variables for loop
      numberFound=0;
      negativeNumber = 0;
      result=0;

      // Translate to a number
      for(int i=0; i<sizeof(pInput); ++i)
      {
         if ((i == 0) && (pInput[i] == '-'))
         {
            negativeNumber = 1;
         }
         else if((pInput[i] >= '0') && (pInput[i] <= '9'))
         {
            numberFound=1;
            result = (result * 10) + (pInput[i] - '0');
         }
         else
         {
            break;
         }
      }
      
      // Verify error
      if( !numberFound )
      {
         *pOs << endl << "You must enter a number between "
              << minInput << " and "
              << maxInput << ": ";
      }

      if (negativeNumber)
      {
         result = result * -1;
      }
      
      // Verify range
      if( numberFound )
      {
         if( result < minInput )
         {
            numberFound = 0;
         }

         if( result > maxInput )
         {
            numberFound = 0;
         }
         
         if( !numberFound )
         {
            *pOs << endl << "The acceptable range is from "
                 << minInput << " and "
                 << maxInput << ": ";
         }
      }
   }
   while( !numberFound );
   
   return result;
}
Пример #2
0
/****************************************************************************\
*
*  GetUserLargeNumber
*
\****************************************************************************/
void Console::GetUserLargeNumber( void *pValue,
                         unsigned int uMaxLen,
                         unsigned int *puRead ) const
{
   unsigned int uBufferSize;
   char *pbBuffer;
   int numberValid;

   // Allocate twice the memory
   uBufferSize = uMaxLen * 2 + 1;
   pbBuffer = new char [uBufferSize];
   assert(pbBuffer);

   do
   {
      numberValid = 1;

      // Get a string from user
      GetUserString(pbBuffer, uBufferSize);

      // Remove trailing blanks
      unsigned int uStringSize = strlen(pbBuffer);
      while(pbBuffer[uStringSize] == ' ')
      {
         pbBuffer[uStringSize] = 0;
         --uStringSize;
      }

      // Need an even number of characters
      if( uStringSize & 1 )
      {
         *pOs << endl << "You must enter an even number of "
                 "hexadecimal digits." << endl << ">";
         numberValid = 0;
         continue;
      }

      // Convert to a number
      unsigned char *pbChar = (unsigned char *)pbBuffer;
      unsigned char *pbTarget = (unsigned char *)pValue;
      for(unsigned int uLoop=0; uLoop<uMaxLen; ++uLoop)
      {
         // Verify if this is the end
         if( *pbChar == 0 )
         {
            *puRead = uLoop;
            return;
         }

         // first hexadecimal digit
         if( *pbChar >= '0' && *pbChar <= '9' )
         {
            *pbTarget = *pbChar - '0';
         }
         else if( *pbChar >= 'a' && *pbChar <= 'f' )
         {
            *pbTarget = *pbChar - 'a' + 10;
         }
         else if( *pbChar >= 'A' && *pbChar <= 'F' )
         {
            *pbTarget = *pbChar - 'A' + 10;
         }
         else
         {
            numberValid = 0;
            break;
         }
         ++pbChar;
         *pbTarget *= 16;

         // second hexadecimal digit
         if( *pbChar >= '0' && *pbChar <= '9' )
         {
            *pbTarget += *pbChar - '0';
         }
         else if( *pbChar >= 'a' && *pbChar <= 'f' )
         {
            *pbTarget += *pbChar - 'a' + 10;
         }
         else if( *pbChar >= 'A' && *pbChar <= 'F' )
         {
            *pbTarget += *pbChar - 'A' + 10;
         }
         else
         {
            numberValid = 0;
            break;
         }
         ++pbChar;

         // prepare for next pass
         ++pbTarget;
      }

      if( !numberValid )
      {
         *pOs << endl << "You must enter an hexadecimal number of "
                 "digits from 0 to f." << endl << ">";
      }

   } while ( !numberValid );

   *puRead = uMaxLen;
}
Пример #3
0
// Do Tree:  convert token stream to expression tree
ExpPart* CExpression::DoTree(int& step, bool unaryMode)
{
	ExpPart* LeftPart = NULL;
	ExpPart* Brackets = NULL;
	bool Bracketing; // Brackets override the operator precedentation

	// Too lazy to scope each case label lol
	ExpInteger* pInt;
	ExpFloat* pFloat;
	ExpString* pStr;
	ExpIdent* pIdent;
	ExpAdd* pAdd;
	ExpSubtract* pSub;
	ExpMultiply* pMult;
	ExpDivide* pDiv;
	ExpMod* pMod;
	ExpPower* pPow;
	ExpDot* pDot;
	ExpSin* pSin;
	ExpCos* pCos;
	ExpTan* pTan;
	ExpSqrt* pSqrt;
	ExpFuncInt* pFuncInt;
	ExpFuncFloat* pFuncFloat;
	ExpFuncStr* pFuncStr;
	ExpEqual* pEqual;
	ExpNotEqual* pNotEqual;
	ExpLess* pLess;
	ExpLessEqual* pLessEqual;
	ExpGreater* pGreater;
	ExpGreaterEqual* pGreaterEqual;
	ExpAnd* pAnd;
	ExpOr* pOr;
	ExpConditional* pConditional;
	ExpAsin* pAsin;
	ExpAcos* pAcos;
	ExpAtan* pAtan;
	ExpAbs* pAbs;
	ExpExp* pExp;
	ExpLn* pLn;
	ExpLog10* pLog10;
	ExpCeil* pCeil;
	ExpRound* pRound;
	ExpRandom* pRandom;
	ExpLen* pLen;
	ExpArray* pArray;
	ExpAt* pAt;
	ExpVariableName* pVariableName;
	bool dotIdentifier;

	Token curTok;

	while (step < toks.size()) {

		curTok = toks[step];

		if (curTok.t == T_NULL)
			break;

		Bracketing = false;

		switch (curTok.t) {

			//////////////////////
			// Operands
			//
			// Operands are simply kept to one side until we find an
			// operator to do something with.

		case T_INTEGER:
			
			pInt = NEW_UNARY_EXP(ExpInteger, pInt);
			pInt->value = _atoi64(CSTR_BUF(curTok.str));

			// Return on close bracket or comma
			CHECK_TERMINATE();

			break;

		case T_FLOAT:

			pFloat = NEW_UNARY_EXP(ExpFloat, pFloat);
			pFloat->value = atof(CSTR_BUF(curTok.str));

			// Return on close bracket or comma
			CHECK_TERMINATE();

			break;

		case T_STRINGLITERAL:

			pStr = NEW_UNARY_EXP(ExpString, pStr);
			pStr->value = curTok.str;

			// Return on close bracket or comma
			CHECK_TERMINATE();

			break;

		case T_VARIABLENAME:

			pVariableName = NEW_UNARY_EXP(ExpVariableName, pVariableName);

			// Store var name
			pVariableName->name = curTok.str;
			pVariableName->name.MakeLower();
			
			// Return on close bracket or comma
			CHECK_TERMINATE();

			break;

		case T_LEFTCURLY:

			pArray = NEW_UNARY_EXP(ExpArray, pArray);

			// NEW_UNARY_EXP increments step, but we want to put it back, because the loop
			// below expects to start on {
			step--;

			// Loop until all elements collected
			while (toks[step].t != T_RIGHTCURLY && step < toks.size()) {

				step++;		// Step over { or ,

				// Obtain element
				ExpPart* element = DoTree(step);

				// Add to elements
				pArray->expElements.push_back(element);

			}

			// Step over }
			step++;

			// Resize the evaluation buffer
			pArray->arr.resize(pArray->expElements.size());

			CHECK_TERMINATE();

			break;


			//////////////////////
			// Operators

		case T_ADD:
			
			pAdd = NEW_BINARY_EXP(ExpAdd, pAdd);

			// If child operator is lower precedence, this node must swap places with the child
			if (HasPrecedence(pAdd, pAdd->r))
				return SwapTree(pAdd);

			return pAdd;

		case T_SUBTRACT:

			pSub = NEW_BINARY_EXP(ExpSubtract, pSub);

			if (HasPrecedence(pSub, pSub->r))
				return SwapTree(pSub);

			return pSub;

		case T_MULTIPLY:

			pMult = NEW_BINARY_EXP(ExpMultiply, pMult);

			if (HasPrecedence(pMult, pMult->r))
				return SwapTree(pMult);

			return pMult;

		case T_DIVIDE:

			pDiv = NEW_BINARY_EXP(ExpDivide, pDiv);

			if (HasPrecedence(pDiv, pDiv->r) || SamePrecedence(pDiv, pDiv->r))
				return SwapTree(pDiv);
			
			// Force left-to-right evaluation
			/*
			if (SamePrecedence(pDiv, pDiv->r))
				SwapRightToLeft(pDiv);
			*/

			return pDiv;

		case T_MOD:

			pMod = NEW_BINARY_EXP(ExpMod, pMod);

			if (HasPrecedence(pMod, pMod->r))
				return SwapTree(pMod);

			// Force left-to-right evaluation
			if (SamePrecedence(pMod, pMod->r))
				SwapRightToLeft(pMod);

			return pMod;

		case T_POWER:

			pPow = NEW_BINARY_EXP(ExpPower, pPow);

			if (HasPrecedence(pPow, pPow->r))
				return SwapTree(pPow);

			// Force left-to-right evaluation
			if (SamePrecedence(pPow, pPow->r))
				SwapRightToLeft(pPow);

			return pPow;

		case T_AT:

			pAt = NEW_BINARY_EXP(ExpAt, pAt);

			if (HasPrecedence(pAt, pAt->r))
				return SwapTree(pAt);

			// Force left-to-right evaluation
			if (SamePrecedence(pAt, pAt->r))
				SwapRightToLeft(pAt);

			return pAt;

		case T_EQUAL:

			pEqual = NEW_BINARY_EXP(ExpEqual, pEqual);

			if (HasPrecedence(pEqual, pEqual->r))
				return SwapTree(pEqual);

			return pEqual;

		case T_NOTEQUAL:

			pNotEqual = NEW_BINARY_EXP(ExpNotEqual, pNotEqual);

			if (HasPrecedence(pNotEqual, pNotEqual->r))
				return SwapTree(pNotEqual);

			return pNotEqual;

		case T_LESS:

			pLess = NEW_BINARY_EXP(ExpLess, pLess);

			if (HasPrecedence(pLess, pLess->r))
				return SwapTree(pLess);

			return pLess;

		case T_LESSEQUAL:

			pLessEqual = NEW_BINARY_EXP(ExpLessEqual, pLessEqual);

			if (HasPrecedence(pLessEqual, pLessEqual->r))
				return SwapTree(pLessEqual);

			return pLessEqual;

		case T_GREATER:

			pGreater = NEW_BINARY_EXP(ExpGreater, pGreater);

			if (HasPrecedence(pGreater, pGreater->r))
				return SwapTree(pGreater);

			return pGreater;

		case T_GREATEREQUAL:

			pGreaterEqual = NEW_BINARY_EXP(ExpGreaterEqual, pGreaterEqual);

			if (HasPrecedence(pGreaterEqual, pGreaterEqual->r))
				return SwapTree(pGreaterEqual);

			return pGreaterEqual;

		case T_AND:

			pAnd = NEW_BINARY_EXP(ExpAnd, pAnd);

			if (HasPrecedence(pAnd, pAnd->r))
				return SwapTree(pAnd);

			return pAnd;

		case T_OR:

			pOr = NEW_BINARY_EXP(ExpOr, pOr);

			if (HasPrecedence(pOr, pOr->r))
				return SwapTree(pOr);

			return pOr;

		case T_CONDITIONAL:

			// a ? b : c
			pConditional = new ExpConditional;
			pConditional->t = T_CONDITIONAL;
			pConditional->pCExp = this;
			pConditional->bracketdepth = Depth;
			pConditional->a = LeftPart;	// Get condition part (a)
			if(!LeftPart)
			{
				throw runtime_error("Syntax Error: Conditional operator a ? b : c\npart a is missing");
			}
			step++;

			// Get TRUE part (b)
			/*if (toks[step].t == T_LEFTBRACKET)
				pConditional->b = DoBrackets(step);
			else*/
				pConditional->b = DoTree(step);
				if(!pConditional->b)
				{
					throw runtime_error("Syntax Error: Conditional operator a ? b : c\npart b is missing");
				}
				pConditional->b = PostSortTree(pConditional->b);

			// Step over colon
			step++;

			// Get FALSE part (c)
			/*if (toks[step].t == T_LEFTBRACKET)
				pConditional->c = DoBrackets(step);
			else*/
				pConditional->c = DoTree(step);
				if(!pConditional->c)
				{
					throw runtime_error("Syntax Error: Conditional operator a ? b : c\npart c is missing");
				}
				pConditional->c = PostSortTree(pConditional->c);

			// (never has precedence)

			return pConditional;

			// Identifier, eg. call without a dot: Object Object(5) MouseX
		case T_IDENTIFIER:

			// Idents cause variability
			isConstant = false;

			pIdent = NEW_UNARY_EXP(ExpIdent, pIdent);
			pIdent->ident = curTok.str;
			//pIdent->pRuntime = pRuntime;
			//pIdent->pSystemObject = &(pRuntime->system);

			// This will store the correct OID for this name, else -1 and load an expression routine
			LookupIdentifier(curTok.str, pIdent);

			// Check for OID caller match
			pIdent->isCallerOid = (pIdent->oid == this->oidCaller);

			// True if dot precedes this identifier (bit of a hack, but hey)
			// We can't check for unary mode, because unary operators use it and it would break "sin Array(1)"
			dotIdentifier = false;
			if (step > 1) if (toks[step-2].t == T_DOT) dotIdentifier = true;

			// Cursor is currently on token after identifier (NEW_UNARY_EXP increments).
			// Check for left bracket & parameters if not part of a dot identifier (ie the x of object.x)
			if (step < toks.size() && !dotIdentifier) if (toks[step].t == T_LEFTBRACKET) {

				// While we're not on the closing bracket
				while (toks[step].t != T_RIGHTBRACKET && step < toks.size()) {

					// Step over left bracket/comma
					step++;

					// Obtain this parameter's tree, closing on the comma
					ExpPart* param = DoTree(step);
					param = PostSortTree(param);
					pIdent->parameters.push_back(param);
				}

				// Step over right bracket
				step++;
			}

			// Now we have params parsed, but if this isn't a system expression, there isn't yet a routine stored for it.
			// This means it is the default return format, eg. Array(5).  Use the Default Return Value address.
			if (this->ObjectNameExists(pIdent->ident)) {
				pIdent->pType = 1;	// nonzero
				//pIdent->pTypeInstances = &(pIdent->pType->instances);
				//pIdent->routine = &CRunObject::ReturnDefaultValue;
			}
			else
				pIdent->pType = NULL;

			pIdent->hasParameters = !pIdent->parameters.empty();

			// Return on close bracket or comma
			CHECK_TERMINATE();

			// Return if function call (followed by lbracket)
			if (toks[step].t == T_LEFTBRACKET)
				return LeftPart;

			break;

		case T_DOT:

			// Plugin returns cause variability
			isConstant = false;

			pDot = new ExpDot;
			pDot->t = T_DOT;
			// Object name part
			pDot->l = (ExpIdent*)LeftPart;
			pDot->pCExp = this;
			//pDot->pRuntime = pRuntime;
			pDot->bracketdepth = Depth;
			pDot->oid = ((ExpIdent*)(pDot->l))->oid;
			//pDot->pType = pRuntime->objects[pDot->oid];
			//pDot->pTypeInstances = &(pDot->pType->instances);
			pDot->unnamedExp = false;
			pDot->objName = ((ExpIdent*)(pDot->l))->ident;

			step++;

			// Check for OID match
			pDot->isCallerOid = (pDot->oid == this->oidCaller);
				
			// Brackets not allowed after dot.  Obtain expression name part.
			pDot->r = (ExpIdent*)DoTree(step, true);

			// Now obtain a list of the parameters.  We are pointing after the expression
			// name part, i.e. after:   obj.exp [->] ( params ...
			// So if parameters exist, this is a left bracket.
			if (step < toks.size()) if (toks[step].t == T_LEFTBRACKET) {

				// While we're not on the closing bracket
				while (toks[step].t != T_RIGHTBRACKET && step < toks.size()) {

					// Step over left bracket/comma
					step++;

					// Obtain this parameter's tree, closing on the comma
					ExpPart* param = DoTree(step);
					param = PostSortTree(param);
					pDot->parameters.push_back(param);
				}

				// Step over right bracket
				step++;
			}

			// Has parameters?
			pDot->hasParameters = !pDot->parameters.empty();

			// Store function name for type checker
			pDot->fname = ((ExpIdent*)(pDot->r))->ident;

			// Dot will have precedence over most operators
			if (HasPrecedence(pDot, pDot->r)) {

				ExpPart* newParent = SwapTree(pDot);

				// Look up the plugin expression routine
				LookupExtExpression(((ExpIdent*)(pDot->l))->oid, ((ExpIdent*)(pDot->r))->ident, pDot);

				return newParent;
			}

			// Look up the plugin expression routine
			LookupExtExpression(((ExpIdent*)(pDot->l))->oid, ((ExpIdent*)(pDot->r))->ident, pDot);

			//return pDot;
			LeftPart = pDot;

			CHECK_TERMINATE();

			break;

			//////////////////////
			// Unary operators

		case T_SIN:

			pSin = NEW_UNARY_OPERATOR(ExpSin, pSin);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_COS:

			pCos = NEW_UNARY_OPERATOR(ExpCos, pCos);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_TAN:

			pTan = NEW_UNARY_OPERATOR(ExpTan, pTan);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_SQRT:

			pSqrt = NEW_UNARY_OPERATOR(ExpSqrt, pSqrt);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_FUNC_INT:

			pFuncInt = NEW_UNARY_OPERATOR(ExpFuncInt, pFuncInt);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_FUNC_FLOAT:

			pFuncFloat = NEW_UNARY_OPERATOR(ExpFuncFloat, pFuncFloat);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_FUNC_STR:

			pFuncStr = NEW_UNARY_OPERATOR(ExpFuncStr, pFuncStr);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_ASIN:

			pAsin = NEW_UNARY_OPERATOR(ExpAsin, pAsin);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_ACOS:

			pAcos = NEW_UNARY_OPERATOR(ExpAcos, pAcos);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_ATAN:

			pAtan = NEW_UNARY_OPERATOR(ExpAtan, pAtan);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_ABS:

			pAbs = NEW_UNARY_OPERATOR(ExpAbs, pAbs);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_EXP:

			pExp = NEW_UNARY_OPERATOR(ExpExp, pExp);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_LN:

			pLn = NEW_UNARY_OPERATOR(ExpLn, pLn);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_LOG10:

			pLog10 = NEW_UNARY_OPERATOR(ExpLog10, pLog10);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_CEIL:

			pCeil = NEW_UNARY_OPERATOR(ExpCeil, pCeil);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_ROUND:

			pRound = NEW_UNARY_OPERATOR(ExpRound, pRound);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_RANDOM:

			pRandom = NEW_UNARY_OPERATOR(ExpRandom, pRandom);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_LEN:

			pLen = NEW_UNARY_OPERATOR(ExpLen, pLen);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_LEFTBRACKET:

			// THIS WILL BE CALLED ALWAYS NOW!!!
			//step++;
			//TOTIGS: Everywhere else you call DoBracket you dont add 1 to the step...
			// resulting in like 2 brackets omfg
			LeftPart = DoBrackets(step);

			if (unaryMode) return LeftPart;

			CHECK_TERMINATE()
			break;
			

		case T_NULL:
			step++;
			break;

		default:
			{
				CString msg = "Syntax error: '";
				msg += curTok.str;
				msg += "' in expression:\n\n";
				CString userstr;
				GetUserString(userstr);
				msg += userstr;
				throw runtime_error((const char*)msg);
			}

		}//switch
	}//while

	return LeftPart;
}