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