ReactOS 0.4.16-dev-92-g0c2cdca
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 */
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
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
65getVKName(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
111ULONG
113{
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
157UCHAR
159 OUT PULONG EntryChar,
160 OUT PCHAR LigatureChar)
161{
163 ULONG CharInfo = CHAR_NORMAL_KEY;
164 UCHAR StateChar;
165 ULONG CharCode;
166
167 /* Calculate the length of the 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
230NextLine(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
274ULONG
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
296ULONG
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
319ULONG
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
334ULONG
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
352ULONG
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
370ULONG
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
388ULONG
389DoDESCRIPTIONS(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
463ULONG
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
538ULONG
539DoKEYNAME(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
613ULONG
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
683ULONG
684DoLIGATURE(PVOID LigatureData)
685{
686 printf("LIGATURE support is not yet implemented. Please bug Arch to fix it\n");
687 return SkipLines();
688}
689
690ULONG
692{
693 printf("ATTRIBUTES support is not yet implemented. Please bug Arch to fix it\n");
694 return SkipLines();
695}
696
697ULONG
699{
700 printf("MODIFIERS support is not yet implemented. Please bug Arch to fix it\n");
701 return SkipLines();
702}
703
704ULONG
705DoDEADKEY(PVOID DeadKeyData)
706{
707 printf("DEADKEY support is not yet implemented. Please bug Arch to fix it\n");
708 return SkipLines();
709}
710
711ULONG
712DoLAYOUT(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 */
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
971ULONG
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 */
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 */
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 */
1148
1149 /* Now enter the output phase */
1150 return DoOutput(StateCount,
1151 ShiftStates,
1152 DescriptionData,
1153 LanguageData,
1155 DeadKeyData,
1156 LigatureData,
1157 KeyNameData,
1158 KeyNameExtData,
1159 KeyNameDeadData);
1160}
1161/* EOF */
unsigned char BOOLEAN
UINT ScanCode
Definition: VirtualKey.c:24
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int toupper(int c)
Definition: utclib.c:881
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define DPRINT1
Definition: precomp.h:8
BOOL Verbose
Definition: chkdsk.c:72
Definition: File.h:16
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const WCHAR Description[]
Definition: oid.c:1266
@ AttributeData
Definition: ntfs.h:168
#define printf
Definition: freeldr.h:97
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
FILE * gfpInput
Definition: main.c:21
#define CHAR_NORMAL_KEY
Definition: kbdtool.h:21
#define KEYWORD_COUNT
Definition: kbdtool.h:19
BOOLEAN SanityCheck
Definition: kbdtool.h:95
#define CHAR_INVALID_KEY
Definition: kbdtool.h:24
#define CHAR_DEAD_KEY
Definition: kbdtool.h:22
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
#define CHAR_LIGATURE_KEY
Definition: kbdtool.h:25
#define CHAR_OTHER_KEY
Definition: kbdtool.h:23
PCHAR gpszFileName
Definition: main.c:20
BOOLEAN UnicodeFile
Definition: kbdtool.h:95
#define ASSERT(a)
Definition: mode.c:44
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
_Check_return_ _CRTIMP char *__cdecl strdup(_In_opt_z_ const char *_Src)
#define exit(n)
Definition: config.h:202
#define memset(x, y, z)
Definition: compat.h:39
SCVK ScVk[]
Definition: data.c:146
VKNAME VKName[]
Definition: data.c:16
CHAR gDescription[256]
Definition: parser.c:19
ULONG isKeyWord(PCHAR p)
Definition: parser.c:53
PCHAR getVKName(IN ULONG VirtualKey, IN BOOLEAN Prefix)
Definition: parser.c:65
ULONG gID
Definition: parser.c:23
UCHAR getCharacterInfo(IN PCHAR State, OUT PULONG EntryChar, OUT PCHAR LigatureChar)
Definition: parser.c:158
ULONG DoLAYOUT(IN PLAYOUT LayoutData, IN PVOID LigatureData, IN PULONG ShiftStates, IN ULONG StateCount)
Definition: parser.c:712
ULONG DoMODIFIERS(VOID)
Definition: parser.c:698
ULONG DoVERSION(VOID)
Definition: parser.c:320
ULONG DoKBD(VOID)
Definition: parser.c:297
LAYOUT g_Layout
Definition: parser.c:25
CHAR gBuf[256]
Definition: parser.c:16
ULONG gKbdLayoutVersion
Definition: parser.c:24
ULONG DoKEYNAME(IN PKEYNAME *KeyNameData)
Definition: parser.c:539
ULONG DoDESCRIPTIONS(IN PKEYNAME *DescriptionData)
Definition: parser.c:389
ULONG DoLIGATURE(PVOID LigatureData)
Definition: parser.c:684
ULONG SkipLines(VOID)
Definition: parser.c:275
CHAR gKBDName[10]
Definition: parser.c:17
ULONG DoATTRIBUTES(PVOID AttributeData)
Definition: parser.c:691
ULONG getVKNum(IN PCHAR p)
Definition: parser.c:112
ULONG DoCOMPANY(VOID)
Definition: parser.c:353
ULONG DoSHIFTSTATE(IN PULONG StateCount, IN OUT PULONG ShiftStates)
Definition: parser.c:614
CHAR gLocaleName[256]
Definition: parser.c:21
ULONG DoDEADKEY(PVOID DeadKeyData)
Definition: parser.c:705
ULONG DoCOPYRIGHT(VOID)
Definition: parser.c:335
ULONG gLineCount
Definition: parser.c:26
BOOLEAN NextLine(PCHAR LineBuffer, ULONG BufferSize, FILE *File)
Definition: parser.c:230
CHAR gCopyright[256]
Definition: parser.c:18
CHAR gVKeyName[32]
Definition: parser.c:22
PCHAR KeyWordList[KEYWORD_COUNT]
Definition: parser.c:29
ULONG DoLOCALENAME(VOID)
Definition: parser.c:371
ULONG DoLANGUAGENAMES(IN PKEYNAME *LanguageData)
Definition: parser.c:464
ULONG DoParsing(VOID)
Definition: parser.c:972
CHAR gCompany[256]
Definition: parser.c:20
base of all file and directory entries
Definition: entries.h:83
Entry(ENTRY_TYPE etype)
Definition: entries.cpp:35
PCHAR Name
Definition: kbdtool.h:30
ULONG Code
Definition: kbdtool.h:29
struct tagKEYNAME * Next
Definition: kbdtool.h:31
USHORT ScanCode
Definition: kbdtool.h:36
UCHAR VirtualKey
Definition: kbdtool.h:37
BOOLEAN Processed
Definition: kbdtool.h:39
PCHAR Name
Definition: kbdtool.h:38
ULONG VirtualKey
Definition: kbdtool.h:44
uint32_t * PULONG
Definition: typedefs.h:59
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_In_ __drv_aliasesMem PSTRING Prefix
Definition: rtlfuncs.h:1644
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175