cfgscan.c revision 9ff100ac
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, 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
379static int
380yyGetNumber(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
415int
416yylex(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