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