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/* 28 * Copyright © 2012 Intel Corporation 29 * Copyright © 2012 Ran Benita <ran234@gmail.com> 30 * 31 * Permission is hereby granted, free of charge, to any person obtaining a 32 * copy of this software and associated documentation files (the "Software"), 33 * to deal in the Software without restriction, including without limitation 34 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 35 * and/or sell copies of the Software, and to permit persons to whom the 36 * Software is furnished to do so, subject to the following conditions: 37 * 38 * The above copyright notice and this permission notice (including the next 39 * paragraph) shall be included in all copies or substantial portions of the 40 * Software. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 45 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 46 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 47 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 48 * DEALINGS IN THE SOFTWARE. 49 * 50 * Author: Daniel Stone <daniel@fooishbar.org> 51 * Ran Benita <ran234@gmail.com> 52 */ 53 54#include "xkbcomp-priv.h" 55#include "ast-build.h" 56#include "include.h" 57 58ParseCommon * 59AppendStmt(ParseCommon *to, ParseCommon *append) 60{ 61 ParseCommon *iter; 62 63 if (!to) 64 return append; 65 66 for (iter = to; iter->next; iter = iter->next); 67 68 iter->next = append; 69 return to; 70} 71 72static ExprDef * 73ExprCreate(enum expr_op_type op, enum expr_value_type type, size_t size) 74{ 75 ExprDef *expr = malloc(size); 76 if (!expr) 77 return NULL; 78 79 expr->common.type = STMT_EXPR; 80 expr->common.next = NULL; 81 expr->expr.op = op; 82 expr->expr.value_type = type; 83 84 return expr; 85} 86 87#define EXPR_CREATE(type_, name_, op_, value_type_) \ 88 ExprDef *name_ = ExprCreate(op_, value_type_, sizeof(type_)); \ 89 if (!name_) \ 90 return NULL; 91 92ExprDef * 93ExprCreateString(xkb_atom_t str) 94{ 95 EXPR_CREATE(ExprString, expr, EXPR_VALUE, EXPR_TYPE_STRING); 96 expr->string.str = str; 97 return expr; 98} 99 100ExprDef * 101ExprCreateInteger(int ival) 102{ 103 EXPR_CREATE(ExprInteger, expr, EXPR_VALUE, EXPR_TYPE_INT); 104 expr->integer.ival = ival; 105 return expr; 106} 107 108ExprDef * 109ExprCreateBoolean(bool set) 110{ 111 EXPR_CREATE(ExprBoolean, expr, EXPR_VALUE, EXPR_TYPE_BOOLEAN); 112 expr->boolean.set = set; 113 return expr; 114} 115 116ExprDef * 117ExprCreateKeyName(xkb_atom_t key_name) 118{ 119 EXPR_CREATE(ExprKeyName, expr, EXPR_VALUE, EXPR_TYPE_KEYNAME); 120 expr->key_name.key_name = key_name; 121 return expr; 122} 123 124ExprDef * 125ExprCreateIdent(xkb_atom_t ident) 126{ 127 EXPR_CREATE(ExprIdent, expr, EXPR_IDENT, EXPR_TYPE_UNKNOWN); 128 expr->ident.ident = ident; 129 return expr; 130} 131 132ExprDef * 133ExprCreateUnary(enum expr_op_type op, enum expr_value_type type, 134 ExprDef *child) 135{ 136 EXPR_CREATE(ExprUnary, expr, op, type); 137 expr->unary.child = child; 138 return expr; 139} 140 141ExprDef * 142ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right) 143{ 144 EXPR_CREATE(ExprBinary, expr, op, EXPR_TYPE_UNKNOWN); 145 146 if (op == EXPR_ASSIGN || left->expr.value_type == EXPR_TYPE_UNKNOWN) 147 expr->expr.value_type = right->expr.value_type; 148 else if (left->expr.value_type == right->expr.value_type || 149 right->expr.value_type == EXPR_TYPE_UNKNOWN) 150 expr->expr.value_type = left->expr.value_type; 151 expr->binary.left = left; 152 expr->binary.right = right; 153 154 return expr; 155} 156 157ExprDef * 158ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field) 159{ 160 EXPR_CREATE(ExprFieldRef, expr, EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN); 161 expr->field_ref.element = element; 162 expr->field_ref.field = field; 163 return expr; 164} 165 166ExprDef * 167ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry) 168{ 169 EXPR_CREATE(ExprArrayRef, expr, EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN); 170 expr->array_ref.element = element; 171 expr->array_ref.field = field; 172 expr->array_ref.entry = entry; 173 return expr; 174} 175 176ExprDef * 177ExprCreateAction(xkb_atom_t name, ExprDef *args) 178{ 179 EXPR_CREATE(ExprAction, expr, EXPR_ACTION_DECL, EXPR_TYPE_UNKNOWN); 180 expr->action.name = name; 181 expr->action.args = args; 182 return expr; 183} 184 185ExprDef * 186ExprCreateKeysymList(xkb_keysym_t sym) 187{ 188 EXPR_CREATE(ExprKeysymList, expr, EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS); 189 190 darray_init(expr->keysym_list.syms); 191 darray_init(expr->keysym_list.symsMapIndex); 192 darray_init(expr->keysym_list.symsNumEntries); 193 194 darray_append(expr->keysym_list.syms, sym); 195 darray_append(expr->keysym_list.symsMapIndex, 0); 196 darray_append(expr->keysym_list.symsNumEntries, 1); 197 198 return expr; 199} 200 201ExprDef * 202ExprCreateMultiKeysymList(ExprDef *expr) 203{ 204 unsigned nLevels = darray_size(expr->keysym_list.symsMapIndex); 205 206 darray_resize(expr->keysym_list.symsMapIndex, 1); 207 darray_resize(expr->keysym_list.symsNumEntries, 1); 208 darray_item(expr->keysym_list.symsMapIndex, 0) = 0; 209 darray_item(expr->keysym_list.symsNumEntries, 0) = nLevels; 210 211 return expr; 212} 213 214ExprDef * 215ExprAppendKeysymList(ExprDef *expr, xkb_keysym_t sym) 216{ 217 unsigned nSyms = darray_size(expr->keysym_list.syms); 218 219 darray_append(expr->keysym_list.symsMapIndex, nSyms); 220 darray_append(expr->keysym_list.symsNumEntries, 1); 221 darray_append(expr->keysym_list.syms, sym); 222 223 return expr; 224} 225 226ExprDef * 227ExprAppendMultiKeysymList(ExprDef *expr, ExprDef *append) 228{ 229 xkb_keysym_t *syms; 230 unsigned nSyms = darray_size(expr->keysym_list.syms); 231 unsigned numEntries = darray_size(append->keysym_list.syms); 232 233 darray_append(expr->keysym_list.symsMapIndex, nSyms); 234 darray_append(expr->keysym_list.symsNumEntries, numEntries); 235 darray_steal(append->keysym_list.syms, &syms, NULL); 236 darray_append_items(expr->keysym_list.syms, syms, numEntries); 237 238 FreeStmt((ParseCommon *) &append); 239 240 return expr; 241} 242 243KeycodeDef * 244KeycodeCreate(xkb_atom_t name, int64_t value) 245{ 246 KeycodeDef *def = malloc(sizeof(*def)); 247 if (!def) 248 return NULL; 249 250 def->common.type = STMT_KEYCODE; 251 def->common.next = NULL; 252 def->name = name; 253 def->value = value; 254 255 return def; 256} 257 258KeyAliasDef * 259KeyAliasCreate(xkb_atom_t alias, xkb_atom_t real) 260{ 261 KeyAliasDef *def = malloc(sizeof(*def)); 262 if (!def) 263 return NULL; 264 265 def->common.type = STMT_ALIAS; 266 def->common.next = NULL; 267 def->alias = alias; 268 def->real = real; 269 270 return def; 271} 272 273VModDef * 274VModCreate(xkb_atom_t name, ExprDef *value) 275{ 276 VModDef *def = malloc(sizeof(*def)); 277 if (!def) 278 return NULL; 279 280 def->common.type = STMT_VMOD; 281 def->common.next = NULL; 282 def->name = name; 283 def->value = value; 284 285 return def; 286} 287 288VarDef * 289VarCreate(ExprDef *name, ExprDef *value) 290{ 291 VarDef *def = malloc(sizeof(*def)); 292 if (!def) 293 return NULL; 294 295 def->common.type = STMT_VAR; 296 def->common.next = NULL; 297 def->name = name; 298 def->value = value; 299 300 return def; 301} 302 303VarDef * 304BoolVarCreate(xkb_atom_t ident, bool set) 305{ 306 ExprDef *name, *value; 307 VarDef *def; 308 if (!(name = ExprCreateIdent(ident))) { 309 return NULL; 310 } 311 if (!(value = ExprCreateBoolean(set))) { 312 FreeStmt((ParseCommon *) name); 313 return NULL; 314 } 315 if (!(def = VarCreate(name, value))) { 316 FreeStmt((ParseCommon *) name); 317 FreeStmt((ParseCommon *) value); 318 return NULL; 319 } 320 return def; 321} 322 323InterpDef * 324InterpCreate(xkb_keysym_t sym, ExprDef *match) 325{ 326 InterpDef *def = malloc(sizeof(*def)); 327 if (!def) 328 return NULL; 329 330 def->common.type = STMT_INTERP; 331 def->common.next = NULL; 332 def->sym = sym; 333 def->match = match; 334 def->def = NULL; 335 336 return def; 337} 338 339KeyTypeDef * 340KeyTypeCreate(xkb_atom_t name, VarDef *body) 341{ 342 KeyTypeDef *def = malloc(sizeof(*def)); 343 if (!def) 344 return NULL; 345 346 def->common.type = STMT_TYPE; 347 def->common.next = NULL; 348 def->merge = MERGE_DEFAULT; 349 def->name = name; 350 def->body = body; 351 352 return def; 353} 354 355SymbolsDef * 356SymbolsCreate(xkb_atom_t keyName, VarDef *symbols) 357{ 358 SymbolsDef *def = malloc(sizeof(*def)); 359 if (!def) 360 return NULL; 361 362 def->common.type = STMT_SYMBOLS; 363 def->common.next = NULL; 364 def->merge = MERGE_DEFAULT; 365 def->keyName = keyName; 366 def->symbols = symbols; 367 368 return def; 369} 370 371GroupCompatDef * 372GroupCompatCreate(unsigned group, ExprDef *val) 373{ 374 GroupCompatDef *def = malloc(sizeof(*def)); 375 if (!def) 376 return NULL; 377 378 def->common.type = STMT_GROUP_COMPAT; 379 def->common.next = NULL; 380 def->merge = MERGE_DEFAULT; 381 def->group = group; 382 def->def = val; 383 384 return def; 385} 386 387ModMapDef * 388ModMapCreate(xkb_atom_t modifier, ExprDef *keys) 389{ 390 ModMapDef *def = malloc(sizeof(*def)); 391 if (!def) 392 return NULL; 393 394 def->common.type = STMT_MODMAP; 395 def->common.next = NULL; 396 def->merge = MERGE_DEFAULT; 397 def->modifier = modifier; 398 def->keys = keys; 399 400 return def; 401} 402 403LedMapDef * 404LedMapCreate(xkb_atom_t name, VarDef *body) 405{ 406 LedMapDef *def = malloc(sizeof(*def)); 407 if (!def) 408 return NULL; 409 410 def->common.type = STMT_LED_MAP; 411 def->common.next = NULL; 412 def->merge = MERGE_DEFAULT; 413 def->name = name; 414 def->body = body; 415 416 return def; 417} 418 419LedNameDef * 420LedNameCreate(unsigned ndx, ExprDef *name, bool virtual) 421{ 422 LedNameDef *def = malloc(sizeof(*def)); 423 if (!def) 424 return NULL; 425 426 def->common.type = STMT_LED_NAME; 427 def->common.next = NULL; 428 def->merge = MERGE_DEFAULT; 429 def->ndx = ndx; 430 def->name = name; 431 def->virtual = virtual; 432 433 return def; 434} 435 436static void 437FreeInclude(IncludeStmt *incl); 438 439IncludeStmt * 440IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge) 441{ 442 IncludeStmt *incl, *first; 443 char *file, *map, *stmt, *tmp, *extra_data; 444 char nextop; 445 446 incl = first = NULL; 447 file = map = NULL; 448 tmp = str; 449 stmt = strdup_safe(str); 450 while (tmp && *tmp) 451 { 452 if (!ParseIncludeMap(&tmp, &file, &map, &nextop, &extra_data)) 453 goto err; 454 455 /* 456 * Given an RMLVO (here layout) like 'us,,fr', the rules parser 457 * will give out something like 'pc+us+:2+fr:3+inet(evdev)'. 458 * We should just skip the ':2' in this case and leave it to the 459 * appropriate section to deal with the empty group. 460 */ 461 if (isempty(file)) { 462 free(file); 463 free(map); 464 free(extra_data); 465 continue; 466 } 467 468 if (first == NULL) { 469 first = incl = malloc(sizeof(*first)); 470 } else { 471 incl->next_incl = malloc(sizeof(*first)); 472 incl = incl->next_incl; 473 } 474 475 if (!incl) { 476 log_wsgo(ctx, 477 "Allocation failure in IncludeCreate; " 478 "Using only part of the include\n"); 479 break; 480 } 481 482 incl->common.type = STMT_INCLUDE; 483 incl->common.next = NULL; 484 incl->merge = merge; 485 incl->stmt = NULL; 486 incl->file = file; 487 incl->map = map; 488 incl->modifier = extra_data; 489 incl->next_incl = NULL; 490 491 if (nextop == '|') 492 merge = MERGE_AUGMENT; 493 else 494 merge = MERGE_OVERRIDE; 495 } 496 497 if (first) 498 first->stmt = stmt; 499 else 500 free(stmt); 501 502 return first; 503 504err: 505 log_err(ctx, "Illegal include statement \"%s\"; Ignored\n", stmt); 506 FreeInclude(first); 507 free(stmt); 508 return NULL; 509} 510 511XkbFile * 512XkbFileCreate(enum xkb_file_type type, char *name, ParseCommon *defs, 513 enum xkb_map_flags flags) 514{ 515 XkbFile *file; 516 517 file = calloc(1, sizeof(*file)); 518 if (!file) 519 return NULL; 520 521 XkbEscapeMapName(name); 522 file->file_type = type; 523 file->topName = strdup_safe(name); 524 file->name = name; 525 file->defs = defs; 526 file->flags = flags; 527 528 return file; 529} 530 531XkbFile * 532XkbFileFromComponents(struct xkb_context *ctx, 533 const struct xkb_component_names *kkctgs) 534{ 535 char *const components[] = { 536 kkctgs->keycodes, kkctgs->types, 537 kkctgs->compat, kkctgs->symbols, 538 }; 539 enum xkb_file_type type; 540 IncludeStmt *include = NULL; 541 XkbFile *file = NULL; 542 ParseCommon *defs = NULL; 543 544 for (type = FIRST_KEYMAP_FILE_TYPE; type <= LAST_KEYMAP_FILE_TYPE; type++) { 545 include = IncludeCreate(ctx, components[type], MERGE_DEFAULT); 546 if (!include) 547 goto err; 548 549 file = XkbFileCreate(type, NULL, (ParseCommon *) include, 0); 550 if (!file) { 551 FreeInclude(include); 552 goto err; 553 } 554 555 defs = AppendStmt(defs, &file->common); 556 } 557 558 file = XkbFileCreate(FILE_TYPE_KEYMAP, NULL, defs, 0); 559 if (!file) 560 goto err; 561 562 return file; 563 564err: 565 FreeXkbFile((XkbFile *) defs); 566 return NULL; 567} 568 569static void 570FreeExpr(ExprDef *expr) 571{ 572 if (!expr) 573 return; 574 575 switch (expr->expr.op) { 576 case EXPR_ACTION_LIST: 577 case EXPR_NEGATE: 578 case EXPR_UNARY_PLUS: 579 case EXPR_NOT: 580 case EXPR_INVERT: 581 FreeStmt((ParseCommon *) expr->unary.child); 582 break; 583 584 case EXPR_DIVIDE: 585 case EXPR_ADD: 586 case EXPR_SUBTRACT: 587 case EXPR_MULTIPLY: 588 case EXPR_ASSIGN: 589 FreeStmt((ParseCommon *) expr->binary.left); 590 FreeStmt((ParseCommon *) expr->binary.right); 591 break; 592 593 case EXPR_ACTION_DECL: 594 FreeStmt((ParseCommon *) expr->action.args); 595 break; 596 597 case EXPR_ARRAY_REF: 598 FreeStmt((ParseCommon *) expr->array_ref.entry); 599 break; 600 601 case EXPR_KEYSYM_LIST: 602 darray_free(expr->keysym_list.syms); 603 darray_free(expr->keysym_list.symsMapIndex); 604 darray_free(expr->keysym_list.symsNumEntries); 605 break; 606 607 default: 608 break; 609 } 610} 611 612static void 613FreeInclude(IncludeStmt *incl) 614{ 615 IncludeStmt *next; 616 617 while (incl) 618 { 619 next = incl->next_incl; 620 621 free(incl->file); 622 free(incl->map); 623 free(incl->modifier); 624 free(incl->stmt); 625 626 free(incl); 627 incl = next; 628 } 629} 630 631void 632FreeStmt(ParseCommon *stmt) 633{ 634 ParseCommon *next; 635 636 while (stmt) 637 { 638 next = stmt->next; 639 640 switch (stmt->type) { 641 case STMT_INCLUDE: 642 FreeInclude((IncludeStmt *) stmt); 643 /* stmt is already free'd here. */ 644 stmt = NULL; 645 break; 646 case STMT_EXPR: 647 FreeExpr((ExprDef *) stmt); 648 break; 649 case STMT_VAR: 650 FreeStmt((ParseCommon *) ((VarDef *) stmt)->name); 651 FreeStmt((ParseCommon *) ((VarDef *) stmt)->value); 652 break; 653 case STMT_TYPE: 654 FreeStmt((ParseCommon *) ((KeyTypeDef *) stmt)->body); 655 break; 656 case STMT_INTERP: 657 FreeStmt((ParseCommon *) ((InterpDef *) stmt)->match); 658 FreeStmt((ParseCommon *) ((InterpDef *) stmt)->def); 659 break; 660 case STMT_VMOD: 661 FreeStmt((ParseCommon *) ((VModDef *) stmt)->value); 662 break; 663 case STMT_SYMBOLS: 664 FreeStmt((ParseCommon *) ((SymbolsDef *) stmt)->symbols); 665 break; 666 case STMT_MODMAP: 667 FreeStmt((ParseCommon *) ((ModMapDef *) stmt)->keys); 668 break; 669 case STMT_GROUP_COMPAT: 670 FreeStmt((ParseCommon *) ((GroupCompatDef *) stmt)->def); 671 break; 672 case STMT_LED_MAP: 673 FreeStmt((ParseCommon *) ((LedMapDef *) stmt)->body); 674 break; 675 case STMT_LED_NAME: 676 FreeStmt((ParseCommon *) ((LedNameDef *) stmt)->name); 677 break; 678 default: 679 break; 680 } 681 682 free(stmt); 683 stmt = next; 684 } 685} 686 687void 688FreeXkbFile(XkbFile *file) 689{ 690 XkbFile *next; 691 692 while (file) 693 { 694 next = (XkbFile *) file->common.next; 695 696 switch (file->file_type) { 697 case FILE_TYPE_KEYMAP: 698 FreeXkbFile((XkbFile *) file->defs); 699 break; 700 701 case FILE_TYPE_TYPES: 702 case FILE_TYPE_COMPAT: 703 case FILE_TYPE_SYMBOLS: 704 case FILE_TYPE_KEYCODES: 705 case FILE_TYPE_GEOMETRY: 706 FreeStmt(file->defs); 707 break; 708 709 default: 710 break; 711 } 712 713 free(file->name); 714 free(file->topName); 715 free(file); 716 file = next; 717 } 718} 719 720static const char *xkb_file_type_strings[_FILE_TYPE_NUM_ENTRIES] = { 721 [FILE_TYPE_KEYCODES] = "xkb_keycodes", 722 [FILE_TYPE_TYPES] = "xkb_types", 723 [FILE_TYPE_COMPAT] = "xkb_compatibility", 724 [FILE_TYPE_SYMBOLS] = "xkb_symbols", 725 [FILE_TYPE_GEOMETRY] = "xkb_geometry", 726 [FILE_TYPE_KEYMAP] = "xkb_keymap", 727 [FILE_TYPE_RULES] = "rules", 728}; 729 730const char * 731xkb_file_type_to_string(enum xkb_file_type type) 732{ 733 if (type > _FILE_TYPE_NUM_ENTRIES) 734 return "unknown"; 735 return xkb_file_type_strings[type]; 736} 737 738static const char *stmt_type_strings[_STMT_NUM_VALUES] = { 739 [STMT_UNKNOWN] = "unknown statement", 740 [STMT_INCLUDE] = "include statement", 741 [STMT_KEYCODE] = "key name definition", 742 [STMT_ALIAS] = "key alias definition", 743 [STMT_EXPR] = "expression", 744 [STMT_VAR] = "variable definition", 745 [STMT_TYPE] = "key type definition", 746 [STMT_INTERP] = "symbol interpretation definition", 747 [STMT_VMOD] = "virtual modifiers definition", 748 [STMT_SYMBOLS] = "key symbols definition", 749 [STMT_MODMAP] = "modifier map declaration", 750 [STMT_GROUP_COMPAT] = "group declaration", 751 [STMT_LED_MAP] = "indicator map declaration", 752 [STMT_LED_NAME] = "indicator name declaration", 753}; 754 755const char * 756stmt_type_to_string(enum stmt_type type) 757{ 758 if (type >= _STMT_NUM_VALUES) 759 return NULL; 760 return stmt_type_strings[type]; 761} 762 763static const char *expr_op_type_strings[_EXPR_NUM_VALUES] = { 764 [EXPR_VALUE] = "literal", 765 [EXPR_IDENT] = "identifier", 766 [EXPR_ACTION_DECL] = "action declaration", 767 [EXPR_FIELD_REF] = "field reference", 768 [EXPR_ARRAY_REF] = "array reference", 769 [EXPR_KEYSYM_LIST] = "list of keysyms", 770 [EXPR_ACTION_LIST] = "list of actions", 771 [EXPR_ADD] = "addition", 772 [EXPR_SUBTRACT] = "subtraction", 773 [EXPR_MULTIPLY] = "multiplication", 774 [EXPR_DIVIDE] = "division", 775 [EXPR_ASSIGN] = "assignment", 776 [EXPR_NOT] = "logical negation", 777 [EXPR_NEGATE] = "arithmetic negation", 778 [EXPR_INVERT] = "bitwise inversion", 779 [EXPR_UNARY_PLUS] = "unary plus", 780}; 781 782const char * 783expr_op_type_to_string(enum expr_op_type type) 784{ 785 if (type >= _EXPR_NUM_VALUES) 786 return NULL; 787 return expr_op_type_strings[type]; 788} 789 790static const char *expr_value_type_strings[_EXPR_TYPE_NUM_VALUES] = { 791 [EXPR_TYPE_UNKNOWN] = "unknown", 792 [EXPR_TYPE_BOOLEAN] = "boolean", 793 [EXPR_TYPE_INT] = "int", 794 [EXPR_TYPE_STRING] = "string", 795 [EXPR_TYPE_ACTION] = "action", 796 [EXPR_TYPE_KEYNAME] = "keyname", 797 [EXPR_TYPE_SYMBOLS] = "symbols", 798}; 799 800const char * 801expr_value_type_to_string(enum expr_value_type type) 802{ 803 if (type >= _EXPR_TYPE_NUM_VALUES) 804 return NULL; 805 return expr_value_type_strings[type]; 806} 807