summaryrefslogtreecommitdiff
path: root/idlc/source/astexpression.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'idlc/source/astexpression.cxx')
-rw-r--r--idlc/source/astexpression.cxx1269
1 files changed, 1269 insertions, 0 deletions
diff --git a/idlc/source/astexpression.cxx b/idlc/source/astexpression.cxx
new file mode 100644
index 000000000000..fd9628663e2d
--- /dev/null
+++ b/idlc/source/astexpression.cxx
@@ -0,0 +1,1269 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_idlc.hxx"
+#include <idlc/astexpression.hxx>
+#include <idlc/astconstant.hxx>
+#include <idlc/astscope.hxx>
+#include <idlc/errorhandler.hxx>
+
+#include <limits.h>
+#include <float.h>
+
+#undef MAXCHAR
+#define MAXCHAR 127
+#undef MINCHAR
+#define MINCHAR -128
+
+using namespace ::rtl;
+
+AstExpression::AstExpression(ExprComb c, AstExpression *pExpr1, AstExpression *pExpr2)
+ : m_combOperator(c)
+ , m_subExpr1(pExpr1)
+ , m_subExpr2(pExpr2)
+ , m_exprValue(NULL)
+ , m_pSymbolicName(NULL)
+{
+ fillDefinitionDetails();
+
+}
+
+AstExpression::AstExpression(sal_Int32 l)
+ : m_combOperator(EC_none)
+ , m_subExpr1(NULL)
+ , m_subExpr2(NULL)
+ , m_exprValue(NULL)
+ , m_pSymbolicName(NULL)
+{
+ fillDefinitionDetails();
+
+ m_exprValue = new AstExprValue();
+ m_exprValue->et = ET_long;
+ m_exprValue->u.lval = l;
+}
+
+AstExpression::AstExpression(sal_Int32 l, ExprType et)
+ : m_combOperator(EC_none)
+ , m_subExpr1(NULL)
+ , m_subExpr2(NULL)
+ , m_exprValue(NULL)
+ , m_pSymbolicName(NULL)
+{
+ fillDefinitionDetails();
+
+ m_exprValue = new AstExprValue();
+ m_exprValue->et = et;
+ m_exprValue->u.lval = l;
+}
+
+AstExpression::AstExpression(sal_Int64 h)
+ : m_combOperator(EC_none)
+ , m_subExpr1(NULL)
+ , m_subExpr2(NULL)
+ , m_exprValue(NULL)
+ , m_pSymbolicName(NULL)
+{
+ fillDefinitionDetails();
+
+ m_exprValue = new AstExprValue();
+ m_exprValue->et = ET_hyper;
+ m_exprValue->u.hval = h;
+}
+
+AstExpression::AstExpression(sal_uInt64 uh)
+ : m_combOperator(EC_none)
+ , m_subExpr1(NULL)
+ , m_subExpr2(NULL)
+ , m_exprValue(NULL)
+ , m_pSymbolicName(NULL)
+{
+ fillDefinitionDetails();
+
+ m_exprValue = new AstExprValue();
+ m_exprValue->et = ET_uhyper;
+ m_exprValue->u.uhval = uh;
+}
+
+AstExpression::AstExpression(double d)
+ : m_combOperator(EC_none)
+ , m_subExpr1(NULL)
+ , m_subExpr2(NULL)
+ , m_exprValue(NULL)
+ , m_pSymbolicName(NULL)
+{
+ fillDefinitionDetails();
+
+ m_exprValue = new AstExprValue();
+ m_exprValue->et = ET_double;
+ m_exprValue->u.dval = d;
+}
+
+AstExpression::AstExpression(::rtl::OString* scopedName)
+ : m_combOperator(EC_symbol)
+ , m_subExpr1(NULL)
+ , m_subExpr2(NULL)
+ , m_exprValue(NULL)
+ , m_pSymbolicName(scopedName)
+{
+ fillDefinitionDetails();
+}
+
+AstExpression::~AstExpression()
+{
+ if ( m_exprValue )
+ delete m_exprValue;
+ if ( m_subExpr1 )
+ delete m_subExpr1;
+ if ( m_subExpr2 )
+ delete m_subExpr2;
+ if ( m_pSymbolicName )
+ delete m_pSymbolicName;
+}
+
+/*
+ * Perform the coercion from the given AstExprValue to the requested
+ * ExprType. Return an AstExprValue if successful, NULL if failed.
+ * must be done for hyper, uhyper
+ */
+static AstExprValue *
+coerce_value(AstExprValue *ev, ExprType t)
+{
+ if (ev == NULL)
+ return NULL;
+
+ switch (t)
+ {
+ case ET_short:
+ switch (ev->et)
+ {
+ case ET_short:
+ return ev;
+ case ET_ushort:
+ if (ev->u.usval > SAL_MAX_INT16)
+ return NULL;
+ ev->u.sval = (sal_Int16)ev->u.usval;
+ ev->et = ET_short;
+ return ev;
+ case ET_long:
+ if (ev->u.lval < SAL_MIN_INT16 || ev->u.lval > SAL_MAX_INT16)
+ return NULL;
+ ev->u.sval = (sal_Int16)ev->u.lval;
+ ev->et = ET_short;
+ return ev;
+ case ET_ulong:
+ if (ev->u.ulval > SAL_MAX_INT16)
+ return NULL;
+ ev->u.sval = (sal_Int16)ev->u.ulval;
+ ev->et = ET_short;
+ return ev;
+ case ET_hyper:
+ if (ev->u.hval < SAL_MIN_INT16 || ev->u.hval > SAL_MAX_INT16)
+ return NULL;
+ ev->u.sval = (sal_Int16)ev->u.hval;
+ ev->et = ET_short;
+ return ev;
+ case ET_uhyper:
+ if (ev->u.uhval > SAL_MAX_INT16)
+ return NULL;
+ ev->u.sval = (sal_Int16)ev->u.uhval;
+ ev->et = ET_short;
+ return ev;
+ case ET_boolean:
+ ev->u.sval = (sal_Int16)ev->u.bval;
+ ev->et = ET_short;
+ return ev;
+ case ET_float:
+ if (ev->u.fval < SAL_MIN_INT16 || ev->u.fval > SAL_MAX_INT16)
+ return NULL;
+ ev->u.sval = (sal_Int16)ev->u.fval;
+ ev->et = ET_short;
+ return ev;
+ case ET_double:
+ if (ev->u.dval < SAL_MIN_INT16 || ev->u.dval > SAL_MAX_INT16)
+ return NULL;
+ ev->u.sval = (sal_Int16)ev->u.dval;
+ ev->et = ET_short;
+ return ev;
+ case ET_byte:
+ ev->u.sval = (sal_Int16)ev->u.byval;
+ ev->et = ET_short;
+ return ev;
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+ case ET_ushort:
+ switch (ev->et)
+ {
+ case ET_short:
+ if (ev->u.sval < 0)
+ return NULL;
+ ev->u.usval = (sal_uInt16)ev->u.sval;
+ ev->et = ET_ushort;
+ return ev;
+ case ET_ushort:
+ return ev;
+ case ET_long:
+ if (ev->u.lval < 0 || ev->u.lval > SAL_MAX_UINT16)
+ return NULL;
+ ev->u.usval = (sal_uInt16)ev->u.lval;
+ ev->et = ET_ushort;
+ return ev;
+ case ET_ulong:
+ if (ev->u.ulval > SAL_MAX_UINT16)
+ return NULL;
+ ev->u.usval = (sal_uInt16)ev->u.ulval;
+ ev->et = ET_ushort;
+ return ev;
+ case ET_hyper:
+ if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT16)
+ return NULL;
+ ev->u.usval = (sal_uInt16)ev->u.hval;
+ ev->et = ET_ushort;
+ return ev;
+ case ET_uhyper:
+ if (ev->u.uhval > SAL_MAX_UINT16)
+ return NULL;
+ ev->u.usval = (sal_uInt16)ev->u.uhval;
+ ev->et = ET_ushort;
+ return ev;
+ case ET_boolean:
+ ev->u.usval = (sal_uInt16)ev->u.bval;
+ ev->et = ET_short;
+ return ev;
+ case ET_float:
+ if (ev->u.fval < 0.0 || ev->u.fval > SAL_MAX_UINT16)
+ return NULL;
+ ev->u.usval = (sal_uInt16)ev->u.fval;
+ ev->et = ET_short;
+ return ev;
+ case ET_double:
+ if (ev->u.dval < 0.0 || ev->u.dval > SAL_MAX_UINT16)
+ return NULL;
+ ev->u.usval = (sal_uInt16)ev->u.dval;
+ ev->et = ET_short;
+ return ev;
+ case ET_byte:
+ ev->u.usval = (sal_uInt16)ev->u.byval;
+ ev->et = ET_ushort;
+ return ev;
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+ case ET_long:
+ switch (ev->et)
+ {
+ case ET_short:
+ ev->u.lval = (sal_Int32)ev->u.sval;
+ ev->et = ET_long;
+ return ev;
+ case ET_ushort:
+ ev->u.lval = (sal_Int32)ev->u.usval;
+ ev->et = ET_long;
+ return ev;
+ case ET_long:
+ return ev;
+ case ET_ulong:
+ if (ev->u.ulval > SAL_MAX_INT32)
+ return NULL;
+ ev->u.lval = (sal_Int32)ev->u.ulval;
+ ev->et = ET_long;
+ return ev;
+ case ET_hyper:
+ if (ev->u.hval < SAL_MIN_INT32 || ev->u.hval > SAL_MAX_INT32)
+ return NULL;
+ ev->u.lval = (sal_Int32)ev->u.hval;
+ ev->et = ET_long;
+ return ev;
+ case ET_uhyper:
+ if (ev->u.uhval > SAL_MAX_INT32)
+ return NULL;
+ ev->u.lval = (sal_Int32)ev->u.uhval;
+ ev->et = ET_long;
+ return ev;
+ case ET_boolean:
+ ev->u.lval = (sal_Int32)ev->u.bval;
+ ev->et = ET_long;
+ return ev;
+ case ET_float:
+ if (ev->u.fval < SAL_MIN_INT32 || ev->u.fval > SAL_MAX_INT32)
+ return NULL;
+ ev->u.lval = (sal_Int32)ev->u.fval;
+ ev->et = ET_long;
+ return ev;
+ case ET_double:
+ if (ev->u.dval < SAL_MIN_INT32 || ev->u.dval > SAL_MAX_INT32)
+ return NULL;
+ ev->u.lval = (sal_Int32)ev->u.dval;
+ ev->et = ET_long;
+ return ev;
+ case ET_byte:
+ ev->u.lval = (sal_Int32) ev->u.byval;
+ ev->et = ET_long;
+ return ev;
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+ case ET_ulong:
+ switch (ev->et)
+ {
+ case ET_short:
+ if (ev->u.sval < 0)
+ return NULL;
+ ev->u.ulval = (sal_uInt32)ev->u.sval;
+ ev->et = ET_ulong;
+ return ev;
+ case ET_ushort:
+ ev->u.ulval = (sal_uInt32)ev->u.usval;
+ ev->et = ET_ulong;
+ return ev;
+ case ET_long:
+ if (ev->u.lval < 0)
+ return NULL;
+ ev->u.ulval = (sal_uInt32)ev->u.lval;
+ ev->et = ET_ulong;
+ return ev;
+ case ET_ulong:
+ return ev;
+ case ET_hyper:
+ if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT32)
+ return NULL;
+ ev->u.lval = (sal_uInt32)ev->u.hval;
+ ev->et = ET_ulong;
+ return ev;
+ case ET_uhyper:
+ if (ev->u.uhval > SAL_MAX_UINT32)
+ return NULL;
+ ev->u.ulval = (sal_uInt32)ev->u.uhval;
+ ev->et = ET_ulong;
+ return ev;
+ case ET_boolean:
+ ev->u.ulval = (sal_uInt32)ev->u.bval;
+ ev->et = ET_ulong;
+ return ev;
+ case ET_float:
+ if (ev->u.fval < 0.0 || ev->u.fval > SAL_MAX_UINT32)
+ return NULL;
+ ev->u.ulval = (sal_uInt32)ev->u.fval;
+ ev->et = ET_ulong;
+ return ev;
+ case ET_double:
+ if (ev->u.dval < 0.0 || ev->u.dval > SAL_MAX_UINT32)
+ return NULL;
+ ev->u.ulval = (sal_uInt32)ev->u.dval;
+ ev->et = ET_ulong;
+ return ev;
+ case ET_byte:
+ ev->u.ulval = (sal_uInt32)ev->u.byval;
+ ev->et = ET_ulong;
+ return ev;
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+ case ET_hyper:
+ switch (ev->et)
+ {
+ case ET_short:
+ ev->u.hval = (sal_Int64)ev->u.sval;
+ ev->et = ET_hyper;
+ return ev;
+ case ET_ushort:
+ ev->u.hval = (sal_Int64)ev->u.usval;
+ ev->et = ET_hyper;
+ return ev;
+ case ET_long:
+ ev->u.hval = (sal_Int64)ev->u.lval;
+ ev->et = ET_hyper;
+ return ev;
+ case ET_ulong:
+ ev->u.hval = (sal_Int64)ev->u.ulval;
+ ev->et = ET_hyper;
+ return ev;
+ case ET_hyper:
+ return ev;
+ case ET_uhyper:
+ if (ev->u.uhval > SAL_MAX_INT64)
+ return NULL;
+ ev->u.hval = (sal_Int64)ev->u.uhval;
+ ev->et = ET_long;
+ return ev;
+ case ET_boolean:
+ ev->u.hval = (sal_Int64)ev->u.bval;
+ ev->et = ET_hyper;
+ return ev;
+ case ET_float:
+ if (ev->u.fval < SAL_MIN_INT64 || ev->u.fval > SAL_MAX_INT64)
+ return NULL;
+ ev->u.hval = (sal_Int64)ev->u.fval;
+ ev->et = ET_hyper;
+ return ev;
+ case ET_double:
+ if (ev->u.dval < SAL_MIN_INT64 || ev->u.dval > SAL_MAX_INT64)
+ return NULL;
+ ev->u.hval = (sal_Int64)ev->u.dval;
+ ev->et = ET_hyper;
+ return ev;
+ case ET_byte:
+ ev->u.hval = (sal_Int64)ev->u.byval;
+ ev->et = ET_hyper;
+ return ev;
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+ case ET_uhyper:
+ switch (ev->et)
+ {
+ case ET_short:
+ if (ev->u.sval < 0)
+ return NULL;
+ ev->u.uhval = (sal_uInt64)ev->u.sval;
+ ev->et = ET_uhyper;
+ return ev;
+ case ET_ushort:
+ ev->u.uhval = (sal_uInt64)ev->u.usval;
+ ev->et = ET_uhyper;
+ return ev;
+ case ET_long:
+ if (ev->u.lval < 0)
+ return NULL;
+ ev->u.uhval = (sal_uInt64)ev->u.lval;
+ ev->et = ET_uhyper;
+ return ev;
+ case ET_ulong:
+ ev->u.uhval = (sal_uInt64)ev->u.ulval;
+ ev->et = ET_uhyper;
+ return ev;
+ case ET_hyper:
+ if (ev->u.hval < 0)
+ return NULL;
+ ev->u.uhval = (sal_uInt64)ev->u.hval;
+ ev->et = ET_uhyper;
+ return ev;
+ case ET_uhyper:
+ return ev;
+ case ET_boolean:
+ ev->u.uhval = (sal_uInt64)ev->u.bval;
+ ev->et = ET_uhyper;
+ return ev;
+ case ET_float:
+ if (ev->u.fval < 0.0 || ev->u.fval > SAL_MAX_UINT64)
+ return NULL;
+ ev->u.uhval = (sal_uInt64)ev->u.fval;
+ ev->et = ET_uhyper;
+ return ev;
+ case ET_double:
+ if (ev->u.dval < 0.0 || ev->u.dval > SAL_MAX_UINT64)
+ return NULL;
+ ev->u.uhval = (sal_uInt64)ev->u.dval;
+ ev->et = ET_uhyper;
+ return ev;
+ case ET_byte:
+ ev->u.uhval = (sal_uInt64)ev->u.byval;
+ ev->et = ET_uhyper;
+ return ev;
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+ case ET_boolean:
+ switch (ev->et)
+ {
+ case ET_short:
+ ev->u.bval = (ev->u.sval == 0) ? sal_False : sal_True;
+ ev->et = ET_boolean;
+ return ev;
+ case ET_ushort:
+ ev->u.bval = (ev->u.usval == 0) ? sal_False : sal_True;
+ ev->et = ET_boolean;
+ return ev;
+ case ET_long:
+ ev->u.bval = (ev->u.lval == 0) ? sal_False : sal_True;
+ ev->et = ET_boolean;
+ return ev;
+ case ET_ulong:
+ ev->u.bval = (ev->u.ulval == 0) ? sal_False : sal_True;
+ ev->et = ET_boolean;
+ return ev;
+ case ET_hyper:
+ ev->u.bval = (ev->u.hval == 0) ? sal_False : sal_True;
+ ev->et = ET_boolean;
+ return ev;
+ case ET_uhyper:
+ ev->u.bval = (ev->u.uhval == 0) ? sal_False : sal_True;
+ ev->et = ET_boolean;
+ return ev;
+ case ET_boolean:
+ return ev;
+ case ET_float:
+ ev->u.bval = (ev->u.fval == 0.0) ? sal_False : sal_True;
+ ev->et = ET_boolean;
+ return ev;
+ case ET_double:
+ ev->u.bval = (ev->u.dval == 0.0) ? sal_False : sal_True;
+ ev->et = ET_boolean;
+ return ev;
+ case ET_byte:
+ ev->u.bval = (ev->u.byval == 0) ? sal_False : sal_True;
+ ev->et = ET_boolean;
+ return ev;
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+ case ET_float:
+ switch (ev->et)
+ {
+ case ET_short:
+ ev->u.fval = (float)ev->u.sval;
+ ev->et = ET_float;
+ return ev;
+ case ET_ushort:
+ ev->u.fval = (float)ev->u.usval;
+ ev->et = ET_float;
+ return ev;
+ case ET_long:
+ ev->u.fval = (float)ev->u.lval;
+ ev->et = ET_float;
+ return ev;
+ case ET_ulong:
+ ev->u.fval = (float)ev->u.ulval;
+ ev->et = ET_float;
+ return ev;
+ case ET_hyper:
+ ev->u.fval = (float)ev->u.hval;
+ ev->et = ET_float;
+ return ev;
+ case ET_uhyper:
+ if ((float)ev->u.ulval > FLT_MAX)
+ return NULL;
+ ev->u.fval = (float)ev->u.ulval;
+ ev->et = ET_float;
+ return ev;
+ case ET_boolean:
+ ev->u.fval = (ev->u.bval == sal_True) ? 1.0f : 0.0f;
+ ev->et = ET_float;
+ return ev;
+ case ET_float:
+ return ev;
+ case ET_double:
+ if ((float)ev->u.dval > FLT_MAX || (float)ev->u.dval < -FLT_MAX)
+ return NULL;
+ ev->u.fval = (float)ev->u.dval;
+ ev->et = ET_float;
+ return ev;
+ case ET_byte:
+ ev->u.fval = (float)ev->u.byval;
+ ev->et = ET_float;
+ return ev;
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+ case ET_double:
+ switch (ev->et)
+ {
+ case ET_short:
+ ev->u.dval = (double)ev->u.sval;
+ ev->et = ET_double;
+ return ev;
+ case ET_ushort:
+ ev->u.dval = (double)ev->u.usval;
+ ev->et = ET_double;
+ return ev;
+ case ET_long:
+ ev->u.dval = (double)ev->u.lval;
+ ev->et = ET_double;
+ return ev;
+ case ET_ulong:
+ ev->u.dval = (double)ev->u.ulval;
+ ev->et = ET_double;
+ return ev;
+ case ET_hyper:
+ ev->u.dval = (double)ev->u.hval;
+ ev->et = ET_double;
+ return ev;
+ case ET_uhyper:
+ if ((double)ev->u.dval > FLT_MAX || (double)ev->u.dval < -FLT_MAX)
+ return NULL;
+ ev->u.dval = (double)ev->u.ulval;
+ ev->et = ET_double;
+ return ev;
+ case ET_boolean:
+ ev->u.dval = (ev->u.bval == sal_True) ? 1.0 : 0.0;
+ ev->et = ET_double;
+ return ev;
+ case ET_float:
+ ev->u.dval = (double)ev->u.fval;
+ ev->et = ET_double;
+ return ev;
+ case ET_double:
+ return ev;
+ case ET_byte:
+ ev->u.dval = (double)ev->u.byval;
+ ev->et = ET_double;
+ return ev;
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+ case ET_byte:
+ switch (ev->et)
+ {
+ case ET_short:
+ if (ev->u.sval < SAL_MIN_INT8 || ev->u.sval > SAL_MAX_UINT8)
+ return NULL;
+ ev->u.byval = (sal_uChar)ev->u.sval;
+ ev->et = ET_byte;
+ return ev;
+ case ET_ushort:
+ if (ev->u.usval > SAL_MAX_UINT8)
+ return NULL;
+ ev->u.byval = (sal_uChar)ev->u.usval;
+ ev->et = ET_byte;
+ return ev;
+ case ET_long:
+ if (ev->u.lval < SAL_MIN_INT8 || ev->u.lval > SAL_MAX_UINT8)
+ return NULL;
+ ev->u.byval = (sal_uChar) ev->u.lval;
+ ev->et = ET_byte;
+ return ev;
+ case ET_ulong:
+ if (ev->u.ulval > SAL_MAX_UINT8)
+ return NULL;
+ ev->u.byval = (sal_uChar) ev->u.ulval;
+ ev->et = ET_byte;
+ return ev;
+ case ET_hyper:
+ if (ev->u.hval < SAL_MIN_INT8 || ev->u.hval > SAL_MAX_UINT8)
+ return NULL;
+ ev->u.byval = (sal_uChar) ev->u.hval;
+ ev->et = ET_byte;
+ return ev;
+ case ET_uhyper:
+ if (ev->u.uhval > SAL_MAX_UINT8)
+ return NULL;
+ ev->u.byval = (sal_uChar) ev->u.uhval;
+ ev->et = ET_byte;
+ return ev;
+ case ET_boolean:
+ ev->u.byval = (ev->u.bval == sal_False) ? 1 : 0;
+ ev->et = ET_byte;
+ return ev;
+ case ET_float:
+ if (ev->u.fval < SAL_MIN_INT8 || ev->u.fval > SAL_MAX_UINT8)
+ return NULL;
+ ev->u.byval = (sal_uChar) ev->u.fval;
+ ev->et = ET_byte;
+ return ev;
+ case ET_double:
+ if (ev->u.dval < SAL_MIN_INT8 || ev->u.dval > SAL_MAX_UINT8)
+ return NULL;
+ ev->u.byval = (sal_uChar) ev->u.dval;
+ ev->et = ET_byte;
+ return ev;
+ case ET_byte:
+ return ev;
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+ default:
+ OSL_ASSERT(false);
+ return NULL;
+ }
+}
+
+/*
+ * Evaluate the expression with the evaluation kind requested. Supported
+ * evaluation kinds are
+ * - EK_const: The expression must evaluate to a constant
+ * - EK_positive_int: The expression must further evaluate to a
+ * positive integer
+ */
+static AstExprValue *
+eval_kind(AstExprValue *ev, EvalKind ek)
+{
+ if (ek == EK_const)
+ return ev;
+ if (ek == EK_positive_int)
+ return coerce_value(ev, ET_ulong);
+
+ return NULL;
+}
+
+AstExprValue* AstExpression::coerce(ExprType t, sal_Bool bAssign)
+{
+ AstExprValue *copy;
+
+ /*
+ * Is it already of the right type?
+ */
+ if (m_exprValue != NULL && m_exprValue->et == t)
+ return m_exprValue;
+ /*
+ * OK, must coerce
+ *
+ * First, evaluate it, then try to coerce result type
+ * If already evaluated, return the result
+ */
+ m_exprValue = eval_internal(EK_const);
+ if (m_exprValue == NULL)
+ return NULL;
+
+ /*
+ * Create a copy to contain coercion result
+ */
+ copy = new AstExprValue;
+
+ copy->et = m_exprValue->et;
+ switch (m_exprValue->et)
+ {
+ case ET_short:
+ copy->u.sval = m_exprValue->u.sval;
+ break;
+ case ET_ushort:
+ copy->u.usval = m_exprValue->u.usval;
+ break;
+ case ET_long:
+ copy->u.lval = m_exprValue->u.lval;
+ break;
+ case ET_ulong:
+ copy->u.ulval = m_exprValue->u.ulval;
+ break;
+ case ET_hyper:
+ copy->u.hval = m_exprValue->u.hval;
+ break;
+ case ET_uhyper:
+ copy->u.uhval = m_exprValue->u.uhval;
+ break;
+ case ET_boolean:
+ copy->u.bval = m_exprValue->u.bval;
+ break;
+ case ET_float:
+ copy->u.fval = m_exprValue->u.fval;
+ break;
+ case ET_double:
+ copy->u.dval = m_exprValue->u.dval;
+ break;
+ case ET_byte:
+ copy->u.byval = m_exprValue->u.byval;
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+
+ if (bAssign)
+ {
+ m_exprValue = coerce_value(copy, t);
+ return m_exprValue;
+ }
+
+ return coerce_value(copy, t);
+}
+
+void AstExpression::evaluate(EvalKind ek)
+{
+ m_exprValue = eval_internal(ek);
+ m_exprValue = eval_kind(m_exprValue, ek);
+}
+
+sal_Bool AstExpression::operator==(AstExpression *pExpr)
+{
+ if (m_combOperator != pExpr->getCombOperator())
+ return sal_False;
+ evaluate(EK_const);
+ pExpr->evaluate(EK_const);
+ if (m_exprValue == NULL || pExpr->getExprValue() == NULL)
+ return sal_False;
+ if (m_exprValue->et != pExpr->getExprValue()->et)
+ return sal_False;
+ switch (m_exprValue->et)
+ {
+ case ET_short:
+ return (m_exprValue->u.sval == pExpr->getExprValue()->u.sval) ? sal_True : sal_False;
+ case ET_ushort:
+ return (m_exprValue->u.usval == pExpr->getExprValue()->u.usval) ? sal_True : sal_False;
+ case ET_long:
+ return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False;
+ case ET_ulong:
+ return (m_exprValue->u.ulval == pExpr->getExprValue()->u.ulval) ? sal_True : sal_False;
+ case ET_hyper:
+ return (m_exprValue->u.hval == pExpr->getExprValue()->u.hval) ? sal_True : sal_False;
+ case ET_uhyper:
+ return (m_exprValue->u.uhval == pExpr->getExprValue()->u.uhval) ? sal_True : sal_False;
+ case ET_float:
+ return (m_exprValue->u.fval == pExpr->getExprValue()->u.fval) ? sal_True : sal_False;
+ case ET_double:
+ return (m_exprValue->u.dval == pExpr->getExprValue()->u.dval) ? sal_True : sal_False;
+ case ET_byte:
+ return (m_exprValue->u.byval == pExpr->getExprValue()->u.byval) ? sal_True : sal_False;
+ case ET_boolean:
+ return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False;
+ default:
+ OSL_ASSERT(false);
+ return sal_False;
+ }
+
+ return sal_False;
+}
+
+sal_Bool AstExpression::compare(AstExpression *pExpr)
+{
+ if (m_combOperator != pExpr->getCombOperator())
+ return sal_False;
+ evaluate(EK_const);
+ pExpr->evaluate(EK_const);
+ if (m_exprValue == NULL || pExpr->getExprValue() == NULL)
+ return sal_False;
+ if (m_exprValue->et != pExpr->getExprValue()->et)
+ return sal_False;
+ switch (m_exprValue->et)
+ {
+ case ET_short:
+ return (m_exprValue->u.sval == pExpr->getExprValue()->u.sval) ? sal_True : sal_False;
+ case ET_ushort:
+ return (m_exprValue->u.usval == pExpr->getExprValue()->u.usval) ? sal_True : sal_False;
+ case ET_long:
+ return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False;
+ case ET_ulong:
+ return (m_exprValue->u.ulval == pExpr->getExprValue()->u.ulval) ? sal_True : sal_False;
+ case ET_hyper:
+ return (m_exprValue->u.hval == pExpr->getExprValue()->u.hval) ? sal_True : sal_False;
+ case ET_uhyper:
+ return (m_exprValue->u.uhval == pExpr->getExprValue()->u.uhval) ? sal_True : sal_False;
+ case ET_float:
+ return (m_exprValue->u.fval == pExpr->getExprValue()->u.fval) ? sal_True : sal_False;
+ case ET_double:
+ return (m_exprValue->u.dval == pExpr->getExprValue()->u.dval) ? sal_True : sal_False;
+ case ET_byte:
+ return (m_exprValue->u.byval == pExpr->getExprValue()->u.byval) ? sal_True : sal_False;
+ case ET_boolean:
+ return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False;
+ default:
+ OSL_ASSERT(false);
+ return sal_False;
+ }
+
+ return sal_False;
+}
+
+void AstExpression::fillDefinitionDetails()
+{
+ m_pScope = idlc()->scopes()->depth() > 0 ? idlc()->scopes()->top() : NULL;
+ m_lineNo = idlc()->getLineNumber();
+ m_fileName = idlc()->getFileName();
+}
+
+AstExprValue* AstExpression::eval_internal(EvalKind ek)
+{
+ /*
+ * Already evaluated?
+ */
+ if ( m_exprValue != NULL )
+ return eval_kind(m_exprValue, ek);
+ /*
+ * OK, must evaluate operator
+ */
+ switch (m_combOperator)
+ {
+ case EC_add:
+ case EC_minus:
+ case EC_mul:
+ case EC_div:
+ case EC_mod:
+ m_exprValue = eval_bin_op(ek);
+ return eval_kind(m_exprValue, ek);
+ case EC_or:
+ case EC_xor:
+ case EC_and:
+ case EC_left:
+ case EC_right:
+ m_exprValue = eval_bit_op(ek);
+ return eval_kind(m_exprValue, ek);
+ case EC_u_plus:
+ case EC_u_minus:
+ case EC_bit_neg:
+ m_exprValue = eval_un_op(ek);
+ return eval_kind(m_exprValue, ek);
+ case EC_symbol:
+ m_exprValue = eval_symbol(ek);
+ return eval_kind(m_exprValue, ek);
+ case EC_none:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+AstExprValue* AstExpression::eval_bin_op(EvalKind ek)
+{
+ AstExprValue *retval = NULL;
+ ExprType eType = ET_double;
+
+ if ( m_combOperator == EC_mod )
+ eType = ET_hyper;
+
+ if (ek != EK_const && ek != EK_positive_int)
+ return NULL;
+ if (m_subExpr1 == NULL || m_subExpr2 == NULL)
+ return NULL;
+ m_subExpr1->setExprValue(m_subExpr1->eval_internal(ek));
+ if (m_subExpr1->getExprValue() == NULL)
+ return NULL;
+ m_subExpr1->setExprValue(m_subExpr1->coerce(eType));
+ if (m_subExpr1->getExprValue() == NULL)
+ return NULL;
+ m_subExpr2->setExprValue(m_subExpr2->eval_internal(ek));
+ if (m_subExpr2->getExprValue() == NULL)
+ return NULL;
+ m_subExpr2->setExprValue(m_subExpr2->coerce(eType));
+ if (m_subExpr2->getExprValue() == NULL)
+ return NULL;
+
+ retval = new AstExprValue();
+ retval->et = eType;
+
+ switch (m_combOperator)
+ {
+ case EC_mod:
+ if (m_subExpr2->getExprValue()->u.hval == 0)
+ return NULL;
+ retval->u.hval = m_subExpr1->getExprValue()->u.hval % m_subExpr2->getExprValue()->u.hval;
+ break;
+ case EC_add:
+ retval->u.dval = m_subExpr1->getExprValue()->u.dval + m_subExpr2->getExprValue()->u.dval;
+ break;
+ case EC_minus:
+ retval->u.dval = m_subExpr1->getExprValue()->u.dval - m_subExpr2->getExprValue()->u.dval;
+ break;
+ case EC_mul:
+ retval->u.dval = m_subExpr1->getExprValue()->u.dval * m_subExpr2->getExprValue()->u.dval;
+ break;
+ case EC_div:
+ if (m_subExpr2->getExprValue()->u.dval == 0.0)
+ return NULL;
+ retval->u.dval = m_subExpr1->getExprValue()->u.dval / m_subExpr2->getExprValue()->u.dval;
+ break;
+ default:
+ return NULL;
+ }
+
+ return retval;
+}
+
+AstExprValue* AstExpression::eval_bit_op(EvalKind ek)
+{
+ AstExprValue *retval = NULL;
+
+ if (ek != EK_const && ek != EK_positive_int)
+ return NULL;
+ if (m_subExpr1 == NULL || m_subExpr2 == NULL)
+ return NULL;
+ m_subExpr1->setExprValue(m_subExpr1->eval_internal(ek));
+ if (m_subExpr1->getExprValue() == NULL)
+ return NULL;
+ m_subExpr1->setExprValue(m_subExpr1->coerce(ET_long));
+ if (m_subExpr1->getExprValue() == NULL)
+ return NULL;
+ m_subExpr2->setExprValue(m_subExpr2->eval_internal(ek));
+ if (m_subExpr2->getExprValue() == NULL)
+ return NULL;
+ m_subExpr2->setExprValue(m_subExpr2->coerce(ET_long));
+ if (m_subExpr2->getExprValue() == NULL)
+ return NULL;
+
+ retval = new AstExprValue;
+ retval->et = ET_long;
+
+ switch (m_combOperator)
+ {
+ case EC_or:
+ retval->u.lval = m_subExpr1->getExprValue()->u.lval | m_subExpr2->getExprValue()->u.lval;
+ break;
+ case EC_xor:
+ retval->u.lval = m_subExpr1->getExprValue()->u.lval ^ m_subExpr2->getExprValue()->u.lval;
+ break;
+ case EC_and:
+ retval->u.lval = m_subExpr1->getExprValue()->u.lval & m_subExpr2->getExprValue()->u.lval;
+ break;
+ case EC_left:
+ retval->u.lval = m_subExpr1->getExprValue()->u.lval << m_subExpr2->getExprValue()->u.lval;
+ break;
+ case EC_right:
+ retval->u.lval = m_subExpr1->getExprValue()->u.lval >> m_subExpr2->getExprValue()->u.lval;
+ break;
+ default:
+ return NULL;
+ }
+
+ return retval;
+}
+
+AstExprValue* AstExpression::eval_un_op(EvalKind ek)
+{
+ AstExprValue *retval = NULL;
+
+ if (m_exprValue != NULL)
+ return m_exprValue;
+
+ if (ek != EK_const && ek != EK_positive_int)
+ return NULL;
+ if (m_subExpr1 == NULL)
+ return NULL;
+ m_subExpr1->setExprValue(m_subExpr1->eval_internal(ek));
+ if (m_subExpr1->getExprValue() == NULL)
+ return NULL;
+ m_subExpr1->setExprValue(m_subExpr1->coerce(ET_double));
+ if (m_subExpr1->getExprValue() == NULL)
+ return NULL;
+
+ retval = new AstExprValue();
+ retval->et = ET_double;
+
+ switch (m_combOperator)
+ {
+ case EC_u_plus:
+ retval->u.lval = m_subExpr1->getExprValue()->u.lval;
+ break;
+ case EC_u_minus:
+ retval->u.lval = -(m_subExpr1->getExprValue()->u.lval);
+ break;
+ case EC_bit_neg:
+ m_subExpr1->setExprValue(m_subExpr1->coerce(ET_long));
+ if (m_subExpr1->getExprValue() == NULL)
+ return NULL;
+ retval->u.lval = ~m_subExpr1->getExprValue()->u.lval;
+ break;
+ default:
+ return NULL;
+ }
+
+ return retval;
+}
+
+AstExprValue* AstExpression::eval_symbol(EvalKind ek)
+{
+ AstScope *pScope = 0;
+ AstDeclaration *pDecl;
+ AstConstant *pConst;
+
+ /*
+ * Is there a symbol stored?
+ */
+ if (m_pSymbolicName == NULL)
+ {
+ idlc()->error()->evalError(this);
+ return NULL;
+ }
+ /*
+ * Get current scope for lookup
+ */
+ if (idlc()->scopes()->depth() > 0)
+ pScope = idlc()->scopes()->topNonNull();
+ if ( !pScope )
+ {
+ idlc()->error()->lookupError(*m_pSymbolicName);
+ return NULL;
+ }
+ /*
+ * Do lookup
+ */
+ pDecl = pScope->lookupByName(*m_pSymbolicName);
+ if (pDecl == NULL)
+ {
+ idlc()->error()->lookupError(*m_pSymbolicName);
+ return NULL;
+ }
+ /*
+ * Is it a constant?
+ */
+ if (pDecl->getNodeType() != NT_const &&
+ pDecl->getNodeType() != NT_enum_val)
+ {
+ idlc()->error()->constantExpected(pDecl, *m_pSymbolicName);
+ return NULL;
+ }
+ if (!idlc()->error()->checkPublished(pDecl))
+ {
+ return NULL;
+ }
+ /*
+ * OK, now evaluate the constant we just got, to produce its value
+ */
+ pConst = static_cast< AstConstant* >(pDecl);
+ if (pConst == NULL)
+ return NULL;
+ return pConst->getConstValue()->eval_internal(ek);
+}
+
+OString AstExpression::toString()
+{
+ OString exprStr;
+ if ( m_combOperator == EC_symbol )
+ return *m_pSymbolicName;
+
+ if ( m_exprValue )
+ {
+ switch (m_exprValue->et)
+ {
+ case ET_short:
+ return OString::valueOf((sal_Int32)m_exprValue->u.sval);
+ case ET_ushort:
+ return OString::valueOf((sal_Int32)m_exprValue->u.usval);
+ case ET_long:
+ return OString::valueOf(m_exprValue->u.lval);
+ case ET_ulong:
+ return OString::valueOf((sal_Int32)m_exprValue->u.ulval);
+ case ET_hyper:
+ return OString::valueOf(m_exprValue->u.hval);
+ case ET_uhyper:
+ return OString::valueOf((sal_Int64)m_exprValue->u.uhval);
+ case ET_float:
+ return OString::valueOf(m_exprValue->u.fval);
+ case ET_double:
+ return OString::valueOf(m_exprValue->u.dval);
+ case ET_byte:
+ return OString::valueOf((sal_Int32)m_exprValue->u.byval);
+ case ET_boolean:
+ if ( m_exprValue->u.lval == 0)
+ return OString("FALSE");
+ else
+ return OString("TRUE");
+ default:
+ OSL_ASSERT(false);
+ return OString();
+ }
+ }
+
+ switch (m_combOperator)
+ {
+ case EC_u_plus:
+ exprStr += OString("+");
+ break;
+ case EC_u_minus:
+ exprStr += OString("-");
+ break;
+ case EC_bit_neg:
+ exprStr += OString("~");
+ break;
+ default:
+ break;
+ }
+ if ( m_subExpr1 )
+ exprStr += m_subExpr1->toString();
+ switch (m_combOperator)
+ {
+ case EC_add:
+ exprStr += OString(" + ");
+ break;
+ case EC_minus:
+ exprStr += OString(" - ");
+ break;
+ case EC_mul:
+ exprStr += OString(" * ");
+ break;
+ case EC_div:
+ exprStr += OString(" / ");
+ break;
+ case EC_mod:
+ exprStr += OString(" % ");
+ break;
+ case EC_or:
+ exprStr += OString(" | ");
+ break;
+ case EC_xor:
+ exprStr += OString(" ^ ");
+ break;
+ case EC_and:
+ exprStr += OString(" & ");
+ break;
+ case EC_left:
+ exprStr += OString(" << ");
+ break;
+ case EC_right:
+ exprStr += OString(" >> ");
+ break;
+ default:
+ break;
+ }
+
+ if ( m_subExpr2 )
+ exprStr += m_subExpr2->toString();
+
+ return exprStr;
+}
+
+// Convert the type of an AST_Expression to a char *
+const sal_Char* SAL_CALL exprTypeToString(ExprType t)
+{
+ switch (t)
+ {
+ case ET_short:
+ return "short";
+ case ET_ushort:
+ return "unsigned short";
+ case ET_long:
+ return "long";
+ case ET_ulong:
+ return "unsigned long";
+ case ET_hyper:
+ return "hyper";
+ case ET_uhyper:
+ return "unsigned hyper";
+ case ET_float:
+ return "float";
+ case ET_double:
+ return "double";
+ case ET_char:
+ return "char";
+ case ET_byte:
+ return "byte";
+ case ET_boolean:
+ return "boolean";
+ case ET_string:
+ return "string";
+ case ET_any:
+ return "any";
+ case ET_type:
+ return "type";
+ case ET_void:
+ return "void";
+ case ET_none:
+ return "none";
+ }
+
+ return ("unkown");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */