1 /************************************************************ 2 * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 * 4 * Permission to use, copy, modify, and distribute this 5 * software and its documentation for any purpose and without 6 * fee is hereby granted, provided that the above copyright 7 * notice appear in all copies and that both that copyright 8 * notice and this permission notice appear in supporting 9 * documentation, and that the name of Silicon Graphics not be 10 * used in advertising or publicity pertaining to distribution 11 * of the software without specific prior written permission. 12 * Silicon Graphics makes no representation about the suitability 13 * of this software for any purpose. It is provided "as is" 14 * without any express or implied warranty. 15 * 16 * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 * THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 * 25 ********************************************************/ 26 27 #include "xkbcomp-priv.h" 28 #include "text.h" 29 #include "expr.h" 30 31 typedef bool (*IdentLookupFunc)(struct xkb_context *ctx, const void *priv, 32 xkb_atom_t field, enum expr_value_type type, 33 unsigned int *val_rtrn); 34 35 bool 36 ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr, 37 const char **elem_rtrn, const char **field_rtrn, 38 ExprDef **index_rtrn) 39 { 40 switch (expr->expr.op) { 41 case EXPR_IDENT: 42 *elem_rtrn = NULL; 43 *field_rtrn = xkb_atom_text(ctx, expr->ident.ident); 44 *index_rtrn = NULL; 45 return true; 46 case EXPR_FIELD_REF: 47 *elem_rtrn = xkb_atom_text(ctx, expr->field_ref.element); 48 *field_rtrn = xkb_atom_text(ctx, expr->field_ref.field); 49 *index_rtrn = NULL; 50 return true; 51 case EXPR_ARRAY_REF: 52 *elem_rtrn = xkb_atom_text(ctx, expr->array_ref.element); 53 *field_rtrn = xkb_atom_text(ctx, expr->array_ref.field); 54 *index_rtrn = expr->array_ref.entry; 55 return true; 56 default: 57 break; 58 } 59 log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->expr.op); 60 return false; 61 } 62 63 static bool 64 SimpleLookup(struct xkb_context *ctx, const void *priv, xkb_atom_t field, 65 enum expr_value_type type, unsigned int *val_rtrn) 66 { 67 const LookupEntry *entry; 68 const char *str; 69 70 if (!priv || field == XKB_ATOM_NONE || type != EXPR_TYPE_INT) 71 return false; 72 73 str = xkb_atom_text(ctx, field); 74 for (entry = priv; entry && entry->name; entry++) { 75 if (istreq(str, entry->name)) { 76 *val_rtrn = entry->value; 77 return true; 78 } 79 } 80 81 return false; 82 } 83 84 /* Data passed in the *priv argument for LookupModMask. */ 85 typedef struct { 86 const struct xkb_mod_set *mods; 87 enum mod_type mod_type; 88 } LookupModMaskPriv; 89 90 static bool 91 LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field, 92 enum expr_value_type type, xkb_mod_mask_t *val_rtrn) 93 { 94 const char *str; 95 xkb_mod_index_t ndx; 96 const LookupModMaskPriv *arg = priv; 97 const struct xkb_mod_set *mods = arg->mods; 98 enum mod_type mod_type = arg->mod_type; 99 100 if (type != EXPR_TYPE_INT) 101 return false; 102 103 str = xkb_atom_text(ctx, field); 104 105 if (istreq(str, "all")) { 106 *val_rtrn = MOD_REAL_MASK_ALL; 107 return true; 108 } 109 110 if (istreq(str, "none")) { 111 *val_rtrn = 0; 112 return true; 113 } 114 115 ndx = XkbModNameToIndex(mods, field, mod_type); 116 if (ndx == XKB_MOD_INVALID) 117 return false; 118 119 *val_rtrn = (1u << ndx); 120 return true; 121 } 122 123 bool 124 ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr, 125 bool *set_rtrn) 126 { 127 bool ok = false; 128 const char *ident; 129 130 switch (expr->expr.op) { 131 case EXPR_VALUE: 132 if (expr->expr.value_type != EXPR_TYPE_BOOLEAN) { 133 log_err(ctx, 134 "Found constant of type %s where boolean was expected\n", 135 expr_value_type_to_string(expr->expr.value_type)); 136 return false; 137 } 138 *set_rtrn = expr->boolean.set; 139 return true; 140 141 case EXPR_IDENT: 142 ident = xkb_atom_text(ctx, expr->ident.ident); 143 if (ident) { 144 if (istreq(ident, "true") || 145 istreq(ident, "yes") || 146 istreq(ident, "on")) { 147 *set_rtrn = true; 148 return true; 149 } 150 else if (istreq(ident, "false") || 151 istreq(ident, "no") || 152 istreq(ident, "off")) { 153 *set_rtrn = false; 154 return true; 155 } 156 } 157 log_err(ctx, "Identifier \"%s\" of type boolean is unknown\n", ident); 158 return false; 159 160 case EXPR_FIELD_REF: 161 log_err(ctx, "Default \"%s.%s\" of type boolean is unknown\n", 162 xkb_atom_text(ctx, expr->field_ref.element), 163 xkb_atom_text(ctx, expr->field_ref.field)); 164 return false; 165 166 case EXPR_INVERT: 167 case EXPR_NOT: 168 ok = ExprResolveBoolean(ctx, expr, set_rtrn); 169 if (ok) 170 *set_rtrn = !*set_rtrn; 171 return ok; 172 case EXPR_ADD: 173 case EXPR_SUBTRACT: 174 case EXPR_MULTIPLY: 175 case EXPR_DIVIDE: 176 case EXPR_ASSIGN: 177 case EXPR_NEGATE: 178 case EXPR_UNARY_PLUS: 179 log_err(ctx, "%s of boolean values not permitted\n", 180 expr_op_type_to_string(expr->expr.op)); 181 break; 182 183 default: 184 log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n", 185 expr->expr.op); 186 break; 187 } 188 189 return false; 190 } 191 192 bool 193 ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr, 194 xkb_keycode_t *kc) 195 { 196 xkb_keycode_t leftRtrn, rightRtrn; 197 198 switch (expr->expr.op) { 199 case EXPR_VALUE: 200 if (expr->expr.value_type != EXPR_TYPE_INT) { 201 log_err(ctx, 202 "Found constant of type %s where an int was expected\n", 203 expr_value_type_to_string(expr->expr.value_type)); 204 return false; 205 } 206 207 *kc = (xkb_keycode_t) expr->integer.ival; 208 return true; 209 210 case EXPR_ADD: 211 case EXPR_SUBTRACT: 212 case EXPR_MULTIPLY: 213 case EXPR_DIVIDE: 214 if (!ExprResolveKeyCode(ctx, expr->binary.left, &leftRtrn) || 215 !ExprResolveKeyCode(ctx, expr->binary.right, &rightRtrn)) 216 return false; 217 218 switch (expr->expr.op) { 219 case EXPR_ADD: 220 *kc = leftRtrn + rightRtrn; 221 break; 222 case EXPR_SUBTRACT: 223 *kc = leftRtrn - rightRtrn; 224 break; 225 case EXPR_MULTIPLY: 226 *kc = leftRtrn * rightRtrn; 227 break; 228 case EXPR_DIVIDE: 229 if (rightRtrn == 0) { 230 log_err(ctx, "Cannot divide by zero: %d / %d\n", 231 leftRtrn, rightRtrn); 232 return false; 233 } 234 235 *kc = leftRtrn / rightRtrn; 236 break; 237 default: 238 break; 239 } 240 241 return true; 242 243 case EXPR_NEGATE: 244 if (!ExprResolveKeyCode(ctx, expr->unary.child, &leftRtrn)) 245 return false; 246 247 *kc = ~leftRtrn; 248 return true; 249 250 case EXPR_UNARY_PLUS: 251 return ExprResolveKeyCode(ctx, expr->unary.child, kc); 252 253 default: 254 log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n", 255 expr->expr.op); 256 break; 257 } 258 259 return false; 260 } 261 262 /** 263 * This function returns ... something. It's a bit of a guess, really. 264 * 265 * If an integer is given in value ctx, it will be returned in ival. 266 * If an ident or field reference is given, the lookup function (if given) 267 * will be called. At the moment, only SimpleLookup use this, and they both 268 * return the results in uval. And don't support field references. 269 * 270 * Cool. 271 */ 272 static bool 273 ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr, 274 int *val_rtrn, IdentLookupFunc lookup, 275 const void *lookupPriv) 276 { 277 bool ok = false; 278 int l, r; 279 unsigned u; 280 ExprDef *left, *right; 281 282 switch (expr->expr.op) { 283 case EXPR_VALUE: 284 if (expr->expr.value_type != EXPR_TYPE_INT) { 285 log_err(ctx, 286 "Found constant of type %s where an int was expected\n", 287 expr_value_type_to_string(expr->expr.value_type)); 288 return false; 289 } 290 291 *val_rtrn = expr->integer.ival; 292 return true; 293 294 case EXPR_IDENT: 295 if (lookup) 296 ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, &u); 297 298 if (!ok) 299 log_err(ctx, "Identifier \"%s\" of type int is unknown\n", 300 xkb_atom_text(ctx, expr->ident.ident)); 301 else 302 *val_rtrn = (int) u; 303 304 return ok; 305 306 case EXPR_FIELD_REF: 307 log_err(ctx, "Default \"%s.%s\" of type int is unknown\n", 308 xkb_atom_text(ctx, expr->field_ref.element), 309 xkb_atom_text(ctx, expr->field_ref.field)); 310 return false; 311 312 case EXPR_ADD: 313 case EXPR_SUBTRACT: 314 case EXPR_MULTIPLY: 315 case EXPR_DIVIDE: 316 left = expr->binary.left; 317 right = expr->binary.right; 318 if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv) || 319 !ExprResolveIntegerLookup(ctx, right, &r, lookup, lookupPriv)) 320 return false; 321 322 switch (expr->expr.op) { 323 case EXPR_ADD: 324 *val_rtrn = l + r; 325 break; 326 case EXPR_SUBTRACT: 327 *val_rtrn = l - r; 328 break; 329 case EXPR_MULTIPLY: 330 *val_rtrn = l * r; 331 break; 332 case EXPR_DIVIDE: 333 if (r == 0) { 334 log_err(ctx, "Cannot divide by zero: %d / %d\n", l, r); 335 return false; 336 } 337 *val_rtrn = l / r; 338 break; 339 default: 340 log_err(ctx, "%s of integers not permitted\n", 341 expr_op_type_to_string(expr->expr.op)); 342 return false; 343 } 344 345 return true; 346 347 case EXPR_ASSIGN: 348 log_wsgo(ctx, "Assignment operator not implemented yet\n"); 349 break; 350 351 case EXPR_NOT: 352 log_err(ctx, "The ! operator cannot be applied to an integer\n"); 353 return false; 354 355 case EXPR_INVERT: 356 case EXPR_NEGATE: 357 left = expr->unary.child; 358 if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv)) 359 return false; 360 361 *val_rtrn = (expr->expr.op == EXPR_NEGATE ? -l : ~l); 362 return true; 363 364 case EXPR_UNARY_PLUS: 365 left = expr->unary.child; 366 return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup, 367 lookupPriv); 368 369 default: 370 log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n", 371 expr->expr.op); 372 break; 373 } 374 375 return false; 376 } 377 378 bool 379 ExprResolveInteger(struct xkb_context *ctx, const ExprDef *expr, 380 int *val_rtrn) 381 { 382 return ExprResolveIntegerLookup(ctx, expr, val_rtrn, NULL, NULL); 383 } 384 385 bool 386 ExprResolveGroup(struct xkb_context *ctx, const ExprDef *expr, 387 xkb_layout_index_t *group_rtrn) 388 { 389 bool ok; 390 int result; 391 392 ok = ExprResolveIntegerLookup(ctx, expr, &result, SimpleLookup, 393 groupNames); 394 if (!ok) 395 return false; 396 397 if (result <= 0 || result > XKB_MAX_GROUPS) { 398 log_err(ctx, "Group index %u is out of range (1..%d)\n", 399 result, XKB_MAX_GROUPS); 400 return false; 401 } 402 403 *group_rtrn = (xkb_layout_index_t) result; 404 return true; 405 } 406 407 bool 408 ExprResolveLevel(struct xkb_context *ctx, const ExprDef *expr, 409 xkb_level_index_t *level_rtrn) 410 { 411 bool ok; 412 int result; 413 414 ok = ExprResolveIntegerLookup(ctx, expr, &result, SimpleLookup, 415 levelNames); 416 if (!ok) 417 return false; 418 419 if (result < 1) { 420 log_err(ctx, "Shift level %d is out of range\n", result); 421 return false; 422 } 423 424 /* Level is zero-indexed from now on. */ 425 *level_rtrn = (unsigned int) (result - 1); 426 return true; 427 } 428 429 bool 430 ExprResolveButton(struct xkb_context *ctx, const ExprDef *expr, int *btn_rtrn) 431 { 432 return ExprResolveIntegerLookup(ctx, expr, btn_rtrn, SimpleLookup, 433 buttonNames); 434 } 435 436 bool 437 ExprResolveString(struct xkb_context *ctx, const ExprDef *expr, 438 xkb_atom_t *val_rtrn) 439 { 440 switch (expr->expr.op) { 441 case EXPR_VALUE: 442 if (expr->expr.value_type != EXPR_TYPE_STRING) { 443 log_err(ctx, "Found constant of type %s, expected a string\n", 444 expr_value_type_to_string(expr->expr.value_type)); 445 return false; 446 } 447 448 *val_rtrn = expr->string.str; 449 return true; 450 451 case EXPR_IDENT: 452 log_err(ctx, "Identifier \"%s\" of type string not found\n", 453 xkb_atom_text(ctx, expr->ident.ident)); 454 return false; 455 456 case EXPR_FIELD_REF: 457 log_err(ctx, "Default \"%s.%s\" of type string not found\n", 458 xkb_atom_text(ctx, expr->field_ref.element), 459 xkb_atom_text(ctx, expr->field_ref.field)); 460 return false; 461 462 case EXPR_ADD: 463 case EXPR_SUBTRACT: 464 case EXPR_MULTIPLY: 465 case EXPR_DIVIDE: 466 case EXPR_ASSIGN: 467 case EXPR_NEGATE: 468 case EXPR_INVERT: 469 case EXPR_NOT: 470 case EXPR_UNARY_PLUS: 471 log_err(ctx, "%s of strings not permitted\n", 472 expr_op_type_to_string(expr->expr.op)); 473 return false; 474 475 default: 476 log_wsgo(ctx, "Unknown operator %d in ResolveString\n", 477 expr->expr.op); 478 break; 479 } 480 return false; 481 } 482 483 bool 484 ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr, 485 unsigned int *val_rtrn, const LookupEntry *values) 486 { 487 if (expr->expr.op != EXPR_IDENT) { 488 log_err(ctx, "Found a %s where an enumerated value was expected\n", 489 expr_op_type_to_string(expr->expr.op)); 490 return false; 491 } 492 493 if (!SimpleLookup(ctx, values, expr->ident.ident, EXPR_TYPE_INT, 494 val_rtrn)) { 495 log_err(ctx, "Illegal identifier %s; expected one of:\n", 496 xkb_atom_text(ctx, expr->ident.ident)); 497 while (values && values->name) 498 { 499 log_err(ctx, "\t%s\n", values->name); 500 values++; 501 } 502 return false; 503 } 504 505 return true; 506 } 507 508 static bool 509 ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr, 510 unsigned int *val_rtrn, IdentLookupFunc lookup, 511 const void *lookupPriv) 512 { 513 bool ok = 0; 514 unsigned int l, r; 515 int v; 516 ExprDef *left, *right; 517 const char *bogus = NULL; 518 519 switch (expr->expr.op) { 520 case EXPR_VALUE: 521 if (expr->expr.value_type != EXPR_TYPE_INT) { 522 log_err(ctx, 523 "Found constant of type %s where a mask was expected\n", 524 expr_value_type_to_string(expr->expr.value_type)); 525 return false; 526 } 527 *val_rtrn = (unsigned int) expr->integer.ival; 528 return true; 529 530 case EXPR_IDENT: 531 ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, 532 val_rtrn); 533 if (!ok) 534 log_err(ctx, "Identifier \"%s\" of type int is unknown\n", 535 xkb_atom_text(ctx, expr->ident.ident)); 536 return ok; 537 538 case EXPR_FIELD_REF: 539 log_err(ctx, "Default \"%s.%s\" of type int is unknown\n", 540 xkb_atom_text(ctx, expr->field_ref.element), 541 xkb_atom_text(ctx, expr->field_ref.field)); 542 return false; 543 544 case EXPR_ARRAY_REF: 545 bogus = "array reference"; 546 547 case EXPR_ACTION_DECL: 548 if (bogus == NULL) 549 bogus = "function use"; 550 log_err(ctx, 551 "Unexpected %s in mask expression; Expression Ignored\n", 552 bogus); 553 return false; 554 555 case EXPR_ADD: 556 case EXPR_SUBTRACT: 557 case EXPR_MULTIPLY: 558 case EXPR_DIVIDE: 559 left = expr->binary.left; 560 right = expr->binary.right; 561 if (!ExprResolveMaskLookup(ctx, left, &l, lookup, lookupPriv) || 562 !ExprResolveMaskLookup(ctx, right, &r, lookup, lookupPriv)) 563 return false; 564 565 switch (expr->expr.op) { 566 case EXPR_ADD: 567 *val_rtrn = l | r; 568 break; 569 case EXPR_SUBTRACT: 570 *val_rtrn = l & (~r); 571 break; 572 case EXPR_MULTIPLY: 573 case EXPR_DIVIDE: 574 log_err(ctx, "Cannot %s masks; Illegal operation ignored\n", 575 (expr->expr.op == EXPR_DIVIDE ? "divide" : "multiply")); 576 return false; 577 default: 578 break; 579 } 580 581 return true; 582 583 case EXPR_ASSIGN: 584 log_wsgo(ctx, "Assignment operator not implemented yet\n"); 585 break; 586 587 case EXPR_INVERT: 588 left = expr->unary.child; 589 if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv)) 590 return false; 591 592 *val_rtrn = ~v; 593 return true; 594 595 case EXPR_UNARY_PLUS: 596 case EXPR_NEGATE: 597 case EXPR_NOT: 598 left = expr->unary.child; 599 if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv)) 600 log_err(ctx, "The %s operator cannot be used with a mask\n", 601 (expr->expr.op == EXPR_NEGATE ? "-" : "!")); 602 return false; 603 604 default: 605 log_wsgo(ctx, "Unknown operator %d in ResolveMask\n", 606 expr->expr.op); 607 break; 608 } 609 610 return false; 611 } 612 613 bool 614 ExprResolveMask(struct xkb_context *ctx, const ExprDef *expr, 615 unsigned int *mask_rtrn, const LookupEntry *values) 616 { 617 return ExprResolveMaskLookup(ctx, expr, mask_rtrn, SimpleLookup, values); 618 } 619 620 bool 621 ExprResolveModMask(struct xkb_context *ctx, const ExprDef *expr, 622 enum mod_type mod_type, const struct xkb_mod_set *mods, 623 xkb_mod_mask_t *mask_rtrn) 624 { 625 LookupModMaskPriv priv = { .mods = mods, .mod_type = mod_type }; 626 return ExprResolveMaskLookup(ctx, expr, mask_rtrn, LookupModMask, &priv); 627 } 628 629 bool 630 ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr, 631 xkb_keysym_t *sym_rtrn) 632 { 633 int val; 634 635 if (expr->expr.op == EXPR_IDENT) { 636 const char *str = xkb_atom_text(ctx, expr->ident.ident); 637 *sym_rtrn = xkb_keysym_from_name(str, 0); 638 if (*sym_rtrn != XKB_KEY_NoSymbol) 639 return true; 640 } 641 642 if (!ExprResolveInteger(ctx, expr, &val)) 643 return false; 644 645 if (val < 0 || val >= 10) 646 return false; 647 648 *sym_rtrn = XKB_KEY_0 + (xkb_keysym_t) val; 649 return true; 650 } 651 652 bool 653 ExprResolveMod(struct xkb_context *ctx, const ExprDef *def, 654 enum mod_type mod_type, const struct xkb_mod_set *mods, 655 xkb_mod_index_t *ndx_rtrn) 656 { 657 xkb_mod_index_t ndx; 658 xkb_atom_t name; 659 660 if (def->expr.op != EXPR_IDENT) { 661 log_err(ctx, 662 "Cannot resolve virtual modifier: " 663 "found %s where a virtual modifier name was expected\n", 664 expr_op_type_to_string(def->expr.op)); 665 return false; 666 } 667 668 name = def->ident.ident; 669 ndx = XkbModNameToIndex(mods, name, mod_type); 670 if (ndx == XKB_MOD_INVALID) { 671 log_err(ctx, 672 "Cannot resolve virtual modifier: " 673 "\"%s\" was not previously declared\n", 674 xkb_atom_text(ctx, name)); 675 return false; 676 } 677 678 *ndx_rtrn = ndx; 679 return true; 680 } 681