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