Synopsis - Cross-Reference

File: /Synopsis/Parsers/IDL/idlexpr.cc
   1// -*- c++ -*-
   2//                          Package   : omniidl
   3// idlexpr.cc               Created on: 1999/10/18
   4//			    Author    : Duncan Grisby (dpg1)
   5//
   6//    Copyright (C) 1999 AT&T Laboratories Cambridge
   7//
   8//  This file is part of omniidl.
   9//
  10//  omniidl is free software; you can redistribute it and/or modify it
  11//  under the terms of the GNU General Public License as published by
  12//  the Free Software Foundation; either version 2 of the License, or
  13//  (at your option) any later version.
  14//
  15//  This program is distributed in the hope that it will be useful,
  16//  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18//  General Public License for more details.
  19//
  20//  You should have received a copy of the GNU General Public License
  21//  along with this program; if not, write to the Free Software
  22//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  23//  02111-1307, USA.
  24//
  25// Description:
  26//   
  27//   Expression evaluation functions
  28
  29// $Id: idlexpr.cc,v 1.10.2.1 2003/03/23 21:01:45 dgrisby Exp $
  30// $Log: idlexpr.cc,v $
  31// Revision 1.10.2.1  2003/03/23 21:01:45  dgrisby
  32// Start of omniORB 4.1.x development branch.
  33//
  34// Revision 1.6.2.6  2001/10/17 16:48:33  dpg1
  35// Minor error message tweaks
  36//
  37// Revision 1.6.2.5  2001/08/29 11:54:20  dpg1
  38// Clean up const handling in IDL compiler.
  39//
  40// Revision 1.6.2.4  2001/03/13 10:32:11  dpg1
  41// Fixed point support.
  42//
  43// Revision 1.6.2.3  2000/10/27 16:31:09  dpg1
  44// Clean up of omniidl dependencies and types, from omni3_develop.
  45//
  46// Revision 1.6.2.2  2000/10/10 10:18:50  dpg1
  47// Update omniidl front-end from omni3_develop.
  48//
  49// Revision 1.4.2.2  2000/08/07 15:34:36  dpg1
  50// Partial back-port of long long from omni3_1_develop.
  51//
  52// Revision 1.4.2.1  2000/06/27 16:00:17  sll
  53// Fixes to WIN 32 related build and compiler issues.
  54//
  55// Revision 1.4  2000/02/04 12:17:09  dpg1
  56// Support for VMS.
  57//
  58// Revision 1.3  1999/11/02 17:07:26  dpg1
  59// Changes to compile on Solaris.
  60//
  61// Revision 1.2  1999/10/29 10:01:31  dpg1
  62// Nicer error reporting.
  63//
  64// Revision 1.1  1999/10/27 14:05:57  dpg1
  65// *** empty log message ***
  66//
  67
  68#include <idlexpr.h>
  69#include <idlerr.h>
  70#include <idlmath.h>
  71#include <idlast.h>
  72
  73const IDL_WChar EMPTY_WSTRING[] = {'!', 0};
  74
  75#define EXPR_ERR(rt, fn, str, rv) \
  76rt IdlExpr::fn() { \
  77  IdlError(file(), line(), "Cannot interpret %s as " str, errText()); \
  78  return rv; \
  79}
  80
  81// Error functions
  82
  83EXPR_ERR(IdlLongVal, evalAsLongV, "an integer", IdlLongVal((IDL_ULong)1))
  84#ifdef HAS_LongLong
  85EXPR_ERR(IdlLongLongVal, evalAsLongLongV, "an integer",
  86         IdlLongLongVal((IDL_ULongLong)1))
  87#endif
  88
  89EXPR_ERR(IDL_Float,        evalAsFloat,      "a float",               1.0)
  90EXPR_ERR(IDL_Double,       evalAsDouble,     "a double",              1.0)
  91EXPR_ERR(IDL_Boolean,      evalAsBoolean,    "a boolean",             0)
  92EXPR_ERR(IDL_Char,         evalAsChar,       "a character",           '!')
  93EXPR_ERR(const char*,      evalAsString,     "a string",              "!")
  94#ifdef HAS_LongDouble
  95EXPR_ERR(IDL_LongDouble,   evalAsLongDouble, "a long double",         1.0)
  96#endif
  97EXPR_ERR(IDL_WChar,        evalAsWChar,      "a wide character",      '!')
  98EXPR_ERR(const IDL_WChar*, evalAsWString,    "a wide string", EMPTY_WSTRING)
  99EXPR_ERR(IDL_Fixed*,       evalAsFixed,      "fixed point", new IDL_Fixed("1"))
 100
 101Enumerator*
 102IdlExpr::
 103evalAsEnumerator(const Enum* target)
 104{
 105  IdlError(file(), line(), "Cannot interpret %s as enumerator", errText());
 106  return 0;
 107}
 108
 109//
 110// Conversions to IDL integer types
 111
 112IDL_Short IdlExpr::evalAsShort()
 113{
 114  IdlLongVal v = evalAsLongV();
 115  if (v.negative) {
 116    if (v.s < -0x8000)
 117      IdlError(file(), line(), "Value too small for short");
 118    return v.s;
 119  }
 120  else {
 121    if (v.u > 0x7fff)
 122      IdlError(file(), line(), "Value too large for short");
 123    return v.u;
 124  }
 125}
 126IDL_Long IdlExpr::evalAsLong()
 127{
 128  IdlLongVal v = evalAsLongV();
 129  if (v.negative) {
 130    return v.s;
 131  }
 132  else {
 133    if (v.u > 0x7fffffff)
 134      IdlError(file(), line(), "Value too large for long");
 135    return v.u;
 136  }
 137}
 138IDL_UShort IdlExpr::evalAsUShort()
 139{
 140  IdlLongVal v = evalAsLongV();
 141
 142  if (v.negative) {
 143    IdlError(file(), line(), "Value too small for unsigned short");
 144  }
 145  else if (v.u > 0xffff) {
 146    IdlError(file(), line(), "Value too large for unsigned short");
 147  }
 148  return v.u;
 149}
 150IDL_ULong IdlExpr::evalAsULong()
 151{
 152  IdlLongVal v = evalAsLongV();
 153
 154  if (v.negative) {
 155    IdlError(file(), line(), "Value too small for unsigned long");
 156  }
 157  return v.u;
 158}
 159IDL_Octet IdlExpr::evalAsOctet()
 160{
 161  IdlLongVal v = evalAsLongV();
 162
 163  if (v.negative) {
 164    IdlError(file(), line(), "Value too small for octet");
 165  }
 166  else if (v.u > 0xff) {
 167    IdlError(file(), line(), "Value too large for octet");
 168  }
 169  return v.u;
 170}
 171#ifdef HAS_LongLong
 172IDL_LongLong IdlExpr::evalAsLongLong()
 173{
 174  IdlLongLongVal v = evalAsLongLongV();
 175  if (v.negative) {
 176    return v.s;
 177  }
 178  else {
 179    if (v.u > _CORBA_LONGLONG_CONST(0x7fffffffffffffff))
 180      IdlError(file(), line(), "Value too large for long long");
 181    return v.u;
 182  }
 183}
 184IDL_ULongLong IdlExpr::evalAsULongLong()
 185{
 186  IdlLongLongVal v = evalAsLongLongV();
 187
 188  if (v.negative) {
 189    IdlError(file(), line(), "Value too small for unsigned long long");
 190  }
 191  return v.u;
 192}
 193#endif
 194
 195// ScopedName handling
 196IdlExpr*
 197IdlExpr::
 198scopedNameToExpr(const char* file, int line, ScopedName* sn)
 199{
 200  const Scope::Entry* se = Scope::current()->findForUse(sn, file, line);
 201
 202  if (se) {
 203    if (se->kind() == Scope::Entry::E_DECL &&
 204	se->decl()->kind() == Decl::D_ENUMERATOR) {
 205      return new EnumExpr(file, line, (Enumerator*)se->decl(), sn);
 206    }
 207    else if (se->kind() == Scope::Entry::E_DECL &&
 208	se->decl()->kind() == Decl::D_CONST) {
 209      return new ConstExpr(file, line, (Const*)se->decl(), sn);
 210    }
 211    else {
 212      char* ssn = sn->toString();
 213      IdlError(file, line, "'%s' is not valid in an expression", ssn);
 214      IdlErrorCont(se->file(), se->line(), "('%s' declared here)", ssn);
 215      delete [] ssn;
 216    }
 217  }
 218  // If entry was not found, findScopedName() will have reported the error
 219  return new DummyExpr(file, line);
 220}
 221
 222const IDL_WChar* DummyExpr::evalAsWString() { return EMPTY_WSTRING; }
 223
 224
 225// Literals
 226
 227IdlLongVal IntegerExpr::evalAsLongV() {
 228#ifdef HAS_LongLong
 229  if (value_ > 0xffffffff) {
 230    IdlError(file(), line(), "Integer literal is too large for unsigned long");
 231    return IdlLongVal((IDL_ULong)1);
 232  }
 233#endif
 234  return IdlLongVal((IDL_ULong)value_);
 235}
 236#ifdef HAS_LongLong
 237IdlLongLongVal IntegerExpr::evalAsLongLongV() {
 238  return IdlLongLongVal((IDL_ULongLong)value_);
 239}
 240#endif
 241
 242const char* StringExpr::evalAsString() {
 243  return value_;
 244}
 245const IDL_WChar* WStringExpr::evalAsWString() {
 246  return value_;
 247}
 248IDL_Char CharExpr::evalAsChar() {
 249  return value_;
 250}
 251IDL_WChar WCharExpr::evalAsWChar() {
 252  return value_;
 253}
 254IDL_Fixed* FixedExpr::evalAsFixed() {
 255  return value_;
 256}
 257
 258// Float
 259IDL_Float FloatExpr::evalAsFloat() {
 260
 261#ifndef _MSC_VER
 262  // Use direct initialisation except for MS Visual C++, which allegedly
 263  // does not work properly with types involving built-in types. To
 264  // play it safe, use copy initialisation instead.
 265  IDL_Float    f(value_);
 266  IdlFloatLiteral g(f);
 267#else
 268  IDL_Float    f = value_;
 269  IdlFloatLiteral g = f;
 270#endif
 271
 272  if (f != g)
 273    IdlWarning(file(), line(), "Loss of precision converting literal "
 274	       "floating point value to float");
 275  return f;
 276}
 277IDL_Double FloatExpr::evalAsDouble() {
 278  IDL_Double   f = value_;
 279#ifdef HAS_LongDouble
 280  IdlFloatLiteral g = f;
 281  if (f != g)
 282    IdlWarning(file(), line(), "Loss of precision converting literal "
 283	       "floating point value to double");
 284#endif
 285  return f;
 286}
 287#ifdef HAS_LongDouble
 288IDL_LongDouble FloatExpr::evalAsLongDouble() {
 289  return value_;
 290}
 291#endif
 292
 293// Boolean
 294IDL_Boolean BooleanExpr::evalAsBoolean() {
 295  return value_;
 296}
 297
 298// Enumerator
 299Enumerator* EnumExpr::evalAsEnumerator(const Enum* target) {
 300
 301  if (value_->container() != target) {
 302    char* vssn = value_->scopedName()->toString();
 303    char* essn  = target->scopedName()->toString();
 304    IdlError(file(), line(), "Enumerator '%s' does not belong to enum '%s'",
 305	     vssn, essn);
 306    delete [] essn;
 307    essn = value_->container()->scopedName()->toString();
 308    IdlErrorCont(value_->file(), value_->line(),
 309		 "(Enumerator '%s' declared in '%s' here)",
 310		 vssn, essn);
 311    delete [] essn;
 312    delete [] vssn;
 313  }
 314  return value_;
 315}
 316
 317// Constant
 318
 319IdlLongVal ConstExpr::evalAsLongV() {
 320  switch (c_->constKind()) {
 321
 322  case IdlType::tk_short:  return IdlLongVal(IDL_Long (c_->constAsShort()));
 323  case IdlType::tk_long:   return IdlLongVal(IDL_Long (c_->constAsLong()));
 324  case IdlType::tk_ushort: return IdlLongVal(IDL_ULong(c_->constAsUShort()));
 325  case IdlType::tk_ulong:  return IdlLongVal(IDL_ULong(c_->constAsULong()));
 326  case IdlType::tk_octet:  return IdlLongVal(IDL_ULong(c_->constAsOctet()));
 327
 328#ifdef HAS_LongLong
 329  case IdlType::tk_longlong:
 330    {
 331      IDL_LongLong v = c_->constAsLongLong();
 332      if (v < -0x80000000 || v > 0xffffffff) goto precision_error;
 333      if (v >= 0)
 334	return IdlLongVal(IDL_ULong(v));
 335      else
 336	return IdlLongVal(IDL_Long(v));
 337    }
 338  case IdlType::tk_ulonglong:
 339    {
 340      IDL_ULongLong v = c_->constAsULongLong();
 341      if (v > 0xffffffff) goto precision_error;
 342      return IdlLongVal(IDL_ULong(v));
 343    }
 344#endif
 345  default:
 346    {
 347      char* ssn = scopedName_->toString();
 348      IdlError(file(), line(),
 349	       "Cannot interpret constant '%s' as an integer", ssn);
 350      IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn);
 351      delete [] ssn;
 352      return IdlLongVal((IDL_ULong)1);
 353    }
 354  }
 355 precision_error:
 356  char* ssn = scopedName_->toString();
 357  IdlError(file(), line(),
 358	   "Value of constant '%s' exceeds precision of target", ssn);
 359  IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn);
 360  delete [] ssn;
 361  return IdlLongVal(IDL_ULong(1));
 362}
 363
 364#ifdef HAS_LongLong
 365
 366IdlLongLongVal ConstExpr::evalAsLongLongV() {
 367  switch (c_->constKind()) {
 368
 369  case IdlType::tk_short:
 370    return IdlLongLongVal(IDL_LongLong(c_->constAsShort()));
 371
 372  case IdlType::tk_long:
 373    return IdlLongLongVal(IDL_LongLong(c_->constAsLong()));
 374
 375  case IdlType::tk_ushort:
 376    return IdlLongLongVal(IDL_ULongLong(c_->constAsUShort()));
 377
 378  case IdlType::tk_ulong:
 379    return IdlLongLongVal(IDL_ULongLong(c_->constAsULong()));
 380
 381  case IdlType::tk_octet:
 382    return IdlLongLongVal(IDL_ULongLong(c_->constAsOctet()));
 383
 384  case IdlType::tk_longlong:
 385    return IdlLongLongVal(c_->constAsLongLong());
 386
 387  case IdlType::tk_ulonglong:
 388    return IdlLongLongVal(c_->constAsULongLong());
 389
 390  default:
 391    {
 392      char* ssn = scopedName_->toString();
 393      IdlError(file(), line(),
 394	       "Cannot interpret constant '%s' as an integer", ssn);
 395      IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn);
 396      delete [] ssn;
 397      return IdlLongLongVal((IDL_ULongLong)1);
 398    }
 399  }
 400}
 401#endif // HAS_LongLong
 402
 403
 404IDL_Float ConstExpr::evalAsFloat() {
 405  IDL_Float r;
 406
 407  switch (c_->constKind()) {
 408  case IdlType::tk_float:      r = c_->constAsFloat();      break;
 409#ifndef __VMS
 410  case IdlType::tk_double:     r = c_->constAsDouble();     break;
 411#else
 412  case IdlType::tk_double:     r = (float)(double)c_->constAsDouble(); break;
 413#endif
 414#ifdef HAS_LongDouble
 415  case IdlType::tk_longdouble: r = c_->constAsLongDouble(); break;
 416#endif
 417  default:
 418    r = 1.0;
 419    char* ssn = scopedName_->toString();
 420    IdlError(file(), line(), "Cannot interpret constant '%s' as float", ssn);
 421    IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn);
 422    delete [] ssn;
 423  }
 424  if (IdlFPOverflow(r)) {
 425    char* ssn = scopedName_->toString();
 426    IdlError(file(), line(), "Value of constant '%s' overflows float", ssn);
 427    IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn);
 428    delete [] ssn;
 429  }
 430  return r;
 431}
 432
 433IDL_Double ConstExpr::evalAsDouble() {
 434  IDL_Double r;
 435
 436  switch (c_->constKind()) {
 437#ifndef __VMS
 438  case IdlType::tk_float:      r = c_->constAsFloat();      break;
 439#else
 440  case IdlType::tk_float:      r = (double)(float)c_->constAsFloat(); break;
 441#endif
 442  case IdlType::tk_double:     r = c_->constAsDouble();     break;
 443#ifdef HAS_LongDouble
 444  case IdlType::tk_longdouble: r = c_->constAsLongDouble(); break;
 445#endif
 446  default:
 447    r = 1.0;
 448    char* ssn = scopedName_->toString();
 449    IdlError(file(), line(), "Cannot interpret constant '%s' as double", ssn);
 450    IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn);
 451    delete [] ssn;
 452  }
 453  if (IdlFPOverflow(r)) {
 454    char* ssn = scopedName_->toString();
 455    IdlError(file(), line(), "Value of constant '%s' overflows double", ssn);
 456    IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn);
 457    delete [] ssn;
 458  }
 459  return r;
 460}
 461
 462#ifdef HAS_LongDouble
 463IDL_LongDouble ConstExpr::evalAsLongDouble() {
 464  IDL_LongDouble r;
 465
 466  switch (c_->constKind()) {
 467  case IdlType::tk_float:      r = c_->constAsFloat();      break;
 468  case IdlType::tk_double:     r = c_->constAsDouble();     break;
 469  case IdlType::tk_longdouble: r = c_->constAsLongDouble(); break;
 470  default:
 471    r = 1.0;
 472    char* ssn = scopedName_->toString();
 473    IdlError(file(), line(),
 474	     "Cannot interpret constant '%s' as long double", ssn);
 475    IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn);
 476    delete [] ssn;
 477  }
 478  if (IdlFPOverflow(r)) { // Don't see how this could happen...
 479    char* ssn = scopedName_->toString();
 480    IdlError(file(), line(),
 481	     "Value of constant '%s' overflows long double", ssn);
 482    IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn);
 483    delete [] ssn;
 484  }
 485  return r;
 486}
 487#endif // HAS_LongDouble
 488
 489
 490#define CONST_EXPR_EVAL(rt, eop, tk, cop, str, rv) \
 491rt ConstExpr::eop() { \
 492  if (c_->constKind() == IdlType::tk) \
 493    return c_->cop(); \
 494  else { \
 495    char* ssn = scopedName_->toString(); \
 496    IdlError(file(), line(), \
 497	     "Cannot interpret constant '%s' as " str, ssn); \
 498    IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn); \
 499    delete [] ssn; \
 500  } \
 501  return rv; \
 502}
 503
 504CONST_EXPR_EVAL(IDL_Boolean, evalAsBoolean, tk_boolean,
 505		constAsBoolean, "boolean", 0)
 506CONST_EXPR_EVAL(IDL_Char, evalAsChar, tk_char,
 507		constAsChar, "character", '!')
 508CONST_EXPR_EVAL(const char*, evalAsString, tk_string,
 509		constAsString, "string", "!")
 510CONST_EXPR_EVAL(IDL_WChar, evalAsWChar, tk_wchar,
 511		constAsWChar, "wide character", '!')
 512CONST_EXPR_EVAL(const IDL_WChar*, evalAsWString, tk_wstring,
 513		constAsWString, "wide string", EMPTY_WSTRING)
 514CONST_EXPR_EVAL(IDL_Fixed*, evalAsFixed, tk_fixed,
 515		constAsFixed, "fixed", new IDL_Fixed("1"))
 516
 517Enumerator* ConstExpr::evalAsEnumerator(const Enum* target) {
 518  if (c_->constKind() == IdlType::tk_enum) {
 519
 520    Enumerator* e = c_->constAsEnumerator();
 521    if (e->container() != target) {
 522      char* ssn = target->scopedName()->toString();
 523      IdlError(file(), line(), "Enumerator '%s' does not belong to enum '%s'",
 524	       e->identifier(), ssn);
 525      delete [] ssn;
 526      ssn = e->container()->scopedName()->toString();
 527      IdlErrorCont(e->file(), e->line(),
 528		   "(Enumerator '%s' declared in '%s' here)",
 529		   e->identifier(), ssn);
 530      delete [] ssn;
 531    }
 532    return c_->constAsEnumerator();
 533  }
 534  else {
 535    char* ssn = scopedName_->toString();
 536    IdlError(file(), line(),
 537	     "Cannot interpret constant '%s' as enumerator", ssn);
 538    IdlErrorCont(c_->file(), c_->line(), "(%s declared here)", ssn);
 539    delete [] ssn;
 540  }
 541  return 0;
 542}
 543
 544
 545// Binary expressions
 546
 547// Or
 548IdlLongVal OrExpr::evalAsLongV() {
 549  IdlLongVal a = a_->evalAsLongV();
 550  IdlLongVal b = b_->evalAsLongV();
 551
 552  if (a.negative)
 553    return IdlLongVal(IDL_Long(a.s | b.s));
 554  else
 555    return IdlLongVal(IDL_ULong(a.u | b.u));
 556}
 557#ifdef HAS_LongLong
 558IdlLongLongVal OrExpr::evalAsLongLongV() {
 559  IdlLongLongVal a = a_->evalAsLongLongV();
 560  IdlLongLongVal b = b_->evalAsLongLongV();
 561
 562  if (a.negative)
 563    return IdlLongLongVal(IDL_LongLong(a.s | b.s));
 564  else
 565    return IdlLongLongVal(IDL_ULongLong(a.u | b.u));
 566}
 567#endif
 568
 569// Xor
 570IdlLongVal XorExpr::evalAsLongV() {
 571  IdlLongVal a = a_->evalAsLongV();
 572  IdlLongVal b = b_->evalAsLongV();
 573
 574  if (a.negative)
 575    return IdlLongVal(IDL_Long(a.s ^ b.s));
 576  else
 577    return IdlLongVal(IDL_ULong(a.u ^ b.u));
 578}
 579#ifdef HAS_LongLong
 580IdlLongLongVal XorExpr::evalAsLongLongV() {
 581  IdlLongLongVal a = a_->evalAsLongLongV();
 582  IdlLongLongVal b = b_->evalAsLongLongV();
 583
 584  if (a.negative)
 585    return IdlLongLongVal(IDL_LongLong(a.s ^ b.s));
 586  else
 587    return IdlLongLongVal(IDL_ULongLong(a.u ^ b.u));
 588}
 589#endif
 590
 591// And
 592IdlLongVal AndExpr::evalAsLongV() {
 593  IdlLongVal a = a_->evalAsLongV();
 594  IdlLongVal b = b_->evalAsLongV();
 595
 596  if (a.negative)
 597    return IdlLongVal(IDL_Long(a.s & b.s));
 598  else
 599    return IdlLongVal(IDL_ULong(a.u & b.u));
 600}
 601#ifdef HAS_LongLong
 602IdlLongLongVal AndExpr::evalAsLongLongV() {
 603  IdlLongLongVal a = a_->evalAsLongLongV();
 604  IdlLongLongVal b = b_->evalAsLongLongV();
 605
 606  if (a.negative)
 607    return IdlLongLongVal(IDL_LongLong(a.s & b.s));
 608  else
 609    return IdlLongLongVal(IDL_ULongLong(a.u & b.u));
 610}
 611#endif
 612
 613// Right shift
 614IdlLongVal RShiftExpr::evalAsLongV() {
 615  IdlLongVal a = a_->evalAsLongV();
 616  IdlLongVal b = b_->evalAsLongV();
 617
 618  // Assume two's complement, and treat b as unsigned. If it's
 619  // actually signed and negative, its unsigned value will be much >
 620  // 64.
 621  if (b.u >= 64) {
 622    IdlError(file(), line(),
 623	     "Right operand of shift operation must be >= 0 and < 64");
 624    return a;
 625  }
 626  if (a.negative)
 627    return IdlLongVal(IDL_Long(a.s >> b.u));
 628  else
 629    return IdlLongVal(IDL_ULong(a.u >> b.u));
 630}
 631#ifdef HAS_LongLong
 632IdlLongLongVal RShiftExpr::evalAsLongLongV() {
 633  IdlLongLongVal a = a_->evalAsLongLongV();
 634  IdlLongLongVal b = b_->evalAsLongLongV();
 635
 636  if (b.u >= 64) {
 637    IdlError(file(), line(),
 638	     "Right operand of shift operation must be >= 0 and < 64");
 639    return a;
 640  }
 641  if (a.negative)
 642    return IdlLongLongVal(IDL_LongLong(a.s >> b.u));
 643  else
 644    return IdlLongLongVal(IDL_ULongLong(a.u >> b.u));
 645}
 646#endif
 647
 648// Left shift
 649IdlLongVal LShiftExpr::evalAsLongV() {
 650  IdlLongVal a = a_->evalAsLongV();
 651  IdlLongVal b = b_->evalAsLongV();
 652
 653  if (b.u >= 64) {
 654    IdlError(file(), line(),
 655	     "Right operand of shift operation must be >= 0 and < 64");
 656    return a;
 657  }
 658  if (a.negative)
 659    return IdlLongVal(IDL_Long(a.s << b.u));
 660  else
 661    return IdlLongVal(IDL_ULong(a.u << b.u));
 662}
 663#ifdef HAS_LongLong
 664IdlLongLongVal LShiftExpr::evalAsLongLongV() {
 665  IdlLongLongVal a = a_->evalAsLongLongV();
 666  IdlLongLongVal b = b_->evalAsLongLongV();
 667
 668  if (b.u >= 64) {
 669    IdlError(file(), line(),
 670	     "Right operand of shift operation must be >= 0 and < 64");
 671    return a;
 672  }
 673  if (a.negative)
 674    return IdlLongLongVal(IDL_LongLong(a.s << b.u));
 675  else
 676    return IdlLongLongVal(IDL_ULongLong(a.u << b.u));
 677}
 678#endif
 679
 680
 681// %
 682IdlLongVal ModExpr::evalAsLongV() {
 683  IdlLongVal a = a_->evalAsLongV();
 684  IdlLongVal b = b_->evalAsLongV();
 685
 686  if (b.u == 0) {
 687    IdlError(file(), line(), "Remainder of division by 0 is undefined");
 688    return a;
 689  }
 690  if (a.negative || b.negative)
 691    IdlWarning(file(), line(), "Result of %% operator involving negative "
 692	       "operands is implementation dependent");
 693
 694  switch ((a.negative ? 1:0) + (b.negative ? 2:0)) {
 695  case 0: return IdlLongVal(IDL_ULong(a.u % b.u));
 696  case 1: return IdlLongVal(-IDL_Long((-a.s) % b.u));
 697  case 2: return IdlLongVal(IDL_ULong(a.u % IDL_ULong(-b.s)));
 698  case 3: return IdlLongVal(-IDL_Long((-a.s) % (-b.s)));
 699  }
 700  return IdlLongVal(IDL_ULong(0)); // Never reach here
 701}
 702#ifdef HAS_LongLong
 703IdlLongLongVal ModExpr::evalAsLongLongV() {
 704  IdlLongLongVal a = a_->evalAsLongLongV();
 705  IdlLongLongVal b = b_->evalAsLongLongV();
 706
 707  if (b.u == 0) {
 708    IdlError(file(), line(), "Remainder of division by 0 is undefined");
 709    return a;
 710  }
 711  if (a.negative || b.negative)
 712    IdlWarning(file(), line(), "Result of %% operator involving negative "
 713	       "operands is platform dependent");
 714
 715  switch ((a.negative ? 1:0) + (b.negative ? 2:0)) {
 716  case 0: return IdlLongLongVal(IDL_ULongLong(a.u % b.u));
 717  case 1: return IdlLongLongVal(IDL_LongLong (a.s % b.u));
 718  case 2: return IdlLongLongVal(IDL_LongLong (a.u % b.s));
 719  case 3: return IdlLongLongVal(IDL_LongLong (a.s % b.s));
 720  }
 721  return IdlLongLongVal(IDL_ULongLong(0)); // Never reach here
 722}
 723#endif
 724
 725
 726// Add
 727IdlLongVal AddExpr::evalAsLongV() {
 728  IdlLongVal a = a_->evalAsLongV();
 729  IdlLongVal b = b_->evalAsLongV();
 730
 731  switch ((a.negative ? 1:0) + (b.negative ? 2:0)) {
 732  case 0:
 733    {
 734      IDL_ULong r = a.u + b.u;
 735      if (r < a.u) goto overflow;
 736      return IdlLongVal(r);
 737    }
 738  case 1:
 739    {
 740      if (IDL_ULong(-a.s) < b.u)
 741	return IdlLongVal(b.u - IDL_ULong(-a.s));
 742      else
 743	return IdlLongVal(a.s + IDL_Long(b.u));
 744    }
 745  case 2:
 746    {
 747      if (IDL_ULong(-b.s) < a.u)
 748	return IdlLongVal(a.u - IDL_ULong(-b.s));
 749      else
 750	return IdlLongVal(IDL_Long(a.u) + b.s);
 751    }
 752  case 3:
 753    {
 754      IDL_Long r = a.s + b.s;
 755      if (r > a.s) goto overflow;
 756      return IdlLongVal(r);
 757    }
 758  }
 759 overflow:
 760  IdlError(file(), line(), "Result of addition overflows");
 761  return a;
 762}
 763
 764#ifdef HAS_LongLong
 765IdlLongLongVal AddExpr::evalAsLongLongV() {
 766  IdlLongLongVal a = a_->evalAsLongLongV();
 767  IdlLongLongVal b = b_->evalAsLongLongV();
 768
 769  switch ((a.negative ? 1:0) + (b.negative ? 2:0)) {
 770  case 0:
 771    {
 772      IDL_ULongLong r = a.u + b.u;
 773      if (r < a.u) goto overflow;
 774      return IdlLongLongVal(r);
 775    }
 776  case 1:
 777    {
 778      if (IDL_ULongLong(-a.s) < b.u)
 779	return IdlLongLongVal(b.u - IDL_ULongLong(-a.s));
 780      else
 781	return IdlLongLongVal(a.s + IDL_LongLong(b.u));
 782    }
 783  case 2:
 784    {
 785      if (IDL_ULongLong(-b.s) < a.u)
 786	return IdlLongLongVal(a.u - IDL_ULongLong(-b.s));
 787      else
 788	return IdlLongLongVal(IDL_LongLong(a.u) + b.s);
 789    }
 790  case 3:
 791    {
 792      IDL_LongLong r = a.s + b.s;
 793      if (r > a.s) goto overflow;
 794      return IdlLongLongVal(r);
 795    }
 796  }
 797 overflow:
 798  IdlError(file(), line(), "Result of addition overflows");
 799  return a;
 800}
 801#endif
 802
 803#define ADD_EXPR_EVAL_F(ret, op, str) \
 804ret AddExpr::op() { \
 805  ret a, b, r; \
 806  a = a_->op(); b = b_->op(); \
 807  r = a+b; \
 808  if (IdlFPOverflow(r)) { \
 809    IdlError(file(), line(), "Result of addition overflows " str); \
 810    r = 1.0; \
 811  } \
 812  return r; \
 813}
 814ADD_EXPR_EVAL_F(IDL_Float,      evalAsFloat,      "float")
 815ADD_EXPR_EVAL_F(IDL_Double,     evalAsDouble,     "double")
 816#ifdef HAS_LongDouble
 817ADD_EXPR_EVAL_F(IDL_LongDouble, evalAsLongDouble, "long double")
 818#endif
 819
 820IDL_Fixed* AddExpr::evalAsFixed() {
 821  IDL_Fixed *a, *b, *r;
 822  a = a_->evalAsFixed(); b = b_->evalAsFixed();
 823  try {
 824    r = new IDL_Fixed(*a + *b);
 825  }
 826  catch (IDL_Fixed::Overflow&) {
 827    IdlError(file(), line(), "Result of addition overflows fixed digits");
 828    r = new IDL_Fixed("1");
 829  }
 830  delete a; delete b;
 831  return r;
 832}
 833
 834// Sub
 835IdlLongVal SubExpr::evalAsLongV() {
 836  IdlLongVal a = a_->evalAsLongV();
 837  IdlLongVal b = b_->evalAsLongV();
 838
 839  switch ((a.negative ? 1:0) + (b.negative ? 2:0)) {
 840  case 0:
 841    {
 842      if (a.u >= b.u) return IdlLongVal(a.u - b.u);
 843      IDL_ULong mr = b.u - a.u;
 844      if (mr > 0x80000000) goto overflow;
 845      return IdlLongVal(IDL_Long(-mr));
 846    }
 847  case 1:
 848    {
 849      IDL_ULong mr = IDL_ULong(-a.s) + b.s;
 850      if (mr > 0x80000000) goto overflow;
 851      return IdlLongVal(IDL_Long(-mr));
 852    }
 853  case 2:
 854    {
 855      IDL_ULong r = a.u + IDL_ULong(-b.s);
 856      if (r < a.u) goto overflow;
 857      return IdlLongVal(r);
 858    }
 859  case 3:
 860    {
 861      IDL_Long r = a.s - b.s;
 862      if (r > a.s) goto overflow;
 863      return IdlLongVal(r);
 864    }
 865  }
 866 overflow:
 867  IdlError(file(), line(), "Result of subtraction overflows");
 868  return a;
 869}
 870
 871#ifdef HAS_LongLong
 872IdlLongLongVal SubExpr::evalAsLongLongV() {
 873  IdlLongLongVal a = a_->evalAsLongLongV();
 874  IdlLongLongVal b = b_->evalAsLongLongV();
 875
 876  switch ((a.negative ? 1:0) + (b.negative ? 2:0)) {
 877  case 0:
 878    {
 879      if (a.u >= b.u) return IdlLongLongVal(a.u - b.u);
 880      IDL_ULongLong mr = b.u - a.u;
 881      if (mr > _CORBA_LONGLONG_CONST(0x8000000000000000)) goto overflow;
 882      return IdlLongLongVal(IDL_LongLong(-mr));
 883    }
 884  case 1:
 885    {
 886      IDL_ULongLong mr = IDL_ULongLong(-a.s) + b.s;
 887      if (mr > _CORBA_LONGLONG_CONST(0x8000000000000000)) goto overflow;
 888      return IdlLongLongVal(IDL_LongLong(-mr));
 889    }
 890  case 2:
 891    {
 892      IDL_ULongLong r = a.u + IDL_ULongLong(-b.s);
 893      if (r < a.u) goto overflow;
 894      return IdlLongLongVal(r);
 895    }
 896  case 3:
 897    {
 898      IDL_LongLong r = a.s - b.s;
 899      if (r > a.s) goto overflow;
 900      return IdlLongLongVal(r);
 901    }
 902  }
 903 overflow:
 904  IdlError(file(), line(), "Result of subtraction overflows");
 905  return a;
 906}
 907#endif
 908
 909
 910#define SUB_EXPR_EVAL_F(ret, op, str) \
 911ret SubExpr::op() { \
 912  ret a, b, r; \
 913  a = a_->op(); b = b_->op(); \
 914  r = a-b; \
 915  if (IdlFPOverflow(r)) { \
 916    IdlError(file(), line(), "Sub-expression overflows " str); \
 917    r = 1.0; \
 918  } \
 919  return r; \
 920}
 921SUB_EXPR_EVAL_F(IDL_Float,      evalAsFloat,      "float")
 922SUB_EXPR_EVAL_F(IDL_Double,     evalAsDouble,     "double")
 923#ifdef HAS_LongDouble
 924SUB_EXPR_EVAL_F(IDL_LongDouble, evalAsLongDouble, "long double")
 925#endif
 926
 927IDL_Fixed* SubExpr::evalAsFixed() {
 928  IDL_Fixed *a, *b, *r;
 929  a = a_->evalAsFixed(); b = b_->evalAsFixed();
 930  try {
 931    r = new IDL_Fixed(*a - *b);
 932  }
 933  catch (IDL_Fixed::Overflow&) {
 934    IdlError(file(), line(), "Sub-expression overflows fixed digits");
 935    r = new IDL_Fixed("1");
 936  }
 937  delete a; delete b;
 938  return r;
 939}
 940
 941
 942
 943// Mult
 944IdlLongVal MultExpr::evalAsLongV() {
 945  IdlLongVal a = a_->evalAsLongV();
 946  IdlLongVal b = b_->evalAsLongV();
 947
 948  switch ((a.negative ? 1:0) + (b.negative ? 2:0)) {
 949  case 0:
 950    {
 951      IDL_ULong r = a.u * b.u;
 952      if (b.u != 0 && (r / b.u) != a.u) goto overflow;
 953      return IdlLongVal(r);
 954    }
 955  case 1:
 956    {
 957      IDL_Long r = a.s * IDL_Long(b.u);
 958      if (b.u != 0 && (r / IDL_Long(b.u)) != a.s) goto overflow;
 959      return IdlLongVal(r);
 960    }
 961  case 2:
 962    {
 963      IDL_Long r = IDL_Long(a.u) * b.s;
 964      if (b.s != 0 && (r / b.s) != IDL_Long(a.u)) goto overflow;
 965      return IdlLongVal(r);
 966    }
 967  case 3:
 968    {
 969      IDL_ULong r = IDL_ULong(-a.s) * IDL_ULong(-b.s);
 970      if (b.s != 0 && (r / IDL_ULong(-b.s)) != IDL_ULong(-a.s)) goto overflow;
 971      return IdlLongVal(r);
 972    }
 973  }
 974 overflow:
 975  IdlError(file(), line(), "Result of multiplication overflows");
 976  return a;
 977}
 978
 979#ifdef HAS_LongLong
 980IdlLongLongVal MultExpr::evalAsLongLongV() {
 981  IdlLongLongVal a = a_->evalAsLongLongV();
 982  IdlLongLongVal b = b_->evalAsLongLongV();
 983
 984  switch ((a.negative ? 1:0) + (b.negative ? 2:0)) {
 985  case 0:
 986    {
 987      IDL_ULongLong r = a.u * b.u;
 988      if (b.u != 0 && (r / b.u) != a.u) goto overflow;
 989      return IdlLongLongVal(r);
 990    }
 991  case 1:
 992    {
 993      IDL_LongLong r = a.s * IDL_LongLong(b.u);
 994      if (b.u != 0 && (r / IDL_LongLong(b.u)) != a.s) goto overflow;
 995      return IdlLongLongVal(r);
 996    }
 997  case 2:
 998    {
 999      IDL_LongLong r = IDL_LongLong(a.u) * b.s;
1000      if (b.s != 0 && (r / b.s) != IDL_LongLong(a.u)) goto overflow;
1001      return IdlLongLongVal(r);
1002    }
1003  case 3:
1004    {
1005      IDL_ULongLong r = IDL_ULongLong(-a.s) * IDL_ULongLong(-b.s);
1006      if (b.s != 0 &&
1007	  (r / IDL_ULongLong(-b.s)) != IDL_ULongLong(-a.s)) goto overflow;
1008      return IdlLongLongVal(r);
1009    }
1010  }
1011 overflow:
1012  IdlError(file(), line(), "Result of multiplication overflows");
1013  return a;
1014}
1015#endif
1016
1017
1018#define MULT_EXPR_EVAL_F(ret, op, str) \
1019ret MultExpr::op() { \
1020  ret a, b, r; \
1021  a = a_->op(); b = b_->op(); \
1022  r = a*b; \
1023  if (IdlFPOverflow(r)) { \
1024    IdlError(file(), line(), "Sub-expression overflows " str); \
1025    r = 1.0; \
1026  } \
1027  return r; \
1028}
1029MULT_EXPR_EVAL_F(IDL_Float,      evalAsFloat,      "float")
1030MULT_EXPR_EVAL_F(IDL_Double,     evalAsDouble,     "double")
1031#ifdef HAS_LongDouble
1032MULT_EXPR_EVAL_F(IDL_LongDouble, evalAsLongDouble, "long double")
1033#endif
1034
1035IDL_Fixed* MultExpr::evalAsFixed() {
1036  IDL_Fixed *a, *b, *r;
1037  a = a_->evalAsFixed(); b = b_->evalAsFixed();
1038  try {
1039    r = new IDL_Fixed(*a * *b);
1040  }
1041  catch (IDL_Fixed::Overflow&) {
1042    IdlError(file(), line(), "Sub-expression overflows fixed digits");
1043    r = new IDL_Fixed("1");
1044  }
1045  delete a; delete b;
1046  return r;
1047}
1048
1049// Div
1050IdlLongVal DivExpr::evalAsLongV() {
1051  IdlLongVal a = a_->evalAsLongV();
1052  IdlLongVal b = b_->evalAsLongV();
1053
1054  if (b.u == 0) {
1055    IdlError(file(), line(), "Divide by zero");
1056    return a;
1057  }
1058
1059  switch ((a.negative ? 1:0) + (b.negative ? 2:0)) {
1060  case 0:
1061    {
1062      return IdlLongVal(a.u / b.u);
1063    }
1064  case 1:
1065    {
1066      IDL_ULong mr = IDL_ULong(-a.s) / b.u;
1067      return IdlLongVal(IDL_Long(-mr));
1068    }
1069  case 2:
1070    {
1071      IDL_ULong mr = a.u / IDL_ULong(-b.s);
1072      if (mr > 0x80000000) goto overflow;
1073      return IdlLongVal(IDL_Long(-mr));
1074    }
1075  case 3:
1076    {
1077      IDL_ULong r = IDL_ULong(-a.s) / IDL_ULong(-b.s);
1078      return IdlLongVal(r);
1079    }
1080  }
1081 overflow:
1082  IdlError(file(), line(), "Result of division overflows");
1083  return a;
1084}
1085
1086#ifdef HAS_LongLong
1087IdlLongLongVal DivExpr::evalAsLongLongV() {
1088  IdlLongLongVal a = a_->evalAsLongLongV();
1089  IdlLongLongVal b = b_->evalAsLongLongV();
1090
1091  if (b.u == 0) {
1092    IdlError(file(), line(), "Divide by zero");
1093    return a;
1094  }
1095
1096  switch ((a.negative ? 1:0) + (b.negative ? 2:0)) {
1097  case 0:
1098    {
1099      return IdlLongLongVal(a.u / b.u);
1100    }
1101  case 1:
1102    {
1103      IDL_ULongLong mr = IDL_ULongLong(-a.s) / b.u;
1104      return IdlLongLongVal(IDL_LongLong(-mr));
1105    }
1106  case 2:
1107    {
1108      IDL_ULongLong mr = a.u / IDL_ULongLong(-b.s);
1109      if (mr > _CORBA_LONGLONG_CONST(0x8000000000000000)) goto overflow;
1110      return IdlLongLongVal(IDL_LongLong(-mr));
1111    }
1112  case 3:
1113    {
1114      IDL_ULongLong r = IDL_ULongLong(-a.s) / IDL_ULongLong(-b.s);
1115      return IdlLongLongVal(r);
1116    }
1117  }
1118 overflow:
1119  IdlError(file(), line(), "Result of division overflows");
1120  return a;
1121}
1122#endif
1123
1124
1125#define DIV_EXPR_EVAL_F(ret, op, str) \
1126ret DivExpr::op() { \
1127  ret a, b, r; \
1128  a = a_->op(); b = b_->op(); \
1129  if (b == 0.0) { \
1130    IdlError(file(), line(), "Divide by zero"); \
1131    b = 1.0; \
1132  } \
1133  r = a/b; \
1134  if (IdlFPOverflow(r)) { \
1135    IdlError(file(), line(), "Sub-expression overflows " str); \
1136    r = 1.0; \
1137  } \
1138  return r; \
1139}
1140DIV_EXPR_EVAL_F(IDL_Float,      evalAsFloat,      "float")
1141DIV_EXPR_EVAL_F(IDL_Double,     evalAsDouble,     "double")
1142#ifdef HAS_LongDouble
1143DIV_EXPR_EVAL_F(IDL_LongDouble, evalAsLongDouble, "long double")
1144#endif
1145
1146IDL_Fixed* DivExpr::evalAsFixed() {
1147  IDL_Fixed *a, *b, *r;
1148  a = a_->evalAsFixed(); b = b_->evalAsFixed();
1149  try {
1150    r = new IDL_Fixed(*a / *b);
1151  }
1152  catch (IDL_Fixed::Overflow&) {
1153    IdlError(file(), line(), "Sub-expression overflows fixed digits");
1154    r = new IDL_Fixed("1");
1155  }
1156  catch (IDL_Fixed::DivideByZero&) {
1157    IdlError(file(), line(), "Divide by zero");
1158    r = new IDL_Fixed("1");
1159  }
1160  delete a; delete b;
1161  return r;
1162}
1163
1164
1165// Invert
1166IdlLongVal InvertExpr::evalAsLongV() {
1167  IdlLongVal e = e_->evalAsLongV();
1168  return IdlLongVal(~e.u);
1169}
1170#ifdef HAS_LongLong
1171IdlLongLongVal InvertExpr::evalAsLongLongV() {
1172  IdlLongLongVal e = e_->evalAsLongLongV();
1173  return IdlLongLongVal(~e.u);
1174}
1175#endif
1176
1177
1178// Minus
1179IdlLongVal MinusExpr::evalAsLongV() {
1180  IdlLongVal e = e_->evalAsLongV();
1181
1182  if (e.negative)
1183    return IdlLongVal(IDL_ULong(-e.s));
1184  else {
1185    if (e.u > 0x80000000)
1186      IdlError(file(), line(), "Result of unary minus overflows");
1187    return IdlLongVal(IDL_Long(-e.u));
1188  }
1189}
1190
1191#ifdef HAS_LongLong
1192IdlLongLongVal MinusExpr::evalAsLongLongV() {
1193  IdlLongLongVal e = e_->evalAsLongLongV();
1194
1195  if (e.negative)
1196    return IdlLongLongVal(IDL_ULongLong(-e.s));
1197  else {
1198    if (e.u > _CORBA_LONGLONG_CONST(0x8000000000000000))
1199      IdlError(file(), line(), "Result of unary minus overflows");
1200    return IdlLongLongVal(IDL_LongLong(-e.u));
1201  }
1202}
1203#endif
1204
1205#define MINUS_EXPR_EVAL(ret, op) \
1206ret MinusExpr::op() { \
1207  return -(e_->op()); \
1208}
1209MINUS_EXPR_EVAL(IDL_Float,      evalAsFloat)
1210MINUS_EXPR_EVAL(IDL_Double,     evalAsDouble)
1211#ifdef HAS_LongDouble
1212MINUS_EXPR_EVAL(IDL_LongDouble, evalAsLongDouble)
1213#endif
1214
1215IDL_Fixed* MinusExpr::evalAsFixed() {
1216  IDL_Fixed* r = new IDL_Fixed(- *(e_->evalAsFixed()));
1217  delete e_->evalAsFixed();
1218  return r;
1219}
1220
1221
1222// Plus
1223#define PLUS_EXPR_EVAL(ret, op) \
1224ret PlusExpr::op() { \
1225  return e_->op(); \
1226}
1227PLUS_EXPR_EVAL(IdlLongVal,     evalAsLongV)
1228#ifdef HAS_LongLong
1229PLUS_EXPR_EVAL(IdlLongLongVal, evalAsLongLongV)
1230#endif
1231PLUS_EXPR_EVAL(IDL_Float,      evalAsFloat)
1232PLUS_EXPR_EVAL(IDL_Double,     evalAsDouble)
1233#ifdef HAS_LongDouble
1234PLUS_EXPR_EVAL(IDL_LongDouble, evalAsLongDouble)
1235#endif
1236PLUS_EXPR_EVAL(IDL_Fixed*,     evalAsFixed)