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