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