Bug Summary

File:keycodes.c
Location:line 511, column 14
Description:Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

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 "keycodes.h"
31#include "misc.h"
32#include "alias.h"
33
34char *
35longText(unsigned long val, unsigned format)
36{
37 char buf[4];
38
39 LongToKeyName(val, buf);
40 return XkbKeyNameText(buf, format);
41}
42
43/***====================================================================***/
44
45void
46LongToKeyName(unsigned long val, char *name)
47{
48 name[0] = ((val >> 24) & 0xff);
49 name[1] = ((val >> 16) & 0xff);
50 name[2] = ((val >> 8) & 0xff);
51 name[3] = (val & 0xff);
52 return;
53}
54
55/***====================================================================***/
56
57typedef struct _IndicatorNameInfo
58{
59 CommonInfo defs;
60 int ndx;
61 Atom name;
62 Boolint virtual;
63} IndicatorNameInfo;
64
65typedef struct _KeyNamesInfo
66{
67 char *name; /* e.g. evdev+aliases(qwerty) */
68 int errorCount;
69 unsigned fileID;
70 unsigned merge;
71 int computedMin; /* lowest keycode stored */
72 int computedMax; /* highest keycode stored */
73 int explicitMin;
74 int explicitMax;
75 int effectiveMin;
76 int effectiveMax;
77 unsigned long names[XkbMaxLegalKeyCode255 + 1]; /* 4-letter name of key, keycode is the index */
78 unsigned files[XkbMaxLegalKeyCode255 + 1];
79 unsigned char has_alt_forms[XkbMaxLegalKeyCode255 + 1];
80 IndicatorNameInfo *leds;
81 AliasInfo *aliases;
82} KeyNamesInfo;
83
84static void HandleKeycodesFile(XkbFile * file,
85 XkbDescPtr xkb,
86 unsigned merge,
87 KeyNamesInfo * info);
88
89static void
90InitIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info)
91{
92 ii->defs.defined = 0;
93 ii->defs.merge = info->merge;
94 ii->defs.fileID = info->fileID;
95 ii->defs.next = NULL((void*)0);
96 ii->ndx = 0;
97 ii->name = None0L;
98 ii->virtual = False0;
99 return;
100}
101
102static void
103ClearIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info)
104{
105 if (ii == info->leds)
106 {
107 ClearCommonInfo(&ii->defs);
108 info->leds = NULL((void*)0);
109 }
110 return;
111}
112
113static IndicatorNameInfo *
114NextIndicatorName(KeyNamesInfo * info)
115{
116 IndicatorNameInfo *ii;
117
118 ii = uTypedAlloc(IndicatorNameInfo)((IndicatorNameInfo *)uAlloc((unsigned)sizeof(IndicatorNameInfo
)))
;
119 if (ii)
120 {
121 InitIndicatorNameInfo(ii, info);
122 info->leds = (IndicatorNameInfo *) AddCommonInfo(&info->leds->defs,
123 (CommonInfo *) ii);
124 }
125 return ii;
126}
127
128static IndicatorNameInfo *
129FindIndicatorByIndex(KeyNamesInfo * info, int ndx)
130{
131 IndicatorNameInfo *old;
132
133 for (old = info->leds; old != NULL((void*)0);
134 old = (IndicatorNameInfo *) old->defs.next)
135 {
136 if (old->ndx == ndx)
137 return old;
138 }
139 return NULL((void*)0);
140}
141
142static IndicatorNameInfo *
143FindIndicatorByName(KeyNamesInfo * info, Atom name)
144{
145 IndicatorNameInfo *old;
146
147 for (old = info->leds; old != NULL((void*)0);
148 old = (IndicatorNameInfo *) old->defs.next)
149 {
150 if (old->name == name)
151 return old;
152 }
153 return NULL((void*)0);
154}
155
156static Boolint
157AddIndicatorName(KeyNamesInfo * info, IndicatorNameInfo * new)
158{
159 IndicatorNameInfo *old;
160 Boolint replace;
161
162 replace = (new->defs.merge == MergeReplace3) ||
163 (new->defs.merge == MergeOverride2);
164 old = FindIndicatorByName(info, new->name);
165 if (old)
166 {
167 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
168 || (warningLevel > 9))
169 {
170 WARN1uWarning("Multiple indicators named %s\n",
171 XkbAtomText(NULL((void*)0), new->name, XkbMessage3));
172 if (old->ndx == new->ndx)
173 {
174 if (old->virtual != new->virtual)
175 {
176 if (replace)
177 old->virtual = new->virtual;
178 ACTION2uAction("Using %s instead of %s\n",
179 (old->virtual ? "virtual" : "real"),
180 (old->virtual ? "real" : "virtual"));
181 }
182 else
183 {
184 ACTIONuAction("Identical definitions ignored\n");
185 }
186 return True1;
187 }
188 else
189 {
190 if (replace)
191 ACTION2uAction("Ignoring %d, using %d\n", old->ndx, new->ndx);
192 else
193 ACTION2uAction("Using %d, ignoring %d\n", old->ndx, new->ndx);
194 }
195 if (replace)
196 {
197 if (info->leds == old)
198 info->leds = (IndicatorNameInfo *) old->defs.next;
199 else
200 {
201 IndicatorNameInfo *tmp;
202 tmp = info->leds;
203 for (; tmp != NULL((void*)0);
204 tmp = (IndicatorNameInfo *) tmp->defs.next)
205 {
206 if (tmp->defs.next == (CommonInfo *) old)
207 {
208 tmp->defs.next = old->defs.next;
209 break;
210 }
211 }
212 }
213 uFree(old);
214 }
215 }
216 }
217 old = FindIndicatorByIndex(info, new->ndx);
218 if (old)
219 {
220 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
221 || (warningLevel > 9))
222 {
223 WARN1uWarning("Multiple names for indicator %d\n", new->ndx);
224 if ((old->name == new->name) && (old->virtual == new->virtual))
225 ACTIONuAction("Identical definitions ignored\n");
226 else
227 {
228 const char *oldType, *newType;
229 Atom using, ignoring;
230 if (old->virtual)
231 oldType = "virtual indicator";
232 else
233 oldType = "real indicator";
234 if (new->virtual)
235 newType = "virtual indicator";
236 else
237 newType = "real indicator";
238 if (replace)
239 {
240 using = new->name;
241 ignoring = old->name;
242 }
243 else
244 {
245 using = old->name;
246 ignoring = new->name;
247 }
248 ACTION4uAction("Using %s %s, ignoring %s %s\n",
249 oldType, XkbAtomText(NULL((void*)0), using, XkbMessage3),
250 newType, XkbAtomText(NULL((void*)0), ignoring, XkbMessage3));
251 }
252 }
253 if (replace)
254 {
255 old->name = new->name;
256 old->virtual = new->virtual;
257 }
258 return True1;
259 }
260 old = new;
261 new = NextIndicatorName(info);
262 if (!new)
263 {
264 WSGO1uInternalError("Couldn't allocate name for indicator %d\n", new->ndx);
265 ACTIONuAction("Ignored\n");
266 return False0;
267 }
268 new->name = old->name;
269 new->ndx = old->ndx;
270 new->virtual = old->virtual;
271 return True1;
272}
273
274static void
275ClearKeyNamesInfo(KeyNamesInfo * info)
276{
277 if (info->name != NULL((void*)0))
278 uFree(info->name);
279 info->name = NULL((void*)0);
280 info->computedMax = info->explicitMax = info->explicitMin = -1;
281 info->computedMin = 256;
282 info->effectiveMin = 8;
283 info->effectiveMax = 255;
284 bzero((char *) info->names, sizeof(info->names))memset((char *) info->names,0,sizeof(info->names));
285 bzero((char *) info->files, sizeof(info->files))memset((char *) info->files,0,sizeof(info->files));
286 bzero((char *) info->has_alt_forms, sizeof(info->has_alt_forms))memset((char *) info->has_alt_forms,0,sizeof(info->has_alt_forms
))
;
287 if (info->leds)
288 ClearIndicatorNameInfo(info->leds, info);
289 if (info->aliases)
290 ClearAliases(&info->aliases);
291 return;
292}
293
294static void
295InitKeyNamesInfo(KeyNamesInfo * info)
296{
297 info->name = NULL((void*)0);
298 info->leds = NULL((void*)0);
299 info->aliases = NULL((void*)0);
300 ClearKeyNamesInfo(info);
301 info->errorCount = 0;
302 return;
303}
304
305static int
306FindKeyByLong(KeyNamesInfo * info, unsigned long name)
307{
308 register int i;
309
310 for (i = info->effectiveMin; i <= info->effectiveMax; i++)
311 {
312 if (info->names[i] == name)
313 return i;
314 }
315 return 0;
316}
317
318/**
319 * Store the name of the key as a long in the info struct under the given
320 * keycode. If the same keys is referred to twice, print a warning.
321 * Note that the key's name is stored as a long, the keycode is the index.
322 */
323static Boolint
324AddKeyName(KeyNamesInfo * info,
325 int kc,
326 char *name, unsigned merge, unsigned fileID, Boolint reportCollisions)
327{
328 int old;
329 unsigned long lval;
330
331 if ((kc < info->effectiveMin) || (kc > info->effectiveMax))
332 {
333 ERROR2uError("Illegal keycode %d for name <%s>\n", kc, name);
334 ACTION2uAction("Must be in the range %d-%d inclusive\n",
335 info->effectiveMin, info->effectiveMax);
336 return False0;
337 }
338 if (kc < info->computedMin)
339 info->computedMin = kc;
340 if (kc > info->computedMax)
341 info->computedMax = kc;
342 lval = KeyNameToLong(name)((((unsigned long)name[0])<<24)|(((unsigned long)name[1
])<<16)|(((unsigned long)name[2])<<8)|name[3])
;
343
344 if (reportCollisions)
345 {
346 reportCollisions = ((warningLevel > 7) ||
347 ((warningLevel > 0)
348 && (fileID == info->files[kc])));
349 }
350
351 if (info->names[kc] != 0)
352 {
353 char buf[6];
354
355 LongToKeyName(info->names[kc], buf);
356 buf[4] = '\0';
357 if (info->names[kc] == lval)
358 {
359 if (info->has_alt_forms[kc] || (merge == MergeAltForm4))
360 {
361 info->has_alt_forms[kc] = True1;
362 }
363 else if (reportCollisions)
364 {
365 WARNuWarning("Multiple identical key name definitions\n");
366 ACTION2uAction("Later occurences of \"<%s> = %d\" ignored\n",
367 buf, kc);
368 }
369 return True1;
370 }
371 if (merge == MergeAugment1)
372 {
373 if (reportCollisions)
374 {
375 WARN1uWarning("Multiple names for keycode %d\n", kc);
376 ACTION2uAction("Using <%s>, ignoring <%s>\n", buf, name);
377 }
378 return True1;
379 }
380 else
381 {
382 if (reportCollisions)
383 {
384 WARN1uWarning("Multiple names for keycode %d\n", kc);
385 ACTION2uAction("Using <%s>, ignoring <%s>\n", name, buf);
386 }
387 info->names[kc] = 0;
388 info->files[kc] = 0;
389 }
390 }
391 old = FindKeyByLong(info, lval);
392 if ((old != 0) && (old != kc))
393 {
394 if (merge == MergeOverride2)
395 {
396 info->names[old] = 0;
397 info->files[old] = 0;
398 info->has_alt_forms[old] = True1;
399 if (reportCollisions)
400 {
401 WARN1uWarning("Key name <%s> assigned to multiple keys\n", name);
402 ACTION2uAction("Using %d, ignoring %d\n", kc, old);
403 }
404 }
405 else if (merge != MergeAltForm4)
406 {
407 if ((reportCollisions) && (warningLevel > 3))
408 {
409 WARN1uWarning("Key name <%s> assigned to multiple keys\n", name);
410 ACTION2uAction("Using %d, ignoring %d\n", old, kc);
411 ACTIONuAction
412 ("Use 'alternate' keyword to assign the same name to multiple keys\n");
413 }
414 return True1;
415 }
416 else
417 {
418 info->has_alt_forms[old] = True1;
419 }
420 }
421 info->names[kc] = lval;
422 info->files[kc] = fileID;
423 info->has_alt_forms[kc] = (merge == MergeAltForm4);
424 return True1;
425}
426
427/***====================================================================***/
428
429static void
430MergeIncludedKeycodes(KeyNamesInfo * into, KeyNamesInfo * from,
431 unsigned merge)
432{
433 register int i;
434 char buf[5];
435
436 if (from->errorCount > 0)
437 {
438 into->errorCount += from->errorCount;
439 return;
440 }
441 if (into->name == NULL((void*)0))
442 {
443 into->name = from->name;
444 from->name = NULL((void*)0);
445 }
446 for (i = from->computedMin; i <= from->computedMax; i++)
447 {
448 unsigned thisMerge;
449 if (from->names[i] == 0)
450 continue;
451 LongToKeyName(from->names[i], buf);
452 buf[4] = '\0';
453 if (from->has_alt_forms[i])
454 thisMerge = MergeAltForm4;
455 else
456 thisMerge = merge;
457 if (!AddKeyName(into, i, buf, thisMerge, from->fileID, False0))
458 into->errorCount++;
459 }
460 if (from->leds)
461 {
462 IndicatorNameInfo *led, *next;
463 for (led = from->leds; led != NULL((void*)0); led = next)
464 {
465 if (merge != MergeDefault0)
466 led->defs.merge = merge;
467 if (!AddIndicatorName(into, led))
468 into->errorCount++;
469 next = (IndicatorNameInfo *) led->defs.next;
470 }
471 }
472 if (!MergeAliases(&into->aliases, &from->aliases, merge))
473 into->errorCount++;
474 if (from->explicitMin > 0)
475 {
476 if ((into->explicitMin < 0)
477 || (into->explicitMin > from->explicitMin))
478 into->effectiveMin = into->explicitMin = from->explicitMin;
479 }
480 if (from->explicitMax > 0)
481 {
482 if ((into->explicitMax < 0)
483 || (into->explicitMax < from->explicitMax))
484 into->effectiveMax = into->explicitMax = from->explicitMax;
485 }
486 return;
487}
488
489/**
490 * Handle the given include statement (e.g. "include "evdev+aliases(qwerty)").
491 *
492 * @param stmt The include statement from the keymap file.
493 * @param xkb Unused for all but the xkb->flags.
494 * @param info Struct to store the key info in.
495 */
496static Boolint
497HandleIncludeKeycodes(IncludeStmt * stmt, XkbDescPtr xkb, KeyNamesInfo * info)
498{
499 unsigned newMerge;
500 XkbFile *rtrn;
501 KeyNamesInfo included = {NULL((void*)0)};
502 Boolint haveSelf;
503
504 haveSelf = False0;
505 if ((stmt->file == NULL((void*)0)) && (stmt->map == NULL((void*)0)))
1
Taking false branch
506 {
507 haveSelf = True1;
508 included = *info;
509 bzero(info, sizeof(KeyNamesInfo))memset(info,0,sizeof(KeyNamesInfo));
510 }
511 else if (strcmp(stmt->file, "computed") == 0)
2
Null pointer passed as an argument to a 'nonnull' parameter
512 {
513 xkb->flags |= AutoKeyNames(1L << 0);
514 info->explicitMin = XkbMinLegalKeyCode8;
515 info->explicitMax = XkbMaxLegalKeyCode255;
516 return (info->errorCount == 0);
517 } /* parse file, store returned info in the xkb struct */
518 else if (ProcessIncludeFile(stmt, XkmKeyNamesIndex4, &rtrn, &newMerge))
519 {
520 InitKeyNamesInfo(&included);
521 HandleKeycodesFile(rtrn, xkb, MergeOverride2, &included);
522 if (stmt->stmt != NULL((void*)0))
523 {
524 if (included.name != NULL((void*)0))
525 uFree(included.name);
526 included.name = stmt->stmt;
527 stmt->stmt = NULL((void*)0);
528 }
529 }
530 else
531 {
532 info->errorCount += 10; /* XXX: why 10?? */
533 return False0;
534 }
535 /* Do we have more than one include statement? */
536 if ((stmt->next != NULL((void*)0)) && (included.errorCount < 1))
537 {
538 IncludeStmt *next;
539 unsigned op;
540 KeyNamesInfo next_incl;
541
542 for (next = stmt->next; next != NULL((void*)0); next = next->next)
543 {
544 if ((next->file == NULL((void*)0)) && (next->map == NULL((void*)0)))
545 {
546 haveSelf = True1;
547 MergeIncludedKeycodes(&included, info, next->merge);
548 ClearKeyNamesInfo(info);
549 }
550 else if (ProcessIncludeFile(next, XkmKeyNamesIndex4, &rtrn, &op))
551 {
552 InitKeyNamesInfo(&next_incl);
553 HandleKeycodesFile(rtrn, xkb, MergeOverride2, &next_incl);
554 MergeIncludedKeycodes(&included, &next_incl, op);
555 ClearKeyNamesInfo(&next_incl);
556 }
557 else
558 {
559 info->errorCount += 10; /* XXX: Why 10?? */
560 return False0;
561 }
562 }
563 }
564 if (haveSelf)
565 *info = included;
566 else
567 {
568 MergeIncludedKeycodes(info, &included, newMerge);
569 ClearKeyNamesInfo(&included);
570 }
571 return (info->errorCount == 0);
572}
573
574/**
575 * Parse the given statement and store the output in the info struct.
576 * e.g. <ESC> = 9
577 */
578static int
579HandleKeycodeDef(KeycodeDef * stmt, unsigned merge, KeyNamesInfo * info)
580{
581 int code;
582 ExprResult result;
583
584 if (!ExprResolveInteger(stmt->value, &result, NULL((void*)0), NULL((void*)0)))
585 {
586 ACTION1uAction("No value keycode assigned to name <%s>\n", stmt->name);
587 return 0;
588 }
589 code = result.ival;
590 if ((code < info->effectiveMin) || (code > info->effectiveMax))
591 {
592 ERROR2uError("Illegal keycode %d for name <%s>\n", code, stmt->name);
593 ACTION2uAction("Must be in the range %d-%d inclusive\n",
594 info->effectiveMin, info->effectiveMax);
595 return 0;
596 }
597 if (stmt->merge != MergeDefault0)
598 {
599 if (stmt->merge == MergeReplace3)
600 merge = MergeOverride2;
601 else
602 merge = stmt->merge;
603 }
604 return AddKeyName(info, code, stmt->name, merge, info->fileID, True1);
605}
606
607#define MIN_KEYCODE_DEF0 0
608#define MAX_KEYCODE_DEF1 1
609
610/**
611 * Handle the minimum/maximum statement of the xkb file.
612 * Sets explicitMin/Max and effectiveMin/Max of the info struct.
613 *
614 * @return 1 on success, 0 otherwise.
615 */
616static int
617HandleKeyNameVar(VarDef * stmt, KeyNamesInfo * info)
618{
619 ExprResult tmp, field;
620 ExprDef *arrayNdx;
621 int which;
622
623 if (ExprResolveLhs(stmt->name, &tmp, &field, &arrayNdx) == 0)
624 return 0; /* internal error, already reported */
625
626 if (tmp.str != NULL((void*)0))
627 {
628 ERROR1uError("Unknown element %s encountered\n", tmp.str);
629 ACTION1uAction("Default for field %s ignored\n", field.str);
630 return 0;
631 }
632 if (uStrCaseCmp(field.str, "minimum")(strcasecmp(field.str,"minimum")) == 0)
633 which = MIN_KEYCODE_DEF0;
634 else if (uStrCaseCmp(field.str, "maximum")(strcasecmp(field.str,"maximum")) == 0)
635 which = MAX_KEYCODE_DEF1;
636 else
637 {
638 ERRORuError("Unknown field encountered\n");
639 ACTION1uAction("Assigment to field %s ignored\n", field.str);
640 return 0;
641 }
642 if (arrayNdx != NULL((void*)0))
643 {
644 ERROR1uError("The %s setting is not an array\n", field.str);
645 ACTIONuAction("Illegal array reference ignored\n");
646 return 0;
647 }
648
649 if (ExprResolveInteger(stmt->value, &tmp, NULL((void*)0), NULL((void*)0)) == 0)
650 {
651 ACTION1uAction("Assignment to field %s ignored\n", field.str);
652 return 0;
653 }
654 if ((tmp.ival < XkbMinLegalKeyCode8) || (tmp.ival > XkbMaxLegalKeyCode255))
655 {
656 ERROR3uError
657 ("Illegal keycode %d (must be in the range %d-%d inclusive)\n",
658 tmp.ival, XkbMinLegalKeyCode8, XkbMaxLegalKeyCode255);
659 ACTION1uAction("Value of \"%s\" not changed\n", field.str);
660 return 0;
661 }
662 if (which == MIN_KEYCODE_DEF0)
663 {
664 if ((info->explicitMax > 0) && (info->explicitMax < tmp.ival))
665 {
666 ERROR2uError
667 ("Minimum key code (%d) must be <= maximum key code (%d)\n",
668 tmp.ival, info->explicitMax);
669 ACTIONuAction("Minimum key code value not changed\n");
670 return 0;
671 }
672 if ((info->computedMax > 0) && (info->computedMin < tmp.ival))
673 {
674 ERROR2uError
675 ("Minimum key code (%d) must be <= lowest defined key (%d)\n",
676 tmp.ival, info->computedMin);
677 ACTIONuAction("Minimum key code value not changed\n");
678 return 0;
679 }
680 info->explicitMin = tmp.ival;
681 info->effectiveMin = tmp.ival;
682 }
683 if (which == MAX_KEYCODE_DEF1)
684 {
685 if ((info->explicitMin > 0) && (info->explicitMin > tmp.ival))
686 {
687 ERROR2uError("Maximum code (%d) must be >= minimum key code (%d)\n",
688 tmp.ival, info->explicitMin);
689 ACTIONuAction("Maximum code value not changed\n");
690 return 0;
691 }
692 if ((info->computedMax > 0) && (info->computedMax > tmp.ival))
693 {
694 ERROR2uError
695 ("Maximum code (%d) must be >= highest defined key (%d)\n",
696 tmp.ival, info->computedMax);
697 ACTIONuAction("Maximum code value not changed\n");
698 return 0;
699 }
700 info->explicitMax = tmp.ival;
701 info->effectiveMax = tmp.ival;
702 }
703 return 1;
704}
705
706static int
707HandleIndicatorNameDef(IndicatorNameDef * def,
708 unsigned merge, KeyNamesInfo * info)
709{
710 IndicatorNameInfo ii;
711 ExprResult tmp;
712
713 if ((def->ndx < 1) || (def->ndx > XkbNumIndicators32))
714 {
715 info->errorCount++;
716 ERROR1uError("Name specified for illegal indicator index %d\n", def->ndx);
717 ACTIONuAction("Ignored\n");
718 return False0;
719 }
720 InitIndicatorNameInfo(&ii, info);
721 ii.ndx = def->ndx;
722 if (!ExprResolveString(def->name, &tmp, NULL((void*)0), NULL((void*)0)))
723 {
724 char buf[20];
725 snprintf(buf, sizeof(buf), "%d", def->ndx);
726 info->errorCount++;
727 return ReportBadType("indicator", "name", buf, "string");
728 }
729 ii.name = XkbInternAtom(NULL((void*)0), tmp.str, False0);
730 ii.virtual = def->virtual;
731 if (!AddIndicatorName(info, &ii))
732 return False0;
733 return True1;
734}
735
736/**
737 * Handle the xkb_keycodes section of a xkb file.
738 * All information about parsed keys is stored in the info struct.
739 *
740 * Such a section may have include statements, in which case this function is
741 * semi-recursive (it calls HandleIncludeKeycodes, which may call
742 * HandleKeycodesFile again).
743 *
744 * @param file The input file (parsed xkb_keycodes section)
745 * @param xkb Necessary to pass down, may have flags changed.
746 * @param merge Merge strategy (MergeOverride, etc.)
747 * @param info Struct to contain the fully parsed key information.
748 */
749static void
750HandleKeycodesFile(XkbFile * file,
751 XkbDescPtr xkb, unsigned merge, KeyNamesInfo * info)
752{
753 ParseCommon *stmt;
754
755 info->name = uStringDup(file->name)((file->name) ? strdup(file->name) : ((void*)0));
756 stmt = file->defs;
757 while (stmt)
758 {
759 switch (stmt->stmtType)
760 {
761 case StmtInclude1: /* e.g. include "evdev+aliases(qwerty)" */
762 if (!HandleIncludeKeycodes((IncludeStmt *) stmt, xkb, info))
763 info->errorCount++;
764 break;
765 case StmtKeycodeDef2: /* e.g. <ESC> = 9; */
766 if (!HandleKeycodeDef((KeycodeDef *) stmt, merge, info))
767 info->errorCount++;
768 break;
769 case StmtKeyAliasDef3: /* e.g. alias <MENU> = <COMP>; */
770 if (!HandleAliasDef((KeyAliasDef *) stmt,
771 merge, info->fileID, &info->aliases))
772 info->errorCount++;
773 break;
774 case StmtVarDef5: /* e.g. minimum, maximum */
775 if (!HandleKeyNameVar((VarDef *) stmt, info))
776 info->errorCount++;
777 break;
778 case StmtIndicatorNameDef13: /* e.g. indicator 1 = "Caps Lock"; */
779 if (!HandleIndicatorNameDef((IndicatorNameDef *) stmt,
780 merge, info))
781 {
782 info->errorCount++;
783 }
784 break;
785 case StmtInterpDef7:
786 case StmtVModDef8:
787 ERRORuError("Keycode files may define key and indicator names only\n");
788 ACTION1uAction("Ignoring definition of %s\n",
789 ((stmt->stmtType ==
790 StmtInterpDef7) ? "a symbol interpretation" :
791 "virtual modifiers"));
792 info->errorCount++;
793 break;
794 default:
795 WSGO1uInternalError("Unexpected statement type %d in HandleKeycodesFile\n",
796 stmt->stmtType);
797 break;
798 }
799 stmt = stmt->next;
800 if (info->errorCount > 10)
801 {
802#ifdef NOISY
803 ERRORuError("Too many errors\n");
804#endif
805 ACTION1uAction("Abandoning keycodes file \"%s\"\n", file->topName);
806 break;
807 }
808 }
809 return;
810}
811
812/**
813 * Compile the xkb_keycodes section, parse it's output, return the results.
814 *
815 * @param file The parsed XKB file (may have include statements requiring
816 * further parsing)
817 * @param result The effective keycodes, as gathered from the file.
818 * @param merge Merge strategy.
819 *
820 * @return True on success, False otherwise.
821 */
822Boolint
823CompileKeycodes(XkbFile * file, XkbFileInfo * result, unsigned merge)
824{
825 KeyNamesInfo info; /* contains all the info after parsing */
826 XkbDescPtr xkb;
827
828 xkb = result->xkb;
829 InitKeyNamesInfo(&info);
830 HandleKeycodesFile(file, xkb, merge, &info);
831
832 /* all the keys are now stored in info */
833
834 if (info.errorCount == 0)
835 {
836 if (info.explicitMin > 0) /* if "minimum" statement was present */
837 xkb->min_key_code = info.effectiveMin;
838 else
839 xkb->min_key_code = info.computedMin;
840 if (info.explicitMax > 0) /* if "maximum" statement was present */
841 xkb->max_key_code = info.effectiveMax;
842 else
843 xkb->max_key_code = info.computedMax;
844 if (XkbAllocNames(xkb, XkbKeyNamesMask(1<<9) | XkbIndicatorNamesMask(1<<8), 0, 0)
845 == Success0)
846 {
847 register int i;
848 xkb->names->keycodes = XkbInternAtom(xkb->dpy, info.name, False0);
849 uDEBUG2(1, "key range: %d..%d\n", xkb->min_key_code,
850 xkb->max_key_code);
851 for (i = info.computedMin; i <= info.computedMax; i++)
852 {
853 LongToKeyName(info.names[i], xkb->names->keys[i].name);
854 uDEBUG2(2, "key %d = %s\n", i,
855 XkbKeyNameText(xkb->names->keys[i].name, XkbMessage));
856 }
857 }
858 else
859 {
860 WSGOuInternalError("Cannot create XkbNamesRec in CompileKeycodes\n");
861 return False0;
862 }
863 if (info.leds)
864 {
865 IndicatorNameInfo *ii;
866 if (XkbAllocIndicatorMaps(xkb) != Success0)
867 {
868 WSGOuInternalError("Couldn't allocate IndicatorRec in CompileKeycodes\n");
869 ACTIONuAction("Physical indicators not set\n");
870 }
871 for (ii = info.leds; ii != NULL((void*)0);
872 ii = (IndicatorNameInfo *) ii->defs.next)
873 {
874 xkb->names->indicators[ii->ndx - 1] =
875 XkbInternAtom(xkb->dpy,
876 XkbAtomGetString(NULL((void*)0), ii->name), False0);
877 if (xkb->indicators != NULL((void*)0))
878 {
879 register unsigned bit;
880 bit = 1 << (ii->ndx - 1);
881 if (ii->virtual)
882 xkb->indicators->phys_indicators &= ~bit;
883 else
884 xkb->indicators->phys_indicators |= bit;
885 }
886 }
887 }
888 if (info.aliases)
889 ApplyAliases(xkb, False0, &info.aliases);
890 return True1;
891 }
892 ClearKeyNamesInfo(&info);
893 return False0;
894}