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