parseutils.c revision 3fb1fa07
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 "xkbpath.h"
30#include <X11/keysym.h>
31#include <X11/extensions/XKBgeom.h>
32#include <limits.h>
33#include <stdlib.h>
34
35XkbFile *rtrnValue;
36
37ParseCommon *
38AppendStmt(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
56ExprDef *
57ExprCreate(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
76ExprDef *
77ExprCreateUnary(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
97ExprDef *
98ExprCreateBinary(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
124KeycodeDef *
125KeycodeCreate(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
146KeyAliasDef *
147KeyAliasCreate(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
169VModDef *
170VModCreate(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
189VarDef *
190VarCreate(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
209VarDef *
210BoolVarCreate(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
221InterpDef *
222InterpCreate(const char *sym_str, 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        if (LookupKeysym(sym_str, &def->sym) == 0)
232            def->ignore = True;
233        else
234            def->ignore = False;
235        def->match = match;
236    }
237    else
238    {
239        FATAL("Couldn't allocate interp definition in parser\n");
240        /* NOTREACHED */
241    }
242    return def;
243}
244
245KeyTypeDef *
246KeyTypeCreate(Atom name, VarDef * body)
247{
248    KeyTypeDef *def;
249
250    def = uTypedAlloc(KeyTypeDef);
251    if (def)
252    {
253        def->common.stmtType = StmtKeyTypeDef;
254        def->common.next = NULL;
255        def->merge = MergeDefault;
256        def->name = name;
257        def->body = body;
258    }
259    else
260    {
261        FATAL("Couldn't allocate key type definition in parser\n");
262        /* NOTREACHED */
263    }
264    return def;
265}
266
267SymbolsDef *
268SymbolsCreate(char *keyName, ExprDef * symbols)
269{
270    SymbolsDef *def;
271
272    def = uTypedAlloc(SymbolsDef);
273    if (def)
274    {
275        def->common.stmtType = StmtSymbolsDef;
276        def->common.next = NULL;
277        def->merge = MergeDefault;
278        bzero(def->keyName, 5);
279        strncpy(def->keyName, keyName, 4);
280        def->symbols = symbols;
281    }
282    else
283    {
284        FATAL("Couldn't allocate symbols definition in parser\n");
285        /* NOTREACHED */
286    }
287    return def;
288}
289
290GroupCompatDef *
291GroupCompatCreate(int group, ExprDef * val)
292{
293    GroupCompatDef *def;
294
295    def = uTypedAlloc(GroupCompatDef);
296    if (def)
297    {
298        def->common.stmtType = StmtGroupCompatDef;
299        def->common.next = NULL;
300        def->merge = MergeDefault;
301        def->group = group;
302        def->def = val;
303    }
304    else
305    {
306        FATAL("Couldn't allocate group compat definition in parser\n");
307        /* NOTREACHED */
308    }
309    return def;
310}
311
312ModMapDef *
313ModMapCreate(Atom modifier, ExprDef * keys)
314{
315    ModMapDef *def;
316
317    def = uTypedAlloc(ModMapDef);
318    if (def)
319    {
320        def->common.stmtType = StmtModMapDef;
321        def->common.next = NULL;
322        def->merge = MergeDefault;
323        def->modifier = modifier;
324        def->keys = keys;
325    }
326    else
327    {
328        FATAL("Couldn't allocate mod mask definition in parser\n");
329        /* NOTREACHED */
330    }
331    return def;
332}
333
334IndicatorMapDef *
335IndicatorMapCreate(Atom name, VarDef * body)
336{
337    IndicatorMapDef *def;
338
339    def = uTypedAlloc(IndicatorMapDef);
340    if (def)
341    {
342        def->common.stmtType = StmtIndicatorMapDef;
343        def->common.next = NULL;
344        def->merge = MergeDefault;
345        def->name = name;
346        def->body = body;
347    }
348    else
349    {
350        FATAL("Couldn't allocate indicator map definition in parser\n");
351        /* NOTREACHED */
352    }
353    return def;
354}
355
356IndicatorNameDef *
357IndicatorNameCreate(int ndx, ExprDef * name, Bool virtual)
358{
359    IndicatorNameDef *def;
360
361    def = uTypedAlloc(IndicatorNameDef);
362    if (def)
363    {
364        def->common.stmtType = StmtIndicatorNameDef;
365        def->common.next = NULL;
366        def->merge = MergeDefault;
367        def->ndx = ndx;
368        def->name = name;
369        def->virtual = virtual;
370    }
371    else
372    {
373        FATAL("Couldn't allocate indicator index definition in parser\n");
374        /* NOTREACHED */
375    }
376    return def;
377}
378
379ExprDef *
380ActionCreate(Atom name, ExprDef * args)
381{
382    ExprDef *act;
383
384    act = uTypedAlloc(ExprDef);
385    if (act)
386    {
387        act->common.stmtType = StmtExpr;
388        act->common.next = NULL;
389        act->op = ExprActionDecl;
390        act->value.action.name = name;
391        act->value.action.args = args;
392        return act;
393    }
394    FATAL("Couldn't allocate ActionDef in parser\n");
395    return NULL;
396}
397
398ExprDef *
399CreateKeysymList(char *sym)
400{
401    ExprDef *def;
402
403    def = ExprCreate(ExprKeysymList, TypeSymbols);
404    if (def)
405    {
406        def->value.list.nSyms = 1;
407        def->value.list.szSyms = 4;
408        def->value.list.syms = uTypedCalloc(4, char *);
409        if (def->value.list.syms != NULL)
410        {
411            def->value.list.syms[0] = sym;
412            return def;
413        }
414    }
415    FATAL("Couldn't allocate expression for keysym list in parser\n");
416    return NULL;
417}
418
419ShapeDef *
420ShapeDeclCreate(Atom name, OutlineDef * outlines)
421{
422    ShapeDef *shape;
423    OutlineDef *ol;
424
425    shape = uTypedAlloc(ShapeDef);
426    if (shape != NULL)
427    {
428        bzero(shape, sizeof(ShapeDef));
429        shape->common.stmtType = StmtShapeDef;
430        shape->common.next = NULL;
431        shape->merge = MergeDefault;
432        shape->name = name;
433        shape->nOutlines = 0;
434        shape->outlines = outlines;
435        for (ol = outlines; ol != NULL; ol = (OutlineDef *) ol->common.next)
436        {
437            if (ol->nPoints > 0)
438                shape->nOutlines++;
439        }
440    }
441    return shape;
442}
443
444OutlineDef *
445OutlineCreate(Atom field, ExprDef * points)
446{
447    OutlineDef *outline;
448    ExprDef *pt;
449
450    outline = uTypedAlloc(OutlineDef);
451    if (outline != NULL)
452    {
453        bzero(outline, sizeof(OutlineDef));
454        outline->common.stmtType = StmtOutlineDef;
455        outline->common.next = NULL;
456        outline->field = field;
457        outline->nPoints = 0;
458        if (points->op == ExprCoord)
459        {
460            for (pt = points; pt != NULL; pt = (ExprDef *) pt->common.next)
461            {
462                outline->nPoints++;
463            }
464        }
465        outline->points = points;
466    }
467    return outline;
468}
469
470KeyDef *
471KeyDeclCreate(char *name, ExprDef * expr)
472{
473    KeyDef *key;
474
475    key = uTypedAlloc(KeyDef);
476    if (key != NULL)
477    {
478        bzero(key, sizeof(KeyDef));
479        key->common.stmtType = StmtKeyDef;
480        key->common.next = NULL;
481        if (name)
482            key->name = name;
483        else
484            key->expr = expr;
485    }
486    return key;
487}
488
489KeyDef *
490KeyDeclMerge(KeyDef * into, KeyDef * from)
491{
492    into->expr =
493        (ExprDef *) AppendStmt(&into->expr->common, &from->expr->common);
494    from->expr = NULL;
495    uFree(from);
496    return into;
497}
498
499RowDef *
500RowDeclCreate(KeyDef * keys)
501{
502    RowDef *row;
503    KeyDef *key;
504
505    row = uTypedAlloc(RowDef);
506    if (row != NULL)
507    {
508        bzero(row, sizeof(RowDef));
509        row->common.stmtType = StmtRowDef;
510        row->common.next = NULL;
511        row->nKeys = 0;
512        row->keys = keys;
513        for (key = keys; key != NULL; key = (KeyDef *) key->common.next)
514        {
515            if (key->common.stmtType == StmtKeyDef)
516                row->nKeys++;
517        }
518    }
519    return row;
520}
521
522SectionDef *
523SectionDeclCreate(Atom name, RowDef * rows)
524{
525    SectionDef *section;
526    RowDef *row;
527
528    section = uTypedAlloc(SectionDef);
529    if (section != NULL)
530    {
531        bzero(section, sizeof(SectionDef));
532        section->common.stmtType = StmtSectionDef;
533        section->common.next = NULL;
534        section->name = name;
535        section->nRows = 0;
536        section->rows = rows;
537        for (row = rows; row != NULL; row = (RowDef *) row->common.next)
538        {
539            if (row->common.stmtType == StmtRowDef)
540                section->nRows++;
541        }
542    }
543    return section;
544}
545
546OverlayKeyDef *
547OverlayKeyCreate(char *under, char *over)
548{
549    OverlayKeyDef *key;
550
551    key = uTypedAlloc(OverlayKeyDef);
552    if (key != NULL)
553    {
554        bzero(key, sizeof(OverlayKeyDef));
555        key->common.stmtType = StmtOverlayKeyDef;
556        strncpy(key->over, over, XkbKeyNameLength);
557        strncpy(key->under, under, XkbKeyNameLength);
558        uFree(over);
559        uFree(under);
560    }
561    return key;
562}
563
564OverlayDef *
565OverlayDeclCreate(Atom name, OverlayKeyDef * keys)
566{
567    OverlayDef *ol;
568    OverlayKeyDef *key;
569
570    ol = uTypedAlloc(OverlayDef);
571    if (ol != NULL)
572    {
573        bzero(ol, sizeof(OverlayDef));
574        ol->common.stmtType = StmtOverlayDef;
575        ol->name = name;
576        ol->keys = keys;
577        for (key = keys; key != NULL;
578             key = (OverlayKeyDef *) key->common.next)
579        {
580            ol->nKeys++;
581        }
582    }
583    return ol;
584}
585
586DoodadDef *
587DoodadCreate(unsigned type, Atom name, VarDef * body)
588{
589    DoodadDef *doodad;
590
591    doodad = uTypedAlloc(DoodadDef);
592    if (doodad != NULL)
593    {
594        bzero(doodad, sizeof(DoodadDef));
595        doodad->common.stmtType = StmtDoodadDef;
596        doodad->common.next = NULL;
597        doodad->type = type;
598        doodad->name = name;
599        doodad->body = body;
600    }
601    return doodad;
602}
603
604ExprDef *
605AppendKeysymList(ExprDef * list, char *sym)
606{
607    if (list->value.list.nSyms >= list->value.list.szSyms)
608    {
609        list->value.list.szSyms *= 2;
610        list->value.list.syms = uTypedRecalloc(list->value.list.syms,
611                                               list->value.list.nSyms,
612                                               list->value.list.szSyms,
613                                               char *);
614        if (list->value.list.syms == NULL)
615        {
616            FATAL("Couldn't resize list of symbols for append\n");
617            return NULL;
618        }
619    }
620    list->value.list.syms[list->value.list.nSyms++] = sym;
621    return list;
622}
623
624int
625LookupKeysym(const char *str, KeySym * sym_rtrn)
626{
627    KeySym sym;
628    char *tmp;
629
630    if ((!str) || (uStrCaseCmp(str, "any") == 0)
631        || (uStrCaseCmp(str, "nosymbol") == 0))
632    {
633        *sym_rtrn = NoSymbol;
634        return 1;
635    }
636    else if ((uStrCaseCmp(str, "none") == 0)
637             || (uStrCaseCmp(str, "voidsymbol") == 0))
638    {
639        *sym_rtrn = XK_VoidSymbol;
640        return 1;
641    }
642    sym = XStringToKeysym(str);
643    if (sym != NoSymbol)
644    {
645        *sym_rtrn = sym;
646        return 1;
647    }
648    if (strlen(str) > 2 && str[0] == '0' && str[1] == 'x') {
649        sym = strtoul(str, &tmp, 16);
650        if (sym != ULONG_MAX && (!tmp || *tmp == '\0')) {
651            *sym_rtrn = sym;
652            return 1;
653        }
654    }
655    return 0;
656}
657
658IncludeStmt *
659IncludeCreate(char *str, unsigned merge)
660{
661    IncludeStmt *incl, *first;
662    char *file, *map, *stmt, *tmp, *extra_data;
663    char nextop;
664    Bool haveSelf;
665
666    haveSelf = False;
667    incl = first = NULL;
668    file = map = NULL;
669    tmp = str;
670    stmt = uStringDup(str);
671    while ((tmp) && (*tmp))
672    {
673        if (XkbParseIncludeMap(&tmp, &file, &map, &nextop, &extra_data))
674        {
675            if ((file == NULL) && (map == NULL))
676            {
677                if (haveSelf)
678                    goto BAIL;
679                haveSelf = True;
680            }
681            if (first == NULL)
682                first = incl = uTypedAlloc(IncludeStmt);
683            else
684            {
685                incl->next = uTypedAlloc(IncludeStmt);
686                incl = incl->next;
687            }
688            if (incl)
689            {
690                incl->common.stmtType = StmtInclude;
691                incl->common.next = NULL;
692                incl->merge = merge;
693                incl->stmt = NULL;
694                incl->file = file;
695                incl->map = map;
696                incl->modifier = extra_data;
697                incl->path = NULL;
698                incl->next = NULL;
699            }
700            else
701            {
702                WSGO("Allocation failure in IncludeCreate\n");
703                ACTION("Using only part of the include\n");
704                break;
705            }
706            if (nextop == '|')
707                merge = MergeAugment;
708            else
709                merge = MergeOverride;
710        }
711        else
712        {
713            goto BAIL;
714        }
715    }
716    if (first)
717        first->stmt = stmt;
718    else if (stmt)
719        uFree(stmt);
720    return first;
721  BAIL:
722    ERROR1("Illegal include statement \"%s\"\n", stmt);
723    ACTION("Ignored\n");
724    while (first)
725    {
726        incl = first->next;
727        if (first->file)
728            uFree(first->file);
729        if (first->map)
730            uFree(first->map);
731        if (first->modifier)
732            uFree(first->modifier);
733        if (first->path)
734            uFree(first->path);
735        first->file = first->map = first->path = NULL;
736        uFree(first);
737        first = incl;
738    }
739    if (stmt)
740        uFree(stmt);
741    return NULL;
742}
743
744#ifdef DEBUG
745void
746PrintStmtAddrs(ParseCommon * stmt)
747{
748    fprintf(stderr, "%p", stmt);
749    if (stmt)
750    {
751        do
752        {
753            fprintf(stderr, "->%p", stmt->next);
754            stmt = stmt->next;
755        }
756        while (stmt);
757    }
758    fprintf(stderr, "\n");
759}
760#endif
761
762static void
763CheckDefaultMap(XkbFile * maps)
764{
765    XkbFile *dflt, *tmp;
766
767    dflt = NULL;
768    for (tmp = maps, dflt = NULL; tmp != NULL;
769         tmp = (XkbFile *) tmp->common.next)
770    {
771        if (tmp->flags & XkbLC_Default)
772        {
773            if (dflt == NULL)
774                dflt = tmp;
775            else
776            {
777                if (warningLevel > 2)
778                {
779                    WARN1("Multiple default components in %s\n",
780                          (scanFile ? scanFile : "(unknown)"));
781                    ACTION2("Using %s, ignoring %s\n",
782                            (dflt->name ? dflt->name : "(first)"),
783                            (tmp->name ? tmp->name : "(subsequent)"));
784                }
785                tmp->flags &= (~XkbLC_Default);
786            }
787        }
788    }
789    return;
790}
791
792int
793XKBParseFile(FILE * file, XkbFile ** pRtrn)
794{
795    if (file)
796    {
797        scan_set_file(file);
798        rtrnValue = NULL;
799        if (yyparse() == 0)
800        {
801            *pRtrn = rtrnValue;
802            CheckDefaultMap(rtrnValue);
803            rtrnValue = NULL;
804            return 1;
805        }
806        *pRtrn = NULL;
807        return 0;
808    }
809    *pRtrn = NULL;
810    return 1;
811}
812
813XkbFile *
814CreateXKBFile(int type, char *name, ParseCommon * defs, unsigned flags)
815{
816    XkbFile *file;
817    static int fileID;
818
819    file = uTypedAlloc(XkbFile);
820    if (file)
821    {
822        XkbEnsureSafeMapName(name);
823        bzero(file, sizeof(XkbFile));
824        file->type = type;
825        file->topName = uStringDup(name);
826        file->name = name;
827        file->defs = defs;
828        file->id = fileID++;
829        file->compiled = False;
830        file->flags = flags;
831    }
832    return file;
833}
834
835unsigned
836StmtSetMerge(ParseCommon * stmt, unsigned merge)
837{
838    if ((merge == MergeAltForm) && (stmt->stmtType != StmtKeycodeDef))
839    {
840        yyerror("illegal use of 'alternate' merge mode");
841        merge = MergeDefault;
842    }
843    return merge;
844}
845