Synopsis - Cross-Reference
File: /Synopsis/Parsers/IDL/idlexpr.cc1// -*- 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)