/*////////// BASE Defs AND INCLUDES ///////////////////////////////////*/ #include #include #include #include #if !defined(_WIN32) #define fcloseall(x) #define strupr(x) do { size_t i; for (i=0; i= MaxBlocks) MainError (SC_TooManyDBlocks, ""); return WriteToBlock (obnum++, btype, buffer, len, bname); } WORD WriteToBuffer (BYTE *str, WORD len) { WORD i = 0; while ( (i='0') && (line[lineptr]<='9')) cvtstr[i++] = line[lineptr++]; cvtstr[i] = 0; return ( (BYTE) (atoi (cvtstr) & 0xFF) ); } WORD ReadWord ( void ) { char cvtstr[8]; BYTE i=0; while ( (line[lineptr]>='0') && (line[lineptr]<='9')) cvtstr[i++] = line[lineptr++]; cvtstr[i] = 0; return ( (WORD) (atoi (cvtstr) & 0xFFFF) ); } BYTE ReadCharacter ( void ) { if (line[lineptr]=='#') { lineptr++; if ( (line[lineptr]=='#') || (line[lineptr]=='!')) return (line[lineptr++]); else return (ReadNumber()); } else return (line[lineptr++]); } void UpdateFlags ( BYTE KEYcom ) { if ((200<=KEYcom) && (KEYcom<=234)) flags |= F_Diacritics; if (162==KEYcom) flags |= F_BEEP; if ((80<=KEYcom) && (KEYcom<=199)) flags |= F_BasicCom; if ((80<=KEYcom) && (KEYcom<=99)) flags |= F_ExtCom; if ((140<=KEYcom) && (KEYcom<=159)) flags |= F_ExtCom; if ((162<=KEYcom) && (KEYcom<=199)) flags |= F_ExtCom; if ((80<=KEYcom) && (KEYcom<=89)) flags |= F_DefShift; if (165==KEYcom) flags |= F_DefShift; if ((150<=KEYcom) && (KEYcom<=154)) flags |= F_APM; if ((120<=KEYcom) && (KEYcom<=139)) { flags |= F_ExtCom; if ( blocks[obnum].WCS_ArraySize<10 ) { blocks[obnum].WCS_SChanges [blocks[obnum].WCS_ArraySize ]. SourceLine = lineNumber; blocks[obnum].WCS_SChanges [blocks[obnum].WCS_ArraySize ]. NewSubmapping = KEYcom-119; blocks[obnum].WCS_ArraySize++; } } } void ParseTransTable ( void ) { BYTE tempbuffer [20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, columnptr,bufferptr,newscancode; NoSpaces (); /*** 1: preceeding R (release) and Scancode ***/ if (toupper(line[lineptr])=='R') { tempbuffer[0] = 0x80; lineptr ++; } tempbuffer[0] |= ReadNumber(); if (prevkey >= tempbuffer[0]) SyntaxError ( SE_UnorderedKeys ); prevkey = tempbuffer[0]; /*** 2: Flags ***/ while (line[lineptr] && (line[lineptr] != 32)) { switch (toupper(line[lineptr])) { case 'C': tempbuffer[1] |= CapsLockFlag; break; case 'N': tempbuffer[1] |= NumLockFlag; break; case 'S': tempbuffer[1] |= ReplaceScanCodeFlag; break; case 'X': tempbuffer[1] |= LockKeyFlag; break; default: SyntaxError ( SE_UnknownFlag ); } lineptr++; } NoSpaces (); /*** 3: Planes ***/ columnptr = (bufferptr= 3); while ( line[lineptr] ) { if (tempbuffer[1] & ReplaceScanCodeFlag) { newscancode = ReadNumber(); if (!line[lineptr] || (line[lineptr] != '/')) SyntaxError (SE_SeparatorExpected); lineptr++; } if (line[lineptr]=='!') /* XCommand */ { lineptr++; tempbuffer[2] |= (1 << (columnptr-3)); switch (toupper(line[lineptr++])) { case 'C': tempbuffer[bufferptr] = 199; break; case 'L': tempbuffer[bufferptr] = 99; break; case 'S': tempbuffer[bufferptr] = 119; break; case 'A': tempbuffer[bufferptr] = 169; break; case 'O': tempbuffer[bufferptr] = 179; break; case 'H': tempbuffer[bufferptr] = 89; break; default: lineptr--; /* there was no section specifier */ } tempbuffer[bufferptr] += ReadNumber(); UpdateFlags ( tempbuffer[bufferptr] ); } else tempbuffer[bufferptr] = ReadCharacter (); if (tempbuffer[1] & ReplaceScanCodeFlag) if (line[lineptr] && (line[lineptr++] != 32)) SyntaxError (SE_SyntaxError); if (((columnptr++) -2)>2+MaxPlanes ) SyntaxError (SE_TooManyPlanes); if (tempbuffer[1] & ReplaceScanCodeFlag) tempbuffer[++bufferptr] = newscancode; NoSpaces (); bufferptr++; } /*** 4: update the length (with length-1)***/ if (tempbuffer[1] & LockKeyFlag) tempbuffer[1] = LockKeyFlag; else { tempbuffer[1] |= ((columnptr-3) -1); if ((columnptr-3)>maxPlanes) { maxPlanes = columnptr-3; maxPlaneLine = lineNumber; } } /* Error if 'C' or 'N' and columns=0,1 */ if ( (tempbuffer[1] & ( CapsLockFlag | NumLockFlag )) && !(tempbuffer[1] & 0x07)) SyntaxError (SE_CNRequiresL1); /*** 5: Copy to buffer ***/ columnptr = (tempbuffer[1] & 0x07) + 1; /* columnptr here used for length */ if (tempbuffer[1] & ReplaceScanCodeFlag ) columnptr <<= 1; WriteToBuffer (tempbuffer, 3 + columnptr); } void ParseCombi ( void ) { BYTE tempbuffer[130], count=0; /*** 1: leading character ***/ NoSpaces (); tempbuffer[0] = ReadCharacter(); NoSpaces (); /*** 2: pairs ***/ while (line[lineptr] /* && (count<63) */ ) { tempbuffer[(count+1)*2] = ReadCharacter(); NoSpaces(); if (!line[lineptr]) SyntaxError (SE_UnexpectedEOL); tempbuffer[(count+1)*2+1] = ReadCharacter(); NoSpaces(); if ((count++) >128) SyntaxError (SE_TooManyDiacritics); } tempbuffer[1] = count; /*** 3: copy to buffer ***/ WriteToBuffer (tempbuffer, (count+1)<<1); } BYTE strpos (char *str1, char *str2) { char *s = strstr (str1,str2); return (s==NULL) ? 0 : (s-str1+1); } BYTE ReadXKeyName ( void ) { BYTE b=0; switch (toupper(line[lineptr])) { case 'F': lineptr++; switch (toupper(line[lineptr])) { case 'S': lineptr++; b = ReadNumber (); if (!b || (b>12)) SyntaxError (SE_InvalidFKeyName); if ( (012)) SyntaxError (SE_InvalidFKeyName); if ( (012)) SyntaxError (SE_InvalidFKeyName); if ( (012)) SyntaxError (SE_InvalidFKeyName); if ( (0='0') && (line[i]<='9')) || ((line[i]>='A') && (line[i]<='Z')) || (line[i]=='_') && (j<20); dsname[j++] = line[i++] ); if (j>20) SyntaxError (SE_IdentifierTooL); if ((line[i]!=']') || (j<1) || (j>19)) SyntaxError (SE_WrongDataSection); dsname[j] = 0; return dsname; } void ParseKeysSection ( void ) { char name[20]; bufferPtr = 0; flags = 0; GetDataSectionName (name); blocks[obnum].WCS_ArraySize = 0; prevkey = 0; while (!feof(fin) && strcmp (GetLine(), "")) { if (line[0]=='[') break; ParseTransTable (); } buffer[bufferPtr++]=0; /* this 0 to indicate no more scancodes */ WriteToNextBlock (BT_KEYS, bufferPtr, name); } void ParseCombiSection ( void ) { char name[20]; BYTE numcombi=0; bufferPtr = 0; flags = 0; GetDataSectionName (name); while (!feof(fin) && strcmp (GetLine(), "")) { if (line[0]=='[') break; ParseCombi (); numcombi++; if (numcombi>35) MainError (SC_TooManyDiacritics, ""); } buffer[bufferPtr++]=0; /* this 0 to indicate no more scancodes */ WriteToNextBlock (BT_COMBI, bufferPtr, name); } void ParseStringSection ( void ) { char name[20]; BYTE numstr = 0; flags = 0; bufferPtr = 0; GetDataSectionName (name); while (!feof(fin) && strcmp (GetLine(), "")) { if (line[0]=='[') break; ParseString (); numstr++; if (numstr>79) MainError (SC_TooManyStrs,""); } WriteToNextBlock (BT_STRING, bufferPtr, name); } /* Pos is set to the next character after the key name Returns: 0: RShift 6: Shift 1: LShift 8: LControl 2: Control 9: LAlt 3: Alt 10: RControl 4: Scroll 11: RAlt 16: KanaLock / UserKey1 17: UserKey2 ... (16..23) 255: error(not found) */ BYTE GetShiftKeyName ( char *s, BYTE *pos ) { char *keynames[] = {"RSHIFT", "LSHIFT", "CTRL", "ALT", "SCROLLLOCK", "NUMLOCK", "CAPSLOCK", "", "LCTRL", "LALT", "RCTRL", "ALTGR", "E0","", "SHIFT","", "KANALOCK"}; int i; if ( strpos(s,"USERKEY") == 1) { i = atoi (&s[7]) + 15; *pos += 7; /* 7==strlen("USERKEY") */ while ( (s[*pos]>='0') && (s[*pos]<='9')) (*pos) ++; return (( (i<16) || (i>23) ) ? 0xFF : i); } for (i=16; i>=0; i--) { if ( (strpos (s, keynames[i]) == 1) && (keynames[i][0]) ) { *pos += strlen (keynames[i])-1; if (i==4) flags |= F_UseScroll; /* use of standard lock keys */ if (i==5) flags |= F_UseNum; if (i==6) flags |= F_UseCaps; if (i==16) i=23; /* KanaLock == UserLock8 */ return i; } } return 0xFF; } void ParsePlanesLine ( BYTE c ) { WORD *w =&planes[c].wtStd; WORD *w2 =&planes[c].wtUsr; BYTE n; planes[c].wtStd = 0; planes[c].exStd = 0; planes[c].wtUsr = 0; planes[c].exUsr = 0; lineptr = 0; strupr (line); while ( line[lineptr] ) { switch ( line[lineptr] ) { case '|': if (w==&planes[c].wtStd) { w = &planes[c].exStd; w2 = &planes[c].exUsr; } else SyntaxError (SE_TooManyVBars); case ' ': break; default : n = GetShiftKeyName (line+lineptr, &lineptr); if (n==0xFF) SyntaxError (SE_InvalidSKeyName); if (n<=15) *w |= (1 << n ); else *w2 |= ( 1 << (n-16)); } lineptr++; } } void ParsePlanesSection ( void ) { if (planenumber>0) MainError (SC_Only1Planes ,""); while (!feof(fin) && strcmp (GetLine(), "") && (planenumber<8)) { if (line[0]=='[') break; ParsePlanesLine (planenumber++); if (planenumber>8) MainError (SC_TooManyPlanes ,""); } } BYTE FindBlockByName (char *oname) { BYTE i; strupr (oname); for (i=0; i=20) SyntaxError (SE_IdentifierTooL); return id; } void ParseSubMappingsLine ( BYTE subm ) { char id[20]; NoSpaces (); submappings[subm].codepage = ReadWord (); submappings[subm].keysofs = 0xFF; submappings[subm].combiofs = 0xFF; submappings[subm].strofs = 0xFF; NoSpaces (); if (!line[lineptr]) SyntaxError (SE_UnexpectedEOL); if (line[lineptr]=='-') lineptr++; else submappings[subm].keysofs = FindBlockByName (ReadIdentifier (id)); NoSpaces (); if (!line[lineptr]) return; if (line[lineptr]=='-') lineptr++; else submappings[subm].combiofs = FindBlockByName (ReadIdentifier (id)); NoSpaces (); if (!line[lineptr]) return; if (line[lineptr]=='-') lineptr++; else submappings[subm].strofs = FindBlockByName (ReadIdentifier (id)); NoSpaces (); if (line[lineptr]) SyntaxError (SE_TooManyIdentifs); } void ParseSubMappingsSection ( void ) { if (submnumber>0) MainError (SC_Only1Submappings,""); while (!feof(fin) && strcmp (GetLine(), "") && (submnumber<16)) { if (line[0]=='[') break; ParseSubMappingsLine ( submnumber++ ) ; } if (submnumber>=16) MainError (SC_TooManySubmappings,""); if (submnumber<2) MainError (SC_2SubmRequired, ""); } void InsertFlags ( char *modstr ) { BYTE i=0; for (; modstr[i]; i++) switch ( modstr[i] ) { case 'C': flags |= F_Diacritics; break; case 'S': flags |= F_BEEP; break; case 'B': flags |= F_BasicCom; break; case 'E': flags |= F_ExtCom; break; case 'L': flags |= F_DefShift; break; case 'J': flags |= F_Japanese; break; case 'A': flags |= F_APM; break; case 'X': flags |= F_XString; break; } } void ParseGeneralLine ( void ) { WORD id = 0; strupr ( line ); if ( strpos (line, "NAME=") == 1) { lineptr = 5; id = ReadWord(); if (line[lineptr++] != ',') SyntaxError ( SE_WrongNameSpec ); names [namesptr++] = id & 0xFF; names [namesptr++] = id >> 8; for (;line[lineptr]; lineptr++) names[namesptr++] = line[lineptr]; names[namesptr++]=','; return; } if ( strpos (line, "DECIMALCHAR=") == 1) { if ( DecChar ) SyntaxError ( SE_TooManyDecChars ); lineptr = 12; DecChar = ReadCharacter(); NoSpaces (); if ( line[lineptr] ) SyntaxError ( SE_ErrInDecChar ); return; } if (strpos (line, "FLAGS=") == 1) { lineptr = 6; InsertFlags (line+lineptr); return; } printf ("Warning: unknown option ignored: %s\n", line); } void ParseGeneralSection ( void ) { if (namesptr>0) MainError (SC_Only1General,""); while (!feof(fin) && strcmp (GetLine(), "") && (namesptr<255)) { if (line[0]=='[') break; ParseGeneralLine (); } namesptr--; /* remove last comma */ if (namesptr==0) MainError (SC_MissingLName,""); /* at least one name */ } /* Uses fout for write */ void fputbuffer (BYTE *buf, WORD bufsize) { WORD j = 0; for (j=0; j> 8, f); } void fputsubmapping ( BYTE n ) { fputw ( submappings[n].codepage, fout ); if ( submappings[n].keysofs != 0xFF ) fputw ( blocks[ submappings[n].keysofs ].offset, fout ); else fputw ( 0, fout ); if ( submappings[n].combiofs != 0xFF ) fputw ( blocks[ submappings[n].combiofs ].offset, fout ); else fputw ( 0, fout ); if ( submappings[n].strofs != 0xFF ) fputw ( blocks[ submappings[n].strofs ].offset, fout ); else fputw ( 0, fout ); } void fputcolumn ( BYTE n ) { fputw ( planes[n].wtStd, fout ); fputw ( planes[n].exStd, fout ); fputw ( planes[n].wtUsr, fout ); fputw ( planes[n].exUsr, fout ); } /*/////////// MAIN BEGINS HERE ///////////////////////////////////////*/ int main ( int argc, char *argv[] ) { int i=0, j=0, k=0; /* other indices */ WORD w=0; char s[10]; /*/////////// PART 1: check parameters ////////////////////////////////*/ printf ("KEY file Compiler version 2.0 [2005/08/10] (creates KL ver %u.%u )\n", Version>>8, Version & 255); puts ("Copyright (c) 2003-2005 by Aitor Santamaria_Merino (under GPL)"); if ( argc<2 ) MainError (SC_WrongNParams, ""); for (i=1; i2) MainError (SC_SyntaxError, argv[i]); switch ( toupper (argv[i][1])) { case '?': ShowHelp (); return 0; case 'B': bare = TRUE; break; default: MainError (SC_UnknownSwitch, argv[i]); } } else { if (!finName[0]) strcpy (finName, argv[i]); else if (!foutName[0]) strcpy (foutName, argv[i]); else MainError (SC_WrongNParams, ""); } } if (!finName[0]) MainError (SC_WrongNParams, ""); /*/////////// PART 2: get filenames ///////////////////////////////////*/ /* Check presence of extension */ for ( i = strlen(finName)-1; (i>=0) && (finName[i]!='\\') && (finName[i]!='.'); i--); if (! ((i>=0) && (finName[i]=='.')) ) strcat (finName, ".KEY"); /* Get second argument */ if (!foutName[0]) { for ( i=strlen(finName)-1; finName[i]!='.'; i--); strncpy (foutName, finName,i+1); strcat (foutName, "KL"); } if ( !strchr(foutName, '.') ) strcat (foutName, ".KL"); /* Try to open the files */ if ((fin = fopen (finName,"rt"))==NULL) MainError (SC_CantOpenSource, finName); /*/////////////////// PART 3: compile ///////////////////////////*/ printf ("Compiling %s...\n",finName); /* 1: remove starting spaces/comments */ while (!feof(fin) && !strcmp (GetLine(), "")); /* 2: parse the sections */ while (!feof(fin)) { if (line[0]!='[') SyntaxError ( SE_SectionHeadExp ); strupr(line); if ( strpos(line,"[KEYS:") == 1 ) ParseKeysSection (); else if ( strpos(line,"[DIACRITICS:") == 1 ) ParseCombiSection (); else if ( strpos(line,"[STRINGS:") == 1 ) ParseStringSection (); else if ( !strcmp(line,"[PRINT]") ) while ( !feof(fin) && (GetLine()[0]!='[') ) puts (line); else while (!feof(fin) && GetLine()[0]!='['); } fclose (fin); /*/////////////////// PART 4: link 1: get link info /////////////*/ printf ("Linking %s...\n",finName); flags = usestrings ? F_XString : 0; /* Initialise global flags */ if ((fin = fopen (finName,"rt"))==NULL) MainError (SC_CantOpenSource, finName); /* 1: remove starting spaces/comments */ while (!feof(fin) && !strcmp (GetLine(), "")); /* 2: parse the sections */ while (!feof(fin)) { if (line[0]!='[') SyntaxError (SE_SectionHeadExp); strupr(line); NoSpaces (); if ( !strcmp(line,"[PLANES]")) ParsePlanesSection (); else if ( !strcmp(line,"[SUBMAPPINGS]")) ParseSubMappingsSection (); else if ( !strcmp(line,"[GENERAL]")) ParseGeneralSection (); else while (!feof(fin) && GetLine()[0]!='['); } fclose (fin); /* forever ;-) */ /* 3: At least one submappings and one general sections */ if (!submnumber) MainError (SC_SubmappingsNeeded, ""); if (!namesptr) MainError (SC_GeneralNeeded, ""); /* 3b: other possible problem: too many planes in a KEYS line */ if ( (planenumber+2) < maxPlanes ) MainError (SC_KEYSoverflowsplanes, itoa (maxPlaneLine,s,10)); /* 4: Warning on change of codepage */ for (i=0; i0) ) for (j=0; j=submnumber) MainError (SC_WrongSMChange, itoa (blocks[submappings[i].keysofs].WCS_SChanges[j].SourceLine,s,10)); w = submappings[k].codepage; if ( w && (submappings[i].codepage) && (submappings[i].codepage != w) ) { printf ("Warning on line %u: change of submapping changes the codepage of KEYB, and\n", blocks[submappings[i].keysofs].WCS_SChanges[j].SourceLine); printf ("will leave KEYB in an inconsistent state (sm: %u -> %u).\n",i,k); } } /*/////////////////// PART 5: link 2: fix-ups //////////////////*/ /* 1: Compute the size of the KeyCB header */ keycboffset = 20 + 8*(submnumber + planenumber); /* 2: Compute the offsets of the blocks */ for (i=0; i