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
37 FILE *yyin = NULL;
38
39 static char scanFileBuf[1024];
40 char *scanFile = scanFileBuf;
41 int lineNum = 0;
42
43 int scanInt;
44 char *scanIntStr;
45 int scanIntClass;
46
47 char *scanStr = NULL;
48 int scanStrLine = 0;
49
50 #define BUFSIZE 512
51 static int nInBuf = 0;
52 static char buf[BUFSIZE];
53
54 #ifdef DEBUG
55
56 extern unsigned debugFlags;
57
58 static char *
tokText(int tok)59 tokText(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
173 int
setScanState(const char * file,int line)174 setScanState(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
183 static int
yyGetString(void)184 yyGetString(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
254 static int
yyGetKeyName(void)255 yyGetKeyName(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
325 static 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 };
339 static int numKeywords = sizeof(keywords) / sizeof(struct _Keyword);
340
341 static int
yyGetIdent(int first)342 yyGetIdent(int first)
343 {
344 int ch, i, found;
345
346 int rtrn = -1;
347
348 buf[0] = first;
349 nInBuf = 1;
350 while (((ch = getc(yyin)) != EOF) && (isalnum(ch) || (ch == '_'))) {
351 if (nInBuf < BUFSIZE - 1)
352 buf[nInBuf++] = ch;
353 }
354 buf[nInBuf++] = '\0';
355 found = 0;
356
357 for (i = 0; (!found) && (i < numKeywords); i++) {
358 if (uStrCaseCmp(buf, keywords[i].keyword) == 0) {
359 rtrn = keywords[i].token;
360 found = 1;
361 }
362 }
363 if (!found) {
364 if (scanStr)
365 free(scanStr);
366 scanStr = uStringDup(buf);
367 scanStrLine = lineNum;
368 rtrn = IDENT;
369 }
370
371 if ((ch != EOF) && (!isspace(ch)))
372 ungetc(ch, yyin);
373 else if (ch == '\n')
374 lineNum++;
375
376 return rtrn;
377 }
378
379 static int
yyGetNumber(int ch)380 yyGetNumber(int ch)
381 {
382 int isFloat = 0;
383
384 buf[0] = ch;
385 nInBuf = 1;
386 while (((ch = getc(yyin)) != EOF) &&
387 (isxdigit(ch) || ((nInBuf == 1) && (ch == 'x')))) {
388 buf[nInBuf++] = ch;
389 }
390 if (ch == '.') {
391 isFloat = 1;
392 buf[nInBuf++] = ch;
393 while (((ch = getc(yyin)) != EOF) && (isxdigit(ch))) {
394 buf[nInBuf++] = ch;
395 }
396 }
397 buf[nInBuf++] = '\0';
398 if ((ch != EOF) && (!isspace(ch)))
399 ungetc(ch, yyin);
400
401 if (isFloat) {
402 float tmp;
403
404 if (sscanf(buf, "%g", &tmp) == 1) {
405 scanInt = tmp * XkbGeomPtsPerMM;
406 return FLOAT;
407 }
408 }
409 else if (sscanf(buf, "%i", &scanInt) == 1)
410 return INTEGER;
411 fprintf(stderr, "Malformed number %s\n", buf);
412 return ERROR;
413 }
414
415 int
yylex(void)416 yylex(void)
417 {
418 int ch;
419 int rtrn;
420
421 do {
422 ch = getc(yyin);
423 if (ch == '\n') {
424 lineNum++;
425 }
426 else if (ch == '/') { /* handle C++ style double-/ comments */
427 int newch = getc(yyin);
428
429 if (newch == '/') {
430 do {
431 ch = getc(yyin);
432 } while ((ch != '\n') && (ch != EOF));
433 lineNum++;
434 }
435 else if (newch != EOF) {
436 ungetc(newch, yyin);
437 }
438 }
439 } while ((ch != EOF) && (isspace(ch)));
440 if (ch == '=')
441 rtrn = EQUALS;
442 else if (ch == '+')
443 rtrn = PLUS;
444 else if (ch == '-')
445 rtrn = MINUS;
446 else if (ch == '/')
447 rtrn = DIVIDE;
448 else if (ch == '*')
449 rtrn = TIMES;
450 else if (ch == '{')
451 rtrn = OBRACE;
452 else if (ch == '}')
453 rtrn = CBRACE;
454 else if (ch == '(')
455 rtrn = OPAREN;
456 else if (ch == ')')
457 rtrn = CPAREN;
458 else if (ch == '[')
459 rtrn = OBRACKET;
460 else if (ch == ']')
461 rtrn = CBRACKET;
462 else if (ch == '.')
463 rtrn = DOT;
464 else if (ch == ',')
465 rtrn = COMMA;
466 else if (ch == ';')
467 rtrn = SEMI;
468 else if (ch == '!')
469 rtrn = EXCLAM;
470 else if (ch == '~')
471 rtrn = INVERT;
472 else if (ch == '"')
473 rtrn = yyGetString();
474 else if (ch == '<')
475 rtrn = yyGetKeyName();
476 else if (isalpha(ch) || (ch == '_'))
477 rtrn = yyGetIdent(ch);
478 else if (isdigit(ch))
479 rtrn = yyGetNumber(ch);
480 else if (ch == EOF)
481 rtrn = END_OF_FILE;
482 else {
483 fprintf(stderr, "Unexpected character %c (%d) in input stream\n",
484 ch, ch);
485 rtrn = ERROR;
486 }
487 #ifdef DEBUG
488 if (debugFlags & 0x2)
489 fprintf(stderr, "scan: %s\n", tokText(rtrn));
490 #endif
491 return rtrn;
492 }
493