Bug Summary

File:maprules.c
Location:line 1390, column 10
Description:Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

1/************************************************************
2 Copyright (c) 1996 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#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#elif defined(HAVE_CONFIG_H1)
30#include <config.h>
31#endif
32
33#include <stdio.h>
34#include <ctype.h>
35#include <stdlib.h>
36
37#define X_INCLUDE_STRING_H
38#define XOS_USE_NO_LOCKING
39#include <X11/Xos_r.h>
40
41#ifndef XKB_IN_SERVER
42
43#include <X11/Xproto.h>
44#include <X11/Xlib.h>
45#include <X11/Xos.h>
46#include <X11/Xfuncs.h>
47#include <X11/Xatom.h>
48#include <X11/keysym.h>
49#include <X11/XKBlib.h>
50#include <X11/extensions/XKBgeom.h>
51#include "XKMformat.h"
52#include "XKBfileInt.h"
53#include "XKBrules.h"
54
55#else
56
57#include <X11/Xproto.h>
58#include <X11/X.h>
59#include <X11/Xos.h>
60#include <X11/Xfuncs.h>
61#include <X11/Xatom.h>
62#include <X11/keysym.h>
63#include "misc.h"
64#include "inputstr.h"
65#include "dix.h"
66#include <X11/extensions/XKBstr.h>
67#define XKBSRV_NEED_FILE_FUNCS
68#include <X11/extensions/XKBsrv.h>
69
70#endif
71
72#ifdef DEBUG
73#define PR_DEBUG(s) fprintf(stderrstderr,s)
74#define PR_DEBUG1(s,a) fprintf(stderrstderr,s,a)
75#define PR_DEBUG2(s,a,b) fprintf(stderrstderr,s,a,b)
76#else
77#define PR_DEBUG(s)
78#define PR_DEBUG1(s,a)
79#define PR_DEBUG2(s,a,b)
80#endif
81
82/***====================================================================***/
83
84#define DFLT_LINE_SIZE128 128
85
86typedef struct {
87 int line_num;
88 int sz_line;
89 int num_line;
90 char buf[DFLT_LINE_SIZE128];
91 char * line;
92} InputLine;
93
94static void
95InitInputLine(InputLine *line)
96{
97 line->line_num= 1;
98 line->num_line= 0;
99 line->sz_line= DFLT_LINE_SIZE128;
100 line->line= line->buf;
101 return;
102}
103
104static void
105FreeInputLine(InputLine *line)
106{
107 if (line->line!=line->buf)
108 _XkbFree(line->line)free(line->line);
109 line->line_num= 1;
110 line->num_line= 0;
111 line->sz_line= DFLT_LINE_SIZE128;
112 line->line= line->buf;
113 return;
114}
115
116static int
117InputLineAddChar(InputLine *line,int ch)
118{
119 if (line->num_line>=line->sz_line) {
120 if (line->line==line->buf) {
121 line->line= (char *)_XkbAlloc(line->sz_line*2)malloc((line->sz_line*2));
122 memcpy(line->line,line->buf,line->sz_line);
123 }
124 else {
125 line->line=(char *)_XkbRealloc((char *)line->line,line->sz_line*2)realloc(((char *)line->line),(line->sz_line*2));
126 }
127 line->sz_line*= 2;
128 }
129 line->line[line->num_line++]= ch;
130 return ch;
131}
132
133#define ADD_CHAR(l,c)((l)->num_line<(l)->sz_line? (int)((l)->line[(l)->
num_line++]= (c)): InputLineAddChar(l,c))
((l)->num_line<(l)->sz_line?\
134 (int)((l)->line[(l)->num_line++]= (c)):\
135 InputLineAddChar(l,c))
136
137#ifdef HAVE_UNLOCKED_STDIO1
138#undef getc
139#define getc(x)getc_unlocked(x) getc_unlocked(x)
140#else
141#define flockfile(x) do {} while (0)
142#define funlockfile(x) do {} while (0)
143#endif
144
145static Boolint
146GetInputLine(FILE *file,InputLine *line,Boolint checkbang)
147{
148int ch;
149Boolint endOfFile,spacePending,slashPending,inComment;
150
151 endOfFile= False0;
152 flockfile(file);
153 while ((!endOfFile)&&(line->num_line==0)) {
154 spacePending= slashPending= inComment= False0;
155 while (((ch=getc(file)getc_unlocked(file))!='\n')&&(ch!=EOF(-1))) {
156 if (ch=='\\') {
157 if ((ch=getc(file)getc_unlocked(file))==EOF(-1))
158 break;
159 if (ch=='\n') {
160 inComment= False0;
161 ch= ' ';
162 line->line_num++;
163 }
164 }
165 if (inComment)
166 continue;
167 if (ch=='/') {
168 if (slashPending) {
169 inComment= True1;
170 slashPending= False0;
171 }
172 else {
173 slashPending= True1;
174 }
175 continue;
176 }
177 else if (slashPending) {
178 if (spacePending) {
179 ADD_CHAR(line,' ')((line)->num_line<(line)->sz_line? (int)((line)->
line[(line)->num_line++]= (' ')): InputLineAddChar(line,' '
))
;
180 spacePending= False0;
181 }
182 ADD_CHAR(line,'/')((line)->num_line<(line)->sz_line? (int)((line)->
line[(line)->num_line++]= ('/')): InputLineAddChar(line,'/'
))
;
183 slashPending= False0;
184 }
185 if (isspace(ch)((*__ctype_b_loc ())[(int) ((ch))] & (unsigned short int)
_ISspace)
) {
186 while (isspace(ch)((*__ctype_b_loc ())[(int) ((ch))] & (unsigned short int)
_ISspace)
&&(ch!='\n')&&(ch!=EOF(-1))) {
187 ch= getc(file)getc_unlocked(file);
188 }
189 if (ch==EOF(-1))
190 break;
191 if ((ch!='\n')&&(line->num_line>0))
192 spacePending= True1;
193 ungetc(ch,file);
194 }
195 else {
196 if (spacePending) {
197 ADD_CHAR(line,' ')((line)->num_line<(line)->sz_line? (int)((line)->
line[(line)->num_line++]= (' ')): InputLineAddChar(line,' '
))
;
198 spacePending= False0;
199 }
200 if (checkbang && ch=='!') {
201 if (line->num_line!=0) {
202 PR_DEBUG("The '!' legal only at start of line\n");
203 PR_DEBUG("Line containing '!' ignored\n");
204 line->num_line= 0;
205 inComment= 0;
206 break;
207 }
208
209 }
210 ADD_CHAR(line,ch)((line)->num_line<(line)->sz_line? (int)((line)->
line[(line)->num_line++]= (ch)): InputLineAddChar(line,ch)
)
;
211 }
212 }
213 if (ch==EOF(-1))
214 endOfFile= True1;
215/* else line->num_line++;*/
216 }
217 funlockfile(file);
218 if ((line->num_line==0)&&(endOfFile))
219 return False0;
220 ADD_CHAR(line,'\0')((line)->num_line<(line)->sz_line? (int)((line)->
line[(line)->num_line++]= ('\0')): InputLineAddChar(line,'\0'
))
;
221 return True1;
222}
223
224/***====================================================================***/
225
226#define MODEL0 0
227#define LAYOUT1 1
228#define VARIANT2 2
229#define OPTION3 3
230#define KEYCODES4 4
231#define SYMBOLS5 5
232#define TYPES6 6
233#define COMPAT7 7
234#define GEOMETRY8 8
235#define KEYMAP9 9
236#define MAX_WORDS10 10
237
238#define PART_MASK0x000F 0x000F
239#define COMPONENT_MASK0x03F0 0x03F0
240
241static const char * cname[MAX_WORDS10] = {
242 "model", "layout", "variant", "option",
243 "keycodes", "symbols", "types", "compat", "geometry", "keymap"
244};
245
246typedef struct _RemapSpec {
247 int number;
248 int num_remap;
249 struct {
250 int word;
251 int index;
252 } remap[MAX_WORDS10];
253} RemapSpec;
254
255typedef struct _FileSpec {
256 char * name[MAX_WORDS10];
257 struct _FileSpec * pending;
258} FileSpec;
259
260typedef struct {
261 char * model;
262 char * layout[XkbNumKbdGroups4+1];
263 char * variant[XkbNumKbdGroups4+1];
264 char * options;
265} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr;
266
267#define NDX_BUFF_SIZE4 4
268
269/***====================================================================***/
270
271static char*
272get_index(char *str, int *ndx)
273{
274 char ndx_buf[NDX_BUFF_SIZE4];
275 char *end;
276
277 if (*str != '[') {
278 *ndx = 0;
279 return str;
280 }
281 str++;
282 end = strchr(str, ']');
283 if (end == NULL((void*)0)) {
284 *ndx = -1;
285 return str - 1;
286 }
287 if ( (end - str) >= NDX_BUFF_SIZE4) {
288 *ndx = -1;
289 return end + 1;
290 }
291 strncpy(ndx_buf, str, end - str);
292 ndx_buf[end - str] = '\0';
293 *ndx = atoi(ndx_buf);
294 return end + 1;
295}
296
297static void
298SetUpRemap(InputLine *line,RemapSpec *remap)
299{
300char * tok,*str;
301unsigned present, l_ndx_present, v_ndx_present;
302register int i;
303int len, ndx;
304_Xstrtokparams strtok_buf;
305#ifdef DEBUG
306Boolint found;
307#endif
308
309
310 l_ndx_present = v_ndx_present = present= 0;
311 str= &line->line[1];
312 len = remap->number;
313 bzero((char *)remap,sizeof(RemapSpec))memset((char *)remap,0,sizeof(RemapSpec));
314 remap->number = len;
315 while ((tok=_XStrtok(str," ",strtok_buf)( strtok_buf = 0, (void)strtok_buf, strtok((str),(" ")) ))!=NULL((void*)0)) {
316#ifdef DEBUG
317 found= False0;
318#endif
319 str= NULL((void*)0);
320 if (strcmp(tok,"=")==0)
321 continue;
322 for (i=0;i<MAX_WORDS10;i++) {
323 len = strlen(cname[i]);
324 if (strncmp(cname[i],tok,len)==0) {
325 if(strlen(tok) > len) {
326 char *end = get_index(tok+len, &ndx);
327 if ((i != LAYOUT1 && i != VARIANT2) ||
328 *end != '\0' || ndx == -1)
329 break;
330 if (ndx < 1 || ndx > XkbNumKbdGroups4) {
331 PR_DEBUG2("Illegal %s index: %d\n", cname[i], ndx);
332 PR_DEBUG1("Index must be in range 1..%d\n",
333 XkbNumKbdGroups);
334 break;
335 }
336 } else {
337 ndx = 0;
338 }
339#ifdef DEBUG
340 found= True1;
341#endif
342 if (present&(1<<i)) {
343 if ((i == LAYOUT1 && l_ndx_present&(1<<ndx)) ||
344 (i == VARIANT2 && v_ndx_present&(1<<ndx)) ) {
345 PR_DEBUG1("Component \"%s\" listed twice\n",tok);
346 PR_DEBUG("Second definition ignored\n");
347 break;
348 }
349 }
350 present |= (1<<i);
351 if (i == LAYOUT1)
352 l_ndx_present |= 1 << ndx;
353 if (i == VARIANT2)
354 v_ndx_present |= 1 << ndx;
355 remap->remap[remap->num_remap].word= i;
356 remap->remap[remap->num_remap++].index= ndx;
357 break;
358 }
359 }
360#ifdef DEBUG
361 if (!found) {
362 fprintf(stderrstderr,"Unknown component \"%s\" ignored\n",tok);
363 }
364#endif
365 }
366 if ((present&PART_MASK0x000F)==0) {
367#ifdef DEBUG
368 unsigned mask= PART_MASK0x000F;
369 fprintf(stderrstderr,"Mapping needs at least one of ");
370 for (i=0; (i<MAX_WORDS10); i++) {
371 if ((1L<<i)&mask) {
372 mask&= ~(1L<<i);
373 if (mask) fprintf(stderrstderr,"\"%s,\" ",cname[i]);
374 else fprintf(stderrstderr,"or \"%s\"\n",cname[i]);
375 }
376 }
377 fprintf(stderrstderr,"Illegal mapping ignored\n");
378#endif
379 remap->num_remap= 0;
380 return;
381 }
382 if ((present&COMPONENT_MASK0x03F0)==0) {
383 PR_DEBUG("Mapping needs at least one component\n");
384 PR_DEBUG("Illegal mapping ignored\n");
385 remap->num_remap= 0;
386 return;
387 }
388 if (((present&COMPONENT_MASK0x03F0)&(1<<KEYMAP9))&&
389 ((present&COMPONENT_MASK0x03F0)!=(1<<KEYMAP9))) {
390 PR_DEBUG("Keymap cannot appear with other components\n");
391 PR_DEBUG("Illegal mapping ignored\n");
392 remap->num_remap= 0;
393 return;
394 }
395 remap->number++;
396 return;
397}
398
399static Boolint
400MatchOneOf(char *wanted,char *vals_defined)
401{
402char *str,*next;
403int want_len= strlen(wanted);
404
405 for (str=vals_defined,next=NULL((void*)0);str!=NULL((void*)0);str=next) {
406 int len;
407 next= strchr(str,',');
408 if (next) {
409 len= next-str;
410 next++;
411 }
412 else {
413 len= strlen(str);
414 }
415 if ((len==want_len)&&(strncmp(wanted,str,len)==0))
416 return True1;
417 }
418 return False0;
419}
420
421/***====================================================================***/
422
423static Boolint
424CheckLine( InputLine * line,
425 RemapSpec * remap,
426 XkbRF_RulePtr rule,
427 XkbRF_GroupPtr group)
428{
429char * str,*tok;
430register int nread, i;
431FileSpec tmp;
432_Xstrtokparams strtok_buf;
433Boolint append = False0;
434
435 if (line->line[0]=='!') {
436 if (line->line[1] == '$' ||
437 (line->line[1] == ' ' && line->line[2] == '$')) {
438 char *gname = strchr(line->line, '$');
439 char *words = strchr(gname, ' ');
440 if(!words)
441 return False0;
442 *words++ = '\0';
443 for (; *words; words++) {
444 if (*words != '=' && *words != ' ')
445 break;
446 }
447 if (*words == '\0')
448 return False0;
449 group->name = _XkbDupString(gname);
450 group->words = _XkbDupString(words);
451 for (i = 1, words = group->words; *words; words++) {
452 if ( *words == ' ') {
453 *words++ = '\0';
454 i++;
455 }
456 }
457 group->number = i;
458 return True1;
459 } else {
460 SetUpRemap(line,remap);
461 return False0;
462 }
463 }
464
465 if (remap->num_remap==0) {
466 PR_DEBUG("Must have a mapping before first line of data\n");
467 PR_DEBUG("Illegal line of data ignored\n");
468 return False0;
469 }
470 bzero((char *)&tmp,sizeof(FileSpec))memset((char *)&tmp,0,sizeof(FileSpec));
471 str= line->line;
472 for (nread= 0;(tok=_XStrtok(str," ",strtok_buf)( strtok_buf = 0, (void)strtok_buf, strtok((str),(" ")) ))!=NULL((void*)0);nread++) {
473 str= NULL((void*)0);
474 if (strcmp(tok,"=")==0) {
475 nread--;
476 continue;
477 }
478 if (nread>remap->num_remap) {
479 PR_DEBUG("Too many words on a line\n");
480 PR_DEBUG1("Extra word \"%s\" ignored\n",tok);
481 continue;
482 }
483 tmp.name[remap->remap[nread].word]= tok;
484 if (*tok == '+' || *tok == '|')
485 append = True1;
486 }
487 if (nread<remap->num_remap) {
488 PR_DEBUG1("Too few words on a line: %s\n", line->line);
489 PR_DEBUG("line ignored\n");
490 return False0;
491 }
492
493 rule->flags= 0;
494 rule->number = remap->number;
495 if (tmp.name[OPTION3])
496 rule->flags|= XkbRF_Option(1L<<2);
497 else if (append)
498 rule->flags|= XkbRF_Append(1L<<3);
499 else
500 rule->flags|= XkbRF_Normal(1L<<4);
501 rule->model= _XkbDupString(tmp.name[MODEL0]);
502 rule->layout= _XkbDupString(tmp.name[LAYOUT1]);
503 rule->variant= _XkbDupString(tmp.name[VARIANT2]);
504 rule->option= _XkbDupString(tmp.name[OPTION3]);
505
506 rule->keycodes= _XkbDupString(tmp.name[KEYCODES4]);
507 rule->symbols= _XkbDupString(tmp.name[SYMBOLS5]);
508 rule->types= _XkbDupString(tmp.name[TYPES6]);
509 rule->compat= _XkbDupString(tmp.name[COMPAT7]);
510 rule->geometry= _XkbDupString(tmp.name[GEOMETRY8]);
511 rule->keymap= _XkbDupString(tmp.name[KEYMAP9]);
512
513 rule->layout_num = rule->variant_num = 0;
514 for (i = 0; i < nread; i++) {
515 if (remap->remap[i].index) {
516 if (remap->remap[i].word == LAYOUT1)
517 rule->layout_num = remap->remap[i].index;
518 if (remap->remap[i].word == VARIANT2)
519 rule->variant_num = remap->remap[i].index;
520 }
521 }
522 return True1;
523}
524
525static char *
526_Concat(char *str1,char *str2)
527{
528int len;
529
530 if ((!str1)||(!str2))
531 return str1;
532 len= strlen(str1)+strlen(str2)+1;
533 str1= _XkbTypedRealloc(str1,len,char)((str1)?(char *)realloc((str1),(len)*sizeof(char)):((char *)calloc
((len),sizeof(char))))
;
534 if (str1)
535 strcat(str1,str2);
536 return str1;
537}
538
539static void
540squeeze_spaces(char *p1)
541{
542 char *p2;
543 for (p2 = p1; *p2; p2++) {
544 *p1 = *p2;
545 if (*p1 != ' ') p1++;
546 }
547 *p1 = '\0';
548}
549
550static Boolint
551MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs)
552{
553
554 bzero((char *)mdefs,sizeof(XkbRF_MultiDefsRec))memset((char *)mdefs,0,sizeof(XkbRF_MultiDefsRec));
555 mdefs->model = defs->model;
556 mdefs->options = _XkbDupString(defs->options);
557 if (mdefs->options) squeeze_spaces(mdefs->options);
558
559 if (defs->layout) {
560 if (!strchr(defs->layout, ',')) {
561 mdefs->layout[0] = defs->layout;
562 } else {
563 char *p;
564 int i;
565 mdefs->layout[1] = _XkbDupString(defs->layout);
566 if (mdefs->layout[1] == NULL((void*)0))
567 return False0;
568 squeeze_spaces(mdefs->layout[1]);
569 p = mdefs->layout[1];
570 for (i = 2; i <= XkbNumKbdGroups4; i++) {
571 if ((p = strchr(p, ','))) {
572 *p++ = '\0';
573 mdefs->layout[i] = p;
574 } else {
575 break;
576 }
577 }
578 if (p && (p = strchr(p, ',')))
579 *p = '\0';
580 }
581 }
582
583 if (defs->variant) {
584 if (!strchr(defs->variant, ',')) {
585 mdefs->variant[0] = defs->variant;
586 } else {
587 char *p;
588 int i;
589 mdefs->variant[1] = _XkbDupString(defs->variant);
590 if (mdefs->variant[1] == NULL((void*)0))
591 return False0;
592 squeeze_spaces(mdefs->variant[1]);
593 p = mdefs->variant[1];
594 for (i = 2; i <= XkbNumKbdGroups4; i++) {
595 if ((p = strchr(p, ','))) {
596 *p++ = '\0';
597 mdefs->variant[i] = p;
598 } else {
599 break;
600 }
601 }
602 if (p && (p = strchr(p, ',')))
603 *p = '\0';
604 }
605 }
606 return True1;
607}
608
609static void
610FreeMultiDefs(XkbRF_MultiDefsPtr defs)
611{
612 if (defs->options) _XkbFree(defs->options)free(defs->options);
613 if (defs->layout[1]) _XkbFree(defs->layout[1])free(defs->layout[1]);
614 if (defs->variant[1]) _XkbFree(defs->variant[1])free(defs->variant[1]);
615}
616
617static void
618Apply(char *src, char **dst)
619{
620 if (src) {
621 if (*src == '+' || *src == '!') {
622 *dst= _Concat(*dst, src);
623 } else {
624 if (*dst == NULL((void*)0))
625 *dst= _XkbDupString(src);
626 }
627 }
628}
629
630static void
631XkbRF_ApplyRule( XkbRF_RulePtr rule,
632 XkbComponentNamesPtr names)
633{
634 rule->flags&= ~XkbRF_PendingMatch(1L<<1); /* clear the flag because it's applied */
635
636 Apply(rule->keycodes, &names->keycodes);
637 Apply(rule->symbols, &names->symbols);
638 Apply(rule->types, &names->types);
639 Apply(rule->compat, &names->compat);
640 Apply(rule->geometry, &names->geometry);
641 Apply(rule->keymap, &names->keymap);
642}
643
644static Boolint
645CheckGroup( XkbRF_RulesPtr rules,
646 char * group_name,
647 char * name)
648{
649 int i;
650 char *p;
651 XkbRF_GroupPtr group;
652
653 for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) {
654 if (! strcmp(group->name, group_name)) {
655 break;
656 }
657 }
658 if (i == rules->num_groups)
659 return False0;
660 for (i = 0, p = group->words; i < group->number; i++, p += strlen(p)+1) {
661 if (! strcmp(p, name)) {
662 return True1;
663 }
664 }
665 return False0;
666}
667
668static int
669XkbRF_CheckApplyRule( XkbRF_RulePtr rule,
670 XkbRF_MultiDefsPtr mdefs,
671 XkbComponentNamesPtr names,
672 XkbRF_RulesPtr rules)
673{
674 Boolint pending = False0;
675
676 if (rule->model != NULL((void*)0)) {
677 if(mdefs->model == NULL((void*)0))
678 return 0;
679 if (strcmp(rule->model, "*") == 0) {
680 pending = True1;
681 } else {
682 if (rule->model[0] == '$') {
683 if (!CheckGroup(rules, rule->model, mdefs->model))
684 return 0;
685 } else {
686 if (strcmp(rule->model, mdefs->model) != 0)
687 return 0;
688 }
689 }
690 }
691 if (rule->option != NULL((void*)0)) {
692 if (mdefs->options == NULL((void*)0))
693 return 0;
694 if ((!MatchOneOf(rule->option,mdefs->options)))
695 return 0;
696 }
697
698 if (rule->layout != NULL((void*)0)) {
699 if(mdefs->layout[rule->layout_num] == NULL((void*)0) ||
700 *mdefs->layout[rule->layout_num] == '\0')
701 return 0;
702 if (strcmp(rule->layout, "*") == 0) {
703 pending = True1;
704 } else {
705 if (rule->layout[0] == '$') {
706 if (!CheckGroup(rules, rule->layout,
707 mdefs->layout[rule->layout_num]))
708 return 0;
709 } else {
710 if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0)
711 return 0;
712 }
713 }
714 }
715 if (rule->variant != NULL((void*)0)) {
716 if (mdefs->variant[rule->variant_num] == NULL((void*)0) ||
717 *mdefs->variant[rule->variant_num] == '\0')
718 return 0;
719 if (strcmp(rule->variant, "*") == 0) {
720 pending = True1;
721 } else {
722 if (rule->variant[0] == '$') {
723 if (!CheckGroup(rules, rule->variant,
724 mdefs->variant[rule->variant_num]))
725 return 0;
726 } else {
727 if (strcmp(rule->variant,
728 mdefs->variant[rule->variant_num]) != 0)
729 return 0;
730 }
731 }
732 }
733 if (pending) {
734 rule->flags|= XkbRF_PendingMatch(1L<<1);
735 return rule->number;
736 }
737 /* exact match, apply it now */
738 XkbRF_ApplyRule(rule,names);
739 return rule->number;
740}
741
742static void
743XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules)
744{
745register int i;
746XkbRF_RulePtr rule;
747
748 for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) {
749 rule->flags&= ~XkbRF_PendingMatch(1L<<1);
750 }
751}
752
753static void
754XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names)
755{
756int i;
757XkbRF_RulePtr rule;
758
759 for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) {
760 if ((rule->flags&XkbRF_PendingMatch(1L<<1))==0)
761 continue;
762 XkbRF_ApplyRule(rule,names);
763 }
764}
765
766static void
767XkbRF_CheckApplyRules( XkbRF_RulesPtr rules,
768 XkbRF_MultiDefsPtr mdefs,
769 XkbComponentNamesPtr names,
770 int flags)
771{
772int i;
773XkbRF_RulePtr rule;
774int skip;
775
776 for (rule = rules->rules, i=0; i < rules->num_rules; rule++, i++) {
777 if ((rule->flags & flags) != flags)
778 continue;
779 skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules);
780 if (skip && !(flags & XkbRF_Option(1L<<2))) {
781 for ( ;(i < rules->num_rules) && (rule->number == skip);
782 rule++, i++);
783 rule--; i--;
784 }
785 }
786}
787
788/***====================================================================***/
789
790static char *
791XkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs)
792{
793char *str, *outstr, *orig, *var;
794int len, ndx;
795
796 orig= name;
797 str= index(name,'%')(strchr((name),('%')));
798 if (str==NULL((void*)0))
799 return name;
800 len= strlen(name);
801 while (str!=NULL((void*)0)) {
802 char pfx= str[1];
803 int extra_len= 0;
804 if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) {
805 extra_len= 1;
806 str++;
807 }
808 else if (pfx=='(') {
809 extra_len= 2;
810 str++;
811 }
812 var = str + 1;
813 str = get_index(var + 1, &ndx);
814 if (ndx == -1) {
815 str = index(str,'%')(strchr((str),('%')));
816 continue;
817 }
818 if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx])
819 len+= strlen(mdefs->layout[ndx])+extra_len;
820 else if ((*var=='m')&&mdefs->model)
821 len+= strlen(mdefs->model)+extra_len;
822 else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx])
823 len+= strlen(mdefs->variant[ndx])+extra_len;
824 if ((pfx=='(')&&(*str==')')) {
825 str++;
826 }
827 str= index(&str[0],'%')(strchr((&str[0]),('%')));
828 }
829 name= (char *)_XkbAlloc(len+1)malloc((len+1));
830 str= orig;
831 outstr= name;
832 while (*str!='\0') {
833 if (str[0]=='%') {
834 char pfx,sfx;
835 str++;
836 pfx= str[0];
837 sfx= '\0';
838 if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) {
839 str++;
840 }
841 else if (pfx=='(') {
842 sfx= ')';
843 str++;
844 }
845 else pfx= '\0';
846
847 var = str;
848 str = get_index(var + 1, &ndx);
849 if (ndx == -1) {
850 continue;
851 }
852 if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) {
853 if (pfx) *outstr++= pfx;
854 strcpy(outstr,mdefs->layout[ndx]);
855 outstr+= strlen(mdefs->layout[ndx]);
856 if (sfx) *outstr++= sfx;
857 }
858 else if ((*var=='m')&&(mdefs->model)) {
859 if (pfx) *outstr++= pfx;
860 strcpy(outstr,mdefs->model);
861 outstr+= strlen(mdefs->model);
862 if (sfx) *outstr++= sfx;
863 }
864 else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) {
865 if (pfx) *outstr++= pfx;
866 strcpy(outstr,mdefs->variant[ndx]);
867 outstr+= strlen(mdefs->variant[ndx]);
868 if (sfx) *outstr++= sfx;
869 }
870 if ((pfx=='(')&&(*str==')'))
871 str++;
872 }
873 else {
874 *outstr++= *str++;
875 }
876 }
877 *outstr++= '\0';
878 if (orig!=name)
879 _XkbFree(orig)free(orig);
880 return name;
881}
882
883/***====================================================================***/
884
885Boolint
886XkbRF_GetComponents( XkbRF_RulesPtr rules,
887 XkbRF_VarDefsPtr defs,
888 XkbComponentNamesPtr names)
889{
890 XkbRF_MultiDefsRec mdefs;
891
892 MakeMultiDefs(&mdefs, defs);
893
894 bzero((char *)names,sizeof(XkbComponentNamesRec))memset((char *)names,0,sizeof(XkbComponentNamesRec));
895 XkbRF_ClearPartialMatches(rules);
896 XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Normal(1L<<4));
897 XkbRF_ApplyPartialMatches(rules, names);
898 XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append(1L<<3));
899 XkbRF_ApplyPartialMatches(rules, names);
900 XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option(1L<<2));
901 XkbRF_ApplyPartialMatches(rules, names);
902
903 if (names->keycodes)
904 names->keycodes= XkbRF_SubstituteVars(names->keycodes, &mdefs);
905 if (names->symbols)
906 names->symbols= XkbRF_SubstituteVars(names->symbols, &mdefs);
907 if (names->types)
908 names->types= XkbRF_SubstituteVars(names->types, &mdefs);
909 if (names->compat)
910 names->compat= XkbRF_SubstituteVars(names->compat, &mdefs);
911 if (names->geometry)
912 names->geometry= XkbRF_SubstituteVars(names->geometry, &mdefs);
913 if (names->keymap)
914 names->keymap= XkbRF_SubstituteVars(names->keymap, &mdefs);
915
916 FreeMultiDefs(&mdefs);
917 return (names->keycodes && names->symbols && names->types &&
918 names->compat && names->geometry ) || names->keymap;
919}
920
921XkbRF_RulePtr
922XkbRF_AddRule(XkbRF_RulesPtr rules)
923{
924 if (rules->sz_rules<1) {
925 rules->sz_rules= 16;
926 rules->num_rules= 0;
927 rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec)((XkbRF_RuleRec *)calloc((rules->sz_rules),sizeof(XkbRF_RuleRec
)))
;
928 }
929 else if (rules->num_rules>=rules->sz_rules) {
930 rules->sz_rules*= 2;
931 rules->rules= _XkbTypedRealloc(rules->rules,rules->sz_rules,((rules->rules)?(XkbRF_RuleRec *)realloc((rules->rules)
,(rules->sz_rules)*sizeof(XkbRF_RuleRec)):((XkbRF_RuleRec *
)calloc((rules->sz_rules),sizeof(XkbRF_RuleRec))))
932 XkbRF_RuleRec)((rules->rules)?(XkbRF_RuleRec *)realloc((rules->rules)
,(rules->sz_rules)*sizeof(XkbRF_RuleRec)):((XkbRF_RuleRec *
)calloc((rules->sz_rules),sizeof(XkbRF_RuleRec))))
;
933 }
934 if (!rules->rules) {
935 rules->sz_rules= rules->num_rules= 0;
936#ifdef DEBUG
937 fprintf(stderrstderr,"Allocation failure in XkbRF_AddRule\n");
938#endif
939 return NULL((void*)0);
940 }
941 bzero((char *)&rules->rules[rules->num_rules],sizeof(XkbRF_RuleRec))memset((char *)&rules->rules[rules->num_rules],0,sizeof
(XkbRF_RuleRec))
;
942 return &rules->rules[rules->num_rules++];
943}
944
945XkbRF_GroupPtr
946XkbRF_AddGroup(XkbRF_RulesPtr rules)
947{
948 if (rules->sz_groups<1) {
949 rules->sz_groups= 16;
950 rules->num_groups= 0;
951 rules->groups= _XkbTypedCalloc(rules->sz_groups,XkbRF_GroupRec)((XkbRF_GroupRec *)calloc((rules->sz_groups),sizeof(XkbRF_GroupRec
)))
;
952 }
953 else if (rules->num_groups >= rules->sz_groups) {
954 rules->sz_groups *= 2;
955 rules->groups= _XkbTypedRealloc(rules->groups,rules->sz_groups,((rules->groups)?(XkbRF_GroupRec *)realloc((rules->groups
),(rules->sz_groups)*sizeof(XkbRF_GroupRec)):((XkbRF_GroupRec
*)calloc((rules->sz_groups),sizeof(XkbRF_GroupRec))))
956 XkbRF_GroupRec)((rules->groups)?(XkbRF_GroupRec *)realloc((rules->groups
),(rules->sz_groups)*sizeof(XkbRF_GroupRec)):((XkbRF_GroupRec
*)calloc((rules->sz_groups),sizeof(XkbRF_GroupRec))))
;
957 }
958 if (!rules->groups) {
959 rules->sz_groups= rules->num_groups= 0;
960 return NULL((void*)0);
961 }
962
963 bzero((char *)&rules->groups[rules->num_groups],sizeof(XkbRF_GroupRec))memset((char *)&rules->groups[rules->num_groups],0,
sizeof(XkbRF_GroupRec))
;
964 return &rules->groups[rules->num_groups++];
965}
966
967Boolint
968XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules)
969{
970InputLine line;
971RemapSpec remap;
972XkbRF_RuleRec trule,*rule;
973XkbRF_GroupRec tgroup,*group;
974
975 if (!(rules && file))
976 return False0;
977 bzero((char *)&remap,sizeof(RemapSpec))memset((char *)&remap,0,sizeof(RemapSpec));
978 bzero((char *)&tgroup,sizeof(XkbRF_GroupRec))memset((char *)&tgroup,0,sizeof(XkbRF_GroupRec));
979 InitInputLine(&line);
980 while (GetInputLine(file,&line,True1)) {
981 if (CheckLine(&line,&remap,&trule,&tgroup)) {
982 if (tgroup.number) {
983 if ((group= XkbRF_AddGroup(rules))!=NULL((void*)0)) {
984 *group= tgroup;
985 bzero((char *)&tgroup,sizeof(XkbRF_GroupRec))memset((char *)&tgroup,0,sizeof(XkbRF_GroupRec));
986 }
987 } else {
988 if ((rule= XkbRF_AddRule(rules))!=NULL((void*)0)) {
989 *rule= trule;
990 bzero((char *)&trule,sizeof(XkbRF_RuleRec))memset((char *)&trule,0,sizeof(XkbRF_RuleRec));
991 }
992 }
993 }
994 line.num_line= 0;
995 }
996 FreeInputLine(&line);
997 return True1;
998}
999
1000Boolint
1001XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules)
1002{
1003FILE * file;
1004char buf[PATH_MAX4096];
1005Boolint ok;
1006
1007 if ((!base)||(!rules))
1008 return False0;
1009 if (locale) {
1010 if (strlen(base)+strlen(locale)+2 > PATH_MAX4096)
1011 return False0;
1012 sprintf(buf,"%s-%s", base, locale);
1013 }
1014 else {
1015 if (strlen(base)+1 > PATH_MAX4096)
1016 return False0;
1017 strcpy(buf,base);
1018 }
1019
1020 file= fopen(buf, "r");
1021 if ((!file)&&(locale)) { /* fallback if locale was specified */
1022 strcpy(buf,base);
1023 file= fopen(buf, "r");
1024 }
1025 if (!file)
1026 return False0;
1027 ok= XkbRF_LoadRules(file,rules);
1028 fclose(file);
1029 return ok;
1030}
1031
1032/***====================================================================***/
1033
1034#define HEAD_NONE0 0
1035#define HEAD_MODEL1 1
1036#define HEAD_LAYOUT2 2
1037#define HEAD_VARIANT3 3
1038#define HEAD_OPTION4 4
1039#define HEAD_EXTRA5 5
1040
1041XkbRF_VarDescPtr
1042XkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars)
1043{
1044 if (vars->sz_desc<1) {
1045 vars->sz_desc= 16;
1046 vars->num_desc= 0;
1047 vars->desc= _XkbTypedCalloc(vars->sz_desc,XkbRF_VarDescRec)((XkbRF_VarDescRec *)calloc((vars->sz_desc),sizeof(XkbRF_VarDescRec
)))
;
1048 }
1049 else if (vars->num_desc>=vars->sz_desc) {
1050 vars->sz_desc*= 2;
1051 vars->desc= _XkbTypedRealloc(vars->desc,vars->sz_desc,XkbRF_VarDescRec)((vars->desc)?(XkbRF_VarDescRec *)realloc((vars->desc),
(vars->sz_desc)*sizeof(XkbRF_VarDescRec)):((XkbRF_VarDescRec
*)calloc((vars->sz_desc),sizeof(XkbRF_VarDescRec))))
;
1052 }
1053 if (!vars->desc) {
1054 vars->sz_desc= vars->num_desc= 0;
1055 PR_DEBUG("Allocation failure in XkbRF_AddVarDesc\n");
1056 return NULL((void*)0);
1057 }
1058 vars->desc[vars->num_desc].name= NULL((void*)0);
1059 vars->desc[vars->num_desc].desc= NULL((void*)0);
1060 return &vars->desc[vars->num_desc++];
1061}
1062
1063XkbRF_VarDescPtr
1064XkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars,XkbRF_VarDescPtr from)
1065{
1066XkbRF_VarDescPtr nd;
1067
1068 if ((nd=XkbRF_AddVarDesc(vars))!=NULL((void*)0)) {
1069 nd->name= _XkbDupString(from->name);
1070 nd->desc= _XkbDupString(from->desc);
1071 }
1072 return nd;
1073}
1074
1075XkbRF_DescribeVarsPtr
1076XkbRF_AddVarToDescribe(XkbRF_RulesPtr rules,char *name)
1077{
1078 if (rules->sz_extra<1) {
1079 rules->num_extra= 0;
1080 rules->sz_extra= 1;
1081 rules->extra_names= _XkbTypedCalloc(rules->sz_extra,char *)((char * *)calloc((rules->sz_extra),sizeof(char *)));
1082 rules->extra= _XkbTypedCalloc(rules->sz_extra, XkbRF_DescribeVarsRec)((XkbRF_DescribeVarsRec *)calloc((rules->sz_extra),sizeof(
XkbRF_DescribeVarsRec)))
;
1083 }
1084 else if (rules->num_extra>=rules->sz_extra) {
1085 rules->sz_extra*= 2;
1086 rules->extra_names= _XkbTypedRealloc(rules->extra_names,rules->sz_extra,((rules->extra_names)?(char * *)realloc((rules->extra_names
),(rules->sz_extra)*sizeof(char *)):((char * *)calloc((rules
->sz_extra),sizeof(char *))))
1087 char *)((rules->extra_names)?(char * *)realloc((rules->extra_names
),(rules->sz_extra)*sizeof(char *)):((char * *)calloc((rules
->sz_extra),sizeof(char *))))
;
1088 rules->extra=_XkbTypedRealloc(rules->extra, rules->sz_extra,((rules->extra)?(XkbRF_DescribeVarsRec *)realloc((rules->
extra),(rules->sz_extra)*sizeof(XkbRF_DescribeVarsRec)):((
XkbRF_DescribeVarsRec *)calloc((rules->sz_extra),sizeof(XkbRF_DescribeVarsRec
))))
1089 XkbRF_DescribeVarsRec)((rules->extra)?(XkbRF_DescribeVarsRec *)realloc((rules->
extra),(rules->sz_extra)*sizeof(XkbRF_DescribeVarsRec)):((
XkbRF_DescribeVarsRec *)calloc((rules->sz_extra),sizeof(XkbRF_DescribeVarsRec
))))
;
1090 }
1091 if ((!rules->extra_names)||(!rules->extra)) {
1092 PR_DEBUG("allocation error in extra parts\n");
1093 rules->sz_extra= rules->num_extra= 0;
1094 rules->extra_names= NULL((void*)0);
1095 rules->extra= NULL((void*)0);
1096 return NULL((void*)0);
1097 }
1098 rules->extra_names[rules->num_extra]= _XkbDupString(name);
1099 bzero(&rules->extra[rules->num_extra],sizeof(XkbRF_DescribeVarsRec))memset(&rules->extra[rules->num_extra],0,sizeof(XkbRF_DescribeVarsRec
))
;
1100 return &rules->extra[rules->num_extra++];
1101}
1102
1103Boolint
1104XkbRF_LoadDescriptions(FILE *file,XkbRF_RulesPtr rules)
1105{
1106InputLine line;
1107XkbRF_VarDescRec tmp;
1108char *tok;
1109int len,headingtype,extra_ndx = 0;
1110
1111 bzero((char *)&tmp, sizeof(XkbRF_VarDescRec))memset((char *)&tmp,0,sizeof(XkbRF_VarDescRec));
1112 headingtype = HEAD_NONE0;
1113 InitInputLine(&line);
1114 for ( ; GetInputLine(file,&line,False0); line.num_line= 0) {
1115 if (line.line[0]=='!') {
1116 tok = strtok(&(line.line[1]), " \t");
1117 if (strcmp(tok,"model") == 0)
1118 headingtype = HEAD_MODEL1;
1119 else if (_XkbStrCaseCmpstrcasecmp(tok,"layout") == 0)
1120 headingtype = HEAD_LAYOUT2;
1121 else if (_XkbStrCaseCmpstrcasecmp(tok,"variant") == 0)
1122 headingtype = HEAD_VARIANT3;
1123 else if (_XkbStrCaseCmpstrcasecmp(tok,"option") == 0)
1124 headingtype = HEAD_OPTION4;
1125 else {
1126 int i;
1127 headingtype = HEAD_EXTRA5;
1128 extra_ndx= -1;
1129 for (i=0;(i<rules->num_extra)&&(extra_ndx<0);i++) {
1130 if (_XkbStrCaseCmpstrcasecmp(tok,rules->extra_names[i]))
1131 extra_ndx= i;
1132 }
1133 if (extra_ndx<0) {
1134 XkbRF_DescribeVarsPtr var;
1135 PR_DEBUG1("Extra heading \"%s\" encountered\n",tok);
1136 var= XkbRF_AddVarToDescribe(rules,tok);
1137 if (var)
1138 extra_ndx= var-rules->extra;
1139 else headingtype= HEAD_NONE0;
1140 }
1141 }
1142 continue;
1143 }
1144
1145 if (headingtype == HEAD_NONE0) {
1146 PR_DEBUG("Must have a heading before first line of data\n");
1147 PR_DEBUG("Illegal line of data ignored\n");
1148 continue;
1149 }
1150
1151 len = strlen(line.line);
1152 if ((tmp.name= strtok(line.line, " \t")) == NULL((void*)0)) {
1153 PR_DEBUG("Huh? No token on line\n");
1154 PR_DEBUG("Illegal line of data ignored\n");
1155 continue;
1156 }
1157 if (strlen(tmp.name) == len) {
1158 PR_DEBUG("No description found\n");
1159 PR_DEBUG("Illegal line of data ignored\n");
1160 continue;
1161 }
1162
1163 tok = line.line + strlen(tmp.name) + 1;
1164 while ((*tok!='\n')&&isspace(*tok)((*__ctype_b_loc ())[(int) ((*tok))] & (unsigned short int
) _ISspace)
)
1165 tok++;
1166 if (*tok == '\0') {
1167 PR_DEBUG("No description found\n");
1168 PR_DEBUG("Illegal line of data ignored\n");
1169 continue;
1170 }
1171 tmp.desc= tok;
1172 switch (headingtype) {
1173 case HEAD_MODEL1:
1174 XkbRF_AddVarDescCopy(&rules->models,&tmp);
1175 break;
1176 case HEAD_LAYOUT2:
1177 XkbRF_AddVarDescCopy(&rules->layouts,&tmp);
1178 break;
1179 case HEAD_VARIANT3:
1180 XkbRF_AddVarDescCopy(&rules->variants,&tmp);
1181 break;
1182 case HEAD_OPTION4:
1183 XkbRF_AddVarDescCopy(&rules->options,&tmp);
1184 break;
1185 case HEAD_EXTRA5:
1186 XkbRF_AddVarDescCopy(&rules->extra[extra_ndx],&tmp);
1187 break;
1188 }
1189 }
1190 FreeInputLine(&line);
1191 if ((rules->models.num_desc==0) && (rules->layouts.num_desc==0) &&
1192 (rules->variants.num_desc==0) && (rules->options.num_desc==0) &&
1193 (rules->num_extra==0)) {
1194 return False0;
1195 }
1196 return True1;
1197}
1198
1199Boolint
1200XkbRF_LoadDescriptionsByName(char *base,char *locale,XkbRF_RulesPtr rules)
1201{
1202FILE * file;
1203char buf[PATH_MAX4096];
1204Boolint ok;
1205
1206 if ((!base)||(!rules))
1207 return False0;
1208 if (locale) {
1209 if (strlen(base)+strlen(locale)+6 > PATH_MAX4096)
1210 return False0;
1211 sprintf(buf,"%s-%s.lst", base, locale);
1212 }
1213 else {
1214 if (strlen(base)+5 > PATH_MAX4096)
1215 return False0;
1216 sprintf(buf,"%s.lst", base);
1217 }
1218
1219 file= fopen(buf, "r");
1220 if ((!file)&&(locale)) { /* fallback if locale was specified */
1221 sprintf(buf,"%s.lst", base);
1222
1223 file= fopen(buf, "r");
1224 }
1225 if (!file)
1226 return False0;
1227 ok= XkbRF_LoadDescriptions(file,rules);
1228 fclose(file);
1229 return ok;
1230}
1231
1232/***====================================================================***/
1233
1234XkbRF_RulesPtr
1235XkbRF_Load(char *base,char *locale,Boolint wantDesc,Boolint wantRules)
1236{
1237XkbRF_RulesPtr rules;
1238
1239 if ((!base)||((!wantDesc)&&(!wantRules)))
1240 return NULL((void*)0);
1241 if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec)((XkbRF_RulesRec *)calloc((1),sizeof(XkbRF_RulesRec))))==NULL((void*)0))
1242 return NULL((void*)0);
1243 if (wantDesc&&(!XkbRF_LoadDescriptionsByName(base,locale,rules))) {
1244 XkbRF_Free(rules,True1);
1245 return NULL((void*)0);
1246 }
1247 if (wantRules&&(!XkbRF_LoadRulesByName(base,locale,rules))) {
1248 XkbRF_Free(rules,True1);
1249 return NULL((void*)0);
1250 }
1251 return rules;
1252}
1253
1254XkbRF_RulesPtr
1255XkbRF_Create(int szRules,int szExtra)
1256{
1257XkbRF_RulesPtr rules;
1258
1259 if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec)((XkbRF_RulesRec *)calloc((1),sizeof(XkbRF_RulesRec))))==NULL((void*)0))
1260 return NULL((void*)0);
1261 if (szRules>0) {
1262 rules->sz_rules= szRules;
1263 rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec)((XkbRF_RuleRec *)calloc((rules->sz_rules),sizeof(XkbRF_RuleRec
)))
;
1264 if (!rules->rules) {
1265 _XkbFree(rules)free(rules);
1266 return NULL((void*)0);
1267 }
1268 }
1269 if (szExtra>0) {
1270 rules->sz_extra= szExtra;
1271 rules->extra= _XkbTypedCalloc(rules->sz_extra,XkbRF_DescribeVarsRec)((XkbRF_DescribeVarsRec *)calloc((rules->sz_extra),sizeof(
XkbRF_DescribeVarsRec)))
;
1272 if (!rules->extra) {
1273 if (rules->rules)
1274 _XkbFree(rules->rules)free(rules->rules);
1275 _XkbFree(rules)free(rules);
1276 return NULL((void*)0);
1277 }
1278 }
1279 return rules;
1280}
1281
1282/***====================================================================***/
1283
1284static void
1285XkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var)
1286{
1287register int i;
1288
1289 for (i=0;i<var->num_desc;i++) {
1290 if (var->desc[i].name)
1291 _XkbFree(var->desc[i].name)free(var->desc[i].name);
1292 if (var->desc[i].desc)
1293 _XkbFree(var->desc[i].desc)free(var->desc[i].desc);
1294 var->desc[i].name= var->desc[i].desc= NULL((void*)0);
1295 }
1296 if (var->desc)
1297 _XkbFree(var->desc)free(var->desc);
1298 var->desc= NULL((void*)0);
1299 return;
1300}
1301
1302void
1303XkbRF_Free(XkbRF_RulesPtr rules,Boolint freeRules)
1304{
1305int i;
1306XkbRF_RulePtr rule;
1307XkbRF_GroupPtr group;
1308
1309 if (!rules)
1310 return;
1311 XkbRF_ClearVarDescriptions(&rules->models);
1312 XkbRF_ClearVarDescriptions(&rules->layouts);
1313 XkbRF_ClearVarDescriptions(&rules->variants);
1314 XkbRF_ClearVarDescriptions(&rules->options);
1315 if (rules->extra) {
1316 for (i = 0; i < rules->num_extra; i++) {
1317 XkbRF_ClearVarDescriptions(&rules->extra[i]);
1318 }
1319 _XkbFree(rules->extra)free(rules->extra);
1320 rules->num_extra= rules->sz_extra= 0;
1321 rules->extra= NULL((void*)0);
1322 }
1323 if (rules->rules) {
1324 for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) {
1325 if (rule->model) _XkbFree(rule->model)free(rule->model);
1326 if (rule->layout) _XkbFree(rule->layout)free(rule->layout);
1327 if (rule->variant) _XkbFree(rule->variant)free(rule->variant);
1328 if (rule->option) _XkbFree(rule->option)free(rule->option);
1329 if (rule->keycodes) _XkbFree(rule->keycodes)free(rule->keycodes);
1330 if (rule->symbols) _XkbFree(rule->symbols)free(rule->symbols);
1331 if (rule->types) _XkbFree(rule->types)free(rule->types);
1332 if (rule->compat) _XkbFree(rule->compat)free(rule->compat);
1333 if (rule->geometry) _XkbFree(rule->geometry)free(rule->geometry);
1334 if (rule->keymap) _XkbFree(rule->keymap)free(rule->keymap);
1335 bzero((char *)rule,sizeof(XkbRF_RuleRec))memset((char *)rule,0,sizeof(XkbRF_RuleRec));
1336 }
1337 _XkbFree(rules->rules)free(rules->rules);
1338 rules->num_rules= rules->sz_rules= 0;
1339 rules->rules= NULL((void*)0);
1340 }
1341
1342 if (rules->groups) {
1343 for (i=0, group=rules->groups;i<rules->num_groups;i++,group++) {
1344 if (group->name) _XkbFree(group->name)free(group->name);
1345 if (group->words) _XkbFree(group->words)free(group->words);
1346 }
1347 _XkbFree(rules->groups)free(rules->groups);
1348 rules->num_groups= 0;
1349 rules->groups= NULL((void*)0);
1350 }
1351 if (freeRules)
1352 _XkbFree(rules)free(rules);
1353 return;
1354}
1355
1356#ifndef XKB_IN_SERVER
1357
1358Boolint
1359XkbRF_GetNamesProp(Display *dpy,char **rf_rtrn,XkbRF_VarDefsPtr vd_rtrn)
1360{
1361Atom rules_atom,actual_type;
1362int fmt;
1363unsigned long nitems,bytes_after;
1364unsigned char *data;
1365char *out, *end;
1366Statusint rtrn;
1367
1368 rules_atom= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM"_XKB_RULES_NAMES",True1);
1369 if (rules_atom==None0L) /* property cannot exist */
1
Assuming 'rules_atom' is not equal to 0
2
Taking false branch
1370 return False0;
1371 rtrn= XGetWindowProperty(dpy,DefaultRootWindow(dpy)((&((_XPrivDisplay)dpy)->screens[(((_XPrivDisplay)dpy)
->default_screen)])->root)
,rules_atom,
1372 0L,_XKB_RF_NAMES_PROP_MAXLEN1024,False0,
1373 XA_STRING((Atom) 31),&actual_type,
1374 &fmt,&nitems,&bytes_after,
1375 (unsigned char **)&data);
1376 if (rtrn!=Success0)
3
Assuming 'rtrn' is equal to 0
4
Taking false branch
1377 return False0;
1378 if (rf_rtrn)
5
Assuming 'rf_rtrn' is null
6
Taking false branch
1379 *rf_rtrn= NULL((void*)0);
1380 (void)bzero((char *)vd_rtrn,sizeof(XkbRF_VarDefsRec))memset((char *)vd_rtrn,0,sizeof(XkbRF_VarDefsRec));
1381 if ((bytes_after>0)||(actual_type!=XA_STRING((Atom) 31))||(fmt!=8)) {
7
Assuming 'bytes_after' is <= 0
8
Assuming 'actual_type' is equal to 31
9
Assuming 'fmt' is equal to 8
10
Taking false branch
1382 if (data) XFree(data);
1383 return (fmt==0?True1:False0);
1384 }
1385
1386 out=(char*)data;
1387 end=out+nitems;
1388 if (out && (*out) && rf_rtrn)
11
Taking false branch
1389 *rf_rtrn= _XkbDupString(out);
1390 out+=strlen(out)+1;
12
Null pointer passed as an argument to a 'nonnull' parameter
1391
1392 if (out<end) {
1393 if (*out)
1394 vd_rtrn->model= _XkbDupString(out);
1395 out+=strlen(out)+1;
1396 }
1397
1398 if (out<end) {
1399 if (*out)
1400 vd_rtrn->layout= _XkbDupString(out);
1401 out+=strlen(out)+1;
1402 }
1403
1404 if (out<end) {
1405 if (*out)
1406 vd_rtrn->variant= _XkbDupString(out);
1407 out+=strlen(out)+1;
1408 }
1409
1410 if (out<end) {
1411 if (*out)
1412 vd_rtrn->options= _XkbDupString(out);
1413 out+=strlen(out)+1;
1414 }
1415
1416 XFree(data);
1417 return True1;
1418}
1419
1420Boolint
1421XkbRF_SetNamesProp(Display *dpy,char *rules_file,XkbRF_VarDefsPtr var_defs)
1422{
1423int len,out;
1424Atom name;
1425char * pval;
1426
1427 len= (rules_file?strlen(rules_file):0);
1428 len+= (var_defs->model?strlen(var_defs->model):0);
1429 len+= (var_defs->layout?strlen(var_defs->layout):0);
1430 len+= (var_defs->variant?strlen(var_defs->variant):0);
1431 len+= (var_defs->options?strlen(var_defs->options):0);
1432 if (len<1)
1433 return True1;
1434
1435 len+= 5; /* trailing NULs */
1436
1437 name= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM"_XKB_RULES_NAMES",False0);
1438 if (name==None0L) { /* should never happen */
1439 _XkbLibError(_XkbErrXReqFailure,"XkbRF_SetNamesProp",X_InternAtom){ _XkbErrCode= (25); _XkbErrLocation= ("XkbRF_SetNamesProp");
_XkbErrData= (16); }
;
1440 return False0;
1441 }
1442 pval= (char *)_XkbAlloc(len)malloc((len));
1443 if (!pval) {
1444 _XkbLibError(_XkbErrBadAlloc,"XkbRF_SetNamesProp",len){ _XkbErrCode= (23); _XkbErrLocation= ("XkbRF_SetNamesProp");
_XkbErrData= (len); }
;
1445 return False0;
1446 }
1447 out= 0;
1448 if (rules_file) {
1449 strcpy(&pval[out],rules_file);
1450 out+= strlen(rules_file);
1451 }
1452 pval[out++]= '\0';
1453 if (var_defs->model) {
1454 strcpy(&pval[out],var_defs->model);
1455 out+= strlen(var_defs->model);
1456 }
1457 pval[out++]= '\0';
1458 if (var_defs->layout) {
1459 strcpy(&pval[out],var_defs->layout);
1460 out+= strlen(var_defs->layout);
1461 }
1462 pval[out++]= '\0';
1463 if (var_defs->variant) {
1464 strcpy(&pval[out],var_defs->variant);
1465 out+= strlen(var_defs->variant);
1466 }
1467 pval[out++]= '\0';
1468 if (var_defs->options) {
1469 strcpy(&pval[out],var_defs->options);
1470 out+= strlen(var_defs->options);
1471 }
1472 pval[out++]= '\0';
1473 if (out!=len) {
1474 _XkbLibError(_XkbErrBadLength,"XkbRF_SetNamesProp",out){ _XkbErrCode= (24); _XkbErrLocation= ("XkbRF_SetNamesProp");
_XkbErrData= (out); }
;
1475 _XkbFree(pval)free(pval);
1476 return False0;
1477 }
1478
1479 XChangeProperty(dpy,DefaultRootWindow(dpy)((&((_XPrivDisplay)dpy)->screens[(((_XPrivDisplay)dpy)
->default_screen)])->root)
,name,XA_STRING((Atom) 31),8,PropModeReplace0,
1480 (unsigned char *)pval,len);
1481 _XkbFree(pval)free(pval);
1482 return True1;
1483}
1484
1485#endif