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