Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

eval.cpp

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/gui/eval.cpp $
 * $Id: eval.cpp 30944 2008-02-23 22:50:18Z sev $
 *
 */

#include "common/system.h"
#include "gui/eval.h"
#include "gui/widget.h"
#include "gui/newgui.h"

#include "graphics/scaler.h"

namespace GUI {

static bool isdelim(char c) {
      return strchr(" ;,+-<>/*%^=()", c) != 0 || c == 9 || c == '\n' || !c;
}

Eval::Eval() {
      loadConstants();
}

Eval::~Eval() {
      _vars.clear();
      _aliases.clear();
}

int Eval::eval(const String &input, const String &section, const String &name, int startpos) {
      int result;

      debug(5, "%s=%s", name.c_str(), input.c_str());

      strncpy(_input, input.c_str(), 256);
      _section = section;
      _name = name;
      _startpos = startpos;

      _pos = 0;

      getToken();

      if (_tokenType == tString)
            return EVAL_STRING_VAR;

      if (!*_token)
            exprError(eBadExpr);

      level2(&result);

      debug(5, "Result: %d", result);

      return result;
}

void Eval::level2(int *result) {
      char op;
      int hold;

      level3(result);

      while ((op = *_token) == '+' || op == '-') {
            getToken();
            level3(&hold);
            arith(op, result, &hold);
      }
}

void Eval::level3(int *result) {
      char op;
      int hold;

      level4(result);

      while ((op = *_token) == '*' || op == '/' || op == '%') {
            getToken();
            level4(&hold);
            arith(op, result, &hold);
      }
}

void Eval::level4(int *result) {
      char op;

      op = 0;
      if ((_tokenType == tDelimiter) && *_token == '+' || *_token == '-') {
            op = *_token;
            getToken();
      }

      level5(result);

      if (op)
            unary(op, result);
}

void Eval::level5(int *result) {
      if ((*_token == '(') && (_tokenType == tDelimiter)) {
            getToken();

            level2(result);

            if (*_token != ')')
                  exprError(eUnclosedBracket);
            getToken();
      } else {
            primitive(result);
      }
}

void Eval::primitive(int *result) {
      if (*_token == ')')
            exprError(eExtraBracket);

      switch (_tokenType) {
      case tVariable:
            *result = getVar_(_token);
            if (*result == EVAL_UNDEF_VAR)
                  exprError(eUndefVar);
            getToken();
            return;
      case tNumber:
            *result = atoi(_token);
            getToken();
            return;
      default:
            exprError(eSyntaxError);
      }
}

void Eval::arith(char op, int *r, int *h) {
      switch (op) {
      case '-':
            *r = *r - *h;
            break;
      case '+':
            *r = *r + *h;
            break;
      case '*':
            *r = *r * *h;
            break;
      case '/':
            *r = (*r) / (*h);
            break;
      case '%':
            *r = (*r) % (*h);
            break;
      }
}

void Eval::unary(char op, int *r) {
      if (op == '-')
            *r = -(*r);
}

void Eval::getToken() {
      char *temp;

      _tokenType = tNone;
      temp = _token;

      if (_input[_pos] == 0) {
            *_token = 0;
            _tokenType = tDelimiter;
            return;
      }
      while (isspace(_input[_pos]))
            _pos++;

      if (_input[_pos] == '"') {
            _pos++;
            while (_input[_pos] != '"' && _input[_pos] != '\n')
                  *temp++ = _input[_pos++];

            if (_input[_pos] == '\n')
                  exprError(eMissingQuote);

            _pos++;
            *temp = 0;

            _tokenType = tString;
            return;
      }

      if (isdigit(_input[_pos])) {
            while (!isdelim(_input[_pos]))
                  *temp++ = _input[_pos++];
            *temp = 0;

            _tokenType = tNumber;
            return;
      }

      if (isalpha(_input[_pos])) {
            while (!isdelim(_input[_pos]))
                  *temp++ = _input[_pos++];
            *temp = 0;
            _tokenType = tVariable;
            return;
      }

      if (!_tokenType && isdelim(_input[_pos])) {
            *temp++ = _input[_pos++];
            *temp = 0;
            _tokenType = tDelimiter;
      }
}

void Eval::exprError(EvalErrors err) {
      static const char *errors[] = {
            "Syntax error",
            "Extra ')'",
            "Missing ')'",
            "Bad expression",
            "Undefined variable",
            "Missing '\"'"
      };

      error("%s in section [%s] expression: \"%s\" start is at: %d near token '%s'",
              errors[err], _section.c_str(), _name.c_str(), _pos + _startpos, _token);
}

struct BuiltinConsts {
      const char *name;
      int value;
};

static const BuiltinConsts builtinConsts[] = {
      {"kButtonWidth", GUI::kButtonWidth},
      {"kButtonHeight", GUI::kButtonHeight},
      {"kSliderWidth", GUI::kSliderWidth},
      {"kSliderHeight", GUI::kSliderHeight},

      {"kBigButtonWidth", GUI::kBigButtonWidth},
      {"kBigButtonHeight", GUI::kBigButtonHeight},
      {"kBigSliderWidth", GUI::kBigSliderWidth},
      {"kBigSliderHeight", GUI::kBigSliderHeight},

      {"kNormalWidgetSize", GUI::kNormalWidgetSize},
      {"kBigWidgetSize", GUI::kBigWidgetSize},

      {"kThumbnailWidth", kThumbnailWidth},

      {"kTextAlignLeft", kTextAlignLeft},
      {"kTextAlignRight", kTextAlignRight},
      {"kTextAlignCenter", kTextAlignCenter},

      {"kFontStyleBold", Theme::kFontStyleBold},
      {"kFontStyleNormal", Theme::kFontStyleNormal},
      {"kFontStyleItalic", Theme::kFontStyleItalic},

      {"kFontStyleFixedBold", Theme::kFontStyleFixedBold},
      {"kFontStyleFixedNormal", Theme::kFontStyleFixedNormal},
      {"kFontStyleFixedItalic", Theme::kFontStyleFixedItalic},

      {"kShadingNone", Theme::kShadingNone},
      {"kShadingDim", Theme::kShadingDim},
      {"kShadingLuminance", Theme::kShadingLuminance},

      {"false", 0},
      {"true", 1},
      {NULL, 0}
};

void Eval::loadConstants() {
      int i;

      for (i = 0; builtinConsts[i].name; i++)
            _vars[builtinConsts[i].name] = builtinConsts[i].value;
}

int Eval::getBuiltinVar(const char *s) {
      if (!strcmp(s, "w"))
            return g_system->getOverlayWidth();

      if (!strcmp(s, "h"))
            return g_system->getOverlayHeight();

      return EVAL_UNDEF_VAR;
}

int Eval::getVar_(const Common::String &s, bool includeAliases) {
      int val;

      val = getBuiltinVar(s.c_str());

      if (val != EVAL_UNDEF_VAR)
            return val;

      const Common::String *var = &s;
      if (includeAliases) {
            AliasesMap::const_iterator itera = _aliases.find(s);
            if (itera != _aliases.end())
                  var = &(itera->_value);
      }

      VariablesMap::const_iterator iterv = _vars.find(*var);
      if (iterv != _vars.end())
            return iterv->_value;

      return EVAL_UNDEF_VAR;
}

void Eval::setVar(const String &section, const String &name, const String &value) {
      _vars[name.c_str() + 4] = eval(value, section, name, 0);
}

void Eval::reset() {
      _vars.clear();
      _aliases.clear();
      loadConstants();
}

} // end of namespace GUI

Generated by  Doxygen 1.6.0   Back to index