parseutils.c revision 83e5f723
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#include <limits.h>
34#include <stdlib.h>
35
36XkbFile *rtrnValue;
37
38ParseCommon *
39AppendStmt(ParseCommon * to, ParseCommon * append)
40{
41    ParseCommon *start = to;
42
43    if (append == NULL)
44        return to;
45    while ((to != NULL) && (to->next != NULL))
46    {
47        to = to->next;
48    }
49    if (to)
50    {
51        to->next = append;
52        return start;
53    }
54    return append;
55}
56
57ExprDef *
58ExprCreate(unsigned op, unsigned type)
59{
60    ExprDef *expr;
61    expr = uTypedAlloc(ExprDef);
62    if (expr)
63    {
64        expr->common.stmtType = StmtExpr;
65        expr->common.next = NULL;
66        expr->op = op;
67        expr->type = type;
68    }
69    else
70    {
71        FATAL("Couldn't allocate expression in parser\n");
72        /* NOTREACHED */
73    }
74    return expr;
75}
76
77ExprDef *
78ExprCreateUnary(unsigned op, unsigned type, ExprDef * child)
79{
80    ExprDef *expr;
81    expr = uTypedAlloc(ExprDef);
82    if (expr)
83    {
84        expr->common.stmtType = StmtExpr;
85        expr->common.next = NULL;
86        expr->op = op;
87        expr->type = type;
88        expr->value.child = child;
89    }
90    else
91    {
92        FATAL("Couldn't allocate expression in parser\n");
93        /* NOTREACHED */
94    }
95    return expr;
96}
97
98ExprDef *
99ExprCreateBinary(unsigned op, ExprDef * left, ExprDef * right)
100{
101    ExprDef *expr;
102    expr = uTypedAlloc(ExprDef);
103    if (expr)
104    {
105        expr->common.stmtType = StmtExpr;
106        expr->common.next = NULL;
107        expr->op = op;
108        if ((op == OpAssign) || (left->type == TypeUnknown))
109            expr->type = right->type;
110        else if ((left->type == right->type) || (right->type == TypeUnknown))
111            expr->type = left->type;
112        else
113            expr->type = TypeUnknown;
114        expr->value.binary.left = left;
115        expr->value.binary.right = right;
116    }
117    else
118    {
119        FATAL("Couldn't allocate expression in parser\n");
120        /* NOTREACHED */
121    }
122    return expr;
123}
124
125KeycodeDef *
126KeycodeCreate(char *name, ExprDef * value)
127{
128    KeycodeDef *def;
129
130    def = uTypedAlloc(KeycodeDef);
131    if (def)
132    {
133        def->common.stmtType = StmtKeycodeDef;
134        def->common.next = NULL;
135        strncpy(def->name, name, XkbKeyNameLength);
136        def->name[XkbKeyNameLength] = '\0';
137        def->value = value;
138    }
139    else
140    {
141        FATAL("Couldn't allocate key name definition in parser\n");
142        /* NOTREACHED */
143    }
144    return def;
145}
146
147KeyAliasDef *
148KeyAliasCreate(char *alias, char *real)
149{
150    KeyAliasDef *def;
151
152    def = uTypedAlloc(KeyAliasDef);
153    if (def)
154    {
155        def->common.stmtType = StmtKeyAliasDef;
156        def->common.next = NULL;
157        strncpy(def->alias, alias, XkbKeyNameLength);
158        def->alias[XkbKeyNameLength] = '\0';
159        strncpy(def->real, real, XkbKeyNameLength);
160        def->real[XkbKeyNameLength] = '\0';
161    }
162    else
163    {
164        FATAL("Couldn't allocate key alias definition in parser\n");
165        /* NOTREACHED */
166    }
167    return def;
168}
169
170VModDef *
171VModCreate(Atom name, ExprDef * value)
172{
173    VModDef *def;
174    def = uTypedAlloc(VModDef);
175    if (def)
176    {
177        def->common.stmtType = StmtVModDef;
178        def->common.next = NULL;
179        def->name = name;
180        def->value = value;
181    }
182    else
183    {
184        FATAL("Couldn't allocate variable definition in parser\n");
185        /* NOTREACHED */
186    }
187    return def;
188}
189
190VarDef *
191VarCreate(ExprDef * name, ExprDef * value)
192{
193    VarDef *def;
194    def = uTypedAlloc(VarDef);
195    if (def)
196    {
197        def->common.stmtType = StmtVarDef;
198        def->common.next = NULL;
199        def->name = name;
200        def->value = value;
201    }
202    else
203    {
204        FATAL("Couldn't allocate variable definition in parser\n");
205        /* NOTREACHED */
206    }
207    return def;
208}
209
210VarDef *
211BoolVarCreate(Atom nameToken, unsigned set)
212{
213    ExprDef *name, *value;
214
215    name = ExprCreate(ExprIdent, TypeUnknown);
216    name->value.str = nameToken;
217    value = ExprCreate(ExprValue, TypeBoolean);
218    value->value.uval = set;
219    return VarCreate(name, value);
220}
221
222InterpDef *
223InterpCreate(KeySym sym, ExprDef * match)
224{
225    InterpDef *def;
226
227    def = uTypedAlloc(InterpDef);
228    if (def)
229    {
230        def->common.stmtType = StmtInterpDef;
231        def->common.next = NULL;
232        def->sym = sym;
233        def->match = match;
234    }
235    else
236    {
237        FATAL("Couldn't allocate interp definition in parser\n");
238        /* NOTREACHED */
239    }
240    return def;
241}
242
243KeyTypeDef *
244KeyTypeCreate(Atom name, VarDef * body)
245{
246    KeyTypeDef *def;
247
248    def = uTypedAlloc(KeyTypeDef);
249    if (def)
250    {
251        def->common.stmtType = StmtKeyTypeDef;
252        def->common.next = NULL;
253        def->merge = MergeDefault;
254        def->name = name;
255        def->body = body;
256    }
257    else
258    {
259        FATAL("Couldn't allocate key type definition in parser\n");
260        /* NOTREACHED */
261    }
262    return def;
263}
264
265SymbolsDef *
266SymbolsCreate(char *keyName, ExprDef * symbols)
267{
268    SymbolsDef *def;
269
270    def = uTypedAlloc(SymbolsDef);
271    if (def)
272    {
273        def->common.stmtType = StmtSymbolsDef;
274        def->common.next = NULL;
275        def->merge = MergeDefault;
276        bzero(def->keyName, 5);
277        strncpy(def->keyName, keyName, 4);
278        def->symbols = symbols;
279    }
280    else
281    {
282        FATAL("Couldn't allocate symbols definition in parser\n");
283        /* NOTREACHED */
284    }
285    return def;
286}
287
288GroupCompatDef *
289GroupCompatCreate(int group, ExprDef * val)
290{
291    GroupCompatDef *def;
292
293    def = uTypedAlloc(GroupCompatDef);
294    if (def)
295    {
296        def->common.stmtType = StmtGroupCompatDef;
297        def->common.next = NULL;
298        def->merge = MergeDefault;
299        def->group = group;
300        def->def = val;
301    }
302    else
303    {
304        FATAL("Couldn't allocate group compat definition in parser\n");
305        /* NOTREACHED */
306    }
307    return def;
308}
309
310ModMapDef *
311ModMapCreate(Atom modifier, ExprDef * keys)
312{
313    ModMapDef *def;
314
315    def = uTypedAlloc(ModMapDef);
316    if (def)
317    {
318        def->common.stmtType = StmtModMapDef;
319        def->common.next = NULL;
320        def->merge = MergeDefault;
321        def->modifier = modifier;
322        def->keys = keys;
323    }
324    else
325    {
326        FATAL("Couldn't allocate mod mask definition in parser\n");
327        /* NOTREACHED */
328    }
329    return def;
330}
331
332IndicatorMapDef *
333IndicatorMapCreate(Atom name, VarDef * body)
334{
335    IndicatorMapDef *def;
336
337    def = uTypedAlloc(IndicatorMapDef);
338    if (def)
339    {
340        def->common.stmtType = StmtIndicatorMapDef;
341        def->common.next = NULL;
342        def->merge = MergeDefault;
343        def->name = name;
344        def->body = body;
345    }
346    else
347    {
348        FATAL("Couldn't allocate indicator map definition in parser\n");
349        /* NOTREACHED */
350    }
351    return def;
352}
353
354IndicatorNameDef *
355IndicatorNameCreate(int ndx, ExprDef * name, Bool virtual)
356{
357    IndicatorNameDef *def;
358
359    def = uTypedAlloc(IndicatorNameDef);
360    if (def)
361    {
362        def->common.stmtType = StmtIndicatorNameDef;
363        def->common.next = NULL;
364        def->merge = MergeDefault;
365        def->ndx = ndx;
366        def->name = name;
367        def->virtual = virtual;
368    }
369    else
370    {
371        FATAL("Couldn't allocate indicator index definition in parser\n");
372        /* NOTREACHED */
373    }
374    return def;
375}
376
377ExprDef *
378ActionCreate(Atom name, ExprDef * args)
379{
380    ExprDef *act;
381
382    act = uTypedAlloc(ExprDef);
383    if (act)
384    {
385        act->common.stmtType = StmtExpr;
386        act->common.next = NULL;
387        act->op = ExprActionDecl;
388        act->value.action.name = name;
389        act->value.action.args = args;
390        return act;
391    }
392    FATAL("Couldn't allocate ActionDef in parser\n");
393    return NULL;
394}
395
396ExprDef *
397CreateKeysymList(char *sym)
398{
399    ExprDef *def;
400
401    def = ExprCreate(ExprKeysymList, TypeSymbols);
402    if (def)
403    {
404        def->value.list.nSyms = 1;
405        def->value.list.szSyms = 4;
406        def->value.list.syms = uTypedCalloc(4, char *);
407        if (def->value.list.syms != NULL)
408        {
409            def->value.list.syms[0] = sym;
410            return def;
411        }
412    }
413    FATAL("Couldn't allocate expression for keysym list in parser\n");
414    return NULL;
415}
416
417ShapeDef *
418ShapeDeclCreate(Atom name, OutlineDef * outlines)
419{
420    ShapeDef *shape;
421    OutlineDef *ol;
422
423    shape = uTypedAlloc(ShapeDef);
424    if (shape != NULL)
425    {
426        bzero(shape, sizeof(ShapeDef));
427        shape->common.stmtType = StmtShapeDef;
428        shape->common.next = NULL;
429        shape->merge = MergeDefault;
430        shape->name = name;
431        shape->nOutlines = 0;
432        shape->outlines = outlines;
433        for (ol = outlines; ol != NULL; ol = (OutlineDef *) ol->common.next)
434        {
435            if (ol->nPoints > 0)
436                shape->nOutlines++;
437        }
438    }
439    return shape;
440}
441
442OutlineDef *
443OutlineCreate(Atom field, ExprDef * points)
444{
445    OutlineDef *outline;
446    ExprDef *pt;
447
448    outline = uTypedAlloc(OutlineDef);
449    if (outline != NULL)
450    {
451        bzero(outline, sizeof(OutlineDef));
452        outline->common.stmtType = StmtOutlineDef;
453        outline->common.next = NULL;
454        outline->field = field;
455        outline->nPoints = 0;
456        if (points->op == ExprCoord)
457        {
458            for (pt = points; pt != NULL; pt = (ExprDef *) pt->common.next)
459            {
460                outline->nPoints++;
461            }
462        }
463        outline->points = points;
464    }
465    return outline;
466}
467
468KeyDef *
469KeyDeclCreate(char *name, ExprDef * expr)
470{
471    KeyDef *key;
472
473    key = uTypedAlloc(KeyDef);
474    if (key != NULL)
475    {
476        bzero(key, sizeof(KeyDef));
477        key->common.stmtType = StmtKeyDef;
478        key->common.next = NULL;
479        if (name)
480            key->name = name;
481        else
482            key->expr = expr;
483    }
484    return key;
485}
486
487KeyDef *
488KeyDeclMerge(KeyDef * into, KeyDef * from)
489{
490    into->expr =
491        (ExprDef *) AppendStmt(&into->expr->common, &from->expr->common);
492    from->expr = NULL;
493    uFree(from);
494    return into;
495}
496
497RowDef *
498RowDeclCreate(KeyDef * keys)
499{
500    RowDef *row;
501    KeyDef *key;
502
503    row = uTypedAlloc(RowDef);
504    if (row != NULL)
505    {
506        bzero(row, sizeof(RowDef));
507        row->common.stmtType = StmtRowDef;
508        row->common.next = NULL;
509        row->nKeys = 0;
510        row->keys = keys;
511        for (key = keys; key != NULL; key = (KeyDef *) key->common.next)
512        {
513            if (key->common.stmtType == StmtKeyDef)
514                row->nKeys++;
515        }
516    }
517    return row;
518}
519
520SectionDef *
521SectionDeclCreate(Atom name, RowDef * rows)
522{
523    SectionDef *section;
524    RowDef *row;
525
526    section = uTypedAlloc(SectionDef);
527    if (section != NULL)
528    {
529        bzero(section, sizeof(SectionDef));
530        section->common.stmtType = StmtSectionDef;
531        section->common.next = NULL;
532        section->name = name;
533        section->nRows = 0;
534        section->rows = rows;
535        for (row = rows; row != NULL; row = (RowDef *) row->common.next)
536        {
537            if (row->common.stmtType == StmtRowDef)
538                section->nRows++;
539        }
540    }
541    return section;
542}
543
544OverlayKeyDef *
545OverlayKeyCreate(char *under, char *over)
546{
547    OverlayKeyDef *key;
548
549    key = uTypedAlloc(OverlayKeyDef);
550    if (key != NULL)
551    {
552        bzero(key, sizeof(OverlayKeyDef));
553        key->common.stmtType = StmtOverlayKeyDef;
554        strncpy(key->over, over, XkbKeyNameLength);
555        strncpy(key->under, under, XkbKeyNameLength);
556        if (over)
557            uFree(over);
558        if (under)
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(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, "0x%x", stmt);
749    if (stmt)
750    {
751        do
752        {
753            fprintf(stderr, "->0x%x", 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        yyin = 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