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