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 <stdio.h> 28#include <stdlib.h> 29#include <ctype.h> 30#include <X11/Xos.h> 31#include <X11/X.h> 32#include <X11/extensions/XKB.h> 33 34#include "tokens.h" 35#include "xkbevd.h" 36 37FILE *yyin = NULL; 38 39static char scanFileBuf[1024]; 40char *scanFile = scanFileBuf; 41int lineNum = 0; 42 43int scanInt; 44char *scanIntStr; 45int scanIntClass; 46 47char *scanStr = NULL; 48int scanStrLine = 0; 49 50#define BUFSIZE 512 51static int nInBuf = 0; 52static char buf[BUFSIZE]; 53 54#ifdef DEBUG 55 56extern unsigned debugFlags; 57 58static char * 59tokText(int tok) 60{ 61 static char buf[32]; 62 63 switch (tok) { 64 case END_OF_FILE: 65 snprintf(buf, sizeof(buf), "END_OF_FILE"); 66 break; 67 case ERROR: 68 snprintf(buf, sizeof(buf), "ERROR"); 69 break; 70 71 case BELL: 72 snprintf(buf, sizeof(buf), "BELL"); 73 break; 74 case ACCESSX: 75 snprintf(buf, sizeof(buf), "ACCESSX"); 76 break; 77 case MESSAGE: 78 snprintf(buf, sizeof(buf), "MESSAGE"); 79 break; 80 81 case NONE: 82 snprintf(buf, sizeof(buf), "NONE"); 83 break; 84 case IGNORE: 85 snprintf(buf, sizeof(buf), "IGNORE"); 86 break; 87 case ECHO: 88 snprintf(buf, sizeof(buf), "ECHO"); 89 break; 90 case PRINT_EV: 91 snprintf(buf, sizeof(buf), "PRINT_EV"); 92 break; 93 case SHELL: 94 snprintf(buf, sizeof(buf), "SHELL"); 95 break; 96 case SOUND: 97 snprintf(buf, sizeof(buf), "SOUND"); 98 break; 99 100 case EQUALS: 101 snprintf(buf, sizeof(buf), "EQUALS"); 102 break; 103 case PLUS: 104 snprintf(buf, sizeof(buf), "PLUS"); 105 break; 106 case MINUS: 107 snprintf(buf, sizeof(buf), "MINUS"); 108 break; 109 case DIVIDE: 110 snprintf(buf, sizeof(buf), "DIVIDE"); 111 break; 112 case TIMES: 113 snprintf(buf, sizeof(buf), "TIMES"); 114 break; 115 case OBRACE: 116 snprintf(buf, sizeof(buf), "OBRACE"); 117 break; 118 case CBRACE: 119 snprintf(buf, sizeof(buf), "CBRACE"); 120 break; 121 case OPAREN: 122 snprintf(buf, sizeof(buf), "OPAREN"); 123 break; 124 case CPAREN: 125 snprintf(buf, sizeof(buf), "CPAREN"); 126 break; 127 case OBRACKET: 128 snprintf(buf, sizeof(buf), "OBRACKET"); 129 break; 130 case CBRACKET: 131 snprintf(buf, sizeof(buf), "CBRACKET"); 132 break; 133 case DOT: 134 snprintf(buf, sizeof(buf), "DOT"); 135 break; 136 case COMMA: 137 snprintf(buf, sizeof(buf), "COMMA"); 138 break; 139 case SEMI: 140 snprintf(buf, sizeof(buf), "SEMI"); 141 break; 142 case EXCLAM: 143 snprintf(buf, sizeof(buf), "EXCLAM"); 144 break; 145 case INVERT: 146 snprintf(buf, sizeof(buf), "INVERT"); 147 break; 148 149 case STRING: 150 snprintf(buf, sizeof(buf), "STRING (%s)", scanStr); 151 break; 152 case INTEGER: 153 snprintf(buf, sizeof(buf), "INTEGER (0x%x)", scanInt); 154 break; 155 case FLOAT: 156 snprintf(buf, sizeof(buf), "FLOAT (%d.%d)", 157 scanInt / XkbGeomPtsPerMM, scanInt % XkbGeomPtsPerMM); 158 break; 159 case IDENT: 160 snprintf(buf, sizeof(buf), "IDENT (%s)", scanStr); 161 break; 162 case KEYNAME: 163 snprintf(buf, sizeof(buf), "KEYNAME (%s)", scanStr); 164 break; 165 default: 166 snprintf(buf, sizeof(buf), "UNKNOWN"); 167 break; 168 } 169 return buf; 170} 171#endif 172 173int 174setScanState(const char *file, int line) 175{ 176 if (file != NULL) 177 strncpy(scanFile, file, 1024); 178 if (line >= 0) 179 lineNum = line; 180 return 1; 181} 182 183static int 184yyGetString(void) 185{ 186 int ch; 187 188 nInBuf = 0; 189 while (((ch = getc(yyin)) != EOF) && (ch != '"')) { 190 if (ch == '\\') { 191 if ((ch = getc(yyin)) != EOF) { 192 if (ch == 'n') 193 ch = '\n'; 194 else if (ch == 't') 195 ch = '\t'; 196 else if (ch == 'v') 197 ch = '\v'; 198 else if (ch == 'b') 199 ch = '\b'; 200 else if (ch == 'r') 201 ch = '\r'; 202 else if (ch == 'f') 203 ch = '\f'; 204 else if (ch == 'e') 205 ch = '\033'; 206 else if (ch == '0') { 207 int tmp, stop; 208 209 ch = stop = 0; 210 if (((tmp = getc(yyin)) != EOF) && (isdigit(tmp)) && 211 (tmp != '8') && (tmp != '9')) { 212 ch = (ch * 8) + (tmp - '0'); 213 } 214 else { 215 stop = 1; 216 ungetc(tmp, yyin); 217 } 218 if ((!stop) && ((tmp = getc(yyin)) != EOF) && (isdigit(tmp)) 219 && (tmp != '8') && (tmp != '9')) { 220 ch = (ch * 8) + (tmp - '0'); 221 } 222 else { 223 stop = 1; 224 ungetc(tmp, yyin); 225 } 226 if ((!stop) && ((tmp = getc(yyin)) != EOF) && (isdigit(tmp)) 227 && (tmp != '8') && (tmp != '9')) { 228 ch = (ch * 8) + (tmp - '0'); 229 } 230 else { 231 stop = 1; 232 ungetc(tmp, yyin); 233 } 234 } 235 } 236 else 237 return ERROR; 238 } 239 240 if (nInBuf < BUFSIZE - 1) 241 buf[nInBuf++] = ch; 242 } 243 if (ch == '"') { 244 buf[nInBuf++] = '\0'; 245 if (scanStr) 246 free(scanStr); 247 scanStr = uStringDup(buf); 248 scanStrLine = lineNum; 249 return STRING; 250 } 251 return ERROR; 252} 253 254static int 255yyGetKeyName(void) 256{ 257 int ch; 258 259 nInBuf = 0; 260 while (((ch = getc(yyin)) != EOF) && (ch != '>')) { 261 if (ch == '\\') { 262 if ((ch = getc(yyin)) != EOF) { 263 if (ch == 'n') 264 ch = '\n'; 265 else if (ch == 't') 266 ch = '\t'; 267 else if (ch == 'v') 268 ch = '\v'; 269 else if (ch == 'b') 270 ch = '\b'; 271 else if (ch == 'r') 272 ch = '\r'; 273 else if (ch == 'f') 274 ch = '\f'; 275 else if (ch == 'e') 276 ch = '\033'; 277 else if (ch == '0') { 278 int tmp, stop; 279 280 ch = stop = 0; 281 if (((tmp = getc(yyin)) != EOF) && (isdigit(tmp)) && 282 (tmp != '8') && (tmp != '9')) { 283 ch = (ch * 8) + (tmp - '0'); 284 } 285 else { 286 stop = 1; 287 ungetc(tmp, yyin); 288 } 289 if ((!stop) && ((tmp = getc(yyin)) != EOF) && (isdigit(tmp)) 290 && (tmp != '8') && (tmp != '9')) { 291 ch = (ch * 8) + (tmp - '0'); 292 } 293 else { 294 stop = 1; 295 ungetc(tmp, yyin); 296 } 297 if ((!stop) && ((tmp = getc(yyin)) != EOF) && (isdigit(tmp)) 298 && (tmp != '8') && (tmp != '9')) { 299 ch = (ch * 8) + (tmp - '0'); 300 } 301 else { 302 stop = 1; 303 ungetc(tmp, yyin); 304 } 305 } 306 } 307 else 308 return ERROR; 309 } 310 311 if (nInBuf < BUFSIZE - 1) 312 buf[nInBuf++] = ch; 313 } 314 if ((ch == '>') && (nInBuf < 5)) { 315 buf[nInBuf++] = '\0'; 316 if (scanStr) 317 free(scanStr); 318 scanStr = uStringDup(buf); 319 scanStrLine = lineNum; 320 return KEYNAME; 321 } 322 return ERROR; 323} 324 325static struct _Keyword { 326 const char *keyword; 327 int token; 328} keywords[] = { 329 { "bell", BELL }, 330 { "accessx", ACCESSX }, 331 { "message", MESSAGE }, 332 { "none", NONE }, 333 { "ignore", IGNORE }, 334 { "echo", ECHO }, 335 { "printevent", PRINT_EV }, 336 { "shell", SHELL }, 337 { "sound", SOUND } 338}; 339static int numKeywords = sizeof(keywords) / sizeof(struct _Keyword); 340 341static int 342yyGetIdent(int first) 343{ 344 int ch, found; 345 int rtrn = -1; 346 347 buf[0] = first; 348 nInBuf = 1; 349 while (((ch = getc(yyin)) != EOF) && (isalnum(ch) || (ch == '_'))) { 350 if (nInBuf < BUFSIZE - 1) 351 buf[nInBuf++] = ch; 352 } 353 buf[nInBuf++] = '\0'; 354 found = 0; 355 356 for (int i = 0; (!found) && (i < numKeywords); i++) { 357 if (uStrCaseCmp(buf, keywords[i].keyword) == 0) { 358 rtrn = keywords[i].token; 359 found = 1; 360 } 361 } 362 if (!found) { 363 if (scanStr) 364 free(scanStr); 365 scanStr = uStringDup(buf); 366 scanStrLine = lineNum; 367 rtrn = IDENT; 368 } 369 370 if ((ch != EOF) && (!isspace(ch))) 371 ungetc(ch, yyin); 372 else if (ch == '\n') 373 lineNum++; 374 375 return rtrn; 376} 377 378static int 379yyGetNumber(int ch) 380{ 381 int isFloat = 0; 382 383 buf[0] = ch; 384 nInBuf = 1; 385 while (((ch = getc(yyin)) != EOF) && 386 (isxdigit(ch) || ((nInBuf == 1) && (ch == 'x')))) { 387 buf[nInBuf++] = ch; 388 } 389 if (ch == '.') { 390 isFloat = 1; 391 buf[nInBuf++] = ch; 392 while (((ch = getc(yyin)) != EOF) && (isxdigit(ch))) { 393 buf[nInBuf++] = ch; 394 } 395 } 396 buf[nInBuf++] = '\0'; 397 if ((ch != EOF) && (!isspace(ch))) 398 ungetc(ch, yyin); 399 400 if (isFloat) { 401 float tmp; 402 403 if (sscanf(buf, "%g", &tmp) == 1) { 404 scanInt = tmp * XkbGeomPtsPerMM; 405 return FLOAT; 406 } 407 } 408 else if (sscanf(buf, "%i", &scanInt) == 1) 409 return INTEGER; 410 fprintf(stderr, "Malformed number %s\n", buf); 411 return ERROR; 412} 413 414int 415yylex(void) 416{ 417 int ch; 418 int rtrn; 419 420 do { 421 ch = getc(yyin); 422 if (ch == '\n') { 423 lineNum++; 424 } 425 else if (ch == '/') { /* handle C++ style double-/ comments */ 426 int newch = getc(yyin); 427 428 if (newch == '/') { 429 do { 430 ch = getc(yyin); 431 } while ((ch != '\n') && (ch != EOF)); 432 lineNum++; 433 } 434 else if (newch != EOF) { 435 ungetc(newch, yyin); 436 } 437 } 438 } while ((ch != EOF) && (isspace(ch))); 439 if (ch == '=') 440 rtrn = EQUALS; 441 else if (ch == '+') 442 rtrn = PLUS; 443 else if (ch == '-') 444 rtrn = MINUS; 445 else if (ch == '/') 446 rtrn = DIVIDE; 447 else if (ch == '*') 448 rtrn = TIMES; 449 else if (ch == '{') 450 rtrn = OBRACE; 451 else if (ch == '}') 452 rtrn = CBRACE; 453 else if (ch == '(') 454 rtrn = OPAREN; 455 else if (ch == ')') 456 rtrn = CPAREN; 457 else if (ch == '[') 458 rtrn = OBRACKET; 459 else if (ch == ']') 460 rtrn = CBRACKET; 461 else if (ch == '.') 462 rtrn = DOT; 463 else if (ch == ',') 464 rtrn = COMMA; 465 else if (ch == ';') 466 rtrn = SEMI; 467 else if (ch == '!') 468 rtrn = EXCLAM; 469 else if (ch == '~') 470 rtrn = INVERT; 471 else if (ch == '"') 472 rtrn = yyGetString(); 473 else if (ch == '<') 474 rtrn = yyGetKeyName(); 475 else if (ch == EOF) 476 rtrn = END_OF_FILE; 477 else if (isalpha(ch) || (ch == '_')) 478 rtrn = yyGetIdent(ch); 479 else if (isdigit(ch)) 480 rtrn = yyGetNumber(ch); 481 else { 482 fprintf(stderr, "Unexpected character %c (%d) in input stream\n", 483 ch, ch); 484 rtrn = ERROR; 485 } 486#ifdef DEBUG 487 if (debugFlags & 0x2) 488 fprintf(stderr, "scan: %s\n", tokText(rtrn)); 489#endif 490 return rtrn; 491} 492