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