Reduce variable scopes
[platform/upstream/libxkbcommon.git] / src / xkbcomp / types.c
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-priv.h"
28 #include "text.h"
29 #include "vmod.h"
30 #include "expr.h"
31 #include "include.h"
32
33 enum type_field {
34     TYPE_FIELD_MASK = (1 << 0),
35     TYPE_FIELD_MAP = (1 << 1),
36     TYPE_FIELD_PRESERVE = (1 << 2),
37     TYPE_FIELD_LEVEL_NAME = (1 << 3),
38 };
39
40 typedef struct {
41     enum type_field defined;
42     enum merge_mode merge;
43
44     xkb_atom_t name;
45     xkb_mod_mask_t mods;
46     xkb_level_index_t num_levels;
47     darray(struct xkb_key_type_entry) entries;
48     darray(xkb_atom_t) level_names;
49 } KeyTypeInfo;
50
51 typedef struct {
52     char *name;
53     int errorCount;
54
55     darray(KeyTypeInfo) types;
56     struct xkb_mod_set mods;
57
58     struct xkb_context *ctx;
59 } KeyTypesInfo;
60
61 /***====================================================================***/
62
63 static inline const char *
64 MapEntryTxt(KeyTypesInfo *info, struct xkb_key_type_entry *entry)
65 {
66     return ModMaskText(info->ctx, &info->mods, entry->mods.mods);
67 }
68
69 static inline const char *
70 TypeTxt(KeyTypesInfo *info, KeyTypeInfo *type)
71 {
72     return xkb_atom_text(info->ctx, type->name);
73 }
74
75 static inline const char *
76 TypeMaskTxt(KeyTypesInfo *info, KeyTypeInfo *type)
77 {
78     return ModMaskText(info->ctx, &info->mods, type->mods);
79 }
80
81 static inline bool
82 ReportTypeShouldBeArray(KeyTypesInfo *info, KeyTypeInfo *type,
83                         const char *field)
84 {
85     return ReportShouldBeArray(info->ctx, "key type", field,
86                                TypeTxt(info, type));
87 }
88
89 static inline bool
90 ReportTypeBadType(KeyTypesInfo *info, KeyTypeInfo *type,
91                   const char *field, const char *wanted)
92 {
93     return ReportBadType(info->ctx, "key type", field,
94                          TypeTxt(info, type), wanted);
95 }
96
97 /***====================================================================***/
98
99 static void
100 InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_context *ctx,
101                  const struct xkb_mod_set *mods)
102 {
103     memset(info, 0, sizeof(*info));
104     info->ctx = ctx;
105     info->mods = *mods;
106 }
107
108 static void
109 ClearKeyTypeInfo(KeyTypeInfo *type)
110 {
111     darray_free(type->entries);
112     darray_free(type->level_names);
113 }
114
115 static void
116 ClearKeyTypesInfo(KeyTypesInfo *info)
117 {
118     free(info->name);
119     darray_free(info->types);
120 }
121
122 static KeyTypeInfo *
123 FindMatchingKeyType(KeyTypesInfo *info, xkb_atom_t name)
124 {
125     KeyTypeInfo *old;
126
127     darray_foreach(old, info->types)
128         if (old->name == name)
129             return old;
130
131     return NULL;
132 }
133
134 static bool
135 AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new, bool same_file)
136 {
137     KeyTypeInfo *old;
138     const int verbosity = xkb_context_get_log_verbosity(info->ctx);
139
140     old = FindMatchingKeyType(info, new->name);
141     if (old) {
142         if (new->merge == MERGE_REPLACE || new->merge == MERGE_OVERRIDE) {
143             if ((same_file && verbosity > 0) || verbosity > 9) {
144                 log_warn(info->ctx,
145                          "Multiple definitions of the %s key type; "
146                          "Earlier definition ignored\n",
147                          xkb_atom_text(info->ctx, new->name));
148             }
149
150             ClearKeyTypeInfo(old);
151             *old = *new;
152             darray_init(new->entries);
153             darray_init(new->level_names);
154             return true;
155         }
156
157         if (same_file)
158             log_vrb(info->ctx, 4,
159                     "Multiple definitions of the %s key type; "
160                     "Later definition ignored\n",
161                     xkb_atom_text(info->ctx, new->name));
162
163         ClearKeyTypeInfo(new);
164         return true;
165     }
166
167     darray_append(info->types, *new);
168     return true;
169 }
170
171 /***====================================================================***/
172
173 static void
174 MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from,
175                       enum merge_mode merge)
176 {
177     if (from->errorCount > 0) {
178         into->errorCount += from->errorCount;
179         return;
180     }
181
182     into->mods = from->mods;
183
184     if (into->name == NULL) {
185         into->name = from->name;
186         from->name = NULL;
187     }
188
189     if (darray_empty(into->types)) {
190         into->types = from->types;
191         darray_init(from->types);
192     }
193     else {
194         KeyTypeInfo *type;
195         darray_foreach(type, from->types) {
196             type->merge = (merge == MERGE_DEFAULT ? type->merge : merge);
197             if (!AddKeyType(into, type, false))
198                 into->errorCount++;
199         }
200     }
201 }
202
203 static void
204 HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge);
205
206 static bool
207 HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *include)
208 {
209     KeyTypesInfo included;
210
211     InitKeyTypesInfo(&included, info->ctx, &info->mods);
212     included.name = include->stmt;
213     include->stmt = NULL;
214
215     for (IncludeStmt *stmt = include; stmt; stmt = stmt->next_incl) {
216         KeyTypesInfo next_incl;
217         XkbFile *file;
218
219         file = ProcessIncludeFile(info->ctx, stmt, FILE_TYPE_TYPES);
220         if (!file) {
221             info->errorCount += 10;
222             ClearKeyTypesInfo(&included);
223             return false;
224         }
225
226         InitKeyTypesInfo(&next_incl, info->ctx, &included.mods);
227
228         HandleKeyTypesFile(&next_incl, file, stmt->merge);
229
230         MergeIncludedKeyTypes(&included, &next_incl, stmt->merge);
231
232         ClearKeyTypesInfo(&next_incl);
233         FreeXkbFile(file);
234     }
235
236     MergeIncludedKeyTypes(info, &included, include->merge);
237     ClearKeyTypesInfo(&included);
238
239     return (info->errorCount == 0);
240 }
241
242 /***====================================================================***/
243
244 static bool
245 SetModifiers(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
246              ExprDef *value)
247 {
248     xkb_mod_mask_t mods;
249
250     if (arrayNdx)
251         log_warn(info->ctx,
252                  "The modifiers field of a key type is not an array; "
253                  "Illegal array subscript ignored\n");
254
255     if (!ExprResolveModMask(info->ctx, value, MOD_BOTH, &info->mods, &mods)) {
256         log_err(info->ctx,
257                 "Key type mask field must be a modifier mask; "
258                 "Key type definition ignored\n");
259         return false;
260     }
261
262     if (type->defined & TYPE_FIELD_MASK) {
263         log_warn(info->ctx,
264                  "Multiple modifier mask definitions for key type %s; "
265                  "Using %s, ignoring %s\n",
266                  xkb_atom_text(info->ctx, type->name),
267                  TypeMaskTxt(info, type),
268                  ModMaskText(info->ctx, &info->mods, mods));
269         return false;
270     }
271
272     type->mods = mods;
273     return true;
274 }
275
276 /***====================================================================***/
277
278 static struct xkb_key_type_entry *
279 FindMatchingMapEntry(KeyTypeInfo *type, xkb_mod_mask_t mods)
280 {
281     struct xkb_key_type_entry *entry;
282
283     darray_foreach(entry, type->entries)
284         if (entry->mods.mods == mods)
285             return entry;
286
287     return NULL;
288 }
289
290 static bool
291 AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type,
292             struct xkb_key_type_entry *new, bool clobber, bool report)
293 {
294     struct xkb_key_type_entry *old;
295
296     old = FindMatchingMapEntry(type, new->mods.mods);
297     if (old) {
298         if (report && old->level != new->level) {
299             log_warn(info->ctx,
300                      "Multiple map entries for %s in %s; "
301                      "Using %d, ignoring %d\n",
302                      MapEntryTxt(info, new), TypeTxt(info, type),
303                      (clobber ? new->level : old->level) + 1,
304                      (clobber ? old->level : new->level) + 1);
305         }
306         else {
307             log_vrb(info->ctx, 10,
308                     "Multiple occurrences of map[%s]= %d in %s; Ignored\n",
309                     MapEntryTxt(info, new), new->level + 1,
310                     TypeTxt(info, type));
311             return true;
312         }
313
314         if (clobber) {
315             if (new->level >= type->num_levels)
316                 type->num_levels = new->level + 1;
317             old->level = new->level;
318         }
319
320         return true;
321     }
322
323     if (new->level >= type->num_levels)
324         type->num_levels = new->level + 1;
325
326     darray_append(type->entries, *new);
327     return true;
328 }
329
330 static bool
331 SetMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
332             ExprDef *value)
333 {
334     struct xkb_key_type_entry entry;
335
336     if (arrayNdx == NULL)
337         return ReportTypeShouldBeArray(info, type, "map entry");
338
339     if (!ExprResolveModMask(info->ctx, arrayNdx, MOD_BOTH, &info->mods,
340                             &entry.mods.mods))
341         return ReportTypeBadType(info, type, "map entry", "modifier mask");
342
343     if (entry.mods.mods & (~type->mods)) {
344         log_vrb(info->ctx, 1,
345                 "Map entry for unused modifiers in %s; "
346                 "Using %s instead of %s\n",
347                 TypeTxt(info, type),
348                 ModMaskText(info->ctx, &info->mods,
349                             entry.mods.mods & type->mods),
350                 MapEntryTxt(info, &entry));
351         entry.mods.mods &= type->mods;
352     }
353
354     if (!ExprResolveLevel(info->ctx, value, &entry.level)) {
355         log_err(info->ctx,
356                 "Level specifications in a key type must be integer; "
357                 "Ignoring malformed level specification\n");
358         return false;
359     }
360
361     entry.preserve.mods = 0;
362
363     return AddMapEntry(info, type, &entry, true, true);
364 }
365
366 /***====================================================================***/
367
368 static bool
369 AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type,
370             xkb_mod_mask_t mods, xkb_mod_mask_t preserve_mods)
371 {
372     struct xkb_key_type_entry *entry;
373     struct xkb_key_type_entry new;
374
375     darray_foreach(entry, type->entries) {
376         if (entry->mods.mods != mods)
377             continue;
378
379         /* Map exists without previous preserve (or "None"); override. */
380         if (entry->preserve.mods == 0) {
381             entry->preserve.mods = preserve_mods;
382             return true;
383         }
384
385         /* Map exists with same preserve; do nothing. */
386         if (entry->preserve.mods == preserve_mods) {
387             log_vrb(info->ctx, 10,
388                     "Identical definitions for preserve[%s] in %s; "
389                     "Ignored\n",
390                     ModMaskText(info->ctx, &info->mods, mods),
391                     TypeTxt(info, type));
392             return true;
393         }
394
395         /* Map exists with different preserve; latter wins. */
396         log_vrb(info->ctx, 1,
397                 "Multiple definitions for preserve[%s] in %s; "
398                 "Using %s, ignoring %s\n",
399                 ModMaskText(info->ctx, &info->mods, mods),
400                 TypeTxt(info, type),
401                 ModMaskText(info->ctx, &info->mods, preserve_mods),
402                 ModMaskText(info->ctx, &info->mods, entry->preserve.mods));
403
404         entry->preserve.mods = preserve_mods;
405         return true;
406     }
407
408     /*
409      * Map does not exist, i.e. preserve[] came before map[].
410      * Create a map with the specified mask mapping to Level1. The level
411      * may be overridden later with an explicit map[] statement.
412      */
413     new.level = 0;
414     new.mods.mods = mods;
415     new.preserve.mods = preserve_mods;
416     darray_append(type->entries, new);
417     return true;
418 }
419
420 static bool
421 SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
422             ExprDef *value)
423 {
424     xkb_mod_mask_t mods, preserve_mods;
425
426     if (arrayNdx == NULL)
427         return ReportTypeShouldBeArray(info, type, "preserve entry");
428
429     if (!ExprResolveModMask(info->ctx, arrayNdx, MOD_BOTH, &info->mods, &mods))
430         return ReportTypeBadType(info, type, "preserve entry",
431                                  "modifier mask");
432
433     if (mods & ~type->mods) {
434         const char *before, *after;
435
436         before = ModMaskText(info->ctx, &info->mods, mods);
437         mods &= type->mods;
438         after = ModMaskText(info->ctx, &info->mods, mods);
439
440         log_vrb(info->ctx, 1,
441                 "Preserve for modifiers not used by the %s type; "
442                 "Index %s converted to %s\n",
443                 TypeTxt(info, type), before, after);
444     }
445
446     if (!ExprResolveModMask(info->ctx, value, MOD_BOTH, &info->mods,
447                             &preserve_mods)) {
448         log_err(info->ctx,
449                 "Preserve value in a key type is not a modifier mask; "
450                 "Ignoring preserve[%s] in type %s\n",
451                 ModMaskText(info->ctx, &info->mods, mods),
452                 TypeTxt(info, type));
453         return false;
454     }
455
456     if (preserve_mods & ~mods) {
457         const char *before, *after;
458
459         before = ModMaskText(info->ctx, &info->mods, preserve_mods);
460         preserve_mods &= mods;
461         after = ModMaskText(info->ctx, &info->mods, preserve_mods);
462
463         log_vrb(info->ctx, 1,
464                 "Illegal value for preserve[%s] in type %s; "
465                 "Converted %s to %s\n",
466                 ModMaskText(info->ctx, &info->mods, mods),
467                 TypeTxt(info, type), before, after);
468     }
469
470     return AddPreserve(info, type, mods, preserve_mods);
471 }
472
473 /***====================================================================***/
474
475 static bool
476 AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type,
477              xkb_level_index_t level, xkb_atom_t name, bool clobber)
478 {
479     /* New name. */
480     if (level >= darray_size(type->level_names)) {
481         darray_resize0(type->level_names, level + 1);
482         goto finish;
483     }
484
485     /* Same level, same name. */
486     if (darray_item(type->level_names, level) == name) {
487         log_vrb(info->ctx, 10,
488                 "Duplicate names for level %d of key type %s; Ignored\n",
489                 level + 1, TypeTxt(info, type));
490         return true;
491     }
492
493     /* Same level, different name. */
494     if (darray_item(type->level_names, level) != XKB_ATOM_NONE) {
495         const char *old, *new;
496         old = xkb_atom_text(info->ctx,
497                             darray_item(type->level_names, level));
498         new = xkb_atom_text(info->ctx, name);
499         log_vrb(info->ctx, 1,
500                 "Multiple names for level %d of key type %s; "
501                 "Using %s, ignoring %s\n",
502                 level + 1, TypeTxt(info, type),
503                 (clobber ? new : old), (clobber ? old : new));
504
505         if (!clobber)
506             return true;
507     }
508
509     /* XXX: What about different level, same name? */
510
511 finish:
512     darray_item(type->level_names, level) = name;
513     return true;
514 }
515
516 static bool
517 SetLevelName(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
518              ExprDef *value)
519 {
520     xkb_level_index_t level;
521     xkb_atom_t level_name;
522
523     if (arrayNdx == NULL)
524         return ReportTypeShouldBeArray(info, type, "level name");
525
526     if (!ExprResolveLevel(info->ctx, arrayNdx, &level))
527         return ReportTypeBadType(info, type, "level name", "integer");
528
529     if (!ExprResolveString(info->ctx, value, &level_name)) {
530         log_err(info->ctx,
531                 "Non-string name for level %d in key type %s; "
532                 "Ignoring illegal level name definition\n",
533                 level + 1, xkb_atom_text(info->ctx, type->name));
534         return false;
535     }
536
537     return AddLevelName(info, type, level, level_name, true);
538 }
539
540 /***====================================================================***/
541
542 static bool
543 SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type,
544                 const char *field, ExprDef *arrayNdx, ExprDef *value)
545 {
546     bool ok = false;
547     enum type_field type_field = 0;
548
549     if (istreq(field, "modifiers")) {
550         type_field = TYPE_FIELD_MASK;
551         ok = SetModifiers(info, type, arrayNdx, value);
552     }
553     else if (istreq(field, "map")) {
554         type_field = TYPE_FIELD_MAP;
555         ok = SetMapEntry(info, type, arrayNdx, value);
556     }
557     else if (istreq(field, "preserve")) {
558         type_field = TYPE_FIELD_PRESERVE;
559         ok = SetPreserve(info, type, arrayNdx, value);
560     }
561     else if (istreq(field, "levelname") || istreq(field, "level_name")) {
562         type_field = TYPE_FIELD_LEVEL_NAME;
563         ok = SetLevelName(info, type, arrayNdx, value);
564     } else {
565         log_err(info->ctx,
566                 "Unknown field %s in key type %s; Definition ignored\n",
567                 field, TypeTxt(info, type));
568     }
569
570     type->defined |= type_field;
571     return ok;
572 }
573
574 static bool
575 HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type)
576 {
577     bool ok = true;
578     const char *elem, *field;
579     ExprDef *arrayNdx;
580
581     for (; def; def = (VarDef *) def->common.next) {
582         ok = ExprResolveLhs(info->ctx, def->name, &elem, &field,
583                             &arrayNdx);
584         if (!ok)
585             continue;
586
587         if (elem && istreq(elem, "type")) {
588             log_err(info->ctx,
589                     "Support for changing the default type has been removed; "
590                     "Statement ignored\n");
591             continue;
592         }
593
594         ok = SetKeyTypeField(info, type, field, arrayNdx, def->value);
595     }
596
597     return ok;
598 }
599
600 static bool
601 HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge)
602 {
603     KeyTypeInfo type = {
604         .defined = 0,
605         .merge = (def->merge == MERGE_DEFAULT ? merge : def->merge),
606         .name = def->name,
607         .mods = 0,
608         .num_levels = 1,
609         .entries = darray_new(),
610         .level_names = darray_new(),
611     };
612
613     if (!HandleKeyTypeBody(info, def->body, &type)) {
614         info->errorCount++;
615         return false;
616     }
617
618     if (!AddKeyType(info, &type, true)) {
619         info->errorCount++;
620         return false;
621     }
622
623     return true;
624 }
625
626 static void
627 HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
628 {
629     bool ok;
630
631     free(info->name);
632     info->name = strdup_safe(file->name);
633
634     for (ParseCommon *stmt = file->defs; stmt; stmt = stmt->next) {
635         switch (stmt->type) {
636         case STMT_INCLUDE:
637             ok = HandleIncludeKeyTypes(info, (IncludeStmt *) stmt);
638             break;
639         case STMT_TYPE:
640             ok = HandleKeyTypeDef(info, (KeyTypeDef *) stmt, merge);
641             break;
642         case STMT_VAR:
643             log_err(info->ctx,
644                     "Support for changing the default type has been removed; "
645                     "Statement ignored\n");
646             ok = true;
647             break;
648         case STMT_VMOD:
649             ok = HandleVModDef(info->ctx, &info->mods, (VModDef *) stmt, merge);
650             break;
651         default:
652             log_err(info->ctx,
653                     "Key type files may not include other declarations; "
654                     "Ignoring %s\n", stmt_type_to_string(stmt->type));
655             ok = false;
656             break;
657         }
658
659         if (!ok)
660             info->errorCount++;
661
662         if (info->errorCount > 10) {
663             log_err(info->ctx,
664                     "Abandoning keytypes file \"%s\"\n", file->name);
665             break;
666         }
667     }
668 }
669
670 /***====================================================================***/
671
672 static bool
673 CopyKeyTypesToKeymap(struct xkb_keymap *keymap, KeyTypesInfo *info)
674 {
675     unsigned num_types;
676     struct xkb_key_type *types;
677
678     num_types = darray_empty(info->types) ? 1 : darray_size(info->types);
679     types = calloc(num_types, sizeof(*types));
680     if (!types)
681         return false;
682
683     /*
684      * If no types were specified, a default unnamed one-level type is
685      * used for all keys.
686      */
687     if (darray_empty(info->types)) {
688         struct xkb_key_type *type = &types[0];
689
690         type->mods.mods = 0;
691         type->num_levels = 1;
692         type->entries = NULL;
693         type->num_entries = 0;
694         type->name = xkb_atom_intern_literal(keymap->ctx, "default");
695         type->level_names = NULL;
696     }
697     else {
698         for (unsigned i = 0; i < num_types; i++) {
699             KeyTypeInfo *def = &darray_item(info->types, i);
700             struct xkb_key_type *type = &types[i];
701
702             type->name = def->name;
703             type->mods.mods = def->mods;
704             darray_steal(def->level_names,
705                          &type->level_names, &type->num_levels);
706             darray_steal(def->entries,
707                          &type->entries, &type->num_entries);
708         }
709     }
710
711     keymap->types_section_name = strdup_safe(info->name);
712     XkbEscapeMapName(keymap->types_section_name);
713     keymap->num_types = num_types;
714     keymap->types = types;
715     keymap->mods = info->mods;
716     return true;
717 }
718
719 /***====================================================================***/
720
721 bool
722 CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
723                 enum merge_mode merge)
724 {
725     KeyTypesInfo info;
726
727     InitKeyTypesInfo(&info, keymap->ctx, &keymap->mods);
728
729     HandleKeyTypesFile(&info, file, merge);
730     if (info.errorCount != 0)
731         goto err_info;
732
733     if (!CopyKeyTypesToKeymap(keymap, &info))
734         goto err_info;
735
736     ClearKeyTypesInfo(&info);
737     return true;
738
739 err_info:
740     ClearKeyTypesInfo(&info);
741     return false;
742 }