Move enum xkb_file_type to xkbcomp/ast.h
[platform/upstream/libxkbcommon.git] / src / xkbcomp / xkbcomp.c
1 /*
2  * Copyright 2009  Dan Nicholson
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * Except as contained in this notice, the names of the authors or their
22  * institutions shall not be used in advertising or otherwise to promote the
23  * sale, use or other dealings in this Software without prior written
24  * authorization from the authors.
25  */
26
27 #include "xkbcomp-priv.h"
28 #include "rules.h"
29
30 typedef bool (*compile_file_fn)(XkbFile *file,
31                                 struct xkb_keymap *keymap,
32                                 enum merge_mode merge);
33
34 static const compile_file_fn compile_file_fns[LAST_KEYMAP_FILE_TYPE + 1] = {
35     [FILE_TYPE_KEYCODES] = CompileKeycodes,
36     [FILE_TYPE_TYPES] = CompileKeyTypes,
37     [FILE_TYPE_COMPAT] = CompileCompatMap,
38     [FILE_TYPE_SYMBOLS] = CompileSymbols,
39 };
40
41 static struct xkb_keymap *
42 compile_keymap_file(struct xkb_context *ctx, XkbFile *file)
43 {
44     bool ok;
45     const char *main_name;
46     struct xkb_keymap *keymap;
47     XkbFile *files[LAST_KEYMAP_FILE_TYPE + 1] = { NULL };
48     enum xkb_file_type type;
49
50     keymap = xkb_map_new(ctx);
51     if (!keymap)
52         goto err;
53
54     main_name = file->name ? file->name : "(unnamed)";
55
56     if (file->file_type != FILE_TYPE_KEYMAP) {
57         log_err(ctx, "Cannot compile a %s file alone into a keymap\n",
58                 xkb_file_type_to_string(file->file_type));
59         goto err;
60     }
61
62     /* Collect section files and check for duplicates. */
63     for (file = (XkbFile *) file->defs; file;
64          file = (XkbFile *) file->common.next) {
65         if (file->file_type < FIRST_KEYMAP_FILE_TYPE ||
66             file->file_type > LAST_KEYMAP_FILE_TYPE) {
67             log_err(ctx, "Cannot define %s in a keymap file\n",
68                     xkb_file_type_to_string(file->file_type));
69             continue;
70         }
71
72         if (files[file->file_type]) {
73             log_err(ctx,
74                     "More than one %s section in keymap file; "
75                     "All sections after the first ignored\n",
76                     xkb_file_type_to_string(file->file_type));
77             continue;
78         }
79
80         if (!file->topName) {
81             free(file->topName);
82             file->topName = strdup(main_name);
83         }
84
85         files[file->file_type] = file;
86     }
87
88     /*
89      * Check that all required section were provided.
90      * Report everything before failing.
91      */
92     ok = true;
93     for (type = FIRST_KEYMAP_FILE_TYPE;
94          type <= LAST_KEYMAP_FILE_TYPE;
95          type++) {
96         if (files[type] == NULL) {
97             log_err(ctx, "Required section %s missing from keymap\n",
98                     xkb_file_type_to_string(type));
99             ok = false;
100         }
101     }
102     if (!ok)
103         goto err;
104
105     /* Compile sections. */
106     for (type = FIRST_KEYMAP_FILE_TYPE;
107          type <= LAST_KEYMAP_FILE_TYPE;
108          type++) {
109         log_dbg(ctx, "Compiling %s \"%s\"\n",
110                 xkb_file_type_to_string(type), files[type]->topName);
111         ok = compile_file_fns[type](files[type], keymap, MERGE_OVERRIDE);
112         if (!ok) {
113             log_err(ctx, "Failed to compile %s\n",
114                     xkb_file_type_to_string(type));
115             goto err;
116         }
117     }
118
119     ok = UpdateModifiersFromCompat(keymap);
120     if (!ok)
121         goto err;
122
123     return keymap;
124
125 err:
126     log_err(ctx, "Failed to compile keymap\n");
127     xkb_map_unref(keymap);
128     return NULL;
129 }
130
131 XKB_EXPORT struct xkb_keymap *
132 xkb_map_new_from_names(struct xkb_context *ctx,
133                        const struct xkb_rule_names *rmlvo_in,
134                        enum xkb_map_compile_flags flags)
135 {
136     bool ok;
137     struct xkb_component_names kccgst;
138     struct xkb_rule_names rmlvo = *rmlvo_in;
139     XkbFile *file;
140     struct xkb_keymap *keymap;
141
142     if (isempty(rmlvo.rules))
143         rmlvo.rules = DEFAULT_XKB_RULES;
144     if (isempty(rmlvo.model))
145         rmlvo.model = DEFAULT_XKB_MODEL;
146     if (isempty(rmlvo.layout))
147         rmlvo.layout = DEFAULT_XKB_LAYOUT;
148
149     ok = xkb_components_from_rules(ctx, &rmlvo, &kccgst);
150     if (!ok) {
151         log_err(ctx,
152                 "Couldn't look up rules '%s', model '%s', layout '%s', "
153                 "variant '%s', options '%s'\n",
154                 rmlvo.rules, rmlvo.model, rmlvo.layout, rmlvo.variant,
155                 rmlvo.options);
156         return NULL;
157     }
158
159     file = XkbFileFromComponents(ctx, &kccgst);
160
161     free(kccgst.keycodes);
162     free(kccgst.types);
163     free(kccgst.compat);
164     free(kccgst.symbols);
165
166     if (!file) {
167         log_err(ctx,
168                 "Failed to generate parsed XKB file from components\n");
169         return NULL;
170     }
171
172     keymap = compile_keymap_file(ctx, file);
173     FreeXkbFile(file);
174     return keymap;
175 }
176
177 XKB_EXPORT struct xkb_keymap *
178 xkb_map_new_from_string(struct xkb_context *ctx,
179                         const char *string,
180                         enum xkb_keymap_format format,
181                         enum xkb_map_compile_flags flags)
182 {
183     bool ok;
184     XkbFile *file;
185     struct xkb_keymap *keymap;
186
187     if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
188         log_err(ctx, "Unsupported keymap format %d\n", format);
189         return NULL;
190     }
191
192     if (!string) {
193         log_err(ctx, "No string specified to generate XKB keymap\n");
194         return NULL;
195     }
196
197     ok = XkbParseString(ctx, string, "input", &file);
198     if (!ok) {
199         log_err(ctx, "Failed to parse input xkb file\n");
200         return NULL;
201     }
202
203     keymap = compile_keymap_file(ctx, file);
204     FreeXkbFile(file);
205     return keymap;
206 }
207
208 XKB_EXPORT struct xkb_keymap *
209 xkb_map_new_from_file(struct xkb_context *ctx,
210                       FILE *file,
211                       enum xkb_keymap_format format,
212                       enum xkb_map_compile_flags flags)
213 {
214     bool ok;
215     XkbFile *xkb_file;
216     struct xkb_keymap *keymap;
217
218     if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
219         log_err(ctx, "Unsupported keymap format %d\n", format);
220         return NULL;
221     }
222
223     if (!file) {
224         log_err(ctx, "No file specified to generate XKB keymap\n");
225         return NULL;
226     }
227
228     ok = XkbParseFile(ctx, file, "(unknown file)", &xkb_file);
229     if (!ok) {
230         log_err(ctx, "Failed to parse input xkb file\n");
231         return NULL;
232     }
233
234     keymap = compile_keymap_file(ctx, xkb_file);
235     FreeXkbFile(xkb_file);
236     return keymap;
237 }