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#include "xkbcomp.h"
28#include "tokens.h"
29#include "expr.h"
30#include "vmod.h"
31#include "action.h"
32#include "misc.h"
33#include "indicators.h"
34
35#define	KEYCODES	0
36#define	GEOMETRY	1
37#define	TYPES		2
38#define	COMPAT		3
39#define	SYMBOLS		4
40#define	MAX_SECTIONS	5
41
42static XkbFile *sections[MAX_SECTIONS];
43
44/**
45 * Compile the given file and store the output in result.
46 * @param file A list of XkbFiles, each denoting one type (e.g.
47 * XkmKeyNamesIdx, etc.)
48 */
49Bool
50CompileKeymap(XkbFile * file, XkbFileInfo * result, unsigned merge)
51{
52    unsigned have;
53    Bool ok;
54    unsigned required, legal;
55    unsigned mainType;
56    char *mainName;
57    LEDInfo *unbound = NULL;
58
59    bzero(sections, MAX_SECTIONS * sizeof(XkbFile *));
60    mainType = file->type;
61    mainName = file->name;
62    switch (mainType)
63    {
64    case XkmSemanticsFile:
65        required = XkmSemanticsRequired;
66        legal = XkmSemanticsLegal;
67        break;
68    case XkmLayoutFile:        /* standard type  if setxkbmap -print */
69        required = XkmLayoutRequired;
70        legal = XkmKeymapLegal;
71        break;
72    case XkmKeymapFile:
73        required = XkmKeymapRequired;
74        legal = XkmKeymapLegal;
75        break;
76    default:
77        ERROR("Cannot compile %s alone into an XKM file\n",
78               XkbConfigText(mainType, XkbMessage));
79        return False;
80    }
81    have = 0;
82    ok = 1;
83    file = (XkbFile *) file->defs;
84    /* Check for duplicate entries in the input file */
85    while ((file) && (ok))
86    {
87        file->topName = mainName;
88        if ((have & (1U << file->type)) != 0)
89        {
90            ERROR("More than one %s section in a %s file\n",
91                   XkbConfigText(file->type, XkbMessage),
92                   XkbConfigText(mainType, XkbMessage));
93            ACTION("All sections after the first ignored\n");
94            ok = False;
95        }
96        else if ((1U << file->type) & (~legal))
97        {
98            ERROR("Cannot define %s in a %s file\n",
99                   XkbConfigText(file->type, XkbMessage),
100                   XkbConfigText(mainType, XkbMessage));
101            ok = False;
102        }
103        else
104            switch (file->type)
105            {
106            case XkmSemanticsFile:
107            case XkmLayoutFile:
108            case XkmKeymapFile:
109                WSGO("Illegal %s configuration in a %s file\n",
110                      XkbConfigText(file->type, XkbMessage),
111                      XkbConfigText(mainType, XkbMessage));
112                ACTION("Ignored\n");
113                ok = False;
114                break;
115            case XkmKeyNamesIndex:
116                sections[KEYCODES] = file;
117                break;
118            case XkmTypesIndex:
119                sections[TYPES] = file;
120                break;
121            case XkmSymbolsIndex:
122                sections[SYMBOLS] = file;
123                break;
124            case XkmCompatMapIndex:
125                sections[COMPAT] = file;
126                break;
127            case XkmGeometryIndex:
128            case XkmGeometryFile:
129                sections[GEOMETRY] = file;
130                break;
131            case XkmVirtualModsIndex:
132            case XkmIndicatorsIndex:
133                WSGO("Found an isolated %s section\n",
134                      XkbConfigText(file->type, XkbMessage));
135                break;
136            default:
137                WSGO("Unknown file type %d\n", file->type);
138                break;
139            }
140        if (ok)
141            have |= (1U << file->type);
142        file = (XkbFile *) file->common.next;
143    }
144    /* compile the sections we have in the file one-by-one, or fail. */
145    if (ok)
146    {
147        if (ok && (sections[KEYCODES] != NULL))
148            ok = CompileKeycodes(sections[KEYCODES], result, MergeOverride);
149        if (ok && (sections[GEOMETRY] != NULL))
150            ok = CompileGeometry(sections[GEOMETRY], result, MergeOverride);
151        if (ok && (sections[TYPES] != NULL))
152            ok = CompileKeyTypes(sections[TYPES], result, MergeOverride);
153        if (ok && (sections[COMPAT] != NULL))
154            ok = CompileCompatMap(sections[COMPAT], result, MergeOverride,
155                                  &unbound);
156        if (ok && (sections[SYMBOLS] != NULL))
157            ok = CompileSymbols(sections[SYMBOLS], result, MergeOverride);
158    }
159    if (!ok)
160        return False;
161    result->defined = have;
162    if (required & (~have))
163    {
164        int i, bit;
165        unsigned missing;
166        missing = required & (~have);
167        for (i = 0, bit = 1; missing != 0; i++, bit <<= 1)
168        {
169            if (missing & bit)
170            {
171                ERROR("Missing %s section in a %s file\n",
172                       XkbConfigText(i, XkbMessage),
173                       XkbConfigText(mainType, XkbMessage));
174                missing &= ~bit;
175            }
176        }
177        ACTION("Description of %s not compiled\n",
178                XkbConfigText(mainType, XkbMessage));
179        ok = False;
180    }
181    ok = BindIndicators(result, True, unbound, NULL);
182    return ok;
183}
184