Interp: More lazy keysym resolution
[platform/upstream/libxkbcommon.git] / src / xkbcomp / parseutils.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 #define DEBUG_VAR parseDebug
28 #include "parseutils.h"
29 #include "xkbmisc.h"
30 #include "xkbpath.h"
31 #include <X11/keysym.h>
32 #include <X11/extensions/XKBgeomcommon.h>
33 #include <X11/Xalloca.h>
34
35 XkbFile *rtrnValue;
36
37 ParseCommon *
38 AppendStmt(ParseCommon * to, ParseCommon * append)
39 {
40     ParseCommon *start = to;
41
42     if (append == NULL)
43         return to;
44     while ((to != NULL) && (to->next != NULL))
45     {
46         to = to->next;
47     }
48     if (to)
49     {
50         to->next = append;
51         return start;
52     }
53     return append;
54 }
55
56 ExprDef *
57 ExprCreate(unsigned op, unsigned type)
58 {
59     ExprDef *expr;
60     expr = uTypedAlloc(ExprDef);
61     if (expr)
62     {
63         expr->common.stmtType = StmtExpr;
64         expr->common.next = NULL;
65         expr->op = op;
66         expr->type = type;
67     }
68     else
69     {
70         FATAL("Couldn't allocate expression in parser\n");
71         /* NOTREACHED */
72     }
73     return expr;
74 }
75
76 ExprDef *
77 ExprCreateUnary(unsigned op, unsigned type, ExprDef * child)
78 {
79     ExprDef *expr;
80     expr = uTypedAlloc(ExprDef);
81     if (expr)
82     {
83         expr->common.stmtType = StmtExpr;
84         expr->common.next = NULL;
85         expr->op = op;
86         expr->type = type;
87         expr->value.child = child;
88     }
89     else
90     {
91         FATAL("Couldn't allocate expression in parser\n");
92         /* NOTREACHED */
93     }
94     return expr;
95 }
96
97 ExprDef *
98 ExprCreateBinary(unsigned op, ExprDef * left, ExprDef * right)
99 {
100     ExprDef *expr;
101     expr = uTypedAlloc(ExprDef);
102     if (expr)
103     {
104         expr->common.stmtType = StmtExpr;
105         expr->common.next = NULL;
106         expr->op = op;
107         if ((op == OpAssign) || (left->type == TypeUnknown))
108             expr->type = right->type;
109         else if ((left->type == right->type) || (right->type == TypeUnknown))
110             expr->type = left->type;
111         else
112             expr->type = TypeUnknown;
113         expr->value.binary.left = left;
114         expr->value.binary.right = right;
115     }
116     else
117     {
118         FATAL("Couldn't allocate expression in parser\n");
119         /* NOTREACHED */
120     }
121     return expr;
122 }
123
124 KeycodeDef *
125 KeycodeCreate(char *name, ExprDef * value)
126 {
127     KeycodeDef *def;
128
129     def = uTypedAlloc(KeycodeDef);
130     if (def)
131     {
132         def->common.stmtType = StmtKeycodeDef;
133         def->common.next = NULL;
134         strncpy(def->name, name, XkbKeyNameLength);
135         def->name[XkbKeyNameLength] = '\0';
136         def->value = value;
137     }
138     else
139     {
140         FATAL("Couldn't allocate key name definition in parser\n");
141         /* NOTREACHED */
142     }
143     return def;
144 }
145
146 KeyAliasDef *
147 KeyAliasCreate(char *alias, char *real)
148 {
149     KeyAliasDef *def;
150
151     def = uTypedAlloc(KeyAliasDef);
152     if (def)
153     {
154         def->common.stmtType = StmtKeyAliasDef;
155         def->common.next = NULL;
156         strncpy(def->alias, alias, XkbKeyNameLength);
157         def->alias[XkbKeyNameLength] = '\0';
158         strncpy(def->real, real, XkbKeyNameLength);
159         def->real[XkbKeyNameLength] = '\0';
160     }
161     else
162     {
163         FATAL("Couldn't allocate key alias definition in parser\n");
164         /* NOTREACHED */
165     }
166     return def;
167 }
168
169 VModDef *
170 VModCreate(Atom name, ExprDef * value)
171 {
172     VModDef *def;
173     def = uTypedAlloc(VModDef);
174     if (def)
175     {
176         def->common.stmtType = StmtVModDef;
177         def->common.next = NULL;
178         def->name = name;
179         def->value = value;
180     }
181     else
182     {
183         FATAL("Couldn't allocate variable definition in parser\n");
184         /* NOTREACHED */
185     }
186     return def;
187 }
188
189 VarDef *
190 VarCreate(ExprDef * name, ExprDef * value)
191 {
192     VarDef *def;
193     def = uTypedAlloc(VarDef);
194     if (def)
195     {
196         def->common.stmtType = StmtVarDef;
197         def->common.next = NULL;
198         def->name = name;
199         def->value = value;
200     }
201     else
202     {
203         FATAL("Couldn't allocate variable definition in parser\n");
204         /* NOTREACHED */
205     }
206     return def;
207 }
208
209 VarDef *
210 BoolVarCreate(Atom nameToken, unsigned set)
211 {
212     ExprDef *name, *value;
213
214     name = ExprCreate(ExprIdent, TypeUnknown);
215     name->value.str = nameToken;
216     value = ExprCreate(ExprValue, TypeBoolean);
217     value->value.uval = set;
218     return VarCreate(name, value);
219 }
220
221 InterpDef *
222 InterpCreate(char *sym, ExprDef * match)
223 {
224     InterpDef *def;
225
226     def = uTypedAlloc(InterpDef);
227     if (def)
228     {
229         def->common.stmtType = StmtInterpDef;
230         def->common.next = NULL;
231         def->sym = strdup(sym);
232         def->match = match;
233     }
234     else
235     {
236         FATAL("Couldn't allocate interp definition in parser\n");
237         /* NOTREACHED */
238     }
239     return def;
240 }
241
242 KeyTypeDef *
243 KeyTypeCreate(Atom name, VarDef * body)
244 {
245     KeyTypeDef *def;
246
247     def = uTypedAlloc(KeyTypeDef);
248     if (def)
249     {
250         def->common.stmtType = StmtKeyTypeDef;
251         def->common.next = NULL;
252         def->merge = MergeDefault;
253         def->name = name;
254         def->body = body;
255     }
256     else
257     {
258         FATAL("Couldn't allocate key type definition in parser\n");
259         /* NOTREACHED */
260     }
261     return def;
262 }
263
264 SymbolsDef *
265 SymbolsCreate(char *keyName, ExprDef * symbols)
266 {
267     SymbolsDef *def;
268
269     def = uTypedAlloc(SymbolsDef);
270     if (def)
271     {
272         def->common.stmtType = StmtSymbolsDef;
273         def->common.next = NULL;
274         def->merge = MergeDefault;
275         bzero(def->keyName, 5);
276         strncpy(def->keyName, keyName, 4);
277         def->symbols = symbols;
278     }
279     else
280     {
281         FATAL("Couldn't allocate symbols definition in parser\n");
282         /* NOTREACHED */
283     }
284     return def;
285 }
286
287 GroupCompatDef *
288 GroupCompatCreate(int group, ExprDef * val)
289 {
290     GroupCompatDef *def;
291
292     def = uTypedAlloc(GroupCompatDef);
293     if (def)
294     {
295         def->common.stmtType = StmtGroupCompatDef;
296         def->common.next = NULL;
297         def->merge = MergeDefault;
298         def->group = group;
299         def->def = val;
300     }
301     else
302     {
303         FATAL("Couldn't allocate group compat definition in parser\n");
304         /* NOTREACHED */
305     }
306     return def;
307 }
308
309 ModMapDef *
310 ModMapCreate(Atom modifier, ExprDef * keys)
311 {
312     ModMapDef *def;
313
314     def = uTypedAlloc(ModMapDef);
315     if (def)
316     {
317         def->common.stmtType = StmtModMapDef;
318         def->common.next = NULL;
319         def->merge = MergeDefault;
320         def->modifier = modifier;
321         def->keys = keys;
322     }
323     else
324     {
325         FATAL("Couldn't allocate mod mask definition in parser\n");
326         /* NOTREACHED */
327     }
328     return def;
329 }
330
331 IndicatorMapDef *
332 IndicatorMapCreate(Atom name, VarDef * body)
333 {
334     IndicatorMapDef *def;
335
336     def = uTypedAlloc(IndicatorMapDef);
337     if (def)
338     {
339         def->common.stmtType = StmtIndicatorMapDef;
340         def->common.next = NULL;
341         def->merge = MergeDefault;
342         def->name = name;
343         def->body = body;
344     }
345     else
346     {
347         FATAL("Couldn't allocate indicator map definition in parser\n");
348         /* NOTREACHED */
349     }
350     return def;
351 }
352
353 IndicatorNameDef *
354 IndicatorNameCreate(int ndx, ExprDef * name, Bool virtual)
355 {
356     IndicatorNameDef *def;
357
358     def = uTypedAlloc(IndicatorNameDef);
359     if (def)
360     {
361         def->common.stmtType = StmtIndicatorNameDef;
362         def->common.next = NULL;
363         def->merge = MergeDefault;
364         def->ndx = ndx;
365         def->name = name;
366         def->virtual = virtual;
367     }
368     else
369     {
370         FATAL("Couldn't allocate indicator index definition in parser\n");
371         /* NOTREACHED */
372     }
373     return def;
374 }
375
376 ExprDef *
377 ActionCreate(Atom name, ExprDef * args)
378 {
379     ExprDef *act;
380
381     act = uTypedAlloc(ExprDef);
382     if (act)
383     {
384         act->common.stmtType = StmtExpr;
385         act->common.next = NULL;
386         act->op = ExprActionDecl;
387         act->value.action.name = name;
388         act->value.action.args = args;
389         return act;
390     }
391     FATAL("Couldn't allocate ActionDef in parser\n");
392     return NULL;
393 }
394
395 ExprDef *
396 CreateKeysymList(char *sym)
397 {
398     ExprDef *def;
399
400     def = ExprCreate(ExprKeysymList, TypeSymbols);
401     if (def)
402     {
403         def->value.list.nSyms = 1;
404         def->value.list.szSyms = 4;
405         def->value.list.syms = uTypedCalloc(4, char *);
406         if (def->value.list.syms != NULL)
407         {
408             def->value.list.syms[0] = sym;
409             return def;
410         }
411     }
412     FATAL("Couldn't allocate expression for keysym list in parser\n");
413     return NULL;
414 }
415
416 ShapeDef *
417 ShapeDeclCreate(Atom name, OutlineDef * outlines)
418 {
419     ShapeDef *shape;
420     OutlineDef *ol;
421
422     shape = uTypedAlloc(ShapeDef);
423     if (shape != NULL)
424     {
425         bzero(shape, sizeof(ShapeDef));
426         shape->common.stmtType = StmtShapeDef;
427         shape->common.next = NULL;
428         shape->merge = MergeDefault;
429         shape->name = name;
430         shape->nOutlines = 0;
431         shape->outlines = outlines;
432         for (ol = outlines; ol != NULL; ol = (OutlineDef *) ol->common.next)
433         {
434             if (ol->nPoints > 0)
435                 shape->nOutlines++;
436         }
437     }
438     return shape;
439 }
440
441 OutlineDef *
442 OutlineCreate(Atom field, ExprDef * points)
443 {
444     OutlineDef *outline;
445     ExprDef *pt;
446
447     outline = uTypedAlloc(OutlineDef);
448     if (outline != NULL)
449     {
450         bzero(outline, sizeof(OutlineDef));
451         outline->common.stmtType = StmtOutlineDef;
452         outline->common.next = NULL;
453         outline->field = field;
454         outline->nPoints = 0;
455         if (points->op == ExprCoord)
456         {
457             for (pt = points; pt != NULL; pt = (ExprDef *) pt->common.next)
458             {
459                 outline->nPoints++;
460             }
461         }
462         outline->points = points;
463     }
464     return outline;
465 }
466
467 KeyDef *
468 KeyDeclCreate(char *name, ExprDef * expr)
469 {
470     KeyDef *key;
471
472     key = uTypedAlloc(KeyDef);
473     if (key != NULL)
474     {
475         bzero(key, sizeof(KeyDef));
476         key->common.stmtType = StmtKeyDef;
477         key->common.next = NULL;
478         if (name)
479             key->name = name;
480         else
481             key->expr = expr;
482     }
483     return key;
484 }
485
486 KeyDef *
487 KeyDeclMerge(KeyDef * into, KeyDef * from)
488 {
489     into->expr =
490         (ExprDef *) AppendStmt(&into->expr->common, &from->expr->common);
491     from->expr = NULL;
492     uFree(from);
493     return into;
494 }
495
496 RowDef *
497 RowDeclCreate(KeyDef * keys)
498 {
499     RowDef *row;
500     KeyDef *key;
501
502     row = uTypedAlloc(RowDef);
503     if (row != NULL)
504     {
505         bzero(row, sizeof(RowDef));
506         row->common.stmtType = StmtRowDef;
507         row->common.next = NULL;
508         row->nKeys = 0;
509         row->keys = keys;
510         for (key = keys; key != NULL; key = (KeyDef *) key->common.next)
511         {
512             if (key->common.stmtType == StmtKeyDef)
513                 row->nKeys++;
514         }
515     }
516     return row;
517 }
518
519 SectionDef *
520 SectionDeclCreate(Atom name, RowDef * rows)
521 {
522     SectionDef *section;
523     RowDef *row;
524
525     section = uTypedAlloc(SectionDef);
526     if (section != NULL)
527     {
528         bzero(section, sizeof(SectionDef));
529         section->common.stmtType = StmtSectionDef;
530         section->common.next = NULL;
531         section->name = name;
532         section->nRows = 0;
533         section->rows = rows;
534         for (row = rows; row != NULL; row = (RowDef *) row->common.next)
535         {
536             if (row->common.stmtType == StmtRowDef)
537                 section->nRows++;
538         }
539     }
540     return section;
541 }
542
543 OverlayKeyDef *
544 OverlayKeyCreate(char *under, char *over)
545 {
546     OverlayKeyDef *key;
547
548     key = uTypedAlloc(OverlayKeyDef);
549     if (key != NULL)
550     {
551         bzero(key, sizeof(OverlayKeyDef));
552         key->common.stmtType = StmtOverlayKeyDef;
553         strncpy(key->over, over, XkbKeyNameLength);
554         strncpy(key->under, under, XkbKeyNameLength);
555         if (over)
556             uFree(over);
557         if (under)
558             uFree(under);
559     }
560     return key;
561 }
562
563 OverlayDef *
564 OverlayDeclCreate(Atom name, OverlayKeyDef * keys)
565 {
566     OverlayDef *ol;
567     OverlayKeyDef *key;
568
569     ol = uTypedAlloc(OverlayDef);
570     if (ol != NULL)
571     {
572         bzero(ol, sizeof(OverlayDef));
573         ol->common.stmtType = StmtOverlayDef;
574         ol->name = name;
575         ol->keys = keys;
576         for (key = keys; key != NULL;
577              key = (OverlayKeyDef *) key->common.next)
578         {
579             ol->nKeys++;
580         }
581     }
582     return ol;
583 }
584
585 DoodadDef *
586 DoodadCreate(unsigned type, Atom name, VarDef * body)
587 {
588     DoodadDef *doodad;
589
590     doodad = uTypedAlloc(DoodadDef);
591     if (doodad != NULL)
592     {
593         bzero(doodad, sizeof(DoodadDef));
594         doodad->common.stmtType = StmtDoodadDef;
595         doodad->common.next = NULL;
596         doodad->type = type;
597         doodad->name = name;
598         doodad->body = body;
599     }
600     return doodad;
601 }
602
603 ExprDef *
604 AppendKeysymList(ExprDef * list, char *sym)
605 {
606     if (list->value.list.nSyms >= list->value.list.szSyms)
607     {
608         list->value.list.szSyms *= 2;
609         list->value.list.syms = uTypedRecalloc(list->value.list.syms,
610                                                list->value.list.nSyms,
611                                                list->value.list.szSyms,
612                                                char *);
613         if (list->value.list.syms == NULL)
614         {
615             FATAL("Couldn't resize list of symbols for append\n");
616             return NULL;
617         }
618     }
619     list->value.list.syms[list->value.list.nSyms++] = sym;
620     return list;
621 }
622
623 int
624 LookupKeysym(char *str, CARD32 * sym_rtrn)
625 {
626     CARD32 sym;
627
628     if ((!str) || (uStrCaseCmp(str, "any") == 0)
629         || (uStrCaseCmp(str, "nosymbol") == 0))
630     {
631         *sym_rtrn = NoSymbol;
632         return 1;
633     }
634     else if ((uStrCaseCmp(str, "none") == 0)
635              || (uStrCaseCmp(str, "voidsymbol") == 0))
636     {
637         *sym_rtrn = XK_VoidSymbol;
638         return 1;
639     }
640     sym = XkbcStringToKeysym(str);
641     if (sym != NoSymbol)
642     {
643         *sym_rtrn = sym;
644         return 1;
645     }
646     return 0;
647 }
648
649 IncludeStmt *
650 IncludeCreate(char *str, unsigned merge)
651 {
652     IncludeStmt *incl, *first;
653     char *file, *map, *stmt, *tmp, *extra_data;
654     char nextop;
655     Bool haveSelf;
656
657     haveSelf = False;
658     incl = first = NULL;
659     file = map = NULL;
660     tmp = str;
661     stmt = _XkbDupString(str);
662     while ((tmp) && (*tmp))
663     {
664         if (XkbParseIncludeMap(&tmp, &file, &map, &nextop, &extra_data))
665         {
666             if ((file == NULL) && (map == NULL))
667             {
668                 if (haveSelf)
669                     goto BAIL;
670                 haveSelf = True;
671             }
672             if (first == NULL)
673                 first = incl = uTypedAlloc(IncludeStmt);
674             else
675             {
676                 incl->next = uTypedAlloc(IncludeStmt);
677                 incl = incl->next;
678             }
679             if (incl)
680             {
681                 incl->common.stmtType = StmtInclude;
682                 incl->common.next = NULL;
683                 incl->merge = merge;
684                 incl->stmt = NULL;
685                 incl->file = file;
686                 incl->map = map;
687                 incl->modifier = extra_data;
688                 incl->path = NULL;
689                 incl->next = NULL;
690             }
691             else
692             {
693                 WSGO("Allocation failure in IncludeCreate\n");
694                 ACTION("Using only part of the include\n");
695                 break;
696             }
697             if (nextop == '|')
698                 merge = MergeAugment;
699             else
700                 merge = MergeOverride;
701         }
702         else
703         {
704             goto BAIL;
705         }
706     }
707     if (first)
708         first->stmt = stmt;
709     else if (stmt)
710         uFree(stmt);
711     return first;
712   BAIL:
713     ERROR("Illegal include statement \"%s\"\n", stmt);
714     ACTION("Ignored\n");
715     while (first)
716     {
717         incl = first->next;
718         if (first->file)
719             uFree(first->file);
720         if (first->map)
721             uFree(first->map);
722         if (first->modifier)
723             uFree(first->modifier);
724         if (first->path)
725             uFree(first->path);
726         first->file = first->map = first->path = NULL;
727         uFree(first);
728         first = incl;
729     }
730     if (stmt)
731         uFree(stmt);
732     return NULL;
733 }
734
735 #ifdef DEBUG
736 void
737 PrintStmtAddrs(ParseCommon * stmt)
738 {
739     fprintf(stderr, "0x%x", stmt);
740     if (stmt)
741     {
742         do
743         {
744             fprintf(stderr, "->0x%x", stmt->next);
745             stmt = stmt->next;
746         }
747         while (stmt);
748     }
749     fprintf(stderr, "\n");
750 }
751 #endif
752
753 static void
754 CheckDefaultMap(XkbFile * maps)
755 {
756     XkbFile *dflt, *tmp;
757
758     dflt = NULL;
759     for (tmp = maps, dflt = NULL; tmp != NULL;
760          tmp = (XkbFile *) tmp->common.next)
761     {
762         if (tmp->flags & XkbLC_Default)
763         {
764             if (dflt == NULL)
765                 dflt = tmp;
766             else
767             {
768                 if (warningLevel > 2)
769                 {
770                     WARN("Multiple default components in %s\n",
771                           (scanFile ? scanFile : "(unknown)"));
772                     ACTION("Using %s, ignoring %s\n",
773                             (dflt->name ? dflt->name : "(first)"),
774                             (tmp->name ? tmp->name : "(subsequent)"));
775                 }
776                 tmp->flags &= (~XkbLC_Default);
777             }
778         }
779     }
780     return;
781 }
782
783 int
784 XKBParseFile(FILE * file, XkbFile ** pRtrn)
785 {
786     if (file)
787     {
788         yyin = file;
789         rtrnValue = NULL;
790         if (yyparse() == 0)
791         {
792             *pRtrn = rtrnValue;
793             CheckDefaultMap(rtrnValue);
794             rtrnValue = NULL;
795             return 1;
796         }
797         *pRtrn = NULL;
798         return 0;
799     }
800     *pRtrn = NULL;
801     return 1;
802 }
803
804 XkbFile *
805 CreateXKBFile(int type, char *name, ParseCommon * defs, unsigned flags)
806 {
807     XkbFile *file;
808     static int fileID;
809
810     file = uTypedAlloc(XkbFile);
811     if (file)
812     {
813         XkbcEnsureSafeMapName(name);
814         bzero(file, sizeof(XkbFile));
815         file->type = type;
816         file->topName = _XkbDupString(name);
817         file->name = name;
818         file->defs = defs;
819         file->id = fileID++;
820         file->compiled = False;
821         file->flags = flags;
822     }
823     return file;
824 }
825
826 unsigned
827 StmtSetMerge(ParseCommon * stmt, unsigned merge)
828 {
829     if ((merge == MergeAltForm) && (stmt->stmtType != StmtKeycodeDef))
830     {
831         yyerror("illegal use of 'alternate' merge mode");
832         merge = MergeDefault;
833     }
834     return merge;
835 }