summaryrefslogtreecommitdiffstats
path: root/katapult/plugins/catalogs/calculatorcatalog
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:45:19 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:45:19 +0000
commit4e1a5c3eebf50657629e2b4eba13649c2b599598 (patch)
tree7757743b67ed172d113dad73a3daa5b8aa6f871a /katapult/plugins/catalogs/calculatorcatalog
downloadkatapult-4e1a5c3eebf50657629e2b4eba13649c2b599598.tar.gz
katapult-4e1a5c3eebf50657629e2b4eba13649c2b599598.zip
Added abandoned KDE3 version of katapult
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/katapult@1084407 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'katapult/plugins/catalogs/calculatorcatalog')
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/Makefile.am20
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.cpp161
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.h51
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.cpp360
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.h122
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/expression.cpp94
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/expression.h60
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/hi128-action-checkmark.pngbin0 -> 11420 bytes
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/hi128-action-no.pngbin0 -> 11268 bytes
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/hi128-app-xcalc.pngbin0 -> 10583 bytes
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/katapult_calculatorcatalog.desktop44
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/parser.cpp1387
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/parser.y120
-rw-r--r--katapult/plugins/catalogs/calculatorcatalog/settings.ui219
14 files changed, 2638 insertions, 0 deletions
diff --git a/katapult/plugins/catalogs/calculatorcatalog/Makefile.am b/katapult/plugins/catalogs/calculatorcatalog/Makefile.am
new file mode 100644
index 0000000..c0753c2
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/Makefile.am
@@ -0,0 +1,20 @@
+# Copyright (C) 2005 Tobi Vollebregt
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(top_srcdir)/katapult/common $(all_includes)
+
+# header files
+noinst_HEADERS = calculatorcatalog.h expression.h actionevalexpr.h
+
+# use automoc
+METASOURCES = AUTO
+
+# install xcalc icon
+KDE_ICON = xcalc checkmark no
+
+# our plugin
+kde_module_LTLIBRARIES = katapult_calculatorcatalog.la
+katapult_calculatorcatalog_la_SOURCES = settings.ui calculatorcatalog.cpp expression.cpp actionevalexpr.cpp parser.cpp
+katapult_calculatorcatalog_la_LDFLAGS = -module $(KDE_RPATH) $(KDE_PLUGIN) $(all_libraries)
+katapult_calculatorcatalog_la_LIBADD = $(LIB_QT) $(LIB_KDECORE) $(LIB_KDEUI) $(LIB_KIO) $(top_builddir)/katapult/common/libkatapult.la
+kde_services_DATA = katapult_calculatorcatalog.desktop
diff --git a/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.cpp b/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.cpp
new file mode 100644
index 0000000..2a786f9
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.cpp
@@ -0,0 +1,161 @@
+/***************************************************************************
+ * Copyright (C) 2005 Tobi Vollebregt *
+ * tobivollebregt@gmail.com *
+ * *
+ * Copyright (C) 2005 by Joe Ferris *
+ * jferris@optimistictech.com *
+ * *
+ * 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. *
+ ***************************************************************************/
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <krun.h>
+#include <kurl.h>
+#include <klocale.h>
+
+#include <qclipboard.h>
+
+#include "calculatorcatalog.h"
+#include "expression.h"
+#include "katapultitem.h"
+#include "actionevalexpr.h"
+
+
+// Conditional compilation to not bloat the lib if
+// KDE already has the following functions.
+// Prevents a deprecated function warning too.
+
+#if !KDE_IS_VERSION(3, 5, 0)
+
+// Copied some code from KDE 3.5 to make it compile on 3.4.
+
+// insert (thousands)-"separator"s into the non-fractional part of str
+static void _insertSeparator(QString &str, const QString &separator, const QString &decimalSymbol)
+{
+ // leave fractional part untouched
+ QString mainPart = str.section(decimalSymbol, 0, 0);
+ QString fracPart = str.section(decimalSymbol, 1, 1, QString::SectionIncludeLeadingSep);
+ if (fracPart==decimalSymbol) fracPart=QString();
+ for (int pos = mainPart.length() - 3; pos > 0; pos -= 3)
+ mainPart.insert(pos, separator);
+ str = mainPart + fracPart;
+}
+
+// This was KLocale::formatNumber(const QString&, bool, int)
+
+static QString formatNumber(const QString &numStr)
+{
+ QString tmpString = numStr;
+
+ // Skip the sign (for now)
+ bool neg = (tmpString[0] == '-');
+ if (neg || tmpString[0] == '+') tmpString.remove(0, 1);
+
+ // Split off exponential part (including 'e'-symbol)
+ QString mantString = tmpString.section('e', 0, 0, QString::SectionCaseInsensitiveSeps);
+ QString expString = tmpString.section('e', 1, 1, QString::SectionCaseInsensitiveSeps | QString::SectionIncludeLeadingSep);
+ if (expString.length()==1) expString=QString();
+
+ // Replace dot with locale decimal separator
+ mantString.replace(QChar('.'), KGlobal::locale()->decimalSymbol());
+
+ // Insert the thousand separators
+ _insertSeparator(mantString, KGlobal::locale()->thousandsSeparator(), KGlobal::locale()->decimalSymbol());
+
+ // How can we know where we should put the sign?
+ mantString.prepend(neg?KGlobal::locale()->negativeSign():KGlobal::locale()->positiveSign());
+
+ return mantString + expString;
+}
+
+#else
+// KDE_VERSION >= 3.5.0
+
+static QString formatNumber(const QString& numStr)
+{
+ return KGlobal::locale()->formatNumber(numStr, false, 0);
+}
+
+#endif
+
+
+ActionEvaluateExpression::ActionEvaluateExpression()
+ : KatapultAction(), _expr(0)
+{
+}
+
+ActionEvaluateExpression::~ActionEvaluateExpression()
+{
+}
+
+QString ActionEvaluateExpression::text() const
+{
+ if (_expr->parseError()) {
+ return i18n("Evaluate Expression");
+ } else {
+ // Format result.
+ int digits = _expr->catalog()->fracDigits();
+ QChar f = _expr->catalog()->scientific() ? 'g' : 'f';
+ QString num = QString::number(_expr->result(), f, digits);
+ // Strip trailing zeroes.
+ if (f == 'f' && digits != 0) {
+ while (num.endsWith("0")) {
+ num = num.left(num.length() - 1);
+ }
+ if (num.endsWith(".")) {
+ num = num.left(num.length() - 1);
+ }
+ }
+ // Localize (choose right implementation based on KDE version, see above).
+ return formatNumber(num);
+ }
+}
+
+QPixmap ActionEvaluateExpression::icon(int size) const
+{
+ return KGlobal::iconLoader()->loadIcon("xcalc", KIcon::NoGroup, size);
+}
+
+bool ActionEvaluateExpression::accepts(const KatapultItem* item) const
+{
+ bool accept = strcmp(item->className(), "Expression") == 0;
+ if (accept) {
+ _expr = (const Expression*)item;
+ }
+ return accept;
+}
+
+void ActionEvaluateExpression::execute(const KatapultItem* item) const
+{
+ if (strcmp(item->className(), "Expression") == 0) {
+ _expr = (const Expression*)item;
+
+ //evaluate expression with assignments enabled
+ _expr->evaluate(true);
+
+ // Copy calculation and result into clipboard (unless there's a parse error).
+ if (!_expr->parseError()) {
+ QClipboard *cb = QApplication::clipboard();
+ QString s = _expr->catalog()->formatString();
+ s.replace("%1", _expr->text());
+ s.replace("%2", text());
+ cb->setText(s, QClipboard::Clipboard);
+ cb->setText(s, QClipboard::Selection);
+ }
+ }
+}
diff --git a/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.h b/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.h
new file mode 100644
index 0000000..6cf23bf
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * Copyright (C) 2005 Tobi Vollebregt *
+ * tobivollebregt@gmail.com *
+ * *
+ * Copyright (C) 2005 by Joe Ferris *
+ * jferris@optimistictech.com *
+ * *
+ * 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. *
+ ***************************************************************************/
+#ifndef ACTIONEVALEXPR_H
+#define ACTIONEVALEXPR_H
+
+#include "katapultaction.h"
+
+class KatapultItem;
+class Expression;
+
+/**
+@author Tobi Vollebregt
+*/
+class ActionEvaluateExpression : public KatapultAction
+{
+ public:
+ ActionEvaluateExpression();
+ ~ActionEvaluateExpression();
+
+ virtual void execute(const KatapultItem*) const;
+ virtual bool accepts(const KatapultItem*) const;
+ virtual QString text() const;
+ virtual QPixmap icon(int) const;
+
+ private:
+ //_expr needs to be mutable because accepts() is const.
+ mutable const Expression* _expr;
+
+};
+
+#endif
diff --git a/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.cpp b/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.cpp
new file mode 100644
index 0000000..c3c5f6d
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.cpp
@@ -0,0 +1,360 @@
+/***************************************************************************
+ * Copyright (C) 2005 Tobi Vollebregt *
+ * tobivollebregt@gmail.com *
+ * *
+ * Copyright (C) 2005 by Joe Ferris *
+ * jferris@optimistictech.com *
+ * *
+ * 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. *
+ ***************************************************************************/
+
+#include <kservicegroup.h>
+#include <ksycocaentry.h>
+#include <ksycocatype.h>
+#include <kapplication.h>
+#include <knuminput.h>
+#include <kcombobox.h>
+
+#include <qcheckbox.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qregexp.h>
+
+#include <math.h>
+
+#include "settings.h"
+#include "calculatorcatalog.h"
+#include "expression.h"
+#include "actionregistry.h"
+#include "actionevalexpr.h"
+#include "status.h"
+
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#ifndef M_E
+#define M_E 2.7182818284590452354
+#endif
+
+
+static double frac(double x)
+{
+ double nowhere;
+ return modf(x, &nowhere);
+}
+
+
+static double deg_sin(double x) { return sin(x * (M_PI / 180.0)); }
+static double deg_cos(double x) { return cos(x * (M_PI / 180.0)); }
+static double deg_tan(double x) { return tan(x * (M_PI / 180.0)); }
+static double deg_asin(double x) { return asin(x) * (180.0 / M_PI); }
+static double deg_acos(double x) { return acos(x) * (180.0 / M_PI); }
+static double deg_atan(double x) { return atan(x) * (180.0 / M_PI); }
+static double deg_sinh(double x) { return sinh(x * (M_PI / 180.0)); }
+static double deg_cosh(double x) { return cosh(x * (M_PI / 180.0)); }
+static double deg_tanh(double x) { return tanh(x * (M_PI / 180.0)); }
+static double deg_asinh(double x) { return asinh(x) * (180.0 / M_PI); }
+static double deg_acosh(double x) { return acosh(x) * (180.0 / M_PI); }
+static double deg_atanh(double x) { return atanh(x) * (180.0 / M_PI); }
+
+
+const CalculatorCatalog::Function CalculatorCatalog::radiansFunctionTable[] =
+{
+ { "sin", 3, sin },
+ { "cos", 3, cos },
+ { "tan", 3, tan },
+ { "asin", 4, asin },
+ { "acos", 4, acos },
+ { "atan", 4, atan },
+ { "sinh", 4, sinh },
+ { "cosh", 4, cosh },
+ { "tanh", 4, tanh },
+ { "asinh", 5, asinh },
+ { "acosh", 5, acosh },
+ { "atanh", 5, atanh },
+ { "sqrt", 4, sqrt },
+ { "log", 3, log10 },
+ { "ln", 2, log },
+ { "exp", 3, exp },
+ { "abs", 3, fabs },
+ { "frac", 4, frac },
+ { "round", 5, round },
+ { "int", 3, trunc },
+ { 0, 0, 0 }
+};
+
+const CalculatorCatalog::Function CalculatorCatalog::degreesFunctionTable[] =
+{
+ { "sin", 3, deg_sin },
+ { "cos", 3, deg_cos },
+ { "tan", 3, deg_tan },
+ { "asin", 4, deg_asin },
+ { "acos", 4, deg_acos },
+ { "atan", 4, deg_atan },
+ { "sinh", 4, deg_sinh },
+ { "cosh", 4, deg_cosh },
+ { "tanh", 4, deg_tanh },
+ { "asinh", 5, deg_asinh },
+ { "acosh", 5, deg_acosh },
+ { "atanh", 5, deg_atanh },
+ { "sqrt", 4, sqrt },
+ { "log", 3, log10 },
+ { "ln", 2, log },
+ { "exp", 3, exp },
+ { "abs", 3, fabs },
+ { "frac", 4, frac },
+ { "round", 5, round },
+ { "int", 3, trunc },
+ { 0, 0, 0 }
+};
+
+
+K_EXPORT_COMPONENT_FACTORY( katapult_calculatorcatalog,
+ KGenericFactory<CalculatorCatalog>( "katapult_calculatorcatalog" ) )
+
+CalculatorCatalog::CalculatorCatalog(QObject*, const char*, const QStringList&): _result(this, QString::null)
+{
+ ActionRegistry::self()->registerAction(new ActionEvaluateExpression());
+
+ setVar(getVarID("pi"), M_PI);
+ setVar(getVarID("e"), M_E);
+}
+
+CalculatorCatalog::~CalculatorCatalog()
+{
+}
+
+void CalculatorCatalog::queryChanged()
+{
+ int newStatus = 0;
+ QString cmd = query();
+
+ if (cmd.isEmpty()) {
+ reset();
+ setBestMatch(Match());
+ } else {
+ if (accepts(cmd)) {
+ int i, origLength = cmd.length(), length = origLength;
+ //autocomplete functions
+ cmd = cmd.lower();
+ for (i = length - 1; i >= 0 && cmd[i].isLetter(); --i) { }
+ if (i != length - 1) {
+ QString start = cmd.mid(i + 1);
+ int lengthOfShortest = 9999, shortest = -1;
+ for (int j = 0; radiansFunctionTable[j].name; ++j) {
+ if (QString(radiansFunctionTable[j].name).startsWith(start)) {
+ if (radiansFunctionTable[j].length < lengthOfShortest) {
+ lengthOfShortest = radiansFunctionTable[j].length;
+ shortest = j;
+ }
+ }
+ }
+ if (shortest != -1) {
+ cmd = cmd.left(i + 1).append(radiansFunctionTable[shortest].name).append("(");
+ length = cmd.length();
+ }
+ }
+ //fix parse errors at end of expression,
+ //ie. close open parentheses, convert operators into NOPs
+ for (i = length - 1; i >= 0 && (cmd[i] == '(' || cmd[i] == ' '); --i) { }
+ if (i < 0 || cmd[i] == '+' || cmd[i] == '-') {
+ cmd.append("0");
+ ++length;
+ } else if (cmd[i] == '*' || cmd[i] == '/' || cmd[i] == '^') {
+ cmd.append("1");
+ ++length;
+ } else if (cmd[i].isLetter() && (i < length - 1 && cmd[i + 1] == '(')) {
+ //just add a 0 if it's a function: we don't bother to backpropagate
+ //through the parse tree (if it existed at all) to figure out a NOP value
+ //for this particular (chain of) function(s).
+ cmd.append("0");
+ ++length;
+ }
+ int openParen = 0;
+ //use cmd.length() here, it may be > than length.
+ for (i = 0; i < length; ++i) {
+ if (cmd[i] == '(') ++openParen;
+ if (cmd[i] == ')') --openParen;
+ }
+ if (openParen > 0) {
+ char* closeParen = new char[openParen + 1];
+ memset(closeParen, ')', openParen);
+ closeParen[openParen] = 0;
+ cmd.append(closeParen);
+ delete[] closeParen;
+ }
+ _result.setText(cmd);
+ setBestMatch(Match(&_result, _result.parseError() ? 10 : 100, origLength));
+ //set status.
+ //add S_Multiple to make sure katapult doesn't auto-exec and close the window
+ //add S_Active to make sure katapult doesn't start the hideTimer or clearTimer
+ newStatus = S_HasResults | S_Multiple | S_Active;
+ } else {
+ newStatus = 0;
+ }
+ }
+ setStatus(newStatus);
+}
+
+void CalculatorCatalog::reset()
+{
+ _result.setText(QString::null);
+}
+
+bool CalculatorCatalog::accepts(const QString& str) const
+{
+ //Heuristic to determine whether the string is an expression or not.
+ //Accept anything containing [()+\\-/*^=.,0-9].
+ return QRegExp("[()+\\-/*^=.,0-9]").search(str) >= 0;
+}
+
+int CalculatorCatalog::getVarID(const char* name)
+{
+ VarNameToIdMap::iterator it = varNameToId.find(QString(name));
+ if (it == varNameToId.end()) {
+ _pendingVarName = QString(name);
+ return -1;
+ }
+ return *it;
+}
+
+double CalculatorCatalog::getVar(int id) const
+{
+ return varIdToValue[id];
+}
+
+double CalculatorCatalog::setVar(int id, double value)
+{
+ if (id == -1) {
+ id = varIdToValue.count();
+ varNameToId.insert(_pendingVarName, id);
+ varIdToValue.push_back(value);
+ } else {
+ varIdToValue[id] = value;
+ }
+ return value;
+}
+
+/*
+void CalculatorCatalog::initialize()
+{
+}
+*/
+
+void CalculatorCatalog::readSettings(KConfigBase* config)
+{
+ _fracDigits = config->readUnsignedNumEntry("FracDigits", 2);
+ _bScientific = config->readBoolEntry("Scientific", false);
+ _bDegrees = config->readBoolEntry("Degrees", false);
+ _bClipboard = config->readBoolEntry("Clipboard", true);
+ _formatString = config->readEntry("FormatString", "%1 = %2");
+}
+
+void CalculatorCatalog::writeSettings(KConfigBase* config)
+{
+ config->writeEntry("FracDigits", fracDigits());
+ config->writeEntry("Scientific", scientific());
+ config->writeEntry("Degrees", degrees());
+ config->writeEntry("Clipboard", clipboard());
+ config->writeEntry("FormatString", formatString());
+}
+
+QWidget * CalculatorCatalog::configure()
+{
+ CalculatorCatalogSettings* settings = new CalculatorCatalogSettings();
+
+ settings->fracDigits->setValue(_fracDigits);
+ connect(settings->fracDigits, SIGNAL(valueChanged(int)), this, SLOT(fracDigitsChanged(int)));
+
+ settings->normal->setChecked(!scientific());
+ settings->scientific->setChecked(scientific());
+ connect(settings->scientific, SIGNAL(toggled(bool)), this, SLOT(scientificChanged(bool)));
+
+ settings->radians->setChecked(!degrees());
+ settings->degrees->setChecked(degrees());
+ connect(settings->degrees, SIGNAL(toggled(bool)), this, SLOT(degreesChanged(bool)));
+
+ settings->clipboard->setChecked(clipboard());
+ connect(settings->clipboard, SIGNAL(toggled(bool)), this, SLOT(clipboardChanged(bool)));
+
+ settings->formatString->setText(formatString());
+ connect(settings->formatString, SIGNAL(textChanged(const QString&)), this, SLOT(formatStringChanged(const QString&)));
+
+ return settings;
+}
+
+void CalculatorCatalog::fracDigitsChanged(int n)
+{
+ _fracDigits = n;
+}
+
+int CalculatorCatalog::fracDigits() const
+{
+ return _fracDigits;
+}
+
+void CalculatorCatalog::scientificChanged(bool en)
+{
+ _bScientific = en;
+}
+
+bool CalculatorCatalog::scientific() const
+{
+ return _bScientific;
+}
+
+void CalculatorCatalog::degreesChanged(bool en)
+{
+ _bDegrees = en;
+}
+
+bool CalculatorCatalog::degrees() const
+{
+ return _bDegrees;
+}
+
+void CalculatorCatalog::formatStringChanged(const QString& fmt)
+{
+ _formatString = fmt;
+}
+
+QString CalculatorCatalog::formatString() const
+{
+ return _formatString;
+}
+
+void CalculatorCatalog::clipboardChanged(bool en)
+{
+ _bClipboard = en;
+}
+
+bool CalculatorCatalog::clipboard() const
+{
+ return _bClipboard;
+}
+
+const CalculatorCatalog::Function* CalculatorCatalog::functionTable() const
+{
+ if (degrees()) {
+ return degreesFunctionTable;
+ } else {
+ return radiansFunctionTable;
+ }
+}
+
+#include "calculatorcatalog.moc"
diff --git a/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.h b/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.h
new file mode 100644
index 0000000..88f03cc
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.h
@@ -0,0 +1,122 @@
+/***************************************************************************
+ * Copyright (C) 2005 Tobi Vollebregt *
+ * tobivollebregt@gmail.com *
+ * *
+ * Copyright (C) 2005 by Joe Ferris *
+ * jferris@optimistictech.com *
+ * *
+ * 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. *
+ ***************************************************************************/
+#ifndef CALCULATORCATALOG_H
+#define CALCULATORCATALOG_H
+
+#include <kgenericfactory.h>
+
+#include <qmap.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qvaluevector.h>
+
+#include "expression.h"
+#include "katapultcatalog.h"
+
+class QWidget;
+
+typedef double (*FunPtr)(double);
+
+/**
+@author Tobi Vollebregt
+ */
+class CalculatorCatalog : public KatapultCatalog
+{
+ Q_OBJECT
+
+ public:
+
+ struct ParserControl {
+ const char* expression;
+ CalculatorCatalog* catalog;
+ bool assignments; //are assignments enabled?
+ double result;
+ };
+
+ struct Function {
+ const char* name;
+ int length;
+ FunPtr fptr;
+ };
+
+ CalculatorCatalog(QObject*, const char*, const QStringList&);
+ virtual ~CalculatorCatalog();
+
+ //virtual void initialize();
+ virtual void readSettings(KConfigBase*);
+ virtual void writeSettings(KConfigBase*);
+ virtual QWidget* configure();
+
+ int getVarID(const char*);
+ double getVar(int) const;
+ double setVar(int, double);
+
+ int fracDigits() const;
+ bool scientific() const;
+ bool degrees() const;
+ bool clipboard() const;
+ QString formatString() const;
+ const Function* functionTable() const;
+
+ protected:
+
+ virtual void queryChanged();
+
+ private:
+
+ typedef QMap<QString, int> VarNameToIdMap;
+ typedef QValueVector<double> VarIdToValueVector;
+
+ static const Function radiansFunctionTable[];
+ static const Function degreesFunctionTable[];
+
+ void reset();
+ bool accepts(const QString&) const;
+
+ Expression _result; // The one result (there's always one).
+
+ VarNameToIdMap varNameToId; // Maps strings to IDs.
+ VarIdToValueVector varIdToValue; // Maps IDs to values.
+ QString _pendingVarName; // Pending while rest of assignment is parsed.
+
+ int _fracDigits; // Number of fractional digits.
+ bool _bScientific; // Normal or scientific mode?
+ bool _bDegrees; // Radians or degrees?
+ bool _bClipboard; // Copy to clipboard?
+ QString _formatString; // for clipboard copy
+
+ private slots:
+
+ void fracDigitsChanged(int);
+ void scientificChanged(bool);
+ void degreesChanged(bool);
+ void clipboardChanged(bool);
+ void formatStringChanged(const QString&);
+
+};
+
+
+/* from parser.y / parser.cpp: */
+int yyparse(CalculatorCatalog::ParserControl*);
+
+#endif
diff --git a/katapult/plugins/catalogs/calculatorcatalog/expression.cpp b/katapult/plugins/catalogs/calculatorcatalog/expression.cpp
new file mode 100644
index 0000000..37e80bc
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/expression.cpp
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * Copyright (C) 2005 Tobi Vollebregt *
+ * tobivollebregt@gmail.com *
+ * *
+ * Copyright (C) 2005 by Joe Ferris *
+ * jferris@optimistictech.com *
+ * *
+ * 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. *
+ ***************************************************************************/
+
+#include <kservice.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+
+#include "calculatorcatalog.h"
+#include "expression.h"
+
+
+Expression::Expression(CalculatorCatalog* catalog, const QString& text): KatapultItem(), _catalog(catalog), _text(text)
+{
+ evaluate();
+}
+
+QPixmap Expression::icon(int size) const
+{
+ const char* icon = "checkmark";
+ if (_parseError) {
+ icon = "no";
+ }
+ return KGlobal::iconLoader()->loadIcon(icon, KIcon::NoGroup, size);
+}
+
+QString Expression::text() const
+{
+ return _text;
+}
+
+void Expression::setText(const QString& text)
+{
+ _text = text;
+ evaluate();
+}
+
+double Expression::result() const
+{
+ return _result;
+}
+
+bool Expression::parseError() const
+{
+ return _parseError;
+}
+
+CalculatorCatalog* Expression::catalog() const
+{
+ return _catalog;
+}
+
+void Expression::evaluate(bool assignments) const
+{
+ if (!_text.isEmpty()) {
+ QString t = _text;
+ CalculatorCatalog::ParserControl cntrl;
+ cntrl.expression = t.replace(',', '.').ascii();
+ cntrl.catalog = _catalog;
+ cntrl.assignments = assignments;
+ if (yyparse(&cntrl) == 0) {
+ _result = cntrl.result;
+ _parseError = false;
+ if (assignments) {
+ _catalog->setVar(_catalog->getVarID("ans"), _result);
+ }
+ } else {
+ _parseError = true;
+ }
+ } else {
+ _parseError = true;
+ }
+}
+
+#include "expression.moc"
diff --git a/katapult/plugins/catalogs/calculatorcatalog/expression.h b/katapult/plugins/catalogs/calculatorcatalog/expression.h
new file mode 100644
index 0000000..6d736f9
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/expression.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * Copyright (C) 2005 Tobi Vollebregt *
+ * tobivollebregt@gmail.com *
+ * *
+ * Copyright (C) 2005 by Joe Ferris *
+ * jferris@optimistictech.com *
+ * *
+ * 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. *
+ ***************************************************************************/
+#ifndef EXPRESSION_H
+#define EXPRESSION_H
+
+#include <katapultitem.h>
+
+class CalculatorCatalog;
+
+/**
+@author Tobi Vollebregt
+*/
+class Expression : public KatapultItem
+{
+ Q_OBJECT
+ public:
+ Expression(CalculatorCatalog*, const QString&);
+
+ virtual QPixmap icon(int) const;
+ virtual QString text() const;
+
+ void setText(const QString&);
+ double result() const;
+ bool parseError() const;
+
+ //evaluate() must be const, or ActionEvaluateExpression::execute() can't call it.
+ //It makes sense because evaluate() does _not_ change the expression,
+ //it just calculates the result and remembers that.
+ void evaluate(bool assignments = false) const;
+
+ CalculatorCatalog* catalog() const;
+
+ private:
+ CalculatorCatalog* const _catalog;
+ QString _text;
+ mutable double _result;
+ mutable bool _parseError;
+};
+
+#endif
diff --git a/katapult/plugins/catalogs/calculatorcatalog/hi128-action-checkmark.png b/katapult/plugins/catalogs/calculatorcatalog/hi128-action-checkmark.png
new file mode 100644
index 0000000..9854f79
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/hi128-action-checkmark.png
Binary files differ
diff --git a/katapult/plugins/catalogs/calculatorcatalog/hi128-action-no.png b/katapult/plugins/catalogs/calculatorcatalog/hi128-action-no.png
new file mode 100644
index 0000000..dae60fe
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/hi128-action-no.png
Binary files differ
diff --git a/katapult/plugins/catalogs/calculatorcatalog/hi128-app-xcalc.png b/katapult/plugins/catalogs/calculatorcatalog/hi128-app-xcalc.png
new file mode 100644
index 0000000..9330ae7
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/hi128-app-xcalc.png
Binary files differ
diff --git a/katapult/plugins/catalogs/calculatorcatalog/katapult_calculatorcatalog.desktop b/katapult/plugins/catalogs/calculatorcatalog/katapult_calculatorcatalog.desktop
new file mode 100644
index 0000000..c528b32
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/katapult_calculatorcatalog.desktop
@@ -0,0 +1,44 @@
+# Copyright (C) 2005 Tobi Vollebregt
+[Desktop Entry]
+Name=Calculator Catalog
+Name[ar]=مستعرض الآلة الحاسبة ( Calculator Catalog )
+Name[bg]=Каталог на калкулатора
+Name[br]=Katalog jederez
+Name[da]=Katalogisér beregninger
+Name[de]=Rechner-Katalog
+Name[el]=Κατάλογος υπολογισμών
+Name[es]=Catalogador de calculadora
+Name[et]=Kalkulaatorikataloog
+Name[fr]=Catalogue calculatrice
+Name[gl]=Catálogo de Calculadora
+Name[it]=Catalogo calcolatrice
+Name[ja]=計算機カタログ
+Name[nb]=Kalkulatorkatalog
+Name[nl]=Rekenmachinecatalogus
+Name[pt]=Catálogo da Calculadora
+Name[pt_BR]=Catálogo da Calculadora
+Name[sv]=Katalogisera beräkningar
+Name[tr]=Hesap Makinesi Kataloğu
+Name[uk]=Каталог калькулятора
+Comment=Catalogs the set of real numbers for easy calculation through katapult.
+Comment[ar]=يستعرض مجموعة ارقامك الحقيقية لعملية الحساب عن طريق katapult.
+Comment[bg]=Каталогизира с Katapult набора от числа с цел лесно пресмятане.
+Comment[da]=Katalogiserer mængden af reelle tal for nem beregning via Katapult.
+Comment[de]=Katalogisiert den Satz reeller Zahlen für einfaches Rechnen mit Katapult
+Comment[el]=Δημιουργεί κατάλογο με πραγματικούς αριθμούς για εύκολους υπολογισμούς μέσω του katapult.
+Comment[es]=Cataloga un conjunto de números reales para realizar con facilidad cálculos a través de katapult.
+Comment[et]=Kataloogib reaalarvud hõlpsaks arvutamiseks Katapulti abil.
+Comment[fr]=Cataloguer un ensemble de valeurs pour un calcul facile via Katapult
+Comment[gl]=Cataloga os números reais para seren calculados mediante katapult.
+Comment[it]=Cataloga l'insieme dei numeri reali per effettuare calcoli facilmente attraverso Katapult.
+Comment[ja]=Katapult から簡単に計算できるように実数のセットをカタログ化
+Comment[nb]=Katalogiserer mengden av reelle tall for enkel beregning via Katapult.
+Comment[nl]=Catalogiseert een set echte getallen voor eenvoudige berekening via katapult.
+Comment[pt]=Cataloga o conjunto de números reais para um cálculo simples através do Katapult.
+Comment[pt_BR]=Cataloga o conjunto de números reais para um cálculo simples através do Katapult.
+Comment[sv]=Katalogiserar mängden reella tal för enkel beräkning via Katapult.
+Comment[uk]=Робить каталог простих чисел для легких підрахунків через Катапульту.
+ServiceTypes=Katapult/Catalog
+Type=Service
+X-KDE-Library=katapult_calculatorcatalog
+X-Katapult-ID=Calculator Catalog
diff --git a/katapult/plugins/catalogs/calculatorcatalog/parser.cpp b/katapult/plugins/catalogs/calculatorcatalog/parser.cpp
new file mode 100644
index 0000000..995cbb2
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/parser.cpp
@@ -0,0 +1,1387 @@
+/* A Bison parser, made by GNU Bison 2.0. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ 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, 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. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Written by Richard Stallman by simplifying the original so called
+ ``semantic'' parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ NUM = 258,
+ FUN = 259,
+ VAR = 260,
+ NEG = 261
+ };
+#endif
+#define NUM 258
+#define FUN 259
+#define VAR 260
+#define NEG 261
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 5 "plugins/catalogs/calculatorcatalog/parser.y"
+
+#define YYLEX_PARAM parsercontrol
+
+#include <math.h>
+#include <stdio.h>
+#include "calculatorcatalog.h"
+
+//void yyerror(char const *);
+#define yyerror(a,b)
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#line 22 "plugins/catalogs/calculatorcatalog/parser.y"
+typedef union YYSTYPE {
+ double val; /* For returning numbers. */
+ FunPtr fptr; /* For returning function pointers. */
+ int id; /* For returning variables. */
+} YYSTYPE;
+/* Line 190 of yacc.c. */
+#line 105 "plugins/catalogs/calculatorcatalog/parser.cpp"
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+#line 39 "plugins/catalogs/calculatorcatalog/parser.y"
+
+static int yylex(YYSTYPE* lvalp, CalculatorCatalog::ParserControl* parsercontrol);
+
+
+/* Line 213 of yacc.c. */
+#line 120 "plugins/catalogs/calculatorcatalog/parser.cpp"
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+# ifndef YYFREE
+# define YYFREE free
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# endif
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# else
+# define YYSTACK_ALLOC alloca
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+ && (! defined (__cplusplus) \
+ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ short int yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined (__GNUC__) && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ register YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+ typedef signed char yysigned_char;
+#else
+ typedef short int yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 13
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 47
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 15
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 3
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 13
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 28
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 261
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const unsigned char yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 13, 14, 9, 8, 2, 7, 2, 10, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 6, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 12, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 11
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const unsigned char yyprhs[] =
+{
+ 0, 0, 3, 5, 9, 11, 15, 19, 23, 27,
+ 30, 34, 38, 43
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+ 16, 0, -1, 17, -1, 5, 6, 17, -1, 3,
+ -1, 17, 8, 17, -1, 17, 7, 17, -1, 17,
+ 9, 17, -1, 17, 10, 17, -1, 7, 17, -1,
+ 17, 12, 17, -1, 13, 17, 14, -1, 4, 13,
+ 17, 14, -1, 5, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const unsigned char yyrline[] =
+{
+ 0, 45, 45, 46, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "NUM", "FUN", "VAR", "'='", "'-'", "'+'",
+ "'*'", "'/'", "NEG", "'^'", "'('", "')'", "$accept", "line", "exp", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const unsigned short int yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 61, 45, 43, 42,
+ 47, 261, 94, 40, 41
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const unsigned char yyr1[] =
+{
+ 0, 15, 16, 16, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const unsigned char yyr2[] =
+{
+ 0, 2, 1, 3, 1, 3, 3, 3, 3, 2,
+ 3, 3, 4, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const unsigned char yydefact[] =
+{
+ 0, 4, 0, 13, 0, 0, 0, 2, 0, 0,
+ 13, 9, 0, 1, 0, 0, 0, 0, 0, 0,
+ 3, 11, 6, 5, 7, 8, 10, 12
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yysigned_char yydefgoto[] =
+{
+ -1, 6, 7
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -12
+static const yysigned_char yypact[] =
+{
+ 12, -12, -11, 2, 17, 17, 3, 35, 17, 17,
+ -12, 6, 19, -12, 17, 17, 17, 17, 17, 27,
+ 35, -12, -3, -3, 6, 6, 6, -12
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yysigned_char yypgoto[] =
+{
+ -12, -12, -4
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const unsigned char yytable[] =
+{
+ 11, 12, 8, 13, 19, 20, 16, 17, 9, 18,
+ 22, 23, 24, 25, 26, 1, 2, 3, 18, 4,
+ 1, 2, 10, 0, 4, 5, 14, 15, 16, 17,
+ 5, 18, 0, 21, 14, 15, 16, 17, 0, 18,
+ 0, 27, 14, 15, 16, 17, 0, 18
+};
+
+static const yysigned_char yycheck[] =
+{
+ 4, 5, 13, 0, 8, 9, 9, 10, 6, 12,
+ 14, 15, 16, 17, 18, 3, 4, 5, 12, 7,
+ 3, 4, 5, -1, 7, 13, 7, 8, 9, 10,
+ 13, 12, -1, 14, 7, 8, 9, 10, -1, 12,
+ -1, 14, 7, 8, 9, 10, -1, 12
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const unsigned char yystos[] =
+{
+ 0, 3, 4, 5, 7, 13, 16, 17, 13, 6,
+ 5, 17, 17, 0, 7, 8, 9, 10, 12, 17,
+ 17, 14, 17, 17, 17, 17, 17, 14
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (parsercontrol, "syntax error: cannot back up");\
+ YYERROR; \
+ } \
+while (0)
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (N) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (0)
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yysymprint (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short int *bottom, short int *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ short int *bottom;
+ short int *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (/* Nothing. */; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+ int yyrule;
+#endif
+{
+ int yyi;
+ unsigned int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ yyrule - 1, yylno);
+ /* Print the symbols being reduced, and their result. */
+ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (Rule); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined (__GLIBC__) && defined (_STRING_H)
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+# if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+# else
+yystrlen (yystr)
+ const char *yystr;
+# endif
+{
+ register const char *yys = yystr;
+
+ while (*yys++ != '\0')
+ continue;
+
+ return yys - yystr - 1;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+# if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+# else
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+# endif
+{
+ register char *yyd = yydest;
+ register const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+ YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (CalculatorCatalog::ParserControl* parsercontrol);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (CalculatorCatalog::ParserControl* parsercontrol)
+#else
+int
+yyparse (parsercontrol)
+ CalculatorCatalog::ParserControl* parsercontrol;
+#endif
+#endif
+{
+ /* The look-ahead symbol. */
+int yychar;
+
+/* The semantic value of the look-ahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+ register int yystate;
+ register int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int yytoken = 0;
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ short int yyssa[YYINITDEPTH];
+ short int *yyss = yyssa;
+ register short int *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK (yyvsp--, yyssp--)
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* When reducing, the number of symbols on the RHS of the reduced
+ rule. */
+ int yylen;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+
+ yyvsp[0] = yylval;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks.
+ */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short int *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow ("parser stack overflow",
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyoverflowlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyoverflowlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ short int *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyoverflowlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a look-ahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to look-ahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a look-ahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 45 "plugins/catalogs/calculatorcatalog/parser.y"
+ { parsercontrol->result = (yyvsp[0].val); ;}
+ break;
+
+ case 3:
+#line 46 "plugins/catalogs/calculatorcatalog/parser.y"
+ { if (parsercontrol->assignments) parsercontrol->catalog->setVar((yyvsp[-2].id), (yyvsp[0].val)); ;}
+ break;
+
+ case 4:
+#line 49 "plugins/catalogs/calculatorcatalog/parser.y"
+ { (yyval.val) = (yyvsp[0].val); ;}
+ break;
+
+ case 5:
+#line 50 "plugins/catalogs/calculatorcatalog/parser.y"
+ { (yyval.val) = (yyvsp[-2].val) + (yyvsp[0].val); ;}
+ break;
+
+ case 6:
+#line 51 "plugins/catalogs/calculatorcatalog/parser.y"
+ { (yyval.val) = (yyvsp[-2].val) - (yyvsp[0].val); ;}
+ break;
+
+ case 7:
+#line 52 "plugins/catalogs/calculatorcatalog/parser.y"
+ { (yyval.val) = (yyvsp[-2].val) * (yyvsp[0].val); ;}
+ break;
+
+ case 8:
+#line 53 "plugins/catalogs/calculatorcatalog/parser.y"
+ { (yyval.val) = (yyvsp[-2].val) / (yyvsp[0].val); ;}
+ break;
+
+ case 9:
+#line 54 "plugins/catalogs/calculatorcatalog/parser.y"
+ { (yyval.val) = -(yyvsp[0].val); ;}
+ break;
+
+ case 10:
+#line 55 "plugins/catalogs/calculatorcatalog/parser.y"
+ { (yyval.val) = pow((yyvsp[-2].val), (yyvsp[0].val)); ;}
+ break;
+
+ case 11:
+#line 56 "plugins/catalogs/calculatorcatalog/parser.y"
+ { (yyval.val) = (yyvsp[-1].val); ;}
+ break;
+
+ case 12:
+#line 57 "plugins/catalogs/calculatorcatalog/parser.y"
+ { (yyval.val) = (*(yyvsp[-3].fptr))((yyvsp[-1].val)); ;}
+ break;
+
+ case 13:
+#line 58 "plugins/catalogs/calculatorcatalog/parser.y"
+ { if ((yyvsp[0].id) == -1) {yyerror(parsercontrol, "undeclared variable"); YYABORT;} (yyval.val) = parsercontrol->catalog->getVar((yyvsp[0].id)); ;}
+ break;
+
+
+ }
+
+/* Line 1037 of yacc.c. */
+#line 1098 "plugins/catalogs/calculatorcatalog/parser.cpp"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+
+
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (YYPACT_NINF < yyn && yyn < YYLAST)
+ {
+ YYSIZE_T yysize = 0;
+ int yytype = YYTRANSLATE (yychar);
+ const char* yyprefix;
+ char *yymsg;
+ int yyx;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 0;
+
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
+ yycount += 1;
+ if (yycount == 5)
+ {
+ yysize = 0;
+ break;
+ }
+ }
+ yysize += (sizeof ("syntax error, unexpected ")
+ + yystrlen (yytname[yytype]));
+ yymsg = (char *) YYSTACK_ALLOC (yysize);
+ if (yymsg != 0)
+ {
+ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+ yyp = yystpcpy (yyp, yytname[yytype]);
+
+ if (yycount < 5)
+ {
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yyp = yystpcpy (yyp, yyprefix);
+ yyp = yystpcpy (yyp, yytname[yyx]);
+ yyprefix = " or ";
+ }
+ }
+ yyerror (parsercontrol, yymsg);
+ YYSTACK_FREE (yymsg);
+ }
+ else
+ yyerror (parsercontrol, "syntax error; also virtual memory exhausted");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror (parsercontrol, "syntax error");
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* If at end of input, pop the error token,
+ then the rest of the stack, then return failure. */
+ if (yychar == YYEOF)
+ for (;;)
+ {
+
+ YYPOPSTACK;
+ if (yyssp == yyss)
+ YYABORT;
+ yydestruct ("Error: popping",
+ yystos[*yyssp], yyvsp);
+ }
+ }
+ else
+ {
+ yydestruct ("Error: discarding", yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+#ifdef __GNUC__
+ /* Pacify GCC when the user code never invokes YYERROR and the label
+ yyerrorlab therefore never appears in user code. */
+ if (0)
+ goto yyerrorlab;
+#endif
+
+yyvsp -= yylen;
+ yyssp -= yylen;
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping", yystos[yystate], yyvsp);
+ YYPOPSTACK;
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yydestruct ("Error: discarding lookahead",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here. |
+`----------------------------------------------*/
+yyoverflowlab:
+ yyerror (parsercontrol, "parser stack overflow");
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+ return yyresult;
+}
+
+
+#line 61 "plugins/catalogs/calculatorcatalog/parser.y"
+
+
+/* The lexical analyzer returns a double floating point
+number on the stack and the token NUM, or the numeric code
+of the character read if not a number. It skips all blanks
+and tabs, and returns 0 for end-of-input. */
+
+#include <ctype.h>
+#include <string.h>
+
+#define exp (parsercontrol->expression)
+
+static int yylex(YYSTYPE* lvalp, CalculatorCatalog::ParserControl* parsercontrol)
+{
+ int c;
+
+ /* Skip white space. */
+ while ((c = *(exp++)) == ' ') {
+ }
+ /* Return end-of-input. */
+ if (c == EOF) {
+ return 0;
+ }
+ /* Process numbers. */
+ if (c == '.' || isdigit(c)) {
+ char *endptr = 0;
+ lvalp->val = strtod(exp - 1, &endptr);
+ exp = endptr;
+ return NUM;
+ }
+ /* Process IDs. */
+ if (isalpha(c)) {
+ int length = 0;
+ char f[128];
+
+ --exp;
+ do {
+ f[length] = tolower(c);
+ ++length;
+ } while ((c = exp[length]) != 0 && isalpha(c));
+ f[length] = 0;
+
+ /* Process functions. */
+ const CalculatorCatalog::Function* const functions = parsercontrol->catalog->functionTable();
+ for (int i = 0; functions[i].name; ++i) {
+ if (length == functions[i].length && strcmp(f, functions[i].name) == 0) {
+ lvalp->fptr = functions[i].fptr;
+ exp += length;
+ return FUN;
+ }
+ }
+
+ /* Process variables. */
+ lvalp->id = parsercontrol->catalog->getVarID(f);
+ exp += length;
+ return VAR;
+ }
+ /* Return a single char. */
+ return c;
+}
+
+
diff --git a/katapult/plugins/catalogs/calculatorcatalog/parser.y b/katapult/plugins/catalogs/calculatorcatalog/parser.y
new file mode 100644
index 0000000..b614a70
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/parser.y
@@ -0,0 +1,120 @@
+/* Author: Tobi Vollebregt */
+
+/* Infix notation calculator. */
+
+%{
+#define YYLEX_PARAM parsercontrol
+
+#include <math.h>
+#include <stdio.h>
+#include "calculatorcatalog.h"
+
+//void yyerror(char const *);
+#define yyerror(a,b)
+%}
+
+/* Be a reentrant parser. */
+%pure_parser
+
+%parse-param {CalculatorCatalog::ParserControl* parsercontrol}
+
+/* Bison declarations. */
+%union {
+ double val; /* For returning numbers. */
+ FunPtr fptr; /* For returning function pointers. */
+ int id; /* For returning variables. */
+}
+
+%token <val> NUM /* Simple double precision number. */
+%token <fptr> FUN /* Function. */
+%token <id> VAR /* Variable. */
+%type <val> exp
+
+%right '=' /* assignment */
+%left '-' '+'
+%left '*' '/'
+%left NEG /* negation--unary minus */
+%right '^' /* exponentiation */
+
+%{
+static int yylex(YYSTYPE* lvalp, CalculatorCatalog::ParserControl* parsercontrol);
+%}
+
+%% /* The grammar follows. */
+
+line: exp { parsercontrol->result = $1; }
+| VAR '=' exp { if (parsercontrol->assignments) parsercontrol->catalog->setVar($1, $3); }
+;
+
+exp: NUM { $$ = $1; }
+| exp '+' exp { $$ = $1 + $3; }
+| exp '-' exp { $$ = $1 - $3; }
+| exp '*' exp { $$ = $1 * $3; }
+| exp '/' exp { $$ = $1 / $3; }
+| '-' exp %prec NEG { $$ = -$2; }
+| exp '^' exp { $$ = pow($1, $3); }
+| '(' exp ')' { $$ = $2; }
+| FUN '(' exp ')' { $$ = (*$1)($3); }
+| VAR { if ($1 == -1) {yyerror(parsercontrol, "undeclared variable"); YYABORT;} $$ = parsercontrol->catalog->getVar($1); }
+;
+
+%%
+
+/* The lexical analyzer returns a double floating point
+number on the stack and the token NUM, or the numeric code
+of the character read if not a number. It skips all blanks
+and tabs, and returns 0 for end-of-input. */
+
+#include <ctype.h>
+#include <string.h>
+
+#define exp (parsercontrol->expression)
+
+static int yylex(YYSTYPE* lvalp, CalculatorCatalog::ParserControl* parsercontrol)
+{
+ int c;
+
+ /* Skip white space. */
+ while ((c = *(exp++)) == ' ') {
+ }
+ /* Return end-of-input. */
+ if (c == EOF) {
+ return 0;
+ }
+ /* Process numbers. */
+ if (c == '.' || isdigit(c)) {
+ char *endptr = 0;
+ lvalp->val = strtod(exp - 1, &endptr);
+ exp = endptr;
+ return NUM;
+ }
+ /* Process IDs. */
+ if (isalpha(c)) {
+ int length = 0;
+ char f[128];
+
+ --exp;
+ do {
+ f[length] = tolower(c);
+ ++length;
+ } while ((c = exp[length]) != 0 && isalpha(c));
+ f[length] = 0;
+
+ /* Process functions. */
+ const CalculatorCatalog::Function* const functions = parsercontrol->catalog->functionTable();
+ for (int i = 0; functions[i].name; ++i) {
+ if (length == functions[i].length && strcmp(f, functions[i].name) == 0) {
+ lvalp->fptr = functions[i].fptr;
+ exp += length;
+ return FUN;
+ }
+ }
+
+ /* Process variables. */
+ lvalp->id = parsercontrol->catalog->getVarID(f);
+ exp += length;
+ return VAR;
+ }
+ /* Return a single char. */
+ return c;
+}
diff --git a/katapult/plugins/catalogs/calculatorcatalog/settings.ui b/katapult/plugins/catalogs/calculatorcatalog/settings.ui
new file mode 100644
index 0000000..67c0faa
--- /dev/null
+++ b/katapult/plugins/catalogs/calculatorcatalog/settings.ui
@@ -0,0 +1,219 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>CalculatorCatalogSettings</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CalculatorCatalogSettings</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>336</width>
+ <height>299</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Number of fractional digits:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fracDigits</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>fracDigits</cstring>
+ </property>
+ <property name="maxValue">
+ <number>10</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="lineStep">
+ <number>1</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Katapult will show this number of fractional digits.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup2</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>normal</cstring>
+ </property>
+ <property name="text">
+ <string>Normal</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>In normal mode, katapult will never show an exponent on a number.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>scientific</cstring>
+ </property>
+ <property name="text">
+ <string>Scientific</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>In scientific mode, katapult will show an exponent on very large or very small numbers.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup3</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>radians</cstring>
+ </property>
+ <property name="text">
+ <string>Radians</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Trigonometric functions expect and return angles in radians (2 pi radians is a full circle).</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>degrees</cstring>
+ </property>
+ <property name="text">
+ <string>Degrees</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Trigonometric functions expect and return angles in degrees (360 degrees is a full circle).</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>clipboard</cstring>
+ </property>
+ <property name="title">
+ <string>Copy to clipboard on execute</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>katapult can copy the expression or the result of the expression to the clipboard if you press the key assigned to "execute action" (by default, this is Enter).</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Copied text:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>formatString</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>formatString</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;i&gt;Hint:&lt;/i&gt; %1 is replaced by the expression, %2 is replaced by the result</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<tabstops>
+ <tabstop>fracDigits</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>