diff --git a/hdr/nls.h b/hdr/nls.h index a4a7c09..4dcf0c7 100644 --- a/hdr/nls.h +++ b/hdr/nls.h @@ -284,8 +284,12 @@ /* * How the kernel and NLSFUNC communicate with each other */ - /* Must be returned by NLSFUNC upon MUX-14-00 */ + /* Must be pased to and returned by NLSFUNC upon MUX-14-00 */ #define NLS_FREEDOS_NLSFUNC_ID 0x534b + /* What version of nlsInfo and accompanying associations + Must be passed to NLSFUNC upon MUX-14-00 to identify the + correct kernel to the tools. */ +#define NLS_FREEDOS_NLSFUNC_VERSION 0xFD01 /* Represents a call to DOS-38 within DOS-65 handlers. Current implementation relys on 0x101! */ #define NLS_DOS_38 0x101 @@ -324,10 +328,10 @@ #define NLS_FLAG_DIRECT_YESNO 0x0004 /* DOS-65-23 */ #define NLS_FLAG_DIRECT_GETDATA 0x0008 /* DOS-65-XX, DOS-38 */ -#define NLS_FLAG_HARDCODED NLS_FLAG_DIRECT_UPCASE \ +#define NLS_FLAG_HARDCODED (NLS_FLAG_DIRECT_UPCASE \ | NLS_FLAG_DIRECT_FUPCASE \ | NLS_FLAG_DIRECT_YESNO \ - | NLS_FLAG_DIRECT_GETDATA + | NLS_FLAG_DIRECT_GETDATA) /* No codepage / country code given */ #define NLS_DEFAULT ((UWORD)-1) @@ -535,8 +539,9 @@ extern BYTE FAR hcTablesStart[], hcTablesEnd[]; COUNTRY.SYS into other files. */ -#define CSYS_FD_IDSTRING "FreeDOS COUNTRY.SYS v1.0\r\n" +#define CSYS_FD_IDSTRING "FreeDOS COUNTRY.SYS v1.0\r\n\x1a" +#if 0 struct csys_function { /* S3: function definition */ UDWORD csys_rpos; /* relative position to actual data */ UWORD csys_length; @@ -550,20 +555,62 @@ struct csys_ccDefinition { /* S1: country/codepage reference */ UWORD csys_cp; UWORD csys_cntry; }; +#endif + +struct csys_ccDefinition { /* country/codepage reference */ + UDWORD csys_pos; /* moving the 4byte value to the front + can increase performance */ + UWORD csys_cntry; + UWORD csys_cp; + UWORD csys_size1; /* size of nlsPackage struct rpos is pointing to */ + +/* initially the object rpos is pointing to conforms to a + struct nlsPackage, where: + struct nlsPackage FAR *nxt; is missing + UWORD cntry, cp; is missing + int flags; is NLS_FLAG_HARDCODED, if the + kernel is to handle the data of its own + UBYTE yeschar; is filled + UBYTE nochar; is filled + unsigned numSubfct; is filled + struct nlsPointer nlsPointers[1]; is filled + the pointer member is the absolute + position of the data within the file + of this structure: + UWORD count + count bytes + The "count" value is not a part + of the data itself. + Also: The data must be ordered corresponding to + NLS_CODE_REORDER_POINTERS. + Also: The last nlsPointer is subfct #1 _incl_ all its + data [is the extended country information: struct nlsExtCntryInfo] +*/ +}; struct csys_numEntries { /* helper structure for "number of entries" */ UWORD csys_entries; }; -/* Actually, this structure is never really used */ -struct nlsCSys_fileHeader { /* S0: primary structure */ - unsigned char csys_idstring[sizeof(CSYS_FD_IDSTRING) - 1]; - /* decrement by 1 to cut off \0 from IDString -- ska */ +/* Header of the COUNTRY.SYS file */ +struct nlsCSys_fileHeader { /* COUNTRY.SYS header */ + unsigned char csys_idstring[sizeof(CSYS_FD_IDSTRING)]; + UWORD csys_maxTotalSize; /* maximal size of the total amount of + any individual definition, that includes + the nlsPackage skeleton and the sum of + all bytes required to load all the + subfunctions individually. + --> The code is to allocate maxTotalSize + and load any country definition of this + file into this buffer without any + overflow. */ + DWORD csys_posIndex; /* absolute position of index table */ }; -struct csys_completeFileHeader { /* as S0, but full 128 bytes */ - unsigned char csys_idstring[sizeof(CSYS_FD_IDSTRING) - 1]; - unsigned char csys_padbytes[128 - (sizeof(CSYS_FD_IDSTRING) - 1)]; +/* Structure created by CountryInfoLoad() */ +struct nlsCSys_loadPackage { + UWORD csys_size; + struct nlsPackage csys_pkg; }; /* standard alignment */ diff --git a/kernel/nls.c b/kernel/nls.c index 5b8b7f3..74a0a39 100644 --- a/kernel/nls.c +++ b/kernel/nls.c @@ -130,7 +130,11 @@ COUNT muxLoadPkg(UWORD cp, UWORD cntry) /* 0x1401 == not installed, not ok to install */ /* 0x14FF == installed */ - r.BX = 0; /* make sure the NLSFUNC ID is updated */ + r.BX = NLS_FREEDOS_NLSFUNC_VERSION; /* What version of nlsInfo */ +#if NLS_FREEDOS_NLSFUNC_VERSION == NLS_FREEDOS_NLSFUNC_ID + /* make sure the NLSFUNC ID is updated */ +#error "NLS_FREEDOS_NLSFUNC_VERSION == NLS_FREEDOS_NLSFUNC_ID" +#endif r.CX = NLS_FREEDOS_NLSFUNC_ID; if (muxGo(0, &r) != 0x14ff) return DE_FILENOTFND; /* No NLSFUNC --> no load */ diff --git a/kernel/nls_load.c b/kernel/nls_load.c index 16d5122..0a4fa65 100644 --- a/kernel/nls_load.c +++ b/kernel/nls_load.c @@ -36,373 +36,16 @@ static BYTE *RcsId = "$Id$"; #endif -#define filename Config.cfgCSYS_fnam -#define cntry Config.cfgCSYS_cntry -#define cp Config.cfgCSYS_cp - -STATIC int err(void) -{ - printf("Syntax error in or invalid COUNTRY.SYS: \"%s\"\n", filename); - return 0; -} - -#define readStruct(s) readStructure(&(s), sizeof(s), fd) -STATIC int readStructure(void *buf, unsigned size, COUNT fd) -{ - if (read(fd, buf, size) == size) - return 1; - - return err(); -} - - /* Evaluate each argument only once */ -#define readFct(p,f) readFct_((p), (f), fd) -int readFct_(void *buf, struct csys_function *fct, COUNT fd) -{ - if (lseek(fd, fct->csys_rpos, 0) >= 0) - return readStructure(buf, fct->csys_length, fd); - return err(); -} - -#define seek(n) rseek((LONG)(n), fd) -static int rseek(LONG rpos, COUNT fd) -{ - if (lseek(fd, rpos, 1) >= 0) - return 1; - - return err(); -} - -COUNT csysOpen(void) -{ - COUNT fd; - struct nlsCSys_fileHeader header; - - if ((fd = open(filename, 0)) < 0) - { - printf("Cannot open: \"%s\"\n", filename); - return 1; - } - - if ((read(fd, &header, sizeof(header)) != sizeof(header)) - ||strcmp(header.csys_idstring, CSYS_FD_IDSTRING) != 0 - || lseek(fd, (LONG) sizeof(struct csys_completeFileHeader), 0) - != (LONG) sizeof(struct csys_completeFileHeader)) - { - printf("No valid COUNTRY.SYS: \"%s\"\n\nTry NLSFUNC /i %s\n", filename, - filename); - close(fd); - return -1; - } - - return fd; -} - -/* Searches for function definition of table #fctID and - moves it at index idx */ -STATIC int chkTable(int idx, int fctID, struct csys_function *fcts, - int numFct) -{ - struct csys_function *fct, hfct; - int i; - - for (i = 0, fct = fcts; i < numFct; ++i, ++fct) - if (fct->csys_fctID == fctID) - { - /* function found */ - if (i == idx) /* already best place */ - return 1; - /* Swap both places */ - fmemcpy(&hfct, fct, sizeof(hfct)); - fmemcpy(fct, &fcts[idx], sizeof(hfct)); - fmemcpy(&fcts[idx], &hfct, sizeof(hfct)); - return 1; - } - - printf("Mandatory table %u not found.\n", fctID); - return 0; -} - -/* - * Description of the algorithm the COUNTRY= information is loaded. - -1) LoadCountry() is activated in pass 1, because it offers the functionality -how to upcase characters to the kernel, it should be activated as -soon as possible within processing CONFIG.SYS. - -2) The method to locate the actual data within COUNTRY.SYS is pretty -basic and straight forward; so no detailed description here. - -3) To reduce permanent memory useage the option NLS_MODIFYABLE_DATA -controls whether or not the loaded NLS pkg may be modified. By default, -modifying this data is _not_ supported. -The reason is to allow to re-use already loaded data, e.g. to use the -same physical table for #2 (normal upcase) and #4 (filename upcase). -NLSFUNC even can re-use the data loaded via COUNTRY= and the hardcoded data. - -4) The problem is that even without point 3) it is not easily possible to -pre-judge how many bytes the NLS pkg will allocate in memory, because -this NLS implementation wants to support a wider range of NLS pkgs; because -neither the number of subfunctions nor the size of the data per subfunction -is fixed globally. -Therefore, the package is built-up incrementally: -4.1) First all function definition structures (S3) are read into memory. -While doing so the position field is transformed into the absolute -position within COUNTRY.SYS. -4.2) Then they are checked if a subfunction is defined more than once. -4.3) Then the entries are sorted in that way that tables 0x23, 1, 2, 4 and 5 -lead the table in that order. -4.4) Then the basic nlsPackage with as many entries within nlsPointers[] -is allocated as there are function definitions left (minus one as the -pseudo-table 0x23 does not require an entry). -4.5) Pseudo-table 0x23 is installed. -4.6) Table 1 is installed at the very end of the nlsPointers[] array. -4.7) In the order all remaining function definitions are installed in -the same order as in the other array. - -5) "Installing" means (except table 0x23): -5.1) Enlarge the nlsPackage structure to hold the necessary bytes of the -function definition (member csys_length). -5.2) Only if NLS_MODIFYABLE_DATA is _not_ defined and table is not #1: -The loaded data is compared to already loaded data and if such pattern is -already found in memory, a pointer to that memory area is used and the -loaded data is discarded. -First the local data is searched through, then the area of the hardcoded -NLS pkg. -Efficiency: function definitions with the same file position can automatically -use the same memory area. - -6) When all function definitions are loaded, the nlsPackage structure is -tightly filled without any pad bytes; two areas are wasted: -a) The area containing the S3 structures, and -b) probably the last loaded data could be found within the memory already, -so the nlsPackage structure is larger than necessary. - -8) But the memory allocation in pass 1 is temporary anyway, because in -the PostConfig() phase, all memory allocations are revoked and created -anew. At this point -- immediately after revoking all memory and -_before_ allocating any new memory -- the NLS pkg is located completely -within memory and one knows exactly which bytes to spare, and which data -can share the same physical memory; but if the normal PostConfig() -process would go on, this information would be lost, because it could be -overwritten. -==> Therefore the almost first operation within PostConfig() is to -move the NLS pkg upto the top (base?) of memory, thus, making sure -it is not overwritten and one need not re-load all the structures from -memory and, by doing so, loose the information which memory can be shared. - -9) Once this operation has been completed, the NLS pkg is joined into the -nlsInfo chain of loaded packages and is made active. - -=== - -To ease implementation the value of FP_SEG(nlsPointers[].pointer) != 0, -if the pointer refers to an absolute place, whereas FP_SEG() == 0, -indicates that the FP_OFF(...) is the offset base-relative to the data -offset; which is base-relative to the "nls" pointer. - */ -int csysLoadPackage(COUNT fd) -{ - struct csys_numEntries entries; - struct csys_ccDefinition entry; - struct csys_function *fcts; - struct nlsPackage *nls; - struct nlsPointer *poi; - int highmark, numFct, i, j; - int totalSize; -#ifndef NLS_MODIFYABLE_DATA - BYTE FAR *p; -#endif -#define numE entries.csys_entries -#define bufp(offset) (((BYTE*)nls) + (offset)) -#define fct fcts[numFct] - - /* When this function is called, the position of the file is - at offset 128 (number of country/codepage pairs) */ - if (!readStruct(entries)) - return 0; - while (numE--) - { - if (!readStruct(entry)) - return 0; - if (entry.csys_cntry == cntry - && (cp == NLS_DEFAULT || entry.csys_cp == cp)) - { - /* Requested entry found! */ - if (!seek(entry.csys_rpos) || !readStruct(entries)) - return 0; - /* Now reading the function definitions at this position */ - if (numE < 5) - { - printf("Syntax error in COUNTRY.SYS: Too few subfunctions\n"); - return 0; - } - /* If the file structure is good, each but one entry (0x23) is - one item within nlsPointers[] array */ - fcts = KernelAlloc(sizeof(struct csys_function) * numE); - numFct = 0; /* number of already loaded fct definition */ - totalSize = 0; - { - if (!readStruct(fct)) - return 0; - switch (fct.csys_fctID) - { - case 0: - case 0x20: - case 0x21: - case 0x22: - case 0xA0: - case 0xA1: - case 0xA2: - printf("Invalid subfunction %u ignored", fct.csys_fctID); - continue; - case 0x23: - if (fct.csys_length != 2) - { - printf("Pseudo-table 35 length mismatch\n"); - continue; - } - } - /* Search if the subfunction is already there */ - for (j = 0; j < numFct && fcts[j].csys_fctID != fct.csys_fctID; - ++j) ; - if (j != numFct) - { - printf("Subfunction %u defined multiple times, ignored\n", - fct.csys_fctID); - continue; - } - - /* OK --> update the rpos member */ - fct.csys_rpos += DosLtell(fd); - totalSize += fct.csys_length; - ++numFct; - } - while (--numE) ; - - /* i is the number of available function definition */ - /* check if all mandatory tables are loaded, at the same - time re-order the function definitions like that: - 0x23, 1, 2, 4, 5 - */ - - /* That's automatically a check that more than 3 definitions - are available */ - if (!chkTable(0, 0x23, fcts, numFct) /* pseudo-table 0x23 yes/no */ - || !chkTable(1, 1, fcts, numFct) /* ext cntry info */ - || !chkTable(2, 2, fcts, numFct) /* normal upcase */ - || !chkTable(3, 4, fcts, numFct) /* filename upcase */ - || !chkTable(4, 5, fcts, numFct)) /* filename terminator chars */ - return 0; - - /* Begin the loading process by to allocate memory as if - we had to load every byte */ - /* One nlsPointers structure is already part of nlsPackage; - two function definitions need no nlsPointers entry (0x32, 1); - one additional byte is required by table 1, but which is - already within totalSize as the length of pseudo-table - 0x23 has been counted. */ - nls = KernelAlloc((data = sizeof(struct nlsPackage) - + (numFct - 3) * sizeof(struct nlsPointer)) + - totalSize); - /* data := first byte not used by the control area of - the nlsPackage structure; at this point it is the - offset where table #1 is to be loaded to */ - - /* Install pseudo-table 0x23 */ - if (!readFct((BYTE *) & nls->yeschar, fcts)) - return 0; - nls->numSubfct = numFct - 1; /* pseudo-table 0x23 */ - - /* Install table #1 has it must overlay the last nlsPointers[] - item */ - *bufp(data) = 1; /* table #1 starts with the subfctID - then the data from the file follows */ - if (!readFct(bufp(++data), ++fcts)) - return 0; - data += fcts->csys_length; /* first byte of local data area */ - highmark = data; /* first unused byte */ - - for (j = 0, poi = nls->nlsPointers; j < numFct - 1; ++j, ++poi) - { - /* consecutively load all functions */ - if (!readFct(bufp(data), ++fcts)) - return 0; - poi->subfct = fcts->csys_fctID; - /* Now the function data is located at the current top of - used memory and, if allowed, the other memory is - tested, if such image is already loaded */ -#ifndef NLS_MODIFYABLE_DATA - /* Try to locate the contents of the buffer */ - /** brute force **/ - /* For the standard tables one need to match tables - 2 and 4 only. */ - for (i = data; i + fcts->csys_length < highmark; ++i) - { - if (memcmp(bufp(i), bufp(highmark), fcts->csys_length) == 0) - { - /* found! */ - /* ==> leave highmark untouch, but modify pointer */ - poi->pointer = MK_FP(0, i); - /* the segment portion == 0 identifies this pointer - as local within the current data area */ - goto nxtEntry; - } - } - /* Now try the hardcoded area */ - for (p = hcTablesStart; p < hcTablesEnd - fcts->csys_length; ++p) - { - if (fmemcmp(p, bufp(highmark), fcts->csys_length) == 0) - { - /* found! */ - /* ==> leave highmark untouch, but modify pointer */ - poi->pointer = p; - /* the segment portion != 0 identifies this is an - absolute pointer */ - goto nxtEntry; - } - } -#endif - /* Either not found or modifyable data allowed */ - poi->pointer = MK_FP(0, highmark); /* local address */ - highmark += fcts->csys_length; /* need to keep the data */ - nxtEntry: - } - /* how many memory is really required */ - Country.cfgCSYS_memory = highmark; - Country.cfgCSYS_data = nls; - return 1; - } - } -#undef numE - if (cp == NLS_DEFAULT) - printf("No definition of country ID %u in file \"%s\"\n", - cntry, filename); - else - printf - ("No definition of country ID %u for codepage %u in file \"%s\"\n", - cntry, cp, filename); - - return 0; -} - -BOOL LoadCountryInfo(char *fnam) -{ - COUNT fd; - int rc; - - if (strlen(fnam) < sizeof(filename)) - { - strcpy(filename, fnam); - if ((fd = csysOpen()) >= 0) - { - rc = csysLoadPackage(fd); - close(fd); - return rc; - } - } - else - printf("Filename too long\n"); - return 0; -} +/** Setup the environment for shared source NLS_LOAD.SRC **/ +/**ska obsoleted #define cfgMemory Config.cfgCSYS_memory */ +/**ska obsoleted #define cfgFilename Config.cfgCSYS_fnam */ +#define cfgFilename nlsInfo.fname /* char FAR * */ +/**ska obsoleted #define cfgCountry Config.cfgCSYS_cntry */ +/**ska obsoleted #define cfgCodepage Config.cfgCSYS_cp */ +#define cfgData Config.cfgCSYS_data /* struct nlsCSys_loadPackage FAR * */ +#define getMem(bytes) KernelAlloc(bytes) +#define openSYSFile(filename) open(filename, 0) /* read-only, binary */ +#define nlsStartOfChain nlsInfo.chain +#define upCaseFct CharMapSrvc +#include "nls_load.src"