1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77#include <nidl.h> 78#include <nametbl.h> 79#include <errors.h> 80#include <astp.h> 81#include <nidlmsg.h> 82#include <nidl_y.h> 83 84static void ASTP_free_exp( 85 AST_exp_n_t * exp 86); 87 88AST_exp_n_t * AST_exp_new 89( 90 unsigned long exp_type 91) 92{ 93 AST_exp_n_t * exp = NEW(AST_exp_n_t); 94 exp->exp_type = exp_type; 95 return exp; 96} 97 98AST_exp_n_t * AST_exp_integer_constant 99( 100 parser_location_p location ATTRIBUTE_UNUSED, 101 long value, 102 int int_signed 103) 104{ 105 AST_exp_n_t * exp = AST_exp_new(AST_EXP_CONSTANT); 106 exp->exp.constant.type = AST_int_const_k; 107 exp->exp.constant.val.integer = value; 108 exp->exp.constant.int_signed = int_signed; 109 return exp; 110} 111 112AST_exp_n_t * AST_exp_char_constant 113( 114 parser_location_p location, 115 char value 116) 117{ 118 AST_exp_n_t * exp = AST_exp_new(AST_EXP_CONSTANT); 119 exp->exp.constant.type = AST_nil_const_k; 120 exp->exp.constant.val.other = AST_char_constant(location, value); 121 return exp; 122} 123 124AST_exp_n_t * AST_exp_identifier 125( 126 parser_location_p location ATTRIBUTE_UNUSED, 127 NAMETABLE_id_t name 128) 129{ 130 AST_exp_n_t * exp = AST_exp_new(AST_EXP_CONSTANT); 131 exp->exp.constant.type = AST_nil_const_k; 132 exp->exp.constant.val.other = NULL; 133 exp->exp.constant.name = name; 134 return exp; 135} 136 137AST_exp_n_t * AST_exp_string_constant 138( 139 parser_location_p location, 140 STRTAB_str_t string 141) 142{ 143 AST_exp_n_t * exp = AST_exp_new(AST_EXP_CONSTANT); 144 exp->exp.constant.type = AST_nil_const_k; 145 exp->exp.constant.val.other = AST_string_constant(location, string); 146 return exp; 147} 148 149AST_exp_n_t * AST_exp_null_constant 150( 151 parser_location_p location 152) 153{ 154 AST_exp_n_t * exp = AST_exp_new(AST_EXP_CONSTANT); 155 exp->exp.constant.type = AST_nil_const_k; 156 exp->exp.constant.val.other = AST_null_constant(location); 157 return exp; 158} 159 160AST_exp_n_t * AST_exp_boolean_constant 161( 162 parser_location_p location, 163 boolean value 164) 165{ 166 AST_exp_n_t * exp = AST_exp_new(AST_EXP_CONSTANT); 167 exp->exp.constant.type = AST_nil_const_k; 168 exp->exp.constant.val.other = AST_boolean_constant(location, value); 169 return exp; 170} 171 172AST_exp_n_t * AST_expression 173( 174 parser_location_p location ATTRIBUTE_UNUSED, 175 unsigned long exp_type, 176 AST_exp_n_t * oper1, 177 AST_exp_n_t * oper2, 178 AST_exp_n_t * oper3 179) 180{ 181 AST_exp_n_t * exp = AST_exp_new(exp_type); 182 exp->exp.expression.oper1 = oper1; 183 exp->exp.expression.oper2 = oper2; 184 exp->exp.expression.oper3 = oper3; 185 186 return exp; 187} 188 189AST_constant_n_t * AST_constant_from_exp 190( 191 parser_location_p location, 192 AST_exp_n_t * exp 193) 194{ 195 AST_constant_n_t * const_return; 196 ASTP_evaluate_expr(location, exp, true); 197 if (exp->exp_type == AST_EXP_CONSTANT) { 198 if (exp->exp.constant.type == AST_int_const_k) { 199 const_return = AST_integer_constant(location, exp->exp.constant.val.integer); 200 const_return->int_signed = exp->exp.constant.int_signed; 201 } 202 else { 203 const_return = exp->exp.constant.val.other; 204 } 205 } 206 else 207 const_return = NULL; 208 return const_return; 209} 210 211/* returns true if the expression is regarded as "simple". 212 * Simple expressions match this criteria: 213 * identifier (parameter, field) 214 * integer constant 215 * <dereference+>identifier 216 * identifier / [248] 217 * identifier * [248] 218 * identifier - 1 219 * identifier + 1 220 * 221 * */ 222boolean ASTP_expr_is_simple 223( 224 parser_location_p location, 225 AST_exp_n_t * exp 226) 227{ 228 if (ASTP_evaluate_expr(location, exp, true)) { 229 return true; 230 } 231 switch(exp->exp_type) { 232 case AST_EXP_CONSTANT: 233 return true; 234 break; 235 case AST_EXP_BINARY_SLASH: 236 case AST_EXP_BINARY_STAR: 237 if (exp->exp.expression.oper1->exp_type == AST_EXP_CONSTANT && 238 ((ASTP_expr_integer_value(location, exp->exp.expression.oper2) == 2) || 239 (ASTP_expr_integer_value(location, exp->exp.expression.oper2) == 4) || 240 (ASTP_expr_integer_value(location, exp->exp.expression.oper2) == 8))) 241 { 242 return true; 243 } 244 break; 245 case AST_EXP_BINARY_PLUS: 246 case AST_EXP_BINARY_MINUS: 247 if (exp->exp.expression.oper1->exp_type == AST_EXP_CONSTANT && 248 ASTP_expr_integer_value(location, exp->exp.expression.oper2) == 1) 249 { 250 return true; 251 } 252 break; 253 case AST_EXP_UNARY_STAR: 254 while(exp->exp_type == AST_EXP_UNARY_STAR) 255 exp = exp->exp.expression.oper1; 256 if (exp->exp_type == AST_EXP_CONSTANT) { 257 258 return true; 259 } 260 break; 261 case AST_EXP_BINARY_AND: 262 /* could be alignment */ 263 if (exp->exp.expression.oper1->exp_type == AST_EXP_BINARY_PLUS 264 && 265 exp->exp.expression.oper2->exp_type == AST_EXP_UNARY_TILDE) 266 { 267 AST_exp_n_t * op1 = exp->exp.expression.oper1; 268 AST_exp_n_t * op2 = exp->exp.expression.oper2; 269 AST_exp_n_t * ident_exp = op1->exp.expression.oper1; 270 long nval = ASTP_expr_integer_value(location, op1->exp.expression.oper2); 271 272 /* allow one level of indirection for the identifier part */ 273 if ((ident_exp->exp_type == AST_EXP_CONSTANT || ( 274 ident_exp->exp_type == AST_EXP_UNARY_STAR && 275 ident_exp->exp.expression.oper1->exp_type == AST_EXP_CONSTANT)) 276 && (nval == 1 || nval == 3 || nval == 7) && 277 ASTP_expr_integer_value(location, op2->exp.expression.oper1) 278 == nval) 279 return true; 280 281 } 282 break; 283 } 284 return false; 285} 286 287long ASTP_expr_integer_value 288( 289 parser_location_p location, 290 AST_exp_n_t * exp 291) 292{ 293 long value; 294 ASTP_evaluate_expr(location, exp, true); 295 if (exp->exp.constant.type == AST_int_const_k) 296 value = exp->exp.constant.val.integer; 297 else { 298 switch(exp->exp.constant.val.other->kind) { 299 case AST_int_const_k: 300 value = exp->exp.constant.val.other->value.int_val; 301 break; 302 case AST_char_const_k: 303 value = exp->exp.constant.val.other->value.char_val; 304 break; 305 case AST_boolean_const_k: 306 value = exp->exp.constant.val.other->value.boolean_val; 307 break; 308 default: 309 value = 0; 310 } 311 } 312 return value; 313} 314 315/* Free an expression node and any child operands */ 316void ASTP_free_exp(AST_exp_n_t * exp) { 317 if (exp == NULL) 318 return; 319 if (exp->exp_type != AST_EXP_CONSTANT) { 320 ASTP_free_exp(exp->exp.expression.oper1); 321 ASTP_free_exp(exp->exp.expression.oper2); 322 ASTP_free_exp(exp->exp.expression.oper3); 323 } 324 FREE(exp); 325} 326 327/* evaluate the expression, reducing it down to a single constant expression 328 * node if possible. 329 * If constant_only is true, this routine will return false when it hits 330 * the name of a parameter to indicate that the expression is not a constant 331 * expression. 332 * */ 333boolean ASTP_evaluate_expr 334( 335 parser_location_p location, 336 AST_exp_n_t * exp, 337 boolean constant_only 338) 339{ 340 boolean result; 341 long val, val1, val2; 342 AST_exp_n_t * op1=NULL, *op2=NULL, *op3=NULL; 343 344 if (exp == NULL) { 345 log_warning(location->lineno, NIDL_EXP_IS_NULL, NULL); 346 return true; 347 } 348 349 if (exp->exp_type == AST_EXP_CONSTANT) { 350 /* resolve binding for identifiers */ 351 if (exp->exp.constant.type == AST_nil_const_k && 352 exp->exp.constant.val.other == NULL) { 353 354 exp->exp.constant.val.other = 355 (AST_constant_n_t*)ASTP_lookup_binding( 356 location, 357 exp->exp.constant.name, 358 fe_constant_n_k, FALSE); 359 360 if (exp->exp.constant.val.other == NULL) 361 return false; 362 363 } 364 /* already reduced to the simplest form */ 365 return true; 366 } else if (exp->exp_type == AST_EXP_TUPLE) { 367 op1 = exp->exp.expression.oper1; 368 369 if (op1->exp.constant.type == AST_nil_const_k && 370 op1->exp.constant.val.other == NULL) { 371 op1->exp.constant.val.other = 372 (AST_constant_n_t *)ASTP_lookup_binding( 373 location, 374 op1->exp.constant.name, 375 fe_constant_n_k, FALSE); 376 if (op1->exp.constant.val.other == NULL) 377 return false; 378 } 379 380 op2 = exp->exp.expression.oper2; 381 382 if (op2->exp.constant.type == AST_nil_const_k && 383 op2->exp.constant.val.other == NULL) { 384 op2->exp.constant.val.other = 385 (AST_constant_n_t *)ASTP_lookup_binding( 386 location, 387 op2->exp.constant.name, 388 fe_constant_n_k, FALSE); 389 if (op2->exp.constant.val.other == NULL) 390 return false; 391 } 392 return true; 393 } 394 395 /* time to evaluate some expressions. 396 * First, reduce the operands to their simplest forms too */ 397 398 result = ASTP_evaluate_expr(location, exp->exp.expression.oper1, constant_only); 399 if (result == false) 400 return false; 401 op1 = exp->exp.expression.oper1; 402 403 if ((exp->exp_type & AST_EXP_2_OP_MASK) != 0) { 404 result = ASTP_evaluate_expr(location, exp->exp.expression.oper2, constant_only); 405 if (result == false) 406 return false; 407 op2 = exp->exp.expression.oper2; 408 } 409 if ((exp->exp_type & AST_EXP_3_OP_MASK) != 0) { 410 result = ASTP_evaluate_expr(location, exp->exp.expression.oper3, constant_only); 411 if (result == false) 412 return false; 413 op3 = exp->exp.expression.oper3; 414 } 415 /* only reached if we are dealing with a constant expression, 416 * and that means that we can play around with the operands */ 417 switch(exp->exp_type) { 418 case AST_EXP_UNARY_NOT: 419 exp->exp.constant.val.integer = 420 !ASTP_expr_integer_value(location, op1); 421 break; 422 case AST_EXP_UNARY_TILDE: 423 exp->exp.constant.val.integer = 424 ~ASTP_expr_integer_value(location, op1); 425 break; 426 case AST_EXP_UNARY_PLUS: /* why this? I can't remember what I was thinking */ 427 exp->exp.constant.val.integer = 428 +ASTP_expr_integer_value(location, op1); 429 break; 430 case AST_EXP_UNARY_MINUS: 431 exp->exp.constant.val.integer = 432 -ASTP_expr_integer_value(location, op1); 433 break; 434 case AST_EXP_UNARY_STAR: 435 return false; 436 case AST_EXP_BINARY_PERCENT: 437 val = ASTP_expr_integer_value(location, op2); 438 if (val == 0) 439 log_error(location->lineno, NIDL_INTDIVBY0, NULL); 440 else 441 val = ASTP_expr_integer_value(location, op1) % val; 442 exp->exp.constant.val.integer = val; 443 break; 444 case AST_EXP_BINARY_SLASH: 445 val = ASTP_expr_integer_value(location, op2); 446 if (val == 0) 447 log_error(location->lineno, NIDL_INTDIVBY0, NULL); 448 else 449 val = ASTP_expr_integer_value(location, op1) / val; 450 exp->exp.constant.val.integer = val; 451 break; 452 case AST_EXP_BINARY_STAR: 453 val1 = ASTP_expr_integer_value(location, op1); 454 val2 = ASTP_expr_integer_value(location, op2); 455 val = val1 * val2; 456 if (val < val1 && val > val2) 457 log_error(location->lineno, NIDL_INTOVERFLOW, KEYWORDS_lookup_text(LONG_KW), NULL); 458 exp->exp.constant.val.integer = val; 459 break; 460 case AST_EXP_BINARY_MINUS: 461 exp->exp.constant.val.integer = 462 ASTP_expr_integer_value(location, op1) - 463 ASTP_expr_integer_value(location, op2); 464 break; 465 case AST_EXP_BINARY_PLUS: 466 exp->exp.constant.val.integer = 467 ASTP_expr_integer_value(location, op1) + 468 ASTP_expr_integer_value(location, op2); 469 break; 470 case AST_EXP_BINARY_RSHIFT: 471 exp->exp.constant.val.integer = 472 ASTP_expr_integer_value(location, op1) >> 473 ASTP_expr_integer_value(location, op2); 474 break; 475 case AST_EXP_BINARY_LSHIFT: 476 exp->exp.constant.val.integer = 477 ASTP_expr_integer_value(location, op1) << 478 ASTP_expr_integer_value(location, op2); 479 break; 480 case AST_EXP_BINARY_GE: 481 exp->exp.constant.val.integer = 482 ASTP_expr_integer_value(location, op1) >= 483 ASTP_expr_integer_value(location, op2); 484 break; 485 case AST_EXP_BINARY_LE: 486 exp->exp.constant.val.integer = 487 ASTP_expr_integer_value(location, op1) <= 488 ASTP_expr_integer_value(location, op2); 489 break; 490 case AST_EXP_BINARY_GT: 491 exp->exp.constant.val.integer = 492 ASTP_expr_integer_value(location, op1) > 493 ASTP_expr_integer_value(location, op2); 494 break; 495 case AST_EXP_BINARY_LT: 496 exp->exp.constant.val.integer = 497 ASTP_expr_integer_value(location, op1) < 498 ASTP_expr_integer_value(location, op2); 499 break; 500 case AST_EXP_BINARY_NE: 501 exp->exp.constant.val.integer = 502 ASTP_expr_integer_value(location, op1) != 503 ASTP_expr_integer_value(location, op2); 504 break; 505 case AST_EXP_BINARY_EQUAL: 506 exp->exp.constant.val.integer = 507 ASTP_expr_integer_value(location, op1) == 508 ASTP_expr_integer_value(location, op2); 509 break; 510 case AST_EXP_BINARY_AND: 511 exp->exp.constant.val.integer = 512 ASTP_expr_integer_value(location, op1) & 513 ASTP_expr_integer_value(location, op2); 514 break; 515 case AST_EXP_BINARY_OR: 516 exp->exp.constant.val.integer = 517 ASTP_expr_integer_value(location, op1) | 518 ASTP_expr_integer_value(location, op2); 519 break; 520 case AST_EXP_BINARY_XOR: 521 exp->exp.constant.val.integer = 522 ASTP_expr_integer_value(location, op1) ^ 523 ASTP_expr_integer_value(location, op2); 524 break; 525 case AST_EXP_BINARY_LOG_AND: 526 exp->exp.constant.val.integer = 527 ASTP_expr_integer_value(location, op1) && 528 ASTP_expr_integer_value(location, op2); 529 break; 530 case AST_EXP_BINARY_LOG_OR: 531 exp->exp.constant.val.integer = 532 ASTP_expr_integer_value(location, op1) || 533 ASTP_expr_integer_value(location, op2); 534 break; 535 case AST_EXP_TERNARY_OP: 536 /* we want to preserve the type for this, so we short-circuit the return */ 537 if (ASTP_expr_integer_value(location, op1)) { 538 assert(op2 != NULL); 539 *exp = *op2; 540 } 541 else { 542 assert(op3 != NULL); 543 *exp = *op3; 544 } 545 return true; 546 default: 547 /* NOTREACHED (hopefully!) */ 548 break; 549 } 550 ASTP_free_exp(op1); 551 ASTP_free_exp(op2); 552 ASTP_free_exp(op3); 553 exp->exp_type = AST_EXP_CONSTANT; 554 exp->exp.constant.type = AST_int_const_k; 555 return true; 556} 557