xref: /reactos/sdk/tools/kbdtool/parser.c (revision 34593d93)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * PROJECT:         ReactOS Build Tools [Keyboard Layout Compiler]
3*c2c66affSColin Finck  * LICENSE:         BSD - See COPYING.BSD in the top level directory
4*c2c66affSColin Finck  * FILE:            tools/kbdtool/parser.c
5*c2c66affSColin Finck  * PURPOSE:         Parsing Logic
6*c2c66affSColin Finck  * PROGRAMMERS:     ReactOS Foundation
7*c2c66affSColin Finck  */
8*c2c66affSColin Finck 
9*c2c66affSColin Finck /* INCLUDES *******************************************************************/
10*c2c66affSColin Finck 
11*c2c66affSColin Finck #include "kbdtool.h"
12*c2c66affSColin Finck 
13*c2c66affSColin Finck /* GLOBALS ********************************************************************/
14*c2c66affSColin Finck 
15*c2c66affSColin Finck /* Internal parser data about everything that was parsed */
16*c2c66affSColin Finck CHAR gBuf[256];
17*c2c66affSColin Finck CHAR gKBDName[10];
18*c2c66affSColin Finck CHAR gCopyright[256];
19*c2c66affSColin Finck CHAR gDescription[256];
20*c2c66affSColin Finck CHAR gCompany[256];
21*c2c66affSColin Finck CHAR gLocaleName[256];
22*c2c66affSColin Finck CHAR gVKeyName[32];
23*c2c66affSColin Finck ULONG gID = 0;
24*c2c66affSColin Finck ULONG gKbdLayoutVersion;
25*c2c66affSColin Finck LAYOUT g_Layout;
26*c2c66affSColin Finck ULONG gLineCount;
27*c2c66affSColin Finck 
28*c2c66affSColin Finck /* Table of keywords the parser recognizes */
29*c2c66affSColin Finck PCHAR KeyWordList[KEYWORD_COUNT] =
30*c2c66affSColin Finck {
31*c2c66affSColin Finck     "KBD",
32*c2c66affSColin Finck     "VERSION",
33*c2c66affSColin Finck     "COPYRIGHT",
34*c2c66affSColin Finck     "COMPANY",
35*c2c66affSColin Finck     "LOCALENAME",
36*c2c66affSColin Finck     "MODIIFERS",
37*c2c66affSColin Finck     "SHIFTSTATE",
38*c2c66affSColin Finck     "ATTRIBUTES",
39*c2c66affSColin Finck     "LAYOUT",
40*c2c66affSColin Finck     "DEADKEY",
41*c2c66affSColin Finck     "LIGATURE",
42*c2c66affSColin Finck     "KEYNAME",
43*c2c66affSColin Finck     "KEYNAME_EXT",
44*c2c66affSColin Finck     "KEYNAME_DEAD",
45*c2c66affSColin Finck     "DESCRIPTIONS",
46*c2c66affSColin Finck     "LANGUAGENAMES",
47*c2c66affSColin Finck     "ENDKBD",
48*c2c66affSColin Finck };
49*c2c66affSColin Finck 
50*c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
51*c2c66affSColin Finck 
52*c2c66affSColin Finck ULONG
isKeyWord(PCHAR p)53*c2c66affSColin Finck isKeyWord(PCHAR p)
54*c2c66affSColin Finck {
55*c2c66affSColin Finck     ULONG i;
56*c2c66affSColin Finck 
57*c2c66affSColin Finck     /* Check if we know this keyword */
58*c2c66affSColin Finck     for (i = 0; i < KEYWORD_COUNT; i++) if (strcmp(KeyWordList[i], p) == 0) break;
59*c2c66affSColin Finck 
60*c2c66affSColin Finck     /* If we didn't find anything, i will be KEYWORD_COUNT, which is invalid */
61*c2c66affSColin Finck     return i;
62*c2c66affSColin Finck }
63*c2c66affSColin Finck 
64*c2c66affSColin Finck PCHAR
getVKName(IN ULONG VirtualKey,IN BOOLEAN Prefix)65*c2c66affSColin Finck getVKName(IN ULONG VirtualKey,
66*c2c66affSColin Finck           IN BOOLEAN Prefix)
67*c2c66affSColin Finck {
68*c2c66affSColin Finck     ULONG i;
69*c2c66affSColin Finck 
70*c2c66affSColin Finck     /* Loop for standard virtual key */
71*c2c66affSColin Finck     if (((VirtualKey >= 'A') && (VirtualKey <= 'Z')) ||
72*c2c66affSColin Finck         ((VirtualKey >= '0') && (VirtualKey <= '9')))
73*c2c66affSColin Finck     {
74*c2c66affSColin Finck         /* Fill out the name */
75*c2c66affSColin Finck         gVKeyName[0] = '\'';
76*c2c66affSColin Finck         gVKeyName[1] = VirtualKey;
77*c2c66affSColin Finck         gVKeyName[2] = '\'';
78*c2c66affSColin Finck         gVKeyName[3] = '\0';
79*c2c66affSColin Finck         return gVKeyName;
80*c2c66affSColin Finck     }
81*c2c66affSColin Finck 
82*c2c66affSColin Finck     /* Check if a prefix is required */
83*c2c66affSColin Finck     if (Prefix)
84*c2c66affSColin Finck     {
85*c2c66affSColin Finck         /* Add it */
86*c2c66affSColin Finck         strcpy(gVKeyName, "VK_");
87*c2c66affSColin Finck     }
88*c2c66affSColin Finck     else
89*c2c66affSColin Finck     {
90*c2c66affSColin Finck         /* Otherwise, don't add anything */
91*c2c66affSColin Finck         strcpy(gVKeyName, "");
92*c2c66affSColin Finck     }
93*c2c66affSColin Finck 
94*c2c66affSColin Finck     /* Loop all virtual keys */
95*c2c66affSColin Finck     for (i = 0; i < 36; i++)
96*c2c66affSColin Finck     {
97*c2c66affSColin Finck         /* Check if this key matches */
98*c2c66affSColin Finck         if (VKName[i].VirtualKey == VirtualKey)
99*c2c66affSColin Finck         {
100*c2c66affSColin Finck             /* Copy the key's name into the buffer */
101*c2c66affSColin Finck             strcat(gVKeyName, VKName[i].Name);
102*c2c66affSColin Finck             return gVKeyName;
103*c2c66affSColin Finck         }
104*c2c66affSColin Finck     }
105*c2c66affSColin Finck 
106*c2c66affSColin Finck     /* If we got here, then we failed, so print out an error name */
107*c2c66affSColin Finck     strcpy(gVKeyName, "#ERROR#");
108*c2c66affSColin Finck     return gVKeyName;
109*c2c66affSColin Finck }
110*c2c66affSColin Finck 
111*c2c66affSColin Finck ULONG
getVKNum(IN PCHAR p)112*c2c66affSColin Finck getVKNum(IN PCHAR p)
113*c2c66affSColin Finck {
114*c2c66affSColin Finck     ULONG Length;
115*c2c66affSColin Finck     ULONG i;
116*c2c66affSColin Finck     ULONG KeyNumber;
117*c2c66affSColin Finck 
118*c2c66affSColin Finck     /* Compute the length of the string */
119*c2c66affSColin Finck     Length = strlen(p);
120*c2c66affSColin Finck     if (!Length) return -1;
121*c2c66affSColin Finck 
122*c2c66affSColin Finck     /* Check if this is is a simple key */
123*c2c66affSColin Finck     if (Length == 1)
124*c2c66affSColin Finck     {
125*c2c66affSColin Finck         /* If it's a number, return it now */
126*c2c66affSColin Finck         if ((*p >= '0') && (*p <= '9')) return *p;
127*c2c66affSColin Finck 
128*c2c66affSColin Finck         /* Otherwise, convert the letter to upper case */
129*c2c66affSColin Finck         *p = toupper(*p);
130*c2c66affSColin Finck 
131*c2c66affSColin Finck         /* And make sure it's a valid letter */
132*c2c66affSColin Finck         if ((*p >= 'A') && (*p <='Z')) return *p;
133*c2c66affSColin Finck 
134*c2c66affSColin Finck         /* Otherwise, fail */
135*c2c66affSColin Finck         return -1;
136*c2c66affSColin Finck     }
137*c2c66affSColin Finck 
138*c2c66affSColin Finck     /* Otherwise, scan our virtual key names */
139*c2c66affSColin Finck     for (i = 0; i < 36; i++)
140*c2c66affSColin Finck     {
141*c2c66affSColin Finck         /* Check if we have a match */
142*c2c66affSColin Finck         if (!strcmp(VKName[i].Name, p)) return VKName[i].VirtualKey;
143*c2c66affSColin Finck     }
144*c2c66affSColin Finck 
145*c2c66affSColin Finck     /*  Check if this is a hex string */
146*c2c66affSColin Finck     if ((*p == '0') && ((*(p + 1) == 'x') || (*(p + 1) == 'X')))
147*c2c66affSColin Finck     {
148*c2c66affSColin Finck         /* Get the key number from the hex string */
149*c2c66affSColin Finck         *(p + 1) = 'x';
150*c2c66affSColin Finck         if (sscanf(p, "0x%x", &KeyNumber) == 1) return KeyNumber;
151*c2c66affSColin Finck     }
152*c2c66affSColin Finck 
153*c2c66affSColin Finck     /* No hope: fail */
154*c2c66affSColin Finck     return -1;
155*c2c66affSColin Finck }
156*c2c66affSColin Finck 
157*c2c66affSColin Finck UCHAR
getCharacterInfo(IN PCHAR State,OUT PULONG EntryChar,OUT PCHAR LigatureChar)158*c2c66affSColin Finck getCharacterInfo(IN PCHAR State,
159*c2c66affSColin Finck                  OUT PULONG EntryChar,
160*c2c66affSColin Finck                  OUT PCHAR LigatureChar)
161*c2c66affSColin Finck {
162*c2c66affSColin Finck     ULONG Length;
163*c2c66affSColin Finck     ULONG CharInfo = CHAR_NORMAL_KEY;
164*c2c66affSColin Finck     UCHAR StateChar;
165*c2c66affSColin Finck     ULONG CharCode;
166*c2c66affSColin Finck 
167*c2c66affSColin Finck     /* Calculate the length of the state */
168*c2c66affSColin Finck     Length = strlen(State);
169*c2c66affSColin Finck 
170*c2c66affSColin Finck     /* Check if this is at least a simple key state */
171*c2c66affSColin Finck     if (Length > 1)
172*c2c66affSColin Finck     {
173*c2c66affSColin Finck         /* Read the first character and check if it's a dead key */
174*c2c66affSColin Finck         StateChar = State[Length - 1];
175*c2c66affSColin Finck         if (StateChar == '@')
176*c2c66affSColin Finck         {
177*c2c66affSColin Finck             /* This is a dead key */
178*c2c66affSColin Finck             CharInfo = CHAR_DEAD_KEY;
179*c2c66affSColin Finck         }
180*c2c66affSColin Finck         else if (StateChar == '%')
181*c2c66affSColin Finck         {
182*c2c66affSColin Finck             /* This is another key */
183*c2c66affSColin Finck             CharInfo = CHAR_OTHER_KEY;
184*c2c66affSColin Finck         }
185*c2c66affSColin Finck     }
186*c2c66affSColin Finck 
187*c2c66affSColin Finck     /* Check if this is a numerical key state */
188*c2c66affSColin Finck     if ((Length - 1) >= 2)
189*c2c66affSColin Finck     {
190*c2c66affSColin Finck         /* Scan for extended character code entry */
191*c2c66affSColin Finck         if ((sscanf(State, "%6x", &CharCode) == 1) &&
192*c2c66affSColin Finck             (((Length == 5) && (State[0] == '0')) ||
193*c2c66affSColin Finck              ((Length == 6) && ((State[0] == '0') && (State[1] == '0')))))
194*c2c66affSColin Finck         {
195*c2c66affSColin Finck             /* Handle a ligature key */
196*c2c66affSColin Finck             CharInfo = CHAR_LIGATURE_KEY;
197*c2c66affSColin Finck 
198*c2c66affSColin Finck             /* Not yet handled */
199*c2c66affSColin Finck             printf("Ligatured character entries not yet supported!\n");
200*c2c66affSColin Finck             exit(1);
201*c2c66affSColin Finck         }
202*c2c66affSColin Finck         else
203*c2c66affSColin Finck         {
204*c2c66affSColin Finck             /* Get the normal character entry */
205*c2c66affSColin Finck             if (sscanf(State, "%4x", &CharCode) == 1)
206*c2c66affSColin Finck             {
207*c2c66affSColin Finck                 /* Does the caller want the key? */
208*c2c66affSColin Finck                 if (EntryChar) *EntryChar = CharCode;
209*c2c66affSColin Finck             }
210*c2c66affSColin Finck             else
211*c2c66affSColin Finck             {
212*c2c66affSColin Finck                 /* The entry is totally invalid */
213*c2c66affSColin Finck                 if (Verbose) printf("An unparseable character entry '%s' was found.\n", State);
214*c2c66affSColin Finck                 if (EntryChar) *EntryChar = 0;
215*c2c66affSColin Finck                 CharInfo = CHAR_INVALID_KEY;
216*c2c66affSColin Finck             }
217*c2c66affSColin Finck         }
218*c2c66affSColin Finck     }
219*c2c66affSColin Finck     else
220*c2c66affSColin Finck     {
221*c2c66affSColin Finck         /* Save the key if the caller requested it */
222*c2c66affSColin Finck         if (EntryChar) *EntryChar = *State;
223*c2c66affSColin Finck     }
224*c2c66affSColin Finck 
225*c2c66affSColin Finck     /* Return the type of character this is */
226*c2c66affSColin Finck     return CharInfo;
227*c2c66affSColin Finck }
228*c2c66affSColin Finck 
229*c2c66affSColin Finck BOOLEAN
NextLine(PCHAR LineBuffer,ULONG BufferSize,FILE * File)230*c2c66affSColin Finck NextLine(PCHAR LineBuffer,
231*c2c66affSColin Finck          ULONG BufferSize,
232*c2c66affSColin Finck          FILE *File)
233*c2c66affSColin Finck {
234*c2c66affSColin Finck     PCHAR p, pp;
235*c2c66affSColin Finck 
236*c2c66affSColin Finck     /* Scan each line */
237*c2c66affSColin Finck     while (fgets(LineBuffer, BufferSize, File))
238*c2c66affSColin Finck     {
239*c2c66affSColin Finck         /* Remember it */
240*c2c66affSColin Finck         gLineCount++;
241*c2c66affSColin Finck 
242*c2c66affSColin Finck         /* Reset the pointer at the beginning of the line */
243*c2c66affSColin Finck         p = LineBuffer;
244*c2c66affSColin Finck 
245*c2c66affSColin Finck         /* Now bypass all whitespace (and tabspace) */
246*c2c66affSColin Finck         while ((*p) && ((*p == ' ') || (*p == '\t'))) p++;
247*c2c66affSColin Finck 
248*c2c66affSColin Finck         /* If this is an old-style comment, skip the line */
249*c2c66affSColin Finck         if (*p == ';')  continue;
250*c2c66affSColin Finck 
251*c2c66affSColin Finck         /* Otherwise, check for new-style comment */
252*c2c66affSColin Finck         pp = strstr(p, "//");
253*c2c66affSColin Finck         if (pp)
254*c2c66affSColin Finck         {
255*c2c66affSColin Finck             /* We have a comment, so terminate there (unless the whole line is one) */
256*c2c66affSColin Finck             if (pp == p) continue;
257*c2c66affSColin Finck             *pp = '\0';
258*c2c66affSColin Finck         }
259*c2c66affSColin Finck         else
260*c2c66affSColin Finck         {
261*c2c66affSColin Finck             /* No comment, so find the new line and terminate there */
262*c2c66affSColin Finck             p = strchr(p, '\n');
263*c2c66affSColin Finck             if (p) *p = '\0';
264*c2c66affSColin Finck         }
265*c2c66affSColin Finck 
266*c2c66affSColin Finck         /* We have a line! */
267*c2c66affSColin Finck         return TRUE;
268*c2c66affSColin Finck     }
269*c2c66affSColin Finck 
270*c2c66affSColin Finck     /* No line found */
271*c2c66affSColin Finck     return FALSE;
272*c2c66affSColin Finck }
273*c2c66affSColin Finck 
274*c2c66affSColin Finck ULONG
SkipLines(VOID)275*c2c66affSColin Finck SkipLines(VOID)
276*c2c66affSColin Finck {
277*c2c66affSColin Finck     ULONG KeyWord;
278*c2c66affSColin Finck     CHAR KeyWordChars[32];
279*c2c66affSColin Finck 
280*c2c66affSColin Finck     /* Scan each line, skipping it if it's not a keyword */
281*c2c66affSColin Finck     while (NextLine(gBuf, sizeof(gBuf), gfpInput))
282*c2c66affSColin Finck     {
283*c2c66affSColin Finck         /* Read a single word */
284*c2c66affSColin Finck         if (sscanf(gBuf, "%s", KeyWordChars) == 1)
285*c2c66affSColin Finck         {
286*c2c66affSColin Finck             /* If the word is a keyword, stop skipping lines */
287*c2c66affSColin Finck             KeyWord = isKeyWord(KeyWordChars);
288*c2c66affSColin Finck             if (KeyWord < KEYWORD_COUNT) return KeyWord;
289*c2c66affSColin Finck         }
290*c2c66affSColin Finck     }
291*c2c66affSColin Finck 
292*c2c66affSColin Finck     /* We skipped all the possible lines, not finding anything */
293*c2c66affSColin Finck     return KEYWORD_COUNT;
294*c2c66affSColin Finck }
295*c2c66affSColin Finck 
296*c2c66affSColin Finck ULONG
DoKBD(VOID)297*c2c66affSColin Finck DoKBD(VOID)
298*c2c66affSColin Finck {
299*c2c66affSColin Finck     /* On Unicode files, we need to find the Unicode marker (FEEF) */
300*c2c66affSColin Finck     ASSERT(UnicodeFile == FALSE);
301*c2c66affSColin Finck 
302*c2c66affSColin Finck     /* Initial values */
303*c2c66affSColin Finck     *gKBDName = '\0';
304*c2c66affSColin Finck     *gDescription = '\0';
305*c2c66affSColin Finck 
306*c2c66affSColin Finck     /* Scan for the values */
307*c2c66affSColin Finck     if (sscanf(gBuf, "KBD %8s \"%40[^\"]\" %d", gKBDName, gDescription, &gID) < 2)
308*c2c66affSColin Finck     {
309*c2c66affSColin Finck         /* Couldn't find them */
310*c2c66affSColin Finck         printf("Unable to read keyboard name or description.\n");
311*c2c66affSColin Finck         exit(1);
312*c2c66affSColin Finck     }
313*c2c66affSColin Finck 
314*c2c66affSColin Finck     /* Debug only */
315*c2c66affSColin Finck     DPRINT1("KBD Name: [%8s] Description: [%40s] ID: [%d]\n", gKBDName, gDescription, gID);
316*c2c66affSColin Finck     return SkipLines();
317*c2c66affSColin Finck }
318*c2c66affSColin Finck 
319*c2c66affSColin Finck ULONG
DoVERSION(VOID)320*c2c66affSColin Finck DoVERSION(VOID)
321*c2c66affSColin Finck {
322*c2c66affSColin Finck     /* Scan for the value */
323*c2c66affSColin Finck     if (sscanf(gBuf, "VERSION %d", &gKbdLayoutVersion) < 1)
324*c2c66affSColin Finck     {
325*c2c66affSColin Finck         /* Couldn't find them */
326*c2c66affSColin Finck         printf("Unable to read keyboard version information.\n");
327*c2c66affSColin Finck     }
328*c2c66affSColin Finck 
329*c2c66affSColin Finck     /* Debug only */
330*c2c66affSColin Finck     DPRINT1("VERSION [%d]\n", gKbdLayoutVersion);
331*c2c66affSColin Finck     return SkipLines();
332*c2c66affSColin Finck }
333*c2c66affSColin Finck 
334*c2c66affSColin Finck ULONG
DoCOPYRIGHT(VOID)335*c2c66affSColin Finck DoCOPYRIGHT(VOID)
336*c2c66affSColin Finck {
337*c2c66affSColin Finck     /* Initial values */
338*c2c66affSColin Finck     *gCopyright = '\0';
339*c2c66affSColin Finck 
340*c2c66affSColin Finck     /* Scan for the value */
341*c2c66affSColin Finck     if (sscanf(gBuf, "COPYRIGHT \"%40[^\"]\"", gCopyright) < 1)
342*c2c66affSColin Finck     {
343*c2c66affSColin Finck         /* Couldn't find them */
344*c2c66affSColin Finck         printf("Unable to read the specified COPYRIGHT string.\n");
345*c2c66affSColin Finck     }
346*c2c66affSColin Finck 
347*c2c66affSColin Finck     /* Debug only */
348*c2c66affSColin Finck     DPRINT1("COPYRIGHT [%40s]\n", gCopyright);
349*c2c66affSColin Finck     return SkipLines();
350*c2c66affSColin Finck }
351*c2c66affSColin Finck 
352*c2c66affSColin Finck ULONG
DoCOMPANY(VOID)353*c2c66affSColin Finck DoCOMPANY(VOID)
354*c2c66affSColin Finck {
355*c2c66affSColin Finck     /* Initial values */
356*c2c66affSColin Finck     *gCompany = '\0';
357*c2c66affSColin Finck 
358*c2c66affSColin Finck     /* Scan for the value */
359*c2c66affSColin Finck     if (sscanf(gBuf, "COMPANY \"%85[^\"]\"", gCompany) < 1)
360*c2c66affSColin Finck     {
361*c2c66affSColin Finck         /* Couldn't find them */
362*c2c66affSColin Finck         printf("Unable to read the specified COMPANY name.\n");
363*c2c66affSColin Finck     }
364*c2c66affSColin Finck 
365*c2c66affSColin Finck     /* Debug only */
366*c2c66affSColin Finck     DPRINT1("COMPANY [%85s]\n", gCompany);
367*c2c66affSColin Finck     return SkipLines();
368*c2c66affSColin Finck }
369*c2c66affSColin Finck 
370*c2c66affSColin Finck ULONG
DoLOCALENAME(VOID)371*c2c66affSColin Finck DoLOCALENAME(VOID)
372*c2c66affSColin Finck {
373*c2c66affSColin Finck     /* Initial values */
374*c2c66affSColin Finck     *gLocaleName = '\0';
375*c2c66affSColin Finck 
376*c2c66affSColin Finck     /* Scan for the value */
377*c2c66affSColin Finck     if (sscanf(gBuf, "LOCALENAME \"%40[^\"]\"", gLocaleName) < 1)
378*c2c66affSColin Finck     {
379*c2c66affSColin Finck         /* Couldn't find them */
380*c2c66affSColin Finck         printf("Unable to read the specified COPYRIGHT string.\n");
381*c2c66affSColin Finck     }
382*c2c66affSColin Finck 
383*c2c66affSColin Finck     /* Debug only */
384*c2c66affSColin Finck     DPRINT1("LOCALENAME [%40s]\n", gLocaleName);
385*c2c66affSColin Finck     return SkipLines();
386*c2c66affSColin Finck }
387*c2c66affSColin Finck 
388*c2c66affSColin Finck ULONG
DoDESCRIPTIONS(IN PKEYNAME * DescriptionData)389*c2c66affSColin Finck DoDESCRIPTIONS(IN PKEYNAME* DescriptionData)
390*c2c66affSColin Finck {
391*c2c66affSColin Finck     ULONG KeyWord = 0;
392*c2c66affSColin Finck     CHAR Token[32];
393*c2c66affSColin Finck     ULONG LanguageCode;
394*c2c66affSColin Finck     PCHAR p, pp;
395*c2c66affSColin Finck     PKEYNAME Description;
396*c2c66affSColin Finck 
397*c2c66affSColin Finck     /* Assume nothing */
398*c2c66affSColin Finck     *DescriptionData = 0;
399*c2c66affSColin Finck 
400*c2c66affSColin Finck     /* Start scanning */
401*c2c66affSColin Finck     while (NextLine(gBuf, 256, gfpInput))
402*c2c66affSColin Finck     {
403*c2c66affSColin Finck         /* Search for token */
404*c2c66affSColin Finck         if (sscanf(gBuf, "%s", Token) != 1) continue;
405*c2c66affSColin Finck 
406*c2c66affSColin Finck         /* Make sure it's not just a comment */
407*c2c66affSColin Finck         if (*Token == ';') continue;
408*c2c66affSColin Finck 
409*c2c66affSColin Finck         /* Make sure it's not a keyword */
410*c2c66affSColin Finck         KeyWord = isKeyWord(Token);
411*c2c66affSColin Finck         if (KeyWord < KEYWORD_COUNT) break;
412*c2c66affSColin Finck 
413*c2c66affSColin Finck         /* Now scan for the language code */
414*c2c66affSColin Finck         if (sscanf(Token, " %4x", &LanguageCode) != 1)
415*c2c66affSColin Finck         {
416*c2c66affSColin Finck             /* Skip */
417*c2c66affSColin Finck             printf("An invalid LANGID was specified.\n");
418*c2c66affSColin Finck             continue;
419*c2c66affSColin Finck         }
420*c2c66affSColin Finck 
421*c2c66affSColin Finck         /* Now get the actual description */
422*c2c66affSColin Finck         if (sscanf(gBuf, " %*4x %s[^\n]", Token) != 1)
423*c2c66affSColin Finck         {
424*c2c66affSColin Finck             /* Skip */
425*c2c66affSColin Finck             printf("A language description is missing.\n");
426*c2c66affSColin Finck             continue;
427*c2c66affSColin Finck         }
428*c2c66affSColin Finck 
429*c2c66affSColin Finck         /* Get the description string and find the ending */
430*c2c66affSColin Finck         p = strstr(gBuf, Token);
431*c2c66affSColin Finck         pp = strchr(p, '\n');
432*c2c66affSColin Finck         if (!pp) pp = strchr(p, '\r');
433*c2c66affSColin Finck 
434*c2c66affSColin Finck         /* Terminate the description string here */
435*c2c66affSColin Finck         if (pp) *pp = 0;
436*c2c66affSColin Finck 
437*c2c66affSColin Finck         /* Now allocate the description */
438*c2c66affSColin Finck         Description = malloc(sizeof(KEYNAME));
439*c2c66affSColin Finck         if (!Description)
440*c2c66affSColin Finck         {
441*c2c66affSColin Finck             /* Fail */
442*c2c66affSColin Finck             printf("Unable to allocate the KEYNAME struct (out of memory?).\n");
443*c2c66affSColin Finck             exit(1);
444*c2c66affSColin Finck         }
445*c2c66affSColin Finck 
446*c2c66affSColin Finck         /* Fill out the structure */
447*c2c66affSColin Finck         Description->Code = LanguageCode;
448*c2c66affSColin Finck         Description->Name = strdup(p);
449*c2c66affSColin Finck         Description->Next = NULL;
450*c2c66affSColin Finck 
451*c2c66affSColin Finck         /* Debug only */
452*c2c66affSColin Finck         DPRINT1("LANGID: [%4x] Description: [%s]\n", Description->Code, Description->Name);
453*c2c66affSColin Finck 
454*c2c66affSColin Finck         /* Point to it and advance the pointer */
455*c2c66affSColin Finck         *DescriptionData = Description;
456*c2c66affSColin Finck         DescriptionData = &Description->Next;
457*c2c66affSColin Finck     }
458*c2c66affSColin Finck 
459*c2c66affSColin Finck     /* We are done */
460*c2c66affSColin Finck     return KeyWord;
461*c2c66affSColin Finck }
462*c2c66affSColin Finck 
463*c2c66affSColin Finck ULONG
DoLANGUAGENAMES(IN PKEYNAME * LanguageData)464*c2c66affSColin Finck DoLANGUAGENAMES(IN PKEYNAME* LanguageData)
465*c2c66affSColin Finck {
466*c2c66affSColin Finck     ULONG KeyWord = 0;
467*c2c66affSColin Finck     CHAR Token[32];
468*c2c66affSColin Finck     ULONG LanguageCode;
469*c2c66affSColin Finck     PCHAR p, pp;
470*c2c66affSColin Finck     PKEYNAME Language;
471*c2c66affSColin Finck 
472*c2c66affSColin Finck     /* Assume nothing */
473*c2c66affSColin Finck     *LanguageData = 0;
474*c2c66affSColin Finck 
475*c2c66affSColin Finck     /* Start scanning */
476*c2c66affSColin Finck     while (NextLine(gBuf, 256, gfpInput))
477*c2c66affSColin Finck     {
478*c2c66affSColin Finck         /* Search for token */
479*c2c66affSColin Finck         if (sscanf(gBuf, "%s", Token) != 1) continue;
480*c2c66affSColin Finck 
481*c2c66affSColin Finck         /* Make sure it's not just a comment */
482*c2c66affSColin Finck         if (*Token == ';') continue;
483*c2c66affSColin Finck 
484*c2c66affSColin Finck         /* Make sure it's not a keyword */
485*c2c66affSColin Finck         KeyWord = isKeyWord(Token);
486*c2c66affSColin Finck         if (KeyWord < KEYWORD_COUNT) break;
487*c2c66affSColin Finck 
488*c2c66affSColin Finck         /* Now scan for the language code */
489*c2c66affSColin Finck         if (sscanf(Token, " %4x", &LanguageCode) != 1)
490*c2c66affSColin Finck         {
491*c2c66affSColin Finck             /* Skip */
492*c2c66affSColin Finck             printf("An invalid LANGID was specified.\n");
493*c2c66affSColin Finck             continue;
494*c2c66affSColin Finck         }
495*c2c66affSColin Finck 
496*c2c66affSColin Finck         /* Now get the actual language */
497*c2c66affSColin Finck         if (sscanf(gBuf, " %*4x %s[^\n]", Token) != 1)
498*c2c66affSColin Finck         {
499*c2c66affSColin Finck             /* Skip */
500*c2c66affSColin Finck             printf("A language name is missing\n");
501*c2c66affSColin Finck             continue;
502*c2c66affSColin Finck         }
503*c2c66affSColin Finck 
504*c2c66affSColin Finck         /* Get the language string and find the ending */
505*c2c66affSColin Finck         p = strstr(gBuf, Token);
506*c2c66affSColin Finck         pp = strchr(p, '\n');
507*c2c66affSColin Finck         if (!pp) pp = strchr(p, '\r');
508*c2c66affSColin Finck 
509*c2c66affSColin Finck         /* Terminate the language string here */
510*c2c66affSColin Finck         if (pp) *pp = 0;
511*c2c66affSColin Finck 
512*c2c66affSColin Finck         /* Now allocate the language */
513*c2c66affSColin Finck         Language = malloc(sizeof(KEYNAME));
514*c2c66affSColin Finck         if (!Language)
515*c2c66affSColin Finck         {
516*c2c66affSColin Finck             /* Fail */
517*c2c66affSColin Finck             printf("Unable to allocate the KEYNAME struct (out of memory?).\n");
518*c2c66affSColin Finck             exit(1);
519*c2c66affSColin Finck         }
520*c2c66affSColin Finck 
521*c2c66affSColin Finck         /* Fill out the structure */
522*c2c66affSColin Finck         Language->Code = LanguageCode;
523*c2c66affSColin Finck         Language->Name = strdup(p);
524*c2c66affSColin Finck         Language->Next = NULL;
525*c2c66affSColin Finck 
526*c2c66affSColin Finck         /* Debug only */
527*c2c66affSColin Finck         DPRINT1("LANGID: [%4x] Name: [%s]\n", Language->Code, Language->Name);
528*c2c66affSColin Finck 
529*c2c66affSColin Finck         /* Point to it and advance the pointer */
530*c2c66affSColin Finck         *LanguageData = Language;
531*c2c66affSColin Finck         LanguageData = &Language->Next;
532*c2c66affSColin Finck     }
533*c2c66affSColin Finck 
534*c2c66affSColin Finck     /* We are done */
535*c2c66affSColin Finck     return KeyWord;
536*c2c66affSColin Finck }
537*c2c66affSColin Finck 
538*c2c66affSColin Finck ULONG
DoKEYNAME(IN PKEYNAME * KeyNameData)539*c2c66affSColin Finck DoKEYNAME(IN PKEYNAME* KeyNameData)
540*c2c66affSColin Finck {
541*c2c66affSColin Finck     ULONG KeyWord = 0;
542*c2c66affSColin Finck     CHAR Token[32];
543*c2c66affSColin Finck     ULONG CharacterCode;
544*c2c66affSColin Finck     PCHAR p, pp;
545*c2c66affSColin Finck     PKEYNAME KeyName;
546*c2c66affSColin Finck 
547*c2c66affSColin Finck     /* Assume nothing */
548*c2c66affSColin Finck     *KeyNameData = 0;
549*c2c66affSColin Finck 
550*c2c66affSColin Finck     /* Start scanning */
551*c2c66affSColin Finck     while (NextLine(gBuf, 256, gfpInput))
552*c2c66affSColin Finck     {
553*c2c66affSColin Finck         /* Search for token */
554*c2c66affSColin Finck         if (sscanf(gBuf, "%s", Token) != 1) continue;
555*c2c66affSColin Finck 
556*c2c66affSColin Finck         /* Make sure it's not just a comment */
557*c2c66affSColin Finck         if (*Token == ';') continue;
558*c2c66affSColin Finck 
559*c2c66affSColin Finck         /* Make sure it's not a keyword */
560*c2c66affSColin Finck         KeyWord = isKeyWord(Token);
561*c2c66affSColin Finck         if (KeyWord < KEYWORD_COUNT) break;
562*c2c66affSColin Finck 
563*c2c66affSColin Finck         /* Now scan for the character code */
564*c2c66affSColin Finck         if (sscanf(Token, " %4x", &CharacterCode) != 1)
565*c2c66affSColin Finck         {
566*c2c66affSColin Finck             /* Skip */
567*c2c66affSColin Finck             printf("An invalid character code was specified.\n");
568*c2c66affSColin Finck             continue;
569*c2c66affSColin Finck         }
570*c2c66affSColin Finck 
571*c2c66affSColin Finck         /* Now get the actual key name */
572*c2c66affSColin Finck         if (sscanf(gBuf, " %*4x %s[^\n]", Token) != 1)
573*c2c66affSColin Finck         {
574*c2c66affSColin Finck             /* Skip */
575*c2c66affSColin Finck             printf("A key name is missing\n");
576*c2c66affSColin Finck             continue;
577*c2c66affSColin Finck         }
578*c2c66affSColin Finck 
579*c2c66affSColin Finck         /* Get the key name string and find the ending */
580*c2c66affSColin Finck         p = strstr(gBuf, Token);
581*c2c66affSColin Finck         pp = strchr(p, '\n');
582*c2c66affSColin Finck         if (!pp) pp = strchr(p, '\r');
583*c2c66affSColin Finck 
584*c2c66affSColin Finck         /* Terminate the key name string here */
585*c2c66affSColin Finck         if (pp) *pp = 0;
586*c2c66affSColin Finck 
587*c2c66affSColin Finck         /* Now allocate the language */
588*c2c66affSColin Finck         KeyName = malloc(sizeof(KEYNAME));
589*c2c66affSColin Finck         if (!KeyName)
590*c2c66affSColin Finck         {
591*c2c66affSColin Finck             /* Fail */
592*c2c66affSColin Finck             printf("Unable to allocate the KEYNAME struct (out of memory?).\n");
593*c2c66affSColin Finck             exit(1);
594*c2c66affSColin Finck         }
595*c2c66affSColin Finck 
596*c2c66affSColin Finck         /* Fill out the structure */
597*c2c66affSColin Finck         KeyName->Code = CharacterCode;
598*c2c66affSColin Finck         KeyName->Name = strdup(p);
599*c2c66affSColin Finck         KeyName->Next = NULL;
600*c2c66affSColin Finck 
601*c2c66affSColin Finck         /* Debug only */
602*c2c66affSColin Finck         DPRINT1("CHARCODE: [%4x] Name: [%s]\n", KeyName->Code, KeyName->Name);
603*c2c66affSColin Finck 
604*c2c66affSColin Finck         /* Point to it and advance the pointer */
605*c2c66affSColin Finck         *KeyNameData = KeyName;
606*c2c66affSColin Finck         KeyNameData = &KeyName->Next;
607*c2c66affSColin Finck     }
608*c2c66affSColin Finck 
609*c2c66affSColin Finck     /* We are done */
610*c2c66affSColin Finck     return KeyWord;
611*c2c66affSColin Finck }
612*c2c66affSColin Finck 
613*c2c66affSColin Finck ULONG
DoSHIFTSTATE(IN PULONG StateCount,IN OUT PULONG ShiftStates)614*c2c66affSColin Finck DoSHIFTSTATE(IN PULONG StateCount,
615*c2c66affSColin Finck              IN OUT PULONG ShiftStates)
616*c2c66affSColin Finck {
617*c2c66affSColin Finck     ULONG KeyWord;
618*c2c66affSColin Finck     ULONG i;
619*c2c66affSColin Finck     ULONG ShiftState;
620*c2c66affSColin Finck     CHAR Token[32];
621*c2c66affSColin Finck 
622*c2c66affSColin Finck     /* Reset the shift states */
623*c2c66affSColin Finck     for (i = 0; i < 8; i++) ShiftStates[i] = -1;
624*c2c66affSColin Finck 
625*c2c66affSColin Finck     /* Start with no states */
626*c2c66affSColin Finck     *StateCount = 0;
627*c2c66affSColin Finck 
628*c2c66affSColin Finck     /* Scan for shift states */
629*c2c66affSColin Finck     while (NextLine(gBuf, 256, gfpInput))
630*c2c66affSColin Finck     {
631*c2c66affSColin Finck         /* Search for token */
632*c2c66affSColin Finck         if (sscanf(gBuf, "%s", Token) != 1) continue;
633*c2c66affSColin Finck 
634*c2c66affSColin Finck         /* Make sure it's not a keyword */
635*c2c66affSColin Finck         KeyWord = isKeyWord(Token);
636*c2c66affSColin Finck         if (KeyWord < KEYWORD_COUNT) break;
637*c2c66affSColin Finck 
638*c2c66affSColin Finck         /* Now scan for the shift state */
639*c2c66affSColin Finck         if (sscanf(gBuf, " %1s[012367]", Token) != 1)
640*c2c66affSColin Finck         {
641*c2c66affSColin Finck             /* We failed -- should we warn? */
642*c2c66affSColin Finck             if (Verbose) printf("An invalid shift state '%s' was found (use 0, 1, 2, 3, 6, or 7.)\n", Token);
643*c2c66affSColin Finck             continue;
644*c2c66affSColin Finck         }
645*c2c66affSColin Finck 
646*c2c66affSColin Finck         /* Now read the state */
647*c2c66affSColin Finck         ShiftState = atoi(Token);
648*c2c66affSColin Finck 
649*c2c66affSColin Finck         /* Scan existing states */
650*c2c66affSColin Finck         for (i = 0; i < *StateCount; i++)
651*c2c66affSColin Finck         {
652*c2c66affSColin Finck             /* Check for duplicate */
653*c2c66affSColin Finck             if ((ShiftStates[i] == ShiftState) && (Verbose))
654*c2c66affSColin Finck             {
655*c2c66affSColin Finck                 /* Warn user */
656*c2c66affSColin Finck                 printf("The state '%d' was duplicated for this Virtual Key.\n", ShiftStates[i]);
657*c2c66affSColin Finck                 break;
658*c2c66affSColin Finck             }
659*c2c66affSColin Finck         }
660*c2c66affSColin Finck 
661*c2c66affSColin Finck         /* Make sure we won't overflow */
662*c2c66affSColin Finck         if (*StateCount < 8)
663*c2c66affSColin Finck         {
664*c2c66affSColin Finck             /* Save this state */
665*c2c66affSColin Finck             ShiftStates[(*StateCount)++] = ShiftState;
666*c2c66affSColin Finck         }
667*c2c66affSColin Finck         else
668*c2c66affSColin Finck         {
669*c2c66affSColin Finck             /* Too many states -- should we warn? */
670*c2c66affSColin Finck             if (Verbose) printf("There were too many states (you defined %d).\n", *StateCount);
671*c2c66affSColin Finck         }
672*c2c66affSColin Finck     }
673*c2c66affSColin Finck 
674*c2c66affSColin Finck     /* Debug only */
675*c2c66affSColin Finck     DPRINT1("Found %d Shift States: [", *StateCount);
676*c2c66affSColin Finck     for (i = 0; i < *StateCount; i++) DPRINT1("%d ", ShiftStates[i]);
677*c2c66affSColin Finck     DPRINT1("]\n");
678*c2c66affSColin Finck 
679*c2c66affSColin Finck     /* We are done */
680*c2c66affSColin Finck     return KeyWord;
681*c2c66affSColin Finck }
682*c2c66affSColin Finck 
683*c2c66affSColin Finck ULONG
DoLIGATURE(PVOID LigatureData)684*c2c66affSColin Finck DoLIGATURE(PVOID LigatureData)
685*c2c66affSColin Finck {
686*c2c66affSColin Finck     printf("LIGATURE support is not yet implemented. Please bug Arch to fix it\n");
687*c2c66affSColin Finck     return SkipLines();
688*c2c66affSColin Finck }
689*c2c66affSColin Finck 
690*c2c66affSColin Finck ULONG
DoATTRIBUTES(PVOID AttributeData)691*c2c66affSColin Finck DoATTRIBUTES(PVOID AttributeData)
692*c2c66affSColin Finck {
693*c2c66affSColin Finck     printf("ATTRIBUTES support is not yet implemented. Please bug Arch to fix it\n");
694*c2c66affSColin Finck     return SkipLines();
695*c2c66affSColin Finck }
696*c2c66affSColin Finck 
697*c2c66affSColin Finck ULONG
DoMODIFIERS(VOID)698*c2c66affSColin Finck DoMODIFIERS(VOID)
699*c2c66affSColin Finck {
700*c2c66affSColin Finck     printf("MODIFIERS support is not yet implemented. Please bug Arch to fix it\n");
701*c2c66affSColin Finck     return SkipLines();
702*c2c66affSColin Finck }
703*c2c66affSColin Finck 
704*c2c66affSColin Finck ULONG
DoDEADKEY(PVOID DeadKeyData)705*c2c66affSColin Finck DoDEADKEY(PVOID DeadKeyData)
706*c2c66affSColin Finck {
707*c2c66affSColin Finck     printf("DEADKEY support is not yet implemented. Please bug Arch to fix it\n");
708*c2c66affSColin Finck     return SkipLines();
709*c2c66affSColin Finck }
710*c2c66affSColin Finck 
711*c2c66affSColin Finck ULONG
DoLAYOUT(IN PLAYOUT LayoutData,IN PVOID LigatureData,IN PULONG ShiftStates,IN ULONG StateCount)712*c2c66affSColin Finck DoLAYOUT(IN PLAYOUT LayoutData,
713*c2c66affSColin Finck          IN PVOID LigatureData,
714*c2c66affSColin Finck          IN PULONG ShiftStates,
715*c2c66affSColin Finck          IN ULONG StateCount)
716*c2c66affSColin Finck {
717*c2c66affSColin Finck     CHAR Token[32];
718*c2c66affSColin Finck     CHAR Cap[8];
719*c2c66affSColin Finck     ULONG KeyWord;
720*c2c66affSColin Finck     ULONG ScanCode, CurrentCode;
721*c2c66affSColin Finck     ULONG TokenCount;
722*c2c66affSColin Finck     ULONG VirtualKey;
723*c2c66affSColin Finck     ULONG i;
724*c2c66affSColin Finck     ULONG Count;
725*c2c66affSColin Finck     BOOLEAN FullEntry;
726*c2c66affSColin Finck     CHAR State[8][8];
727*c2c66affSColin Finck     ULONG ScanCodeCount = -1;
728*c2c66affSColin Finck     PLAYOUTENTRY Entry;
729*c2c66affSColin Finck     UCHAR CharacterType;
730*c2c66affSColin Finck     CHAR LigatureChar;
731*c2c66affSColin Finck 
732*c2c66affSColin Finck     /* Zero out the layout */
733*c2c66affSColin Finck     memset(LayoutData, 0, sizeof(LAYOUT));
734*c2c66affSColin Finck 
735*c2c66affSColin Finck     /* Read each line */
736*c2c66affSColin Finck     Entry = &LayoutData->Entry[0];
737*c2c66affSColin Finck     while (NextLine(gBuf, 256, gfpInput))
738*c2c66affSColin Finck     {
739*c2c66affSColin Finck         /* Search for token */
740*c2c66affSColin Finck         if (sscanf(gBuf, "%s", Token) != 1) continue;
741*c2c66affSColin Finck 
742*c2c66affSColin Finck         /* Make sure it's not just a comment */
743*c2c66affSColin Finck         if (*Token == ';') continue;
744*c2c66affSColin Finck 
745*c2c66affSColin Finck         /* Make sure it's not a keyword */
746*c2c66affSColin Finck         KeyWord = isKeyWord(Token);
747*c2c66affSColin Finck         if (KeyWord < KEYWORD_COUNT) break;
748*c2c66affSColin Finck 
749*c2c66affSColin Finck         /* Now read the entry */
750*c2c66affSColin Finck         TokenCount = sscanf(gBuf, " %x %s %s", &ScanCode, Token, Cap);
751*c2c66affSColin Finck         if (TokenCount == 3)
752*c2c66affSColin Finck         {
753*c2c66affSColin Finck             /* Full entry with cap */
754*c2c66affSColin Finck             FullEntry = TRUE;
755*c2c66affSColin Finck         }
756*c2c66affSColin Finck         else if (TokenCount != 2)
757*c2c66affSColin Finck         {
758*c2c66affSColin Finck             /* Fail, invalid LAYOUT entry */
759*c2c66affSColin Finck             printf("There are not enough columns in the layout list.\n");
760*c2c66affSColin Finck             exit(1);
761*c2c66affSColin Finck         }
762*c2c66affSColin Finck         else
763*c2c66affSColin Finck         {
764*c2c66affSColin Finck             /* Simplified layout with no cap */
765*c2c66affSColin Finck             FullEntry = FALSE;
766*c2c66affSColin Finck         }
767*c2c66affSColin Finck 
768*c2c66affSColin Finck         /* One more */
769*c2c66affSColin Finck         DPRINT1("RAW ENTRY: [%x %s %s]\n", ScanCode, Token, Cap);
770*c2c66affSColin Finck         Entry++;
771*c2c66affSColin Finck         if (++ScanCodeCount >= 110)
772*c2c66affSColin Finck         {
773*c2c66affSColin Finck             /* Too many! */
774*c2c66affSColin Finck             printf("ScanCode %02x - too many scancodes here to parse.\n", ScanCode);
775*c2c66affSColin Finck             exit(1);
776*c2c66affSColin Finck         }
777*c2c66affSColin Finck 
778*c2c66affSColin Finck         /* Fill out this entry */
779*c2c66affSColin Finck         Entry->ScanCode = ScanCode;
780*c2c66affSColin Finck         Entry->LineCount = gLineCount;
781*c2c66affSColin Finck 
782*c2c66affSColin Finck         /* Loop scancode table */
783*c2c66affSColin Finck         for (i = 0; i < 110; i++)
784*c2c66affSColin Finck         {
785*c2c66affSColin Finck             /* Get the current code */
786*c2c66affSColin Finck             CurrentCode = ScVk[i].ScanCode;
787*c2c66affSColin Finck             if (CurrentCode == 0xFFFF)
788*c2c66affSColin Finck             {
789*c2c66affSColin Finck                 /* New code */
790*c2c66affSColin Finck                 if (Verbose) printf("A new scancode is being defined: 0x%2X, %s\n", Entry->ScanCode, Token);
791*c2c66affSColin Finck 
792*c2c66affSColin Finck                 /* Fill out the entry */
793*c2c66affSColin Finck                 Entry->VirtualKey = getVKNum(Token);
794*c2c66affSColin Finck                 break;
795*c2c66affSColin Finck             }
796*c2c66affSColin Finck             else if (ScanCode == CurrentCode)
797*c2c66affSColin Finck             {
798*c2c66affSColin Finck                 /* Make sure we didn't already process it */
799*c2c66affSColin Finck                 if (ScVk[i].Processed)
800*c2c66affSColin Finck                 {
801*c2c66affSColin Finck                     /* Fail */
802*c2c66affSColin Finck                     printf("Scancode %X was previously defined.\n", ScanCode);
803*c2c66affSColin Finck                     exit(1);
804*c2c66affSColin Finck                 }
805*c2c66affSColin Finck 
806*c2c66affSColin Finck                 /* Check if there is a valid virtual key */
807*c2c66affSColin Finck                 if (ScVk[i].VirtualKey == 0xFFFF)
808*c2c66affSColin Finck                 {
809*c2c66affSColin Finck                     /* Fail */
810*c2c66affSColin Finck                     printf("The Scancode you tried to use (%X) is reserved.\n", ScanCode);
811*c2c66affSColin Finck                     exit(1);
812*c2c66affSColin Finck                 }
813*c2c66affSColin Finck 
814*c2c66affSColin Finck                 /* Fill out the entry */
815*c2c66affSColin Finck                 Entry->OriginalVirtualKey = ScVk[i].VirtualKey;
816*c2c66affSColin Finck                 Entry->Name = ScVk[i].Name;
817*c2c66affSColin Finck                 break;
818*c2c66affSColin Finck             }
819*c2c66affSColin Finck         }
820*c2c66affSColin Finck 
821*c2c66affSColin Finck         /* The entry is now processed */
822*c2c66affSColin Finck         Entry->Processed = TRUE;
823*c2c66affSColin Finck         ScVk[i].Processed = TRUE;
824*c2c66affSColin Finck 
825*c2c66affSColin Finck         /* Get the virtual key from the entry */
826*c2c66affSColin Finck         VirtualKey = getVKNum(Token);
827*c2c66affSColin Finck         Entry->VirtualKey = VirtualKey;
828*c2c66affSColin Finck         DPRINT1("ENTRY: [%x %x %x %s] with ",
829*c2c66affSColin Finck                 Entry->VirtualKey, Entry->OriginalVirtualKey, Entry->ScanCode, Entry->Name);
830*c2c66affSColin Finck 
831*c2c66affSColin Finck         /* Make sure it's valid */
832*c2c66affSColin Finck         if (VirtualKey == 0xFFFF)
833*c2c66affSColin Finck         {
834*c2c66affSColin Finck             /* Warn the user */
835*c2c66affSColin Finck             if (Verbose) printf("An invalid Virtual Key '%s' was defined.\n", Token);
836*c2c66affSColin Finck             continue;
837*c2c66affSColin Finck         }
838*c2c66affSColin Finck 
839*c2c66affSColin Finck         /* Is this a full entry */
840*c2c66affSColin Finck         if (FullEntry)
841*c2c66affSColin Finck         {
842*c2c66affSColin Finck             /* Do we have SGCAP data? Set cap mode to 2 */
843*c2c66affSColin Finck             if (!strcmp(Cap, "SGCAP")) *Cap = '2';
844*c2c66affSColin Finck 
845*c2c66affSColin Finck             /* Read the cap mode */
846*c2c66affSColin Finck             if (sscanf(Cap, "%1d[012]", &Entry->Cap) != 1)
847*c2c66affSColin Finck             {
848*c2c66affSColin Finck                 /* Invalid cap mode */
849*c2c66affSColin Finck                 printf("invalid Cap specified (%s). Must be 0, 1, or 2.\n", Cap);
850*c2c66affSColin Finck                 exit(1);
851*c2c66affSColin Finck             }
852*c2c66affSColin Finck         }
853*c2c66affSColin Finck 
854*c2c66affSColin Finck         /* Read the states */
855*c2c66affSColin Finck         Count = sscanf(gBuf,
856*c2c66affSColin Finck                        " %*s %*s %*s %s %s %s %s %s %s %s %s",
857*c2c66affSColin Finck                        State[0],
858*c2c66affSColin Finck                        State[1],
859*c2c66affSColin Finck                        State[2],
860*c2c66affSColin Finck                        State[3],
861*c2c66affSColin Finck                        State[4],
862*c2c66affSColin Finck                        State[5],
863*c2c66affSColin Finck                        State[6],
864*c2c66affSColin Finck                        State[7]);
865*c2c66affSColin Finck         Entry->StateCount = Count;
866*c2c66affSColin Finck         DPRINT1("%d STATES: [", Count);
867*c2c66affSColin Finck 
868*c2c66affSColin Finck         /* Check if there are less than 2 states */
869*c2c66affSColin Finck         if ((Count < 2) && (FullEntry))
870*c2c66affSColin Finck         {
871*c2c66affSColin Finck             /* Fail */
872*c2c66affSColin Finck             printf("You must have at least 2 characters.\n");
873*c2c66affSColin Finck             exit(1);
874*c2c66affSColin Finck         }
875*c2c66affSColin Finck 
876*c2c66affSColin Finck         /* Loop all states */
877*c2c66affSColin Finck         for (i = 0; i < Count; i++)
878*c2c66affSColin Finck         {
879*c2c66affSColin Finck             /* Check if this is an undefined state */
880*c2c66affSColin Finck             DPRINT1("%s ", State[i]);
881*c2c66affSColin Finck             if (!strcmp(State[i], "-1"))
882*c2c66affSColin Finck             {
883*c2c66affSColin Finck                 /* No data for this state */
884*c2c66affSColin Finck                 Entry->CharData[i] = -1;
885*c2c66affSColin Finck                 continue;
886*c2c66affSColin Finck             }
887*c2c66affSColin Finck 
888*c2c66affSColin Finck             /* Otherwise, check what kind of character this is */
889*c2c66affSColin Finck             CharacterType = getCharacterInfo(State[i],
890*c2c66affSColin Finck                                              &Entry->CharData[i],
891*c2c66affSColin Finck                                              &LigatureChar);
892*c2c66affSColin Finck             if (CharacterType == CHAR_DEAD_KEY)
893*c2c66affSColin Finck             {
894*c2c66affSColin Finck                 /* Save it as such */
895*c2c66affSColin Finck                 Entry->DeadCharData[i] = 1;
896*c2c66affSColin Finck             }
897*c2c66affSColin Finck             else if (CharacterType == CHAR_OTHER_KEY)
898*c2c66affSColin Finck             {
899*c2c66affSColin Finck                 /* Save it as such */
900*c2c66affSColin Finck                 Entry->OtherCharData[i] = 1;
901*c2c66affSColin Finck             }
902*c2c66affSColin Finck         }
903*c2c66affSColin Finck 
904*c2c66affSColin Finck         /* Check for sanity checks */
905*c2c66affSColin Finck         DPRINT1("]\n");
906*c2c66affSColin Finck         if (SanityCheck)
907*c2c66affSColin Finck         {
908*c2c66affSColin Finck             /* Not yet handled... */
909*c2c66affSColin Finck             printf("Sanity checks not yet handled!\n");
910*c2c66affSColin Finck             exit(1);
911*c2c66affSColin Finck         }
912*c2c66affSColin Finck 
913*c2c66affSColin Finck         /* Check if we had SGCAP data */
914*c2c66affSColin Finck         if (Entry->Cap & 2)
915*c2c66affSColin Finck         {
916*c2c66affSColin Finck             /* Not yet handled... */
917*c2c66affSColin Finck             printf("SGCAP state not yet handled!\n");
918*c2c66affSColin Finck             exit(1);
919*c2c66affSColin Finck         }
920*c2c66affSColin Finck     }
921*c2c66affSColin Finck 
922*c2c66affSColin Finck     /* Check if we have found any ScanCode in the file */
923*c2c66affSColin Finck 
924*c2c66affSColin Finck     if (ScanCodeCount == -1)
925*c2c66affSColin Finck     {
926*c2c66affSColin Finck         printf("No ScanCode found!\n");
927*c2c66affSColin Finck         exit(1);
928*c2c66affSColin Finck     }
929*c2c66affSColin Finck 
930*c2c66affSColin Finck     /* Process the scan code table */
931*c2c66affSColin Finck     Entry = &LayoutData->Entry[ScanCodeCount];
932*c2c66affSColin Finck     for (i = 0; i < 110; i++)
933*c2c66affSColin Finck     {
934*c2c66affSColin Finck         /* Get the scan code */
935*c2c66affSColin Finck         CurrentCode = ScVk[i].ScanCode;
936*c2c66affSColin Finck         if (CurrentCode == 0xFFFF) break;
937*c2c66affSColin Finck 
938*c2c66affSColin Finck         /* Check if this entry had been processed */
939*c2c66affSColin Finck         if (ScVk[i].Processed)
940*c2c66affSColin Finck         {
941*c2c66affSColin Finck             /* Skip it */
942*c2c66affSColin Finck             ScVk[i].Processed = FALSE;
943*c2c66affSColin Finck         }
944*c2c66affSColin Finck         else
945*c2c66affSColin Finck         {
946*c2c66affSColin Finck             /* Do we have too many? */
947*c2c66affSColin Finck             if (++ScanCodeCount >= 110)
948*c2c66affSColin Finck             {
949*c2c66affSColin Finck                 /* Fail */
950*c2c66affSColin Finck                 printf("ScanCode %02x - too many scancodes here to parse.\n", CurrentCode);
951*c2c66affSColin Finck                 exit(1);
952*c2c66affSColin Finck             }
953*c2c66affSColin Finck 
954*c2c66affSColin Finck             /* Build an entry for it */
955*c2c66affSColin Finck             Entry++;
956*c2c66affSColin Finck             Entry->ScanCode = CurrentCode;
957*c2c66affSColin Finck             Entry->VirtualKey = ScVk[i].VirtualKey;
958*c2c66affSColin Finck             Entry->OriginalVirtualKey = ScVk[i].VirtualKey;
959*c2c66affSColin Finck             Entry->Name = ScVk[i].Name;
960*c2c66affSColin Finck             Entry->Processed = TRUE;
961*c2c66affSColin Finck             Entry->LineCount = 0;
962*c2c66affSColin Finck             DPRINT1("AUTOMATIC ENTRY: [%x %x %s]\n",
963*c2c66affSColin Finck                     Entry->VirtualKey, Entry->ScanCode, Entry->Name);
964*c2c66affSColin Finck         }
965*c2c66affSColin Finck     }
966*c2c66affSColin Finck 
967*c2c66affSColin Finck     /* Skip what's left */
968*c2c66affSColin Finck     return KeyWord;
969*c2c66affSColin Finck }
970*c2c66affSColin Finck 
971*c2c66affSColin Finck ULONG
DoParsing(VOID)972*c2c66affSColin Finck DoParsing(VOID)
973*c2c66affSColin Finck {
974*c2c66affSColin Finck     ULONG KeyWords[KEYWORD_COUNT];
975*c2c66affSColin Finck     ULONG KeyWord;
976*c2c66affSColin Finck     ULONG StateCount;
977*c2c66affSColin Finck     ULONG ShiftStates[8];
978*c2c66affSColin Finck     PKEYNAME DescriptionData = NULL, LanguageData = NULL;
979*c2c66affSColin Finck     PKEYNAME KeyNameData = NULL, KeyNameExtData = NULL, KeyNameDeadData = NULL;
980*c2c66affSColin Finck     PVOID AttributeData = NULL, LigatureData = NULL, DeadKeyData = NULL;
981*c2c66affSColin Finck 
982*c2c66affSColin Finck     /* Parse keywords */
983*c2c66affSColin Finck     gLineCount = 0;
984*c2c66affSColin Finck     KeyWord = SkipLines();
985*c2c66affSColin Finck     if (KeyWord >= KEYWORD_COUNT)
986*c2c66affSColin Finck     {
987*c2c66affSColin Finck         /* Invalid keyword count, fail */
988*c2c66affSColin Finck         fclose(gfpInput);
989*c2c66affSColin Finck         printf("No keywords were found in '%s'.\n", gpszFileName);
990*c2c66affSColin Finck         exit(1);
991*c2c66affSColin Finck     }
992*c2c66affSColin Finck 
993*c2c66affSColin Finck     /* Now parse the keywords */
994*c2c66affSColin Finck     memset(KeyWords, 0, sizeof(KeyWords));
995*c2c66affSColin Finck     while (KeyWord < (KEYWORD_COUNT - 1))
996*c2c66affSColin Finck     {
997*c2c66affSColin Finck         /* Save this keyword */
998*c2c66affSColin Finck         KeyWords[KeyWord]++;
999*c2c66affSColin Finck 
1000*c2c66affSColin Finck         /* Check for duplicate entires, other than DEADKEY, which is okay */
1001*c2c66affSColin Finck         if ((KeyWord != 9) && (KeyWords[KeyWord] > 1) && (Verbose))
1002*c2c66affSColin Finck         {
1003*c2c66affSColin Finck             /* On a verbose run, warn the user */
1004*c2c66affSColin Finck             printf("The '%s' keyword appeared multiple times.\n",
1005*c2c66affSColin Finck                    KeyWordList[KeyWord]);
1006*c2c66affSColin Finck         }
1007*c2c66affSColin Finck 
1008*c2c66affSColin Finck         /* Now parse this keyword */
1009*c2c66affSColin Finck         switch (KeyWord)
1010*c2c66affSColin Finck         {
1011*c2c66affSColin Finck             /* KBD */
1012*c2c66affSColin Finck             case 0:
1013*c2c66affSColin Finck 
1014*c2c66affSColin Finck                 DPRINT1("Found KBD section\n");
1015*c2c66affSColin Finck                 KeyWord = DoKBD();
1016*c2c66affSColin Finck                 break;
1017*c2c66affSColin Finck 
1018*c2c66affSColin Finck             /* VERSION */
1019*c2c66affSColin Finck             case 1:
1020*c2c66affSColin Finck 
1021*c2c66affSColin Finck                 DPRINT1("Found VERSION section\n");
1022*c2c66affSColin Finck                 KeyWord = DoVERSION();
1023*c2c66affSColin Finck                 break;
1024*c2c66affSColin Finck 
1025*c2c66affSColin Finck             /* COPYRIGHT */
1026*c2c66affSColin Finck             case 2:
1027*c2c66affSColin Finck 
1028*c2c66affSColin Finck                 DPRINT1("Found COPYRIGHT section\n");
1029*c2c66affSColin Finck                 KeyWord = DoCOPYRIGHT();
1030*c2c66affSColin Finck                 break;
1031*c2c66affSColin Finck 
1032*c2c66affSColin Finck             /* COMPANY */
1033*c2c66affSColin Finck             case 3:
1034*c2c66affSColin Finck 
1035*c2c66affSColin Finck                 DPRINT1("Found COMPANY section\n");
1036*c2c66affSColin Finck                 KeyWord = DoCOMPANY();
1037*c2c66affSColin Finck                 break;
1038*c2c66affSColin Finck 
1039*c2c66affSColin Finck             /* LOCALENAME */
1040*c2c66affSColin Finck             case 4:
1041*c2c66affSColin Finck 
1042*c2c66affSColin Finck                 DPRINT1("Found LOCALENAME section\n");
1043*c2c66affSColin Finck                 KeyWord = DoLOCALENAME();
1044*c2c66affSColin Finck                 break;
1045*c2c66affSColin Finck 
1046*c2c66affSColin Finck             /* MODIFIERS */
1047*c2c66affSColin Finck             case 5:
1048*c2c66affSColin Finck 
1049*c2c66affSColin Finck                 DPRINT1("Found MODIFIERS section\n");
1050*c2c66affSColin Finck                 KeyWord = DoMODIFIERS();
1051*c2c66affSColin Finck                 break;
1052*c2c66affSColin Finck 
1053*c2c66affSColin Finck             /* SHIFTSTATE */
1054*c2c66affSColin Finck             case 6:
1055*c2c66affSColin Finck 
1056*c2c66affSColin Finck                 DPRINT1("Found SHIFTSTATE section\n");
1057*c2c66affSColin Finck                 KeyWord = DoSHIFTSTATE(&StateCount, ShiftStates);
1058*c2c66affSColin Finck                 if (StateCount < 2)
1059*c2c66affSColin Finck                 {
1060*c2c66affSColin Finck                     /* Fail */
1061*c2c66affSColin Finck                     fclose(gfpInput);
1062*c2c66affSColin Finck                     printf("ERROR");
1063*c2c66affSColin Finck                     exit(1);
1064*c2c66affSColin Finck                 }
1065*c2c66affSColin Finck                 break;
1066*c2c66affSColin Finck 
1067*c2c66affSColin Finck             /* ATTRIBUTES */
1068*c2c66affSColin Finck             case 7:
1069*c2c66affSColin Finck 
1070*c2c66affSColin Finck                 DPRINT1("Found ATTRIBUTES section\n");
1071*c2c66affSColin Finck                 KeyWord = DoATTRIBUTES(&AttributeData);
1072*c2c66affSColin Finck                 break;
1073*c2c66affSColin Finck 
1074*c2c66affSColin Finck             /* LAYOUT */
1075*c2c66affSColin Finck             case 8:
1076*c2c66affSColin Finck 
1077*c2c66affSColin Finck                 DPRINT1("Found LAYOUT section\n");
1078*c2c66affSColin Finck                 KeyWord = DoLAYOUT(&g_Layout,
1079*c2c66affSColin Finck                                    &LigatureData,
1080*c2c66affSColin Finck                                    ShiftStates,
1081*c2c66affSColin Finck                                    StateCount);
1082*c2c66affSColin Finck                 break;
1083*c2c66affSColin Finck 
1084*c2c66affSColin Finck             /* DEADKEY */
1085*c2c66affSColin Finck             case 9:
1086*c2c66affSColin Finck 
1087*c2c66affSColin Finck                 DPRINT1("Found DEADKEY section\n");
1088*c2c66affSColin Finck                 KeyWord = DoDEADKEY(&DeadKeyData);
1089*c2c66affSColin Finck                 break;
1090*c2c66affSColin Finck 
1091*c2c66affSColin Finck             /* LIGATURE */
1092*c2c66affSColin Finck             case 10:
1093*c2c66affSColin Finck 
1094*c2c66affSColin Finck                 DPRINT1("Found LIGATURE section\n");
1095*c2c66affSColin Finck                 KeyWord = DoLIGATURE(&LigatureData);
1096*c2c66affSColin Finck                 break;
1097*c2c66affSColin Finck 
1098*c2c66affSColin Finck             /* KEYNAME */
1099*c2c66affSColin Finck             case 11:
1100*c2c66affSColin Finck 
1101*c2c66affSColin Finck                 DPRINT1("Found KEYNAME section\n");
1102*c2c66affSColin Finck                 KeyWord = DoKEYNAME(&KeyNameData);
1103*c2c66affSColin Finck                 break;
1104*c2c66affSColin Finck 
1105*c2c66affSColin Finck             /* KEYNAME_EXT */
1106*c2c66affSColin Finck             case 12:
1107*c2c66affSColin Finck 
1108*c2c66affSColin Finck                 DPRINT1("Found KEYNAME_EXT section\n");
1109*c2c66affSColin Finck                 KeyWord = DoKEYNAME(&KeyNameExtData);
1110*c2c66affSColin Finck                 break;
1111*c2c66affSColin Finck 
1112*c2c66affSColin Finck             /* KEYNAME_DEAD */
1113*c2c66affSColin Finck             case 13:
1114*c2c66affSColin Finck 
1115*c2c66affSColin Finck                 DPRINT1("Found KEYNAME_DEAD section\n");
1116*c2c66affSColin Finck                 KeyWord = DoKEYNAME(&KeyNameDeadData);
1117*c2c66affSColin Finck                 break;
1118*c2c66affSColin Finck 
1119*c2c66affSColin Finck             /* DESCRIPTIONS */
1120*c2c66affSColin Finck             case 14:
1121*c2c66affSColin Finck 
1122*c2c66affSColin Finck                 DPRINT1("Found DESCRIPTIONS section\n");
1123*c2c66affSColin Finck                 KeyWord = DoDESCRIPTIONS(&DescriptionData);
1124*c2c66affSColin Finck                 break;
1125*c2c66affSColin Finck 
1126*c2c66affSColin Finck             /* LANGUAGENAMES */
1127*c2c66affSColin Finck             case 15:
1128*c2c66affSColin Finck 
1129*c2c66affSColin Finck                 DPRINT1("Found LANGUAGENAMES section\n");
1130*c2c66affSColin Finck                 KeyWord = DoLANGUAGENAMES(&LanguageData);
1131*c2c66affSColin Finck                 break;
1132*c2c66affSColin Finck 
1133*c2c66affSColin Finck             /* ENDKBD */
1134*c2c66affSColin Finck             case 16:
1135*c2c66affSColin Finck 
1136*c2c66affSColin Finck                 DPRINT1("Found ENDKBD section\n");
1137*c2c66affSColin Finck                 KeyWord = SkipLines();
1138*c2c66affSColin Finck                 break;
1139*c2c66affSColin Finck 
1140*c2c66affSColin Finck 
1141*c2c66affSColin Finck             default:
1142*c2c66affSColin Finck                 break;
1143*c2c66affSColin Finck         }
1144*c2c66affSColin Finck     }
1145*c2c66affSColin Finck 
1146*c2c66affSColin Finck     /* We are done */
1147*c2c66affSColin Finck     fclose(gfpInput);
1148*c2c66affSColin Finck 
1149*c2c66affSColin Finck     /* Now enter the output phase */
1150*c2c66affSColin Finck     return DoOutput(StateCount,
1151*c2c66affSColin Finck                     ShiftStates,
1152*c2c66affSColin Finck                     DescriptionData,
1153*c2c66affSColin Finck                     LanguageData,
1154*c2c66affSColin Finck                     AttributeData,
1155*c2c66affSColin Finck                     DeadKeyData,
1156*c2c66affSColin Finck                     LigatureData,
1157*c2c66affSColin Finck                     KeyNameData,
1158*c2c66affSColin Finck                     KeyNameExtData,
1159*c2c66affSColin Finck                     KeyNameDeadData);
1160*c2c66affSColin Finck }
1161*c2c66affSColin Finck /* EOF */
1162