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