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 <stdlib.h> 28#include <stdio.h> 29#include <ctype.h> 30#include <X11/Xos.h> 31#include <X11/Xlib.h> 32#include <X11/XKBlib.h> 33 34#include "tokens.h" 35#define DEBUG_VAR scanDebug 36#include "utils.h" 37#include "parseutils.h" 38 39#ifdef DEBUG 40unsigned int scanDebug; 41#endif 42 43static FILE *yyin; 44 45static char scanFileBuf[1024] = {0}; 46char *scanFile = scanFileBuf; 47int lineNum = 0; 48 49int scanInt; 50 51char scanBuf[1024]; 52static int scanStrLine = 0; 53 54#define BUFSIZE 4096 55static char readBuf[BUFSIZE]; 56static int readBufPos = 0; 57static int readBufLen = 0; 58 59#ifdef DEBUG 60extern int debugFlags; 61 62static char * 63tokText(int tok) 64{ 65 static char buf[32]; 66 67 switch (tok) 68 { 69 case END_OF_FILE: 70 snprintf(buf, sizeof(buf), "END_OF_FILE"); 71 break; 72 case ERROR_TOK: 73 snprintf(buf, sizeof(buf), "ERROR"); 74 break; 75 76 case XKB_KEYMAP: 77 snprintf(buf, sizeof(buf), "XKB_KEYMAP"); 78 break; 79 case XKB_KEYCODES: 80 snprintf(buf, sizeof(buf), "XKB_KEYCODES"); 81 break; 82 case XKB_TYPES: 83 snprintf(buf, sizeof(buf), "XKB_TYPES"); 84 break; 85 case XKB_SYMBOLS: 86 snprintf(buf, sizeof(buf), "XKB_SYMBOLS"); 87 break; 88 case XKB_COMPATMAP: 89 snprintf(buf, sizeof(buf), "XKB_COMPATMAP"); 90 break; 91 case XKB_GEOMETRY: 92 snprintf(buf, sizeof(buf), "XKB_GEOMETRY"); 93 break; 94 case XKB_SEMANTICS: 95 snprintf(buf, sizeof(buf), "XKB_SEMANTICS"); 96 break; 97 case XKB_LAYOUT: 98 snprintf(buf, sizeof(buf), "XKB_LAYOUT"); 99 break; 100 101 case INCLUDE: 102 snprintf(buf, sizeof(buf), "INCLUDE"); 103 break; 104 case OVERRIDE: 105 snprintf(buf, sizeof(buf), "OVERRIDE"); 106 break; 107 case AUGMENT: 108 snprintf(buf, sizeof(buf), "AUGMENT"); 109 break; 110 case REPLACE: 111 snprintf(buf, sizeof(buf), "REPLACE"); 112 break; 113 case ALTERNATE: 114 snprintf(buf, sizeof(buf), "ALTERNATE"); 115 break; 116 117 case VIRTUAL_MODS: 118 snprintf(buf, sizeof(buf), "VIRTUAL_MODS"); 119 break; 120 case TYPE: 121 snprintf(buf, sizeof(buf), "TYPE"); 122 break; 123 case INTERPRET: 124 snprintf(buf, sizeof(buf), "INTERPRET"); 125 break; 126 case ACTION_TOK: 127 snprintf(buf, sizeof(buf), "ACTION"); 128 break; 129 case KEY: 130 snprintf(buf, sizeof(buf), "KEY"); 131 break; 132 case ALIAS: 133 snprintf(buf, sizeof(buf), "ALIAS"); 134 break; 135 case GROUP: 136 snprintf(buf, sizeof(buf), "GROUP"); 137 break; 138 case MODIFIER_MAP: 139 snprintf(buf, sizeof(buf), "MODIFIER_MAP"); 140 break; 141 case INDICATOR: 142 snprintf(buf, sizeof(buf), "INDICATOR"); 143 break; 144 case SHAPE: 145 snprintf(buf, sizeof(buf), "SHAPE"); 146 break; 147 case KEYS: 148 snprintf(buf, sizeof(buf), "KEYS"); 149 break; 150 case ROW: 151 snprintf(buf, sizeof(buf), "ROW"); 152 break; 153 case SECTION: 154 snprintf(buf, sizeof(buf), "SECTION"); 155 break; 156 case OVERLAY: 157 snprintf(buf, sizeof(buf), "OVERLAY"); 158 break; 159 case TEXT: 160 snprintf(buf, sizeof(buf), "TEXT"); 161 break; 162 case OUTLINE: 163 snprintf(buf, sizeof(buf), "OUTLINE"); 164 break; 165 case SOLID: 166 snprintf(buf, sizeof(buf), "SOLID"); 167 break; 168 case LOGO: 169 snprintf(buf, sizeof(buf), "LOGO"); 170 break; 171 case VIRTUAL: 172 snprintf(buf, sizeof(buf), "VIRTUAL"); 173 break; 174 175 case EQUALS: 176 snprintf(buf, sizeof(buf), "EQUALS"); 177 break; 178 case PLUS: 179 snprintf(buf, sizeof(buf), "PLUS"); 180 break; 181 case MINUS: 182 snprintf(buf, sizeof(buf), "MINUS"); 183 break; 184 case DIVIDE: 185 snprintf(buf, sizeof(buf), "DIVIDE"); 186 break; 187 case TIMES: 188 snprintf(buf, sizeof(buf), "TIMES"); 189 break; 190 case OBRACE: 191 snprintf(buf, sizeof(buf), "OBRACE"); 192 break; 193 case CBRACE: 194 snprintf(buf, sizeof(buf), "CBRACE"); 195 break; 196 case OPAREN: 197 snprintf(buf, sizeof(buf), "OPAREN"); 198 break; 199 case CPAREN: 200 snprintf(buf, sizeof(buf), "CPAREN"); 201 break; 202 case OBRACKET: 203 snprintf(buf, sizeof(buf), "OBRACKET"); 204 break; 205 case CBRACKET: 206 snprintf(buf, sizeof(buf), "CBRACKET"); 207 break; 208 case DOT: 209 snprintf(buf, sizeof(buf), "DOT"); 210 break; 211 case COMMA: 212 snprintf(buf, sizeof(buf), "COMMA"); 213 break; 214 case SEMI: 215 snprintf(buf, sizeof(buf), "SEMI"); 216 break; 217 case EXCLAM: 218 snprintf(buf, sizeof(buf), "EXCLAM"); 219 break; 220 case INVERT: 221 snprintf(buf, sizeof(buf), "INVERT"); 222 break; 223 224 case STRING: 225 snprintf(buf, sizeof(buf), "STRING (%s)", scanBuf); 226 break; 227 case INTEGER: 228 snprintf(buf, sizeof(buf), "INTEGER (0x%x)", scanInt); 229 break; 230 case FLOAT: 231 snprintf(buf, sizeof(buf), "FLOAT (%d.%d)", 232 scanInt / XkbGeomPtsPerMM, scanInt % XkbGeomPtsPerMM); 233 break; 234 case IDENT: 235 snprintf(buf, sizeof(buf), "IDENT (%s)", scanBuf); 236 break; 237 case KEYNAME: 238 snprintf(buf, sizeof(buf), "KEYNAME (%s)", scanBuf); 239 break; 240 241 case PARTIAL: 242 snprintf(buf, sizeof(buf), "PARTIAL"); 243 break; 244 case DEFAULT: 245 snprintf(buf, sizeof(buf), "DEFAULT"); 246 break; 247 case HIDDEN: 248 snprintf(buf, sizeof(buf), "HIDDEN"); 249 break; 250 251 case ALPHANUMERIC_KEYS: 252 snprintf(buf, sizeof(buf), "ALPHANUMERIC_KEYS"); 253 break; 254 case MODIFIER_KEYS: 255 snprintf(buf, sizeof(buf), "MODIFIER_KEYS"); 256 break; 257 case KEYPAD_KEYS: 258 snprintf(buf, sizeof(buf), "KEYPAD_KEYS"); 259 break; 260 case FUNCTION_KEYS: 261 snprintf(buf, sizeof(buf), "FUNCTION_KEYS"); 262 break; 263 case ALTERNATE_GROUP: 264 snprintf(buf, sizeof(buf), "ALTERNATE_GROUP"); 265 break; 266 267 default: 268 snprintf(buf, sizeof(buf), "UNKNOWN"); 269 break; 270 } 271 return buf; 272} 273#endif 274 275void 276scan_set_file(FILE *file) 277{ 278 readBufLen = 0; 279 readBufPos = 0; 280 yyin = file; 281} 282 283static int 284scanchar(void) 285{ 286 if (readBufPos >= readBufLen) { 287 readBufLen = fread(readBuf, 1, BUFSIZE, yyin); 288 readBufPos = 0; 289 if (!readBufLen) 290 return EOF; 291 if (feof(yyin)) 292 readBuf[readBufLen] = EOF; 293 } 294 295 return readBuf[readBufPos++]; 296} 297 298static void 299unscanchar(int c) 300{ 301 if (readBuf[--readBufPos] != c) { 302 fprintf(stderr, "UNGETCHAR FAILED! Put back %c, was expecting %c at " 303 "position %d, buf is '%s'\n", c, readBuf[readBufPos], 304 readBufPos, readBuf); 305 _exit(94); 306 } 307} 308 309int 310setScanState(char *file, int line) 311{ 312 if (file != NULL) 313 strncpy(scanFile, file, 1024); 314 if (line >= 0) 315 lineNum = line; 316 return 1; 317} 318 319static int 320yyGetString(void) 321{ 322 int ch, i; 323 324 i = 0; 325 while (((ch = scanchar()) != EOF) && (ch != '"')) 326 { 327 if (ch == '\\') 328 { 329 if ((ch = scanchar()) != EOF) 330 { 331 if (ch == 'n') 332 ch = '\n'; 333 else if (ch == 't') 334 ch = '\t'; 335 else if (ch == 'v') 336 ch = '\v'; 337 else if (ch == 'b') 338 ch = '\b'; 339 else if (ch == 'r') 340 ch = '\r'; 341 else if (ch == 'f') 342 ch = '\f'; 343 else if (ch == 'e') 344 ch = '\033'; 345 else if (ch == '0') 346 { 347 int tmp, stop; 348 ch = stop = 0; 349 if (((tmp = scanchar()) != EOF) && (isdigit(tmp)) 350 && (tmp != '8') && (tmp != '9')) 351 { 352 ch = (ch * 8) + (tmp - '0'); 353 } 354 else 355 { 356 stop = 1; 357 unscanchar(tmp); 358 } 359 if (!stop) 360 { 361 if (((tmp = scanchar()) != EOF) 362 && (isdigit(tmp)) && (tmp != '8') && (tmp != '9')) 363 { 364 ch = (ch * 8) + (tmp - '0'); 365 } 366 else 367 { 368 stop = 1; 369 unscanchar(tmp); 370 } 371 } 372 if (!stop) 373 { 374 if (((tmp = scanchar()) != EOF) 375 && (isdigit(tmp)) && (tmp != '8') && (tmp != '9')) 376 { 377 ch = (ch * 8) + (tmp - '0'); 378 } 379 else 380 { 381 stop = 1; 382 unscanchar(tmp); 383 } 384 } 385 } 386 } 387 else 388 return ERROR_TOK; 389 } 390 if (i < sizeof(scanBuf) - 1) 391 scanBuf[i++] = ch; 392 } 393 scanBuf[i] = '\0'; 394 if (ch == '"') 395 { 396 scanStrLine = lineNum; 397 return STRING; 398 } 399 return ERROR_TOK; 400} 401 402static int 403yyGetKeyName(void) 404{ 405 int ch, i; 406 407 i = 0; 408 while (((ch = scanchar()) != EOF) && (ch != '>')) 409 { 410 if (ch == '\\') 411 { 412 if ((ch = scanchar()) != EOF) 413 { 414 if (ch == 'n') 415 ch = '\n'; 416 else if (ch == 't') 417 ch = '\t'; 418 else if (ch == 'v') 419 ch = '\v'; 420 else if (ch == 'b') 421 ch = '\b'; 422 else if (ch == 'r') 423 ch = '\r'; 424 else if (ch == 'f') 425 ch = '\f'; 426 else if (ch == 'e') 427 ch = '\033'; 428 else if (ch == '0') 429 { 430 int tmp, stop; 431 ch = stop = 0; 432 if (((tmp = scanchar()) != EOF) && (isdigit(tmp)) 433 && (tmp != '8') && (tmp != '9')) 434 { 435 ch = (ch * 8) + (tmp - '0'); 436 } 437 else 438 { 439 stop = 1; 440 unscanchar(tmp); 441 } 442 if ((!stop) && ((tmp = scanchar()) != EOF) 443 && (isdigit(tmp)) && (tmp != '8') && (tmp != '9')) 444 { 445 ch = (ch * 8) + (tmp - '0'); 446 } 447 else 448 { 449 stop = 1; 450 unscanchar(tmp); 451 } 452 if ((!stop) && ((tmp = scanchar()) != EOF) 453 && (isdigit(tmp)) && (tmp != '8') && (tmp != '9')) 454 { 455 ch = (ch * 8) + (tmp - '0'); 456 } 457 else 458 { 459 stop = 1; 460 unscanchar(tmp); 461 } 462 } 463 } 464 else 465 return ERROR_TOK; 466 } 467 if (i < sizeof(scanBuf) - 1) 468 scanBuf[i++] = ch; 469 } 470 scanBuf[i] = '\0'; 471 if ((ch == '>') && (i < 5)) 472 { 473 scanStrLine = lineNum; 474 return KEYNAME; 475 } 476 return ERROR_TOK; 477} 478 479static struct _Keyword 480{ 481 const char *keyword; 482 int token; 483} keywords[] = 484{ 485 { 486 "xkb_keymap", XKB_KEYMAP}, 487 { 488 "xkb_keycodes", XKB_KEYCODES}, 489 { 490 "xkb_types", XKB_TYPES}, 491 { 492 "xkb_symbols", XKB_SYMBOLS}, 493 { 494 "xkb_compat", XKB_COMPATMAP}, 495 { 496 "xkb_compat_map", XKB_COMPATMAP}, 497 { 498 "xkb_compatibility", XKB_COMPATMAP}, 499 { 500 "xkb_compatibility_map", XKB_COMPATMAP}, 501 { 502 "xkb_geometry", XKB_GEOMETRY}, 503 { 504 "xkb_semantics", XKB_SEMANTICS}, 505 { 506 "xkb_layout", XKB_LAYOUT}, 507 { 508 "include", INCLUDE}, 509 { 510 "override", OVERRIDE}, 511 { 512 "augment", AUGMENT}, 513 { 514 "replace", REPLACE}, 515 { 516 "alternate", ALTERNATE}, 517 { 518 "partial", PARTIAL}, 519 { 520 "default", DEFAULT}, 521 { 522 "hidden", HIDDEN}, 523 { 524 "virtual_modifiers", VIRTUAL_MODS}, 525 { 526 "type", TYPE}, 527 { 528 "interpret", INTERPRET}, 529 { 530 "action", ACTION_TOK}, 531 { 532 "key", KEY}, 533 { 534 "alias", ALIAS}, 535 { 536 "group", GROUP}, 537 { 538 "modmap", MODIFIER_MAP}, 539 { 540 "mod_map", MODIFIER_MAP}, 541 { 542 "modifier_map", MODIFIER_MAP}, 543 { 544 "indicator", INDICATOR}, 545 { 546 "shape", SHAPE}, 547 { 548 "row", ROW}, 549 { 550 "keys", KEYS}, 551 { 552 "section", SECTION}, 553 { 554 "overlay", OVERLAY}, 555 { 556 "text", TEXT}, 557 { 558 "outline", OUTLINE}, 559 { 560 "solid", SOLID}, 561 { 562 "logo", LOGO}, 563 { 564 "virtual", VIRTUAL}, 565 { 566 "alphanumeric_keys", ALPHANUMERIC_KEYS}, 567 { 568 "modifier_keys", MODIFIER_KEYS}, 569 { 570 "keypad_keys", KEYPAD_KEYS}, 571 { 572 "function_keys", FUNCTION_KEYS}, 573 { 574 "alternate_group", ALTERNATE_GROUP} 575}; 576static int numKeywords = sizeof(keywords) / sizeof(struct _Keyword); 577 578static int 579yyGetIdent(int first) 580{ 581 int ch, j, found; 582 int rtrn = IDENT; 583 584 scanBuf[0] = first; 585 j = 1; 586 while (((ch = scanchar()) != EOF) && (isalnum(ch) || (ch == '_'))) 587 { 588 if (j < sizeof(scanBuf) - 1) 589 scanBuf[j++] = ch; 590 } 591 scanBuf[j++] = '\0'; 592 found = 0; 593 594 for (int i = 0; (!found) && (i < numKeywords); i++) 595 { 596 if (uStrCaseCmp(scanBuf, keywords[i].keyword) == 0) 597 { 598 rtrn = keywords[i].token; 599 found = 1; 600 } 601 } 602 if (!found) 603 { 604 scanStrLine = lineNum; 605 rtrn = IDENT; 606 } 607 608 if ((ch != EOF) && (!isspace(ch))) 609 unscanchar(ch); 610 else if (ch == '\n') 611 lineNum++; 612 613 return rtrn; 614} 615 616static int 617yyGetNumber(int ch) 618{ 619 const int nMaxBuffSize = 1024; 620 int isFloat = 0; 621 char buf[nMaxBuffSize]; 622 int nInBuf = 0; 623 624 buf[0] = ch; 625 nInBuf = 1; 626 while (((ch = scanchar()) != EOF) 627 && (isxdigit(ch) || ((nInBuf == 1) && (ch == 'x'))) 628 && nInBuf < (nMaxBuffSize - 1)) 629 { 630 buf[nInBuf++] = ch; 631 } 632 if ((ch == '.') && (nInBuf < (nMaxBuffSize - 1))) 633 { 634 isFloat = 1; 635 buf[nInBuf++] = ch; 636 while (((ch = scanchar()) != EOF) && (isxdigit(ch)) 637 && nInBuf < (nMaxBuffSize - 1)) 638 { 639 buf[nInBuf++] = ch; 640 } 641 } 642 buf[nInBuf++] = '\0'; 643 if ((ch != EOF) && (!isspace(ch))) 644 unscanchar(ch); 645 646 if (isFloat) 647 { 648 float tmp; 649 if (sscanf(buf, "%g", &tmp) == 1) 650 { 651 scanInt = tmp * XkbGeomPtsPerMM; 652 return FLOAT; 653 } 654 } 655 else if (sscanf(buf, "%i", &scanInt) == 1) 656 return INTEGER; 657 fprintf(stderr, "Malformed number %s\n", buf); 658 return ERROR_TOK; 659} 660 661int 662yylex(void) 663{ 664 int ch; 665 int rtrn; 666 667 do 668 { 669 ch = scanchar(); 670 if (ch == '\n') 671 { 672 lineNum++; 673 } 674 else if (ch == '#') 675 { /* handle shell style '#' comments */ 676 do 677 { 678 ch = scanchar(); 679 } 680 while ((ch != '\n') && (ch != EOF)); 681 lineNum++; 682 } 683 else if (ch == '/') 684 { /* handle C++ style double-/ comments */ 685 int newch = scanchar(); 686 if (newch == '/') 687 { 688 do 689 { 690 ch = scanchar(); 691 } 692 while ((ch != '\n') && (ch != EOF)); 693 lineNum++; 694 } 695 else if (newch != EOF) 696 { 697 unscanchar(newch); 698 } 699 } 700 } 701 while ((ch != EOF) && (isspace(ch))); 702 if (ch == '=') 703 rtrn = EQUALS; 704 else if (ch == '+') 705 rtrn = PLUS; 706 else if (ch == '-') 707 rtrn = MINUS; 708 else if (ch == '/') 709 rtrn = DIVIDE; 710 else if (ch == '*') 711 rtrn = TIMES; 712 else if (ch == '{') 713 rtrn = OBRACE; 714 else if (ch == '}') 715 rtrn = CBRACE; 716 else if (ch == '(') 717 rtrn = OPAREN; 718 else if (ch == ')') 719 rtrn = CPAREN; 720 else if (ch == '[') 721 rtrn = OBRACKET; 722 else if (ch == ']') 723 rtrn = CBRACKET; 724 else if (ch == '.') 725 rtrn = DOT; 726 else if (ch == ',') 727 rtrn = COMMA; 728 else if (ch == ';') 729 rtrn = SEMI; 730 else if (ch == '!') 731 rtrn = EXCLAM; 732 else if (ch == '~') 733 rtrn = INVERT; 734 else if (ch == '"') 735 rtrn = yyGetString(); 736 else if (ch == '<') 737 rtrn = yyGetKeyName(); 738 else if (isalpha(ch) || (ch == '_')) 739 rtrn = yyGetIdent(ch); 740 else if (isdigit(ch)) 741 rtrn = yyGetNumber(ch); 742 else if (ch == EOF) 743 rtrn = END_OF_FILE; 744 else 745 { 746#ifdef DEBUG 747 if (debugFlags) 748 fprintf(stderr, 749 "Unexpected character %c (%d) in input stream\n", ch, ch); 750#endif 751 rtrn = ERROR_TOK; 752 } 753#ifdef DEBUG 754 if (debugFlags & 0x2) 755 fprintf(stderr, "scan: %s\n", tokText(rtrn)); 756#endif 757 return rtrn; 758} 759