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