File: | xkb/maprules.c |
Location: | line 167, column 25 |
Description: | Value stored to 'inComment' is never read |
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_H1 |
28 | #include <dix-config.h> |
29 | #endif |
30 | |
31 | #include <stdio.h> |
32 | #include <ctype.h> |
33 | #include <stdlib.h> |
34 | |
35 | #define X_INCLUDE_STRING_H |
36 | #define XOS_USE_NO_LOCKING |
37 | #include <X11/Xos_r.h> |
38 | |
39 | #include <X11/Xproto.h> |
40 | #include <X11/X.h> |
41 | #include <X11/Xos.h> |
42 | #include <X11/Xfuncs.h> |
43 | #include <X11/Xatom.h> |
44 | #include <X11/keysym.h> |
45 | #include "misc.h" |
46 | #include "inputstr.h" |
47 | #include "dix.h" |
48 | #include "os.h" |
49 | #include "xkbstr.h" |
50 | #define XKBSRV_NEED_FILE_FUNCS |
51 | #include <xkbsrv.h> |
52 | |
53 | /***====================================================================***/ |
54 | |
55 | #define DFLT_LINE_SIZE128 128 |
56 | |
57 | typedef struct { |
58 | int line_num; |
59 | int sz_line; |
60 | int num_line; |
61 | char buf[DFLT_LINE_SIZE128]; |
62 | char *line; |
63 | } InputLine; |
64 | |
65 | static void |
66 | InitInputLine(InputLine * line) |
67 | { |
68 | line->line_num = 1; |
69 | line->num_line = 0; |
70 | line->sz_line = DFLT_LINE_SIZE128; |
71 | line->line = line->buf; |
72 | return; |
73 | } |
74 | |
75 | static void |
76 | FreeInputLine(InputLine * line) |
77 | { |
78 | if (line->line != line->buf) |
79 | free(line->line); |
80 | line->line_num = 1; |
81 | line->num_line = 0; |
82 | line->sz_line = DFLT_LINE_SIZE128; |
83 | line->line = line->buf; |
84 | return; |
85 | } |
86 | |
87 | static int |
88 | InputLineAddChar(InputLine * line, int ch) |
89 | { |
90 | if (line->num_line >= line->sz_line) { |
91 | if (line->line == line->buf) { |
92 | line->line = malloc(line->sz_line * 2); |
93 | memcpy(line->line, line->buf, line->sz_line)__builtin___memcpy_chk (line->line, line->buf, line-> sz_line, __builtin_object_size (line->line, 0)); |
94 | } |
95 | else { |
96 | line->line = realloc((char *) line->line, line->sz_line * 2); |
97 | } |
98 | line->sz_line *= 2; |
99 | } |
100 | line->line[line->num_line++] = ch; |
101 | return ch; |
102 | } |
103 | |
104 | #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?\ |
105 | (int)((l)->line[(l)->num_line++]= (c)):\ |
106 | InputLineAddChar(l,c)) |
107 | |
108 | static Bool |
109 | GetInputLine(FILE * file, InputLine * line, Bool checkbang) |
110 | { |
111 | int ch; |
112 | Bool endOfFile, spacePending, slashPending, inComment; |
113 | |
114 | endOfFile = FALSE0; |
115 | while ((!endOfFile) && (line->num_line == 0)) { |
116 | spacePending = slashPending = inComment = FALSE0; |
117 | while (((ch = getc(file)) != '\n') && (ch != EOF(-1))) { |
118 | if (ch == '\\') { |
119 | if ((ch = getc(file)) == EOF(-1)) |
120 | break; |
121 | if (ch == '\n') { |
122 | inComment = FALSE0; |
123 | ch = ' '; |
124 | line->line_num++; |
125 | } |
126 | } |
127 | if (inComment) |
128 | continue; |
129 | if (ch == '/') { |
130 | if (slashPending) { |
131 | inComment = TRUE1; |
132 | slashPending = FALSE0; |
133 | } |
134 | else { |
135 | slashPending = TRUE1; |
136 | } |
137 | continue; |
138 | } |
139 | else if (slashPending) { |
140 | if (spacePending) { |
141 | ADD_CHAR(line, ' ')((line)->num_line<(line)->sz_line? (int)((line)-> line[(line)->num_line++]= (' ')): InputLineAddChar(line,' ' )); |
142 | spacePending = FALSE0; |
143 | } |
144 | ADD_CHAR(line, '/')((line)->num_line<(line)->sz_line? (int)((line)-> line[(line)->num_line++]= ('/')): InputLineAddChar(line,'/' )); |
145 | slashPending = FALSE0; |
146 | } |
147 | if (isspace(ch)) { |
148 | while (isspace(ch) && (ch != '\n') && (ch != EOF(-1))) { |
149 | ch = getc(file); |
150 | } |
151 | if (ch == EOF(-1)) |
152 | break; |
153 | if ((ch != '\n') && (line->num_line > 0)) |
154 | spacePending = TRUE1; |
155 | ungetc(ch, file); |
156 | } |
157 | else { |
158 | if (spacePending) { |
159 | ADD_CHAR(line, ' ')((line)->num_line<(line)->sz_line? (int)((line)-> line[(line)->num_line++]= (' ')): InputLineAddChar(line,' ' )); |
160 | spacePending = FALSE0; |
161 | } |
162 | if (checkbang && ch == '!') { |
163 | if (line->num_line != 0) { |
164 | DebugF("The '!' legal only at start of line\n"); |
165 | DebugF("Line containing '!' ignored\n"); |
166 | line->num_line = 0; |
167 | inComment = 0; |
Value stored to 'inComment' is never read | |
168 | break; |
169 | } |
170 | |
171 | } |
172 | ADD_CHAR(line, ch)((line)->num_line<(line)->sz_line? (int)((line)-> line[(line)->num_line++]= (ch)): InputLineAddChar(line,ch) ); |
173 | } |
174 | } |
175 | if (ch == EOF(-1)) |
176 | endOfFile = TRUE1; |
177 | /* else line->num_line++;*/ |
178 | } |
179 | if ((line->num_line == 0) && (endOfFile)) |
180 | return FALSE0; |
181 | ADD_CHAR(line, '\0')((line)->num_line<(line)->sz_line? (int)((line)-> line[(line)->num_line++]= ('\0')): InputLineAddChar(line,'\0' )); |
182 | return TRUE1; |
183 | } |
184 | |
185 | /***====================================================================***/ |
186 | |
187 | #define MODEL0 0 |
188 | #define LAYOUT1 1 |
189 | #define VARIANT2 2 |
190 | #define OPTION3 3 |
191 | #define KEYCODES4 4 |
192 | #define SYMBOLS5 5 |
193 | #define TYPES6 6 |
194 | #define COMPAT7 7 |
195 | #define GEOMETRY8 8 |
196 | #define MAX_WORDS9 9 |
197 | |
198 | #define PART_MASK0x000F 0x000F |
199 | #define COMPONENT_MASK0x03F0 0x03F0 |
200 | |
201 | static const char *cname[MAX_WORDS9] = { |
202 | "model", "layout", "variant", "option", |
203 | "keycodes", "symbols", "types", "compat", "geometry" |
204 | }; |
205 | |
206 | typedef struct _RemapSpec { |
207 | int number; |
208 | int num_remap; |
209 | struct { |
210 | int word; |
211 | int index; |
212 | } remap[MAX_WORDS9]; |
213 | } RemapSpec; |
214 | |
215 | typedef struct _FileSpec { |
216 | char *name[MAX_WORDS9]; |
217 | struct _FileSpec *pending; |
218 | } FileSpec; |
219 | |
220 | typedef struct { |
221 | const char *model; |
222 | const char *layout[XkbNumKbdGroups4 + 1]; |
223 | const char *variant[XkbNumKbdGroups4 + 1]; |
224 | const char *options; |
225 | } XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr; |
226 | |
227 | #define NDX_BUFF_SIZE4 4 |
228 | |
229 | /***====================================================================***/ |
230 | |
231 | static char * |
232 | get_index(char *str, int *ndx) |
233 | { |
234 | char ndx_buf[NDX_BUFF_SIZE4]; |
235 | char *end; |
236 | |
237 | if (*str != '[') { |
238 | *ndx = 0; |
239 | return str; |
240 | } |
241 | str++; |
242 | end = strchr(str, ']'); |
243 | if (end == NULL((void*)0)) { |
244 | *ndx = -1; |
245 | return str - 1; |
246 | } |
247 | if ((end - str) >= NDX_BUFF_SIZE4) { |
248 | *ndx = -1; |
249 | return end + 1; |
250 | } |
251 | strlcpy(ndx_buf, str, 1 + end - str)__builtin___strlcpy_chk (ndx_buf, str, 1 + end - str, __builtin_object_size (ndx_buf, 2 > 1 ? 1 : 0)); |
252 | *ndx = atoi(ndx_buf); |
253 | return end + 1; |
254 | } |
255 | |
256 | static void |
257 | SetUpRemap(InputLine * line, RemapSpec * remap) |
258 | { |
259 | char *tok, *str; |
260 | unsigned present, l_ndx_present, v_ndx_present; |
261 | register int i; |
262 | int len, ndx; |
263 | _Xstrtokparams strtok_buf; |
264 | Bool found; |
265 | |
266 | l_ndx_present = v_ndx_present = present = 0; |
267 | str = &line->line[1]; |
268 | len = remap->number; |
269 | memset((char *) remap, 0, sizeof(RemapSpec))__builtin___memset_chk ((char *) remap, 0, sizeof(RemapSpec), __builtin_object_size ((char *) remap, 0)); |
270 | remap->number = len; |
271 | while ((tok = _XStrtok(str, " ", strtok_buf)( strtok_buf = 0, (void)strtok_buf, strtok((str),(" ")) )) != NULL((void*)0)) { |
272 | found = FALSE0; |
273 | str = NULL((void*)0); |
274 | if (strcmp(tok, "=") == 0) |
275 | continue; |
276 | for (i = 0; i < MAX_WORDS9; i++) { |
277 | len = strlen(cname[i]); |
278 | if (strncmp(cname[i], tok, len) == 0) { |
279 | if (strlen(tok) > len) { |
280 | char *end = get_index(tok + len, &ndx); |
281 | |
282 | if ((i != LAYOUT1 && i != VARIANT2) || |
283 | *end != '\0' || ndx == -1) |
284 | break; |
285 | if (ndx < 1 || ndx > XkbNumKbdGroups4) { |
286 | DebugF("Illegal %s index: %d\n", cname[i], ndx); |
287 | DebugF("Index must be in range 1..%d\n", |
288 | XkbNumKbdGroups); |
289 | break; |
290 | } |
291 | } |
292 | else { |
293 | ndx = 0; |
294 | } |
295 | found = TRUE1; |
296 | if (present & (1 << i)) { |
297 | if ((i == LAYOUT1 && l_ndx_present & (1 << ndx)) || |
298 | (i == VARIANT2 && v_ndx_present & (1 << ndx))) { |
299 | DebugF("Component \"%s\" listed twice\n", tok); |
300 | DebugF("Second definition ignored\n"); |
301 | break; |
302 | } |
303 | } |
304 | present |= (1 << i); |
305 | if (i == LAYOUT1) |
306 | l_ndx_present |= 1 << ndx; |
307 | if (i == VARIANT2) |
308 | v_ndx_present |= 1 << ndx; |
309 | remap->remap[remap->num_remap].word = i; |
310 | remap->remap[remap->num_remap++].index = ndx; |
311 | break; |
312 | } |
313 | } |
314 | if (!found) { |
315 | fprintf(stderr__stderrp, "Unknown component \"%s\" ignored\n", tok); |
316 | } |
317 | } |
318 | if ((present & PART_MASK0x000F) == 0) { |
319 | unsigned mask = PART_MASK0x000F; |
320 | |
321 | ErrorF("Mapping needs at least one of "); |
322 | for (i = 0; (i < MAX_WORDS9); i++) { |
323 | if ((1L << i) & mask) { |
324 | mask &= ~(1L << i); |
325 | if (mask) |
326 | DebugF("\"%s,\" ", cname[i]); |
327 | else |
328 | DebugF("or \"%s\"\n", cname[i]); |
329 | } |
330 | } |
331 | DebugF("Illegal mapping ignored\n"); |
332 | remap->num_remap = 0; |
333 | return; |
334 | } |
335 | if ((present & COMPONENT_MASK0x03F0) == 0) { |
336 | DebugF("Mapping needs at least one component\n"); |
337 | DebugF("Illegal mapping ignored\n"); |
338 | remap->num_remap = 0; |
339 | return; |
340 | } |
341 | remap->number++; |
342 | return; |
343 | } |
344 | |
345 | static Bool |
346 | MatchOneOf(const char *wanted, const char *vals_defined) |
347 | { |
348 | const char *str, *next; |
349 | int want_len = strlen(wanted); |
350 | |
351 | for (str = vals_defined, next = NULL((void*)0); str != NULL((void*)0); str = next) { |
352 | int len; |
353 | |
354 | next = strchr(str, ','); |
355 | if (next) { |
356 | len = next - str; |
357 | next++; |
358 | } |
359 | else { |
360 | len = strlen(str); |
361 | } |
362 | if ((len == want_len) && (strncmp(wanted, str, len) == 0)) |
363 | return TRUE1; |
364 | } |
365 | return FALSE0; |
366 | } |
367 | |
368 | /***====================================================================***/ |
369 | |
370 | static Bool |
371 | CheckLine(InputLine * line, |
372 | RemapSpec * remap, XkbRF_RulePtr rule, XkbRF_GroupPtr group) |
373 | { |
374 | char *str, *tok; |
375 | register int nread, i; |
376 | FileSpec tmp; |
377 | _Xstrtokparams strtok_buf; |
378 | Bool append = FALSE0; |
379 | |
380 | if (line->line[0] == '!') { |
381 | if (line->line[1] == '$' || |
382 | (line->line[1] == ' ' && line->line[2] == '$')) { |
383 | char *gname = strchr(line->line, '$'); |
384 | char *words = strchr(gname, ' '); |
385 | |
386 | if (!words) |
387 | return FALSE0; |
388 | *words++ = '\0'; |
389 | for (; *words; words++) { |
390 | if (*words != '=' && *words != ' ') |
391 | break; |
392 | } |
393 | if (*words == '\0') |
394 | return FALSE0; |
395 | group->name = Xstrdup(gname); |
396 | group->words = Xstrdup(words); |
397 | for (i = 1, words = group->words; *words; words++) { |
398 | if (*words == ' ') { |
399 | *words++ = '\0'; |
400 | i++; |
401 | } |
402 | } |
403 | group->number = i; |
404 | return TRUE1; |
405 | } |
406 | else { |
407 | SetUpRemap(line, remap); |
408 | return FALSE0; |
409 | } |
410 | } |
411 | |
412 | if (remap->num_remap == 0) { |
413 | DebugF("Must have a mapping before first line of data\n"); |
414 | DebugF("Illegal line of data ignored\n"); |
415 | return FALSE0; |
416 | } |
417 | memset((char *) &tmp, 0, sizeof(FileSpec))__builtin___memset_chk ((char *) &tmp, 0, sizeof(FileSpec ), __builtin_object_size ((char *) &tmp, 0)); |
418 | str = line->line; |
419 | for (nread = 0; (tok = _XStrtok(str, " ", strtok_buf)( strtok_buf = 0, (void)strtok_buf, strtok((str),(" ")) )) != NULL((void*)0); nread++) { |
420 | str = NULL((void*)0); |
421 | if (strcmp(tok, "=") == 0) { |
422 | nread--; |
423 | continue; |
424 | } |
425 | if (nread > remap->num_remap) { |
426 | DebugF("Too many words on a line\n"); |
427 | DebugF("Extra word \"%s\" ignored\n", tok); |
428 | continue; |
429 | } |
430 | tmp.name[remap->remap[nread].word] = tok; |
431 | if (*tok == '+' || *tok == '|') |
432 | append = TRUE1; |
433 | } |
434 | if (nread < remap->num_remap) { |
435 | DebugF("Too few words on a line: %s\n", line->line); |
436 | DebugF("line ignored\n"); |
437 | return FALSE0; |
438 | } |
439 | |
440 | rule->flags = 0; |
441 | rule->number = remap->number; |
442 | if (tmp.name[OPTION3]) |
443 | rule->flags |= XkbRF_Option(1L<<2); |
444 | else if (append) |
445 | rule->flags |= XkbRF_Append(1L<<3); |
446 | else |
447 | rule->flags |= XkbRF_Normal(1L<<4); |
448 | rule->model = Xstrdup(tmp.name[MODEL0]); |
449 | rule->layout = Xstrdup(tmp.name[LAYOUT1]); |
450 | rule->variant = Xstrdup(tmp.name[VARIANT2]); |
451 | rule->option = Xstrdup(tmp.name[OPTION3]); |
452 | |
453 | rule->keycodes = Xstrdup(tmp.name[KEYCODES4]); |
454 | rule->symbols = Xstrdup(tmp.name[SYMBOLS5]); |
455 | rule->types = Xstrdup(tmp.name[TYPES6]); |
456 | rule->compat = Xstrdup(tmp.name[COMPAT7]); |
457 | rule->geometry = Xstrdup(tmp.name[GEOMETRY8]); |
458 | |
459 | rule->layout_num = rule->variant_num = 0; |
460 | for (i = 0; i < nread; i++) { |
461 | if (remap->remap[i].index) { |
462 | if (remap->remap[i].word == LAYOUT1) |
463 | rule->layout_num = remap->remap[i].index; |
464 | if (remap->remap[i].word == VARIANT2) |
465 | rule->variant_num = remap->remap[i].index; |
466 | } |
467 | } |
468 | return TRUE1; |
469 | } |
470 | |
471 | static char * |
472 | _Concat(char *str1, const char *str2) |
473 | { |
474 | int len; |
475 | |
476 | if ((!str1) || (!str2)) |
477 | return str1; |
478 | len = strlen(str1) + strlen(str2) + 1; |
479 | str1 = realloc(str1, len * sizeof(char)); |
480 | if (str1) |
481 | strcat(str1, str2)__builtin___strcat_chk (str1, str2, __builtin_object_size (str1 , 2 > 1 ? 1 : 0)); |
482 | return str1; |
483 | } |
484 | |
485 | static void |
486 | squeeze_spaces(char *p1) |
487 | { |
488 | char *p2; |
489 | |
490 | for (p2 = p1; *p2; p2++) { |
491 | *p1 = *p2; |
492 | if (*p1 != ' ') |
493 | p1++; |
494 | } |
495 | *p1 = '\0'; |
496 | } |
497 | |
498 | static Bool |
499 | MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs) |
500 | { |
501 | char *options; |
502 | memset((char *) mdefs, 0, sizeof(XkbRF_MultiDefsRec))__builtin___memset_chk ((char *) mdefs, 0, sizeof(XkbRF_MultiDefsRec ), __builtin_object_size ((char *) mdefs, 0)); |
503 | mdefs->model = defs->model; |
504 | options = Xstrdup(defs->options); |
505 | if (options) |
506 | squeeze_spaces(options); |
507 | mdefs->options = options; |
508 | |
509 | if (defs->layout) { |
510 | if (!strchr(defs->layout, ',')) { |
511 | mdefs->layout[0] = defs->layout; |
512 | } |
513 | else { |
514 | char *p; |
515 | char *layout; |
516 | int i; |
517 | |
518 | layout = Xstrdup(defs->layout); |
519 | if (layout == NULL((void*)0)) |
520 | return FALSE0; |
521 | squeeze_spaces(layout); |
522 | mdefs->layout[1] = layout; |
523 | p = layout; |
524 | for (i = 2; i <= XkbNumKbdGroups4; i++) { |
525 | if ((p = strchr(p, ','))) { |
526 | *p++ = '\0'; |
527 | mdefs->layout[i] = p; |
528 | } |
529 | else { |
530 | break; |
531 | } |
532 | } |
533 | if (p && (p = strchr(p, ','))) |
534 | *p = '\0'; |
535 | } |
536 | } |
537 | |
538 | if (defs->variant) { |
539 | if (!strchr(defs->variant, ',')) { |
540 | mdefs->variant[0] = defs->variant; |
541 | } |
542 | else { |
543 | char *p; |
544 | char *variant; |
545 | int i; |
546 | |
547 | variant = Xstrdup(defs->variant); |
548 | if (variant == NULL((void*)0)) |
549 | return FALSE0; |
550 | squeeze_spaces(variant); |
551 | mdefs->variant[1] = variant; |
552 | p = variant; |
553 | for (i = 2; i <= XkbNumKbdGroups4; i++) { |
554 | if ((p = strchr(p, ','))) { |
555 | *p++ = '\0'; |
556 | mdefs->variant[i] = p; |
557 | } |
558 | else { |
559 | break; |
560 | } |
561 | } |
562 | if (p && (p = strchr(p, ','))) |
563 | *p = '\0'; |
564 | } |
565 | } |
566 | return TRUE1; |
567 | } |
568 | |
569 | static void |
570 | FreeMultiDefs(XkbRF_MultiDefsPtr defs) |
571 | { |
572 | free((void *) defs->options); |
573 | free((void *) defs->layout[1]); |
574 | free((void *) defs->variant[1]); |
575 | } |
576 | |
577 | static void |
578 | Apply(const char *src, char **dst) |
579 | { |
580 | if (src) { |
581 | if (*src == '+' || *src == '!') { |
582 | *dst = _Concat(*dst, src); |
583 | } |
584 | else { |
585 | if (*dst == NULL((void*)0)) |
586 | *dst = Xstrdup(src); |
587 | } |
588 | } |
589 | } |
590 | |
591 | static void |
592 | XkbRF_ApplyRule(XkbRF_RulePtr rule, XkbComponentNamesPtr names) |
593 | { |
594 | rule->flags &= ~XkbRF_PendingMatch(1L<<1); /* clear the flag because it's applied */ |
595 | |
596 | Apply(rule->keycodes, &names->keycodes); |
597 | Apply(rule->symbols, &names->symbols); |
598 | Apply(rule->types, &names->types); |
599 | Apply(rule->compat, &names->compat); |
600 | Apply(rule->geometry, &names->geometry); |
601 | } |
602 | |
603 | static Bool |
604 | CheckGroup(XkbRF_RulesPtr rules, const char *group_name, const char *name) |
605 | { |
606 | int i; |
607 | char *p; |
608 | XkbRF_GroupPtr group; |
609 | |
610 | for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) { |
611 | if (!strcmp(group->name, group_name)) { |
612 | break; |
613 | } |
614 | } |
615 | if (i == rules->num_groups) |
616 | return FALSE0; |
617 | for (i = 0, p = group->words; i < group->number; i++, p += strlen(p) + 1) { |
618 | if (!strcmp(p, name)) { |
619 | return TRUE1; |
620 | } |
621 | } |
622 | return FALSE0; |
623 | } |
624 | |
625 | static int |
626 | XkbRF_CheckApplyRule(XkbRF_RulePtr rule, |
627 | XkbRF_MultiDefsPtr mdefs, |
628 | XkbComponentNamesPtr names, XkbRF_RulesPtr rules) |
629 | { |
630 | Bool pending = FALSE0; |
631 | |
632 | if (rule->model != NULL((void*)0)) { |
633 | if (mdefs->model == NULL((void*)0)) |
634 | return 0; |
635 | if (strcmp(rule->model, "*") == 0) { |
636 | pending = TRUE1; |
637 | } |
638 | else { |
639 | if (rule->model[0] == '$') { |
640 | if (!CheckGroup(rules, rule->model, mdefs->model)) |
641 | return 0; |
642 | } |
643 | else { |
644 | if (strcmp(rule->model, mdefs->model) != 0) |
645 | return 0; |
646 | } |
647 | } |
648 | } |
649 | if (rule->option != NULL((void*)0)) { |
650 | if (mdefs->options == NULL((void*)0)) |
651 | return 0; |
652 | if ((!MatchOneOf(rule->option, mdefs->options))) |
653 | return 0; |
654 | } |
655 | |
656 | if (rule->layout != NULL((void*)0)) { |
657 | if (mdefs->layout[rule->layout_num] == NULL((void*)0) || |
658 | *mdefs->layout[rule->layout_num] == '\0') |
659 | return 0; |
660 | if (strcmp(rule->layout, "*") == 0) { |
661 | pending = TRUE1; |
662 | } |
663 | else { |
664 | if (rule->layout[0] == '$') { |
665 | if (!CheckGroup(rules, rule->layout, |
666 | mdefs->layout[rule->layout_num])) |
667 | return 0; |
668 | } |
669 | else { |
670 | if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0) |
671 | return 0; |
672 | } |
673 | } |
674 | } |
675 | if (rule->variant != NULL((void*)0)) { |
676 | if (mdefs->variant[rule->variant_num] == NULL((void*)0) || |
677 | *mdefs->variant[rule->variant_num] == '\0') |
678 | return 0; |
679 | if (strcmp(rule->variant, "*") == 0) { |
680 | pending = TRUE1; |
681 | } |
682 | else { |
683 | if (rule->variant[0] == '$') { |
684 | if (!CheckGroup(rules, rule->variant, |
685 | mdefs->variant[rule->variant_num])) |
686 | return 0; |
687 | } |
688 | else { |
689 | if (strcmp(rule->variant, |
690 | mdefs->variant[rule->variant_num]) != 0) |
691 | return 0; |
692 | } |
693 | } |
694 | } |
695 | if (pending) { |
696 | rule->flags |= XkbRF_PendingMatch(1L<<1); |
697 | return rule->number; |
698 | } |
699 | /* exact match, apply it now */ |
700 | XkbRF_ApplyRule(rule, names); |
701 | return rule->number; |
702 | } |
703 | |
704 | static void |
705 | XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) |
706 | { |
707 | register int i; |
708 | XkbRF_RulePtr rule; |
709 | |
710 | for (i = 0, rule = rules->rules; i < rules->num_rules; i++, rule++) { |
711 | rule->flags &= ~XkbRF_PendingMatch(1L<<1); |
712 | } |
713 | } |
714 | |
715 | static void |
716 | XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules, XkbComponentNamesPtr names) |
717 | { |
718 | int i; |
719 | XkbRF_RulePtr rule; |
720 | |
721 | for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) { |
722 | if ((rule->flags & XkbRF_PendingMatch(1L<<1)) == 0) |
723 | continue; |
724 | XkbRF_ApplyRule(rule, names); |
725 | } |
726 | } |
727 | |
728 | static void |
729 | XkbRF_CheckApplyRules(XkbRF_RulesPtr rules, |
730 | XkbRF_MultiDefsPtr mdefs, |
731 | XkbComponentNamesPtr names, int flags) |
732 | { |
733 | int i; |
734 | XkbRF_RulePtr rule; |
735 | int skip; |
736 | |
737 | for (rule = rules->rules, i = 0; i < rules->num_rules; rule++, i++) { |
738 | if ((rule->flags & flags) != flags) |
739 | continue; |
740 | skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules); |
741 | if (skip && !(flags & XkbRF_Option(1L<<2))) { |
742 | for (; (i < rules->num_rules) && (rule->number == skip); |
743 | rule++, i++); |
744 | rule--; |
745 | i--; |
746 | } |
747 | } |
748 | } |
749 | |
750 | /***====================================================================***/ |
751 | |
752 | static char * |
753 | XkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs) |
754 | { |
755 | char *str, *outstr, *orig, *var; |
756 | int len, ndx; |
757 | |
758 | orig = name; |
759 | str = index(name, '%'); |
760 | if (str == NULL((void*)0)) |
761 | return name; |
762 | len = strlen(name); |
763 | while (str != NULL((void*)0)) { |
764 | char pfx = str[1]; |
765 | int extra_len = 0; |
766 | |
767 | if ((pfx == '+') || (pfx == '|') || (pfx == '_') || (pfx == '-')) { |
768 | extra_len = 1; |
769 | str++; |
770 | } |
771 | else if (pfx == '(') { |
772 | extra_len = 2; |
773 | str++; |
774 | } |
775 | var = str + 1; |
776 | str = get_index(var + 1, &ndx); |
777 | if (ndx == -1) { |
778 | str = index(str, '%'); |
779 | continue; |
780 | } |
781 | if ((*var == 'l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) |
782 | len += strlen(mdefs->layout[ndx]) + extra_len; |
783 | else if ((*var == 'm') && mdefs->model) |
784 | len += strlen(mdefs->model) + extra_len; |
785 | else if ((*var == 'v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) |
786 | len += strlen(mdefs->variant[ndx]) + extra_len; |
787 | if ((pfx == '(') && (*str == ')')) { |
788 | str++; |
789 | } |
790 | str = index(&str[0], '%'); |
791 | } |
792 | name = malloc(len + 1); |
793 | str = orig; |
794 | outstr = name; |
795 | while (*str != '\0') { |
796 | if (str[0] == '%') { |
797 | char pfx, sfx; |
798 | |
799 | str++; |
800 | pfx = str[0]; |
801 | sfx = '\0'; |
802 | if ((pfx == '+') || (pfx == '|') || (pfx == '_') || (pfx == '-')) { |
803 | str++; |
804 | } |
805 | else if (pfx == '(') { |
806 | sfx = ')'; |
807 | str++; |
808 | } |
809 | else |
810 | pfx = '\0'; |
811 | |
812 | var = str; |
813 | str = get_index(var + 1, &ndx); |
814 | if (ndx == -1) { |
815 | continue; |
816 | } |
817 | if ((*var == 'l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) { |
818 | if (pfx) |
819 | *outstr++ = pfx; |
820 | strcpy(outstr, mdefs->layout[ndx])__builtin___strcpy_chk (outstr, mdefs->layout[ndx], __builtin_object_size (outstr, 2 > 1 ? 1 : 0)); |
821 | outstr += strlen(mdefs->layout[ndx]); |
822 | if (sfx) |
823 | *outstr++ = sfx; |
824 | } |
825 | else if ((*var == 'm') && (mdefs->model)) { |
826 | if (pfx) |
827 | *outstr++ = pfx; |
828 | strcpy(outstr, mdefs->model)__builtin___strcpy_chk (outstr, mdefs->model, __builtin_object_size (outstr, 2 > 1 ? 1 : 0)); |
829 | outstr += strlen(mdefs->model); |
830 | if (sfx) |
831 | *outstr++ = sfx; |
832 | } |
833 | else if ((*var == 'v') && mdefs->variant[ndx] && |
834 | *mdefs->variant[ndx]) { |
835 | if (pfx) |
836 | *outstr++ = pfx; |
837 | strcpy(outstr, mdefs->variant[ndx])__builtin___strcpy_chk (outstr, mdefs->variant[ndx], __builtin_object_size (outstr, 2 > 1 ? 1 : 0)); |
838 | outstr += strlen(mdefs->variant[ndx]); |
839 | if (sfx) |
840 | *outstr++ = sfx; |
841 | } |
842 | if ((pfx == '(') && (*str == ')')) |
843 | str++; |
844 | } |
845 | else { |
846 | *outstr++ = *str++; |
847 | } |
848 | } |
849 | *outstr++ = '\0'; |
850 | if (orig != name) |
851 | free(orig); |
852 | return name; |
853 | } |
854 | |
855 | /***====================================================================***/ |
856 | |
857 | Bool |
858 | XkbRF_GetComponents(XkbRF_RulesPtr rules, |
859 | XkbRF_VarDefsPtr defs, XkbComponentNamesPtr names) |
860 | { |
861 | XkbRF_MultiDefsRec mdefs; |
862 | |
863 | MakeMultiDefs(&mdefs, defs); |
864 | |
865 | memset((char *) names, 0, sizeof(XkbComponentNamesRec))__builtin___memset_chk ((char *) names, 0, sizeof(XkbComponentNamesRec ), __builtin_object_size ((char *) names, 0)); |
866 | XkbRF_ClearPartialMatches(rules); |
867 | XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Normal(1L<<4)); |
868 | XkbRF_ApplyPartialMatches(rules, names); |
869 | XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append(1L<<3)); |
870 | XkbRF_ApplyPartialMatches(rules, names); |
871 | XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option(1L<<2)); |
872 | XkbRF_ApplyPartialMatches(rules, names); |
873 | |
874 | if (names->keycodes) |
875 | names->keycodes = XkbRF_SubstituteVars(names->keycodes, &mdefs); |
876 | if (names->symbols) |
877 | names->symbols = XkbRF_SubstituteVars(names->symbols, &mdefs); |
878 | if (names->types) |
879 | names->types = XkbRF_SubstituteVars(names->types, &mdefs); |
880 | if (names->compat) |
881 | names->compat = XkbRF_SubstituteVars(names->compat, &mdefs); |
882 | if (names->geometry) |
883 | names->geometry = XkbRF_SubstituteVars(names->geometry, &mdefs); |
884 | |
885 | FreeMultiDefs(&mdefs); |
886 | return (names->keycodes && names->symbols && names->types && |
887 | names->compat && names->geometry); |
888 | } |
889 | |
890 | static XkbRF_RulePtr |
891 | XkbRF_AddRule(XkbRF_RulesPtr rules) |
892 | { |
893 | if (rules->sz_rules < 1) { |
894 | rules->sz_rules = 16; |
895 | rules->num_rules = 0; |
896 | rules->rules = calloc(rules->sz_rules, sizeof(XkbRF_RuleRec)); |
897 | } |
898 | else if (rules->num_rules >= rules->sz_rules) { |
899 | rules->sz_rules *= 2; |
900 | rules->rules = realloc(rules->rules, |
901 | rules->sz_rules * sizeof(XkbRF_RuleRec)); |
902 | } |
903 | if (!rules->rules) { |
904 | rules->sz_rules = rules->num_rules = 0; |
905 | DebugF("Allocation failure in XkbRF_AddRule\n"); |
906 | return NULL((void*)0); |
907 | } |
908 | memset((char *) &rules->rules[rules->num_rules], 0, sizeof(XkbRF_RuleRec))__builtin___memset_chk ((char *) &rules->rules[rules-> num_rules], 0, sizeof(XkbRF_RuleRec), __builtin_object_size ( (char *) &rules->rules[rules->num_rules], 0)); |
909 | return &rules->rules[rules->num_rules++]; |
910 | } |
911 | |
912 | static XkbRF_GroupPtr |
913 | XkbRF_AddGroup(XkbRF_RulesPtr rules) |
914 | { |
915 | if (rules->sz_groups < 1) { |
916 | rules->sz_groups = 16; |
917 | rules->num_groups = 0; |
918 | rules->groups = calloc(rules->sz_groups, sizeof(XkbRF_GroupRec)); |
919 | } |
920 | else if (rules->num_groups >= rules->sz_groups) { |
921 | rules->sz_groups *= 2; |
922 | rules->groups = realloc(rules->groups, |
923 | rules->sz_groups * sizeof(XkbRF_GroupRec)); |
924 | } |
925 | if (!rules->groups) { |
926 | rules->sz_groups = rules->num_groups = 0; |
927 | return NULL((void*)0); |
928 | } |
929 | |
930 | memset((char *) &rules->groups[rules->num_groups], 0,__builtin___memset_chk ((char *) &rules->groups[rules-> num_groups], 0, sizeof(XkbRF_GroupRec), __builtin_object_size ((char *) &rules->groups[rules->num_groups], 0)) |
931 | sizeof(XkbRF_GroupRec))__builtin___memset_chk ((char *) &rules->groups[rules-> num_groups], 0, sizeof(XkbRF_GroupRec), __builtin_object_size ((char *) &rules->groups[rules->num_groups], 0)); |
932 | return &rules->groups[rules->num_groups++]; |
933 | } |
934 | |
935 | Bool |
936 | XkbRF_LoadRules(FILE * file, XkbRF_RulesPtr rules) |
937 | { |
938 | InputLine line; |
939 | RemapSpec remap; |
940 | XkbRF_RuleRec trule, *rule; |
941 | XkbRF_GroupRec tgroup, *group; |
942 | |
943 | if (!(rules && file)) |
944 | return FALSE0; |
945 | memset((char *) &remap, 0, sizeof(RemapSpec))__builtin___memset_chk ((char *) &remap, 0, sizeof(RemapSpec ), __builtin_object_size ((char *) &remap, 0)); |
946 | memset((char *) &tgroup, 0, sizeof(XkbRF_GroupRec))__builtin___memset_chk ((char *) &tgroup, 0, sizeof(XkbRF_GroupRec ), __builtin_object_size ((char *) &tgroup, 0)); |
947 | InitInputLine(&line); |
948 | while (GetInputLine(file, &line, TRUE1)) { |
949 | if (CheckLine(&line, &remap, &trule, &tgroup)) { |
950 | if (tgroup.number) { |
951 | if ((group = XkbRF_AddGroup(rules)) != NULL((void*)0)) { |
952 | *group = tgroup; |
953 | memset((char *) &tgroup, 0, sizeof(XkbRF_GroupRec))__builtin___memset_chk ((char *) &tgroup, 0, sizeof(XkbRF_GroupRec ), __builtin_object_size ((char *) &tgroup, 0)); |
954 | } |
955 | } |
956 | else { |
957 | if ((rule = XkbRF_AddRule(rules)) != NULL((void*)0)) { |
958 | *rule = trule; |
959 | memset((char *) &trule, 0, sizeof(XkbRF_RuleRec))__builtin___memset_chk ((char *) &trule, 0, sizeof(XkbRF_RuleRec ), __builtin_object_size ((char *) &trule, 0)); |
960 | } |
961 | } |
962 | } |
963 | line.num_line = 0; |
964 | } |
965 | FreeInputLine(&line); |
966 | return TRUE1; |
967 | } |
968 | |
969 | Bool |
970 | XkbRF_LoadRulesByName(char *base, char *locale, XkbRF_RulesPtr rules) |
971 | { |
972 | FILE *file; |
973 | char buf[PATH_MAX1024]; |
974 | Bool ok; |
975 | |
976 | if ((!base) || (!rules)) |
977 | return FALSE0; |
978 | if (locale) { |
979 | if (snprintf(buf, PATH_MAX, "%s-%s", base, locale)__builtin___snprintf_chk (buf, 1024, 0, __builtin_object_size (buf, 2 > 1 ? 1 : 0), "%s-%s", base, locale) >= PATH_MAX1024) |
980 | return FALSE0; |
981 | } |
982 | else { |
983 | if (strlen(base) + 1 > PATH_MAX1024) |
984 | return FALSE0; |
985 | strcpy(buf, base)__builtin___strcpy_chk (buf, base, __builtin_object_size (buf , 2 > 1 ? 1 : 0)); |
986 | } |
987 | |
988 | file = fopen(buf, "r"); |
989 | if ((!file) && (locale)) { /* fallback if locale was specified */ |
990 | strcpy(buf, base)__builtin___strcpy_chk (buf, base, __builtin_object_size (buf , 2 > 1 ? 1 : 0)); |
991 | file = fopen(buf, "r"); |
992 | } |
993 | if (!file) |
994 | return FALSE0; |
995 | ok = XkbRF_LoadRules(file, rules); |
996 | fclose(file); |
997 | return ok; |
998 | } |
999 | |
1000 | /***====================================================================***/ |
1001 | |
1002 | XkbRF_RulesPtr |
1003 | XkbRF_Create(void) |
1004 | { |
1005 | return calloc(1, sizeof(XkbRF_RulesRec)); |
1006 | } |
1007 | |
1008 | /***====================================================================***/ |
1009 | |
1010 | void |
1011 | XkbRF_Free(XkbRF_RulesPtr rules, Bool freeRules) |
1012 | { |
1013 | int i; |
1014 | XkbRF_RulePtr rule; |
1015 | XkbRF_GroupPtr group; |
1016 | |
1017 | if (!rules) |
1018 | return; |
1019 | if (rules->rules) { |
1020 | for (i = 0, rule = rules->rules; i < rules->num_rules; i++, rule++) { |
1021 | free((void *) rule->model); |
1022 | free((void *) rule->layout); |
1023 | free((void *) rule->variant); |
1024 | free((void *) rule->option); |
1025 | free((void *) rule->keycodes); |
1026 | free((void *) rule->symbols); |
1027 | free((void *) rule->types); |
1028 | free((void *) rule->compat); |
1029 | free((void *) rule->geometry); |
1030 | memset((char *) rule, 0, sizeof(XkbRF_RuleRec))__builtin___memset_chk ((char *) rule, 0, sizeof(XkbRF_RuleRec ), __builtin_object_size ((char *) rule, 0)); |
1031 | } |
1032 | free(rules->rules); |
1033 | rules->num_rules = rules->sz_rules = 0; |
1034 | rules->rules = NULL((void*)0); |
1035 | } |
1036 | |
1037 | if (rules->groups) { |
1038 | for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) { |
1039 | free((void *) group->name); |
1040 | free(group->words); |
1041 | } |
1042 | free(rules->groups); |
1043 | rules->num_groups = 0; |
1044 | rules->groups = NULL((void*)0); |
1045 | } |
1046 | if (freeRules) |
1047 | free(rules); |
1048 | return; |
1049 | } |