From 0fddf1f8481d68b2fd95a126e64f9ee8ea23a6e1 Mon Sep 17 00:00:00 2001 From: Jim Tabor Date: Sun, 6 Aug 2000 05:50:17 +0000 Subject: [PATCH] Add new files and update cvs with patches and changes git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@61 6ac86273-5f31-0410-b378-82cca8765d1b --- kernel/001-437.nls | 240 --------------- kernel/config.c | 135 ++++++--- kernel/config.h | 38 +++ kernel/dosfns.c | 61 +++- kernel/fatdir.c | 68 ++++- kernel/fatfs.c | 9 +- kernel/fcbfns.c | 37 ++- kernel/globals.h | 26 +- kernel/int2f.asm | 126 +++++++- kernel/inthndlr.c | 92 +++--- kernel/kernel.asm | 9 +- kernel/kernel.mak | 17 +- kernel/main.c | 7 +- kernel/memmgr.c | 88 +++++- kernel/network.c | 5 +- kernel/newstuff.c | 180 ++++++++++- kernel/nls.c | 725 ++++++++++++++++++++++++++++++--------------- kernel/nls_hc.asm | 109 +++++++ kernel/nls_hc.c | 194 ------------ kernel/nls_load.c | 388 ++++++++++++++++++++++++ kernel/nlssupt.asm | 9 +- kernel/proto.h | 45 ++- kernel/task.c | 25 +- sys/sys.c | 3 + 24 files changed, 1795 insertions(+), 841 deletions(-) delete mode 100644 kernel/001-437.nls create mode 100644 kernel/config.h create mode 100644 kernel/nls_hc.asm delete mode 100644 kernel/nls_hc.c create mode 100644 kernel/nls_load.c diff --git a/kernel/001-437.nls b/kernel/001-437.nls deleted file mode 100644 index dbfa77f..0000000 --- a/kernel/001-437.nls +++ /dev/null @@ -1,240 +0,0 @@ - -/****************************************************************/ -/* */ -/* 001-437.nls */ -/* DOS-C */ -/* */ -/* National Languge Support USA Code Page */ -/* */ -/* Copyright (c) 1996 */ -/* Pasquale J. Villani */ -/* All Rights Reserved */ -/* */ -/* Copyright (c) 1996 */ -/* Steffen Kaiser */ -/* All Rights Reserved */ -/* */ -/* This file is part of DOS-C. */ -/* */ -/* DOS-C is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version */ -/* 2, or (at your option) any later version. */ -/* */ -/* DOS-C is distributed in the hope that it will be useful, but */ -/* WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ -/* the GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public */ -/* License along with DOS-C; see the file COPYING. If not, */ -/* write to the Free Software Foundation, 675 Mass Ave, */ -/* Cambridge, MA 02139, USA. */ -/****************************************************************/ - -/* $Logfile: D:/dos-c/src/kernel/001-437.nlv $ */ -#ifdef VERSION_STRINGS -static BYTE *RcsId = "$Header$"; -#endif - -/* - * $Log$ - * Revision 1.3 2000/05/25 20:56:20 jimtabor - * Fixed project history - * - * Revision 1.2 2000/05/08 04:29:59 jimtabor - * Update CVS to 2020 - * - * Revision 1.1.1.1 2000/05/06 19:34:53 jhall1 - * The FreeDOS Kernel. A DOS kernel that aims to be 100% compatible with - * MS-DOS. Distributed under the GNU GPL. - * - * Revision 1.2 2000/03/09 06:07:10 kernel - * 2017f updates by James Tabor - * - * Revision 1.1.1.1 1999/03/29 15:40:36 jprice - * New version without IPL.SYS - * - * Revision 1.2 1999/01/22 04:13:25 jprice - * Formating - * - * Revision 1.1.1.1 1999/01/20 05:51:01 jprice - * Imported sources - * - * - * Rev 1.2 29 May 1996 21:03:46 patv - * bug fixes for v0.91a - * - * Rev 1.1 19 Feb 1996 4:34:48 patv - * Corrected typo - * - * Rev 1.0 19 Feb 1996 3:37:48 patv - * Initial revision. - */ - -/* This initialization segment is included into the file where needed. */ -/* It's cuurently included in the following file: nls.c. */ -{ - { - { - 0, 0, 0, 0, 0, 0, 0, 0 - } - , - "\\COUNTRY.SYS", - 437, - 6, - { - { - (VOID FAR *) & nlsInfo.upNCsize, 2 - } - , - { - (VOID FAR *) & nlsInfo.upFCsize, 4 - } - , - { - (VOID FAR *) & nlsInfo.nlsFn, 5 - } - , - { - (VOID FAR *) & nlsInfo.collSize, 6 - } - , - { - (VOID FAR *) & nlsInfo.nlsExtCtryInfo.countryCode, 1 - } - , - { - (VOID FAR *) & nlsInfo.dbcSize, 7 - } - } - , - - 1, /* country code */ - 437, /* code page */ - { - 0, /* date format */ - { - /* currency string */ - '$', '\x00', '\x00', '\x00', '\x00', /* 0 - 4 */ - } - , - { /* thousand separator */ - ',', '\x00' /* 0 - 1 */ - } - , - { /* decimal point */ - '.', '\x00' /* 0 - 1 */ - } - , - { /* date separator */ - '-', '\x00' /* 0 - 1 */ - } - , - { /* time separator */ - ':', '\x00' /* 0 - 1 */ - } - , - 0, /* currency format */ - 2, /* currency prescision */ - 0, /* time format */ - CharMapSrvc, /* upcase function */ - { /* data separator */ - ',', '\x00' /* 0 - 1 */ - } - } - } - , - 'Y', 'N', /* Yes/No prompt characters */ - 128, /* upcase table */ - { - '\x80', '\x9a', 'E', 'A', '\x8e', 'A', '\x8f', '\x80' /* 0 - 7 */ - ,'E', 'E', 'E', 'I', 'I', 'I', '\x8e', '\x8f' /* 8 - 15 */ - ,'\x90', '\x92', '\x92', 'O', '\x99', 'O', 'U', 'U' /* 16 - 23 */ - ,'Y', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f' /* 24 - 31 */ - ,'A', 'I', 'O', 'U', '\xa5', '\xa5', '\xa6', '\xa7' /* 32 - 39 */ - ,'\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf' /* 40 - 47 */ - ,'\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7' /* 48 - 55 */ - ,'\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf' /* 56 - 63 */ - ,'\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7' /* 64 - 71 */ - ,'\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf' /* 72 - 79 */ - ,'\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7' /* 80 - 87 */ - ,'\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf' /* 88 - 95 */ - ,'\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7' /* 96 - 103 */ - ,'\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef' /* 104 - 111 */ - ,'\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7' /* 112 - 119 */ - ,'\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff' /* 120 - 127 */ - } - , - 128, /* file name upcase table */ - { - '\x80', '\x9a', 'E', 'A', '\x8e', 'A', '\x8f', '\x80' /* 0 - 7 */ - ,'E', 'E', 'E', 'I', 'I', 'I', '\x8e', '\x8f' /* 8 - 15 */ - ,'\x90', '\x92', '\x92', 'O', '\x99', 'O', 'U', 'U' /* 16 - 23 */ - ,'Y', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f' /* 24 - 31 */ - ,'A', 'I', 'O', 'U', '\xa5', '\xa5', '\xa6', '\xa7' /* 32 - 39 */ - ,'\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf' /* 40 - 47 */ - ,'\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7' /* 48 - 55 */ - ,'\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf' /* 56 - 63 */ - ,'\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7' /* 64 - 71 */ - ,'\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf' /* 72 - 79 */ - ,'\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7' /* 80 - 87 */ - ,'\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf' /* 88 - 95 */ - ,'\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7' /* 96 - 103 */ - ,'\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef' /* 104 - 111 */ - ,'\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7' /* 112 - 119 */ - ,'\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff' /* 120 - 127 */ - } - , - 256, /* collating sequence table */ - { - '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07' /* 0 - 7 */ - ,'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f' /* 8 - 15 */ - ,'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17' /* 16 - 23 */ - ,'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f' /* 24 - 31 */ - ,' ', '!', '"', '#', '$', '%', '&', '\'' /* 32 - 39 */ - ,'(', ')', '*', '+', ',', '-', '.', '/' /* 40 - 47 */ - ,'0', '1', '2', '3', '4', '5', '6', '7' /* 48 - 55 */ - ,'8', '9', ':', ';', '<', '=', '>', '?' /* 56 - 63 */ - ,'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G' /* 64 - 71 */ - ,'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O' /* 72 - 79 */ - ,'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W' /* 80 - 87 */ - ,'X', 'Y', 'Z', '[', '\\', ']', '^', '_' /* 88 - 95 */ - ,'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G' /* 96 - 103 */ - ,'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O' /* 104 - 111 */ - ,'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W' /* 112 - 119 */ - ,'X', 'Y', 'Z', '{', '|', '}', '~', '\x7f' /* 120 - 127 */ - ,'C', 'U', 'E', 'A', 'A', 'A', 'A', 'C' /* 128 - 135 */ - ,'E', 'E', 'E', 'I', 'I', 'I', 'A', 'A' /* 136 - 143 */ - ,'E', 'A', 'A', 'O', 'O', 'O', 'U', 'U' /* 144 - 151 */ - ,'Y', 'O', 'U', '$', '$', '$', '$', '$' /* 152 - 159 */ - ,'A', 'I', 'O', 'U', 'N', 'N', '\xa6', '\xa7' /* 160 - 167 */ - ,'?', '\xa9', '\xaa', '\xab', '\xac', '!', '"', '"' /* 168 - 175 */ - ,'\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7' /* 176 - 183 */ - ,'\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf' /* 184 - 191 */ - ,'\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7' /* 192 - 199 */ - ,'\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf' /* 200 - 207 */ - ,'\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7' /* 208 - 215 */ - ,'\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf' /* 216 - 223 */ - ,'\xe0', 'S', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7' /* 224 - 231 */ - ,'\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef' /* 232 - 239 */ - ,'\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7' /* 240 - 247 */ - ,'\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff' /* 248 - 255 */ - } - , - 0, /* no DBC support */ - 0, /* DBC end marker */ - { - 22, /* size of permittable character structure */ - 1, /* reserved */ - '\x00', '\xff', /* first/last permittable character */ - 0, /* reserved */ - '\x00', ' ', /* first/last excluded character */ - 2, /* reserved */ - 14, /* number of separators */ - { /* separators */ - '.', '"', '/', '\\', '[', ']', ':', '|', /* 0 - 7 */ - '<', '>', '+', '=', ';', ',' /* 8 - 13 */ - } - } -} diff --git a/kernel/config.c b/kernel/config.c index 2a57f1e..9596cb1 100644 --- a/kernel/config.c +++ b/kernel/config.c @@ -39,6 +39,9 @@ static BYTE *RcsId = "$Id$"; /* * $Log$ + * Revision 1.6 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.5 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * @@ -148,12 +151,14 @@ static BYTE FAR *lpOldLast; static BYTE FAR *upOldLast; static COUNT nCfgLine; static COUNT nPass; +static COUNT UmbState; static BYTE szLine[256]; static BYTE szBuf[256]; int singleStep = 0; INIT VOID zumcb_init(mcb FAR * mcbp, UWORD size); +INIT VOID mumcb_init(mcb FAR * mcbp, UWORD size); INIT VOID Buffers(BYTE * pLine); INIT VOID sysScreenMode(BYTE * pLine); @@ -201,7 +206,7 @@ static struct table commands[] = {"country", 1, Country}, {"device", 2, Device}, {"devicehigh", 2, DeviceHigh}, - {"dos", 1, Dosmem}, + {"dos", 2, Dosmem}, {"fcbs", 1, Fcbs}, {"files", 1, Files}, {"lastdrive", 1, Lastdrive}, @@ -229,6 +234,8 @@ INIT void PreConfig(void) { /* Set pass number */ nPass = 0; + VgaSet = 0; + UmbState = 0; /* Initialize the base memory pointers */ lpOldLast = lpBase = AlignParagraph((BYTE FAR *) & last); @@ -301,9 +308,6 @@ INIT void PreConfig(void) /* Also, run config.sys to load drivers. */ INIT void PostConfig(void) { - - COUNT tmp = 0xc000; - /* Set pass number */ nPass = 2; /* compute lastdrive ... */ @@ -368,19 +372,6 @@ INIT void PostConfig(void) FP_SEG(lpBase), FP_OFF(lpBase)); #endif - if(uppermem_link) - { - upBase = MK_FP(tmp , 0); - uppermem_root = FP_SEG(upBase) + ((FP_OFF(upBase) + 0x0f) >> 4); - umcb_init((mcb FAR *) (MK_FP(uppermem_root, 0)), 0 ); - - upBase += 16; - -#ifdef DEBUG - printf("UMB Allocation completed: top at 0x%04x:0x%04x\n", - FP_SEG(upBase), FP_OFF(upBase)); -#endif - } } @@ -403,15 +394,34 @@ INIT VOID configDone(VOID) mcb_init((mcb FAR *) (MK_FP(first_mcb, 0)), (ram_top << 6) - first_mcb - 1); - if(uppermem_link) + if(UmbState == 1) { - uppermem_root = FP_SEG(upBase) + ((FP_OFF(upBase) + 0x0f) >> 4); - zumcb_init((mcb FAR *) (MK_FP(uppermem_root, 0)), - (UMB_top << 6) - uppermem_root - 1); + + mumcb_init((mcb FAR *) (MK_FP(0x9fff, 0)), + umb_start - 0x9fff); + +/* make last end of mem block normal with SC */ + + mumcb_init((mcb FAR *) (MK_FP(uppermem_root, 0)), + (FP_SEG(upBase) + ((FP_OFF(upBase) + 0x0f) >> 4)) - uppermem_root - 1); + + uppermem_root = FP_SEG(upBase) + ((FP_OFF(upBase) + 0x0f) >> 4); + + zumcb_init((mcb FAR *) (MK_FP(uppermem_root, 0)), + (umb_start + UMB_top ) - uppermem_root - 1); + upBase += 16; + } +#ifdef DEBUG + printf("UMB Allocation completed: top at 0x%04x:0x%04x\n", + FP_SEG(upBase), FP_OFF(upBase)); +#endif + /* The standard handles should be reopened here, because we may have loaded new console or printer drivers in CONFIG.SYS */ + + } INIT VOID DoConfig(VOID) @@ -484,6 +494,37 @@ INIT VOID DoConfig(VOID) while (!bEof && *pLine != EOF) { +/* + Do it here in the loop. +*/ + if(UmbState == 2){ + if(!Umb_Test()){ + UmbState = 1; + upBase = MK_FP(umb_start , 0); + uppermem_root = umb_start; + +/* master sig for umb region with full size */ + + umcb_init((mcb FAR *) upBase, UMB_top ); + upBase += 16; + +/* reset root */ + + uppermem_root = FP_SEG(upBase) + ((FP_OFF(upBase) + 0x0f) >> 4); + +/* setup the real mcb for the devicehigh block */ + + zumcb_init((mcb FAR *) (MK_FP(uppermem_root, 0)), UMB_top - 1); + upBase += 16; + +#ifdef DEBUG + printf("UMB Allocation completed: top at 0x%04x:0x%04x\n", + FP_SEG(upBase), FP_OFF(upBase)); +#endif + } + } + + for (pTmp = pLine; pTmp - szLine < LINESIZE; pTmp++) { if (*pTmp == '\r' || *pTmp == EOF) @@ -676,22 +717,17 @@ INIT static VOID Lastdrive(BYTE * pLine) Config.cfgLastdrive = max(Config.cfgLastdrive, drv); } +/* + UmbState of confidence, 1 is sure, 2 maybe, 4 unknown and 0 no way. +*/ + INIT static VOID Dosmem(BYTE * pLine) { - COUNT tmp; - COUNT FAR * u = MK_FP(0xc000, 0); - + if(UmbState == 0){ + uppermem_link = 0; + uppermem_root = 0; GetStringArg(pLine, szBuf); - uppermem_link = strcmp(szBuf, "UMB") ? 1 : 0; - - if(uppermem_link) - { - tmp = *u; - *u = 0x1234; - if(*u == 0x1234) - *u = tmp; - else - uppermem_link = 0; + UmbState = strcmp(szBuf, "UMB") ? 2 : 0; } } @@ -827,7 +863,7 @@ INIT static VOID Break(BYTE * pLine) INIT static VOID DeviceHigh(BYTE * pLine) { - if(uppermem_link) + if(UmbState == 1) { LoadDevice(pLine, UMB_top, TRUE); } @@ -1036,23 +1072,34 @@ INIT VOID mcbp->m_type = MCB_LAST; mcbp->m_psp = FREE_PSP; + +/* if(UmbState == 1)*/ + + mcbp->m_size = (size - 1); +/* mcbp->m_size = size; +*/ for (i = 0; i < 8; i++) mcbp->m_name[i] = '\0'; mem_access_mode = FIRST_FIT; } + +/* master umb sig */ + INIT VOID umcb_init(mcb FAR * mcbp, UWORD size) { COUNT i; static char name[8] = "UMB "; - mcbp->m_type = 0x4d; - mcbp->m_psp = 0x08; + mcbp->m_type = MCB_LAST; + mcbp->m_psp = (UWORD) FP_SEG( mcbp ); + mcbp->m_psp++; mcbp->m_size = size; for (i = 0; i < 8; i++) mcbp->m_name[i] = name[i]; } + INIT VOID zumcb_init(mcb FAR * mcbp, UWORD size) { @@ -1061,6 +1108,19 @@ INIT VOID mcbp->m_psp = FREE_PSP; mcbp->m_size = size; } + +INIT VOID + mumcb_init(mcb FAR * mcbp, UWORD size) +{ + COUNT i; + static char name[8] = "SC\0\0\0\0\0\0"; + + mcbp->m_type = MCB_NORMAL; + mcbp->m_psp = 8; + mcbp->m_size = size; + for (i = 0; i < 8; i++) + mcbp->m_name[i] = name[i]; +} #endif INIT VOID @@ -1071,3 +1131,4 @@ INIT VOID strcpy(d, s); } + diff --git a/kernel/config.h b/kernel/config.h new file mode 100644 index 0000000..0a800fa --- /dev/null +++ b/kernel/config.h @@ -0,0 +1,38 @@ +/****************************************************************/ +/* */ +/* config.h */ +/* DOS-C */ +/* */ +/* Global data structures and declarations */ +/* */ +/* Copyright (c) 2000 */ +/* Steffen Kaiser */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version */ +/* 2, or (at your option) any later version. */ +/* */ +/* DOS-C is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ +/* the GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public */ +/* License along with DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + + +#ifdef DEBUG + /* Enable debugging of NLS part */ + + /* Caution: Enabling NLS debugging usually generates + _a_lot_ of noise. */ +/*& #define NLS_DEBUG */ + +#endif diff --git a/kernel/dosfns.c b/kernel/dosfns.c index ce3727a..38c23b8 100644 --- a/kernel/dosfns.c +++ b/kernel/dosfns.c @@ -34,6 +34,9 @@ static BYTE *dosfnsRcsId = "$Id$"; /* * $Log$ + * Revision 1.8 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.7 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * @@ -814,6 +817,15 @@ COUNT DosOpen(BYTE FAR * fname, COUNT mode) WORD i; COUNT drive, result; +/* /// Added to adjust for filenames which begin with ".\" + The problem was manifesting itself in the inability + to run an program whose filename (without the extension) + was longer than six characters and the PATH variable + contained ".", unless you explicitly specified the full + path to the executable file. + Jun 11, 2000 - rbc */ + if ( (fname[0] == '.') && (fname[1] == '\\') ) fname += 2; + /* test if mode is in range */ if ((mode & ~SFT_OMASK) != 0) return DE_INVLDACC; @@ -1170,7 +1182,17 @@ COUNT DosGetFattr(BYTE FAR * name, UWORD FAR * attrp) return result; } - if (CDSp->cds_table[drive].cdsFlags & CDSNETWDRV) +/* /// Added check for "d:\", which returns 0x10 (subdirectory) under DOS. + - Ron Cemer */ + if ( (PriPathName[0] != '\0') + && (PriPathName[1] == ':') + && ( (PriPathName[2] == '/') || (PriPathName[2] == '\\') ) + && (PriPathName[3] == '\0') ) { + *attrp = 0x10; + return SUCCESS; + } + + if (CDSp->cds_table[drive].cdsFlags & CDSNETWDRV) { last_cds = current_ldt; current_ldt = &CDSp->cds_table[drive]; @@ -1180,8 +1202,21 @@ COUNT DosGetFattr(BYTE FAR * name, UWORD FAR * attrp) *attrp = srfa[0]; } else { - result = dos_getfattr(name, attrp); +/* /// Use truename()'s result, which we already have in PriPathName. + I copy it to tmp_name because PriPathName is global and seems + to get trashed somewhere in transit. + The reason for using truename()'s result is that dos_?etfattr() + are very low-level functions and don't handle full path expansion + or cleanup, such as converting "c:\a\b\.\c\.." to "C:\A\B". + - Ron Cemer +*/ + BYTE tmp_name[128]; + int i; + for (i = 0; PriPathName[i] != '\0'; i++) tmp_name[i] = PriPathName[i]; + tmp_name[i] = '\0'; + result = dos_getfattr(tmp_name, attrp); } +/* Sorry Ron someone else found this, see history.txt */ return result; } @@ -1214,7 +1249,16 @@ COUNT DosSetFattr(BYTE FAR * name, UWORD FAR * attrp) current_ldt = last_cds; } else { - result = dos_setfattr(name, attrp); +/* /// Use truename()'s result, which we already have in PriPathName. + I copy it to tmp_name because PriPathName is global and seems + to get trashed somewhere in transit. + - Ron Cemer +*/ + BYTE tmp_name[128]; + int i; + for (i = 0; PriPathName[i] != '\0'; i++) tmp_name[i] = PriPathName[i]; + tmp_name[i] = '\0'; + result = dos_setfattr(name, attrp); } return result; } @@ -1362,9 +1406,16 @@ struct dhdr FAR * IsDevice(BYTE FAR * fname) SecPathName[i] = ' '; SecPathName[i] = 0; - /* if we have an extension, can't be a device */ + +/* /// BUG!!! This is absolutely wrong. A filename of "NUL.LST" must be + treated EXACTLY the same as a filename of "NUL". The existence or + content of the extension is irrelevent in determining whether a + filename refers to a device. + - Ron Cemer + // if we have an extension, can't be a device <--- WRONG. if (*froot != '.') { +*/ for (dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp->dh_next) { if (fnmatch((BYTE FAR *) SecPathName, (BYTE FAR *) dhp->dh_name, FNAME_SIZE, FALSE)) @@ -1372,7 +1423,7 @@ struct dhdr FAR * IsDevice(BYTE FAR * fname) return dhp; } } - } + return (struct dhdr FAR *)0; } diff --git a/kernel/fatdir.c b/kernel/fatdir.c index 760d343..d005fba 100644 --- a/kernel/fatdir.c +++ b/kernel/fatdir.c @@ -36,6 +36,9 @@ static BYTE *fatdirRcsId = "$Id$"; /* * $Log$ + * Revision 1.9 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.8 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * @@ -291,7 +294,7 @@ struct f_node FAR *dir_open(BYTE FAR * dirname) /* find the entry... */ i = FALSE; - upFMem((BYTE FAR *) TempBuffer, FNAME_SIZE + FEXT_SIZE); + DosUpFMem((BYTE FAR *) TempBuffer, FNAME_SIZE + FEXT_SIZE); while (dir_read(fnp) == DIRENT_SIZE) { @@ -592,7 +595,7 @@ COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name) /* current directory, do a seek and read, then close the fnode. */ /* Start out by initializing the dirmatch structure. */ - dmp->dm_drive = default_drive; + dmp->dm_drive = default_drive ; dmp->dm_entry = 0; dmp->dm_cluster = 0; @@ -609,7 +612,7 @@ COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name) */ if (nDrive >= 0) { - dmp->dm_drive = nDrive; + dmp->dm_drive = nDrive ; } else nDrive = default_drive; @@ -652,7 +655,7 @@ COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name) SearchDir.dir_ext[i] = ' '; /* Convert everything to uppercase. */ - upFMem(SearchDir.dir_name, FNAME_SIZE + FEXT_SIZE); + DosUpFMem(SearchDir.dir_name, FNAME_SIZE + FEXT_SIZE); /* Copy the raw pattern from our data segment to the DTA. */ fbcopy((BYTE FAR *) SearchDir.dir_name, dmp->dm_name_pat, @@ -666,6 +669,56 @@ COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name) return SUCCESS; } + /* /// Added code here to do matching against device names. + DOS findfirst will match exact device names if the + filename portion (excluding the extension) contains + a valid device name. + Credits: some of this code was ripped off from truename() + in newstuff.c. + - Ron Cemer */ + if (!(attr & D_VOLID)) { + char Name[FNAME_SIZE]; + int d, wild = 0; + for (d = 0; d < FNAME_SIZE; d++) { + if ((Name[d] = SearchDir.dir_name[d]) == '?') { + wild = 1; + break; + } + } + if (!wild) { + struct dhdr FAR *dhp; + for (dhp = (struct dhdr FAR *)&nul_dev; + dhp != (struct dhdr FAR *)-1; + dhp = dhp->dh_next) { + if (fnmatch + ((BYTE FAR *)&Name, + (BYTE FAR *)dhp->dh_name, + FNAME_SIZE, + FALSE)) { + /* Found a matching device. */ + dmp->dm_entry = 0; + dmp->dm_cluster = 0; + dmp->dm_flags.f_dmod = 0; + dmp->dm_flags.f_droot = 0; + dmp->dm_flags.f_dnew = 0; + dmp->dm_flags.f_ddir = 0; + dmp->dm_flags.f_dfull = 0; + dmp->dm_dirstart = 0; + dmp->dm_attr_fnd = D_DEVICE; + dmp->dm_time = dos_gettime(); + dmp->dm_date = dos_getdate(); + dmp->dm_size = 0L; + for (d = 0; ( (d < FNAME_SIZE) && (Name[d] != ' ') ); d++) + dmp->dm_name[d] = Name[d]; + dmp->dm_name[d] = '\0'; + return SUCCESS; + } + } + } + } + /* /// End of additions. - Ron Cemer */ + + /* Now search through the directory to find the entry... */ /* Special handling - the volume id is only in the root */ /* directory and only searched for once. So we need to open */ @@ -741,6 +794,9 @@ COUNT dos_findnext(void) /* assign our match parameters pointer. */ dmp = (dmatch FAR *) dta; + /* /// findnext will always fail on a device name. - Ron Cemer */ + if (dmp->dm_attr_fnd == D_DEVICE) return DE_FILENOTFND; + /* * The new version of SHSUCDX 1.0 looks at the dm_drive byte to * test 40h. I used RamView to see location MSD 116:04be and @@ -752,7 +808,7 @@ COUNT dos_findnext(void) * So, assume bit 6 is redirector and bit 7 is network. * jt */ - nDrive = dmp->dm_drive & 0x1f; + nDrive = dmp->dm_drive & 0x1f; if (nDrive > (lastdrive -1)) { return DE_INVLDDRV; @@ -780,7 +836,7 @@ COUNT dos_findnext(void) /* Force the fnode into read-write mode */ fnp->f_mode = RDWR; - if (dmp->dm_drive > (lastdrive -1)) { + if (dmp->dm_drive > (lastdrive)) { return DE_INVLDDRV; } /* Select the default to help non-drive specified path */ diff --git a/kernel/fatfs.c b/kernel/fatfs.c index 2d25f77..e6a9241 100644 --- a/kernel/fatfs.c +++ b/kernel/fatfs.c @@ -36,6 +36,9 @@ BYTE *RcsId = "$Id$"; /* * $Log$ + * Revision 1.6 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.5 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * @@ -377,9 +380,9 @@ static struct f_node FAR * } /* Convert the name into an absolute name for comparison... */ - upFMem((BYTE FAR *) dname, strlen(dname)); - upFMem((BYTE FAR *) fname, FNAME_SIZE); - upFMem((BYTE FAR *) fext, FEXT_SIZE); + DosUpFString((BYTE FAR *) dname); + DosUpFMem((BYTE FAR *) fname, FNAME_SIZE); + DosUpFMem((BYTE FAR *) fext, FEXT_SIZE); return fnp; } diff --git a/kernel/fcbfns.c b/kernel/fcbfns.c index 7e91cd1..9d474a8 100644 --- a/kernel/fcbfns.c +++ b/kernel/fcbfns.c @@ -35,6 +35,9 @@ static BYTE *RcsId = "$Id$"; /* * $Log$ + * Revision 1.6 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.5 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * @@ -223,7 +226,7 @@ WORD FcbParseFname(int wTestMode, BYTE FAR ** lpFileName, fcb FAR * lpFcb) /* Now check for drive specification */ if (*(*lpFileName + 1) == ':') { - REG BYTE Drive = upChar(**lpFileName); + REG BYTE Drive = DosUpFChar(**lpFileName); /* non-portable construct to be changed */ if (Drive < 'A' || Drive > 'Z') @@ -299,7 +302,7 @@ BYTE FAR *GetNameField(BYTE FAR * lpFileName, BYTE FAR * lpDestField, } if (*lpFileName == '?') *pbWildCard = TRUE; - *lpDestField++ = upChar(*lpFileName++); + *lpDestField++ = DosUpFChar(*lpFileName++); ++nIndex; } @@ -476,7 +479,6 @@ BOOL FcbGetFileSize(xfcb FAR * lpXfcb) lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); /* check for a device */ - /* if we have an extension, can't be a device */ if (IsDevice(PriPathName) || (lpFcb->fcb_recsiz == 0)) { return FALSE; @@ -645,7 +647,6 @@ BOOL FcbCreate(xfcb FAR * lpXfcb) lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); /* check for a device */ - /* if we have an extension, can't be a device */ dhp = IsDevice(PriPathName); if (dhp) { @@ -781,7 +782,6 @@ BOOL FcbOpen(xfcb FAR * lpXfcb) lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); /* check for a device */ - /* if we have an extension, can't be a device */ dhp = IsDevice(PriPathName); if (dhp ) { @@ -858,7 +858,6 @@ BOOL FcbDelete(xfcb FAR * lpXfcb) } /* check for a device */ - /* if we have an extension, can't be a device */ if (IsDevice(PriPathName)) { return FALSE; @@ -897,7 +896,6 @@ BOOL FcbRename(xfcb FAR * lpXfcb) lpRenameFcb = (rfcb FAR *) CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); /* check for a device */ - /* if we have an extension, can't be a device */ if (IsDevice(PriPathName)) { return FALSE; @@ -1108,7 +1106,7 @@ BOOL FcbFindFirst(xfcb FAR * lpXfcb) dta = (BYTE FAR *) & Dmatch; /* Next initialze local variables by moving them from the fcb */ - lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); + lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive); if (lpXfcb->xfcb_flag == 0xff) { wAttr = lpXfcb->xfcb_attrib; @@ -1118,8 +1116,10 @@ BOOL FcbFindFirst(xfcb FAR * lpXfcb) else wAttr = D_ALL; - *lpDir++ = PriPathName[0] - 'A'; - if (dos_findfirst(wAttr, PriPathName) != SUCCESS) + *lpDir++ = FcbDrive; + + + if (dos_findfirst(wAttr, SecPathName) != SUCCESS) { dta = lpPsp->ps_dta; return FALSE; @@ -1129,16 +1129,19 @@ BOOL FcbFindFirst(xfcb FAR * lpXfcb) lpFcb->fcb_dirclst = Dmatch.dm_cluster; lpFcb->fcb_diroff = Dmatch.dm_entry; + /* - This is undocumented and seen using Pcwatch. + This is undocumented and seen using Pcwatch and Ramview. The First byte is the current directory count and the second seems to be the attribute byte. */ + lpFcb->fcb_sftno = Dmatch.dm_drive; /* MSD seems to save this @ fcb_date.*/ #if 0 lpFcb->fcb_cublock = Dmatch.dm_entry; lpFcb->fcb_cublock *= 0x100; lpFcb->fcb_cublock += wAttr; #endif + dta = lpPsp->ps_dta; return TRUE; } @@ -1157,7 +1160,7 @@ BOOL FcbFindNext(xfcb FAR * lpXfcb) dta = (BYTE FAR *) & Dmatch; /* Next initialze local variables by moving them from the fcb */ - lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); + lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive); if ((xfcb FAR *) lpFcb != lpXfcb) { wAttr = lpXfcb->xfcb_attrib; @@ -1169,10 +1172,10 @@ BOOL FcbFindNext(xfcb FAR * lpXfcb) /* Reconstrct the dirmatch structure from the fcb */ *lpDir++ = FcbDrive; - Dmatch.dm_drive = FcbDrive ? FcbDrive - 1 : default_drive; + Dmatch.dm_drive = lpFcb->fcb_sftno; fbcopy(lpFcb->fcb_fname, (BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE); - upFMem((BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE); + DosUpFMem((BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE); Dmatch.dm_attr_srch = wAttr; Dmatch.dm_entry = lpFcb->fcb_diroff; @@ -1188,13 +1191,17 @@ BOOL FcbFindNext(xfcb FAR * lpXfcb) MoveDirInfo((dmatch FAR *) & Dmatch, (struct dirent FAR *)lpDir); lpFcb->fcb_dirclst = Dmatch.dm_cluster; lpFcb->fcb_diroff = Dmatch.dm_entry; - dta = lpPsp->ps_dta; + + lpFcb->fcb_sftno = Dmatch.dm_drive; #if 0 lpFcb->fcb_cublock = Dmatch.dm_entry; lpFcb->fcb_cublock *= 0x100; lpFcb->fcb_cublock += wAttr; #endif + + dta = lpPsp->ps_dta; return TRUE; } #endif + diff --git a/kernel/globals.h b/kernel/globals.h index 7f4126d..5c1dbdd 100644 --- a/kernel/globals.h +++ b/kernel/globals.h @@ -36,8 +36,8 @@ static BYTE *Globals_hRcsId = "$Id$"; /* * $Log$ - * Revision 1.4 2000/06/21 18:16:46 jimtabor - * Add UMB code, patch, and code fixes + * Revision 1.5 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes * * Revision 1.3 2000/05/25 20:56:21 jimtabor * Fixed project history @@ -180,6 +180,7 @@ static BYTE *Globals_hRcsId = "$Id$"; #include "error.h" #include "version.h" #include "network.h" +#include "config.h" /* JPP: for testing/debuging disk IO */ /*#define DISPLAY_GETBLOCK */ @@ -424,6 +425,7 @@ extern BYTE NetDelay, extern UWORD first_mcb, /* Start of user memory */ UMB_top, + umb_start, uppermem_root; /* Start of umb chain ? */ extern struct dpb FAR *DPBp; /* First drive Parameter Block */ @@ -462,6 +464,7 @@ extern BYTE CritErrLocus, CritErrAction, CritErrClass, + VgaSet, njoined; /* number of joined devices */ extern UWORD Int21AX; @@ -609,8 +612,17 @@ GLOBAL struct config BYTE cfgLastdrive; /* last drive */ BYTE cfgStacks; /* number of stacks */ UWORD cfgStackSize; /* stacks size for each stack */ -} -Config + /* COUNTRY= + In Pass #1 these information is collected and in PostConfig() + the NLS package is loaded into memory. + -- 2000/06/11 ska*/ + WORD cfgCSYS_cntry; /* country ID to be loaded */ + WORD cfgCSYS_cp; /* requested codepage; NLS_DEFAULT if default */ + BYTE cfgCSYS_fnam[NAMEMAX]; /* filename of COUNTRY= */ + WORD cfgCSYS_memory; /* number of bytes required for the NLS pkg; + 0 if none */ + VOID FAR *cfgCSYS_data; /* where the loaded data is for PostConfig() */ +} Config #ifdef MAIN = { @@ -623,6 +635,12 @@ Config NLAST, NSTACKS, 128 + /* COUNTRY= is initialized within DoConfig() */ + ,0 /* country ID */ + ,0 /* codepage */ + ,"" /* filename */ + ,0 /* amount required memory */ + ,0 /* pointer to loaded data */ }; #else ; diff --git a/kernel/int2f.asm b/kernel/int2f.asm index 273d553..64b55e9 100644 --- a/kernel/int2f.asm +++ b/kernel/int2f.asm @@ -30,6 +30,9 @@ ; $Id$ ; ; $Log$ +; Revision 1.6 2000/08/06 05:50:17 jimtabor +; Add new files and update cvs with patches and changes +; ; Revision 1.5 2000/06/21 18:16:46 jimtabor ; Add UMB code, patch, and code fixes ; @@ -83,9 +86,13 @@ ; %include "segs.inc" + %include "stacks.inc" segment _TEXT - extern _nul_dev:wrt DGROUP + extern _nul_dev:wrt DGROUP + extern _umb_start:wrt DGROUP + extern _UMB_top:wrt DGROUP + extern _syscall_MUX14:wrt _TEXT global _int2f_handler _int2f_handler: @@ -107,8 +114,27 @@ Int2f3: cmp ah,10h ; SHARE.EXE interrupt? je Int2f1 ; yes, do installation check cmp ah,14h ; NLSFUNC.EXE interrupt? - je Int2f1 ; yes, do installation check - iret ; Default, interrupt return + jne Int2f?iret ; yes, do installation check +Int2f?14: ;; MUX-14 -- NLSFUNC API + ;; all functions are passed to syscall_MUX14 + push bp ; Preserve BP later on + PUSH$ALL + call _syscall_MUX14 + pop bp ; Discard incoming AX + push ax ; Correct stack for POP$ALL + POP$ALL + mov bp, sp + or ax, ax + jnz Int2f?14?1 ; must return set carry + ;; -6 == -2 (CS), -2 (IP), -2 (flags) + ;; current SP = on old_BP + and BYTE [bp-6], 0feh ; clear carry as no error condition + pop bp + iret +Int2f?14?1: or BYTE [bp-6], 1 + pop bp +Int2f?iret: + iret ; ;return dos data seg. @@ -285,3 +311,97 @@ int2f_call: pop bp pop bp ret +; +; Test to see if a umb driver has been loaded. +; +; From RB list and Dosemu xms.c. +; +; Call the XMS driver "Request upper memory block" function with: +; AH = 10h +; DX = size of block in paragraphs +; Return: AX = status +; 0001h success +; BX = segment address of UMB +; DX = actual size of block +; 0000h failure +; BL = error code (80h,B0h,B1h) (see #02775) +; DX = largest available block +; +; (Table 02775) +; Values for XMS error code returned in BL: +; 00h successful +; 80h function not implemented +; B0h only a smaller UMB is available +; B1h no UMB's are available +; B2h UMB segment number is invalid +; +; + global _Umb_Test +_Umb_Test + push bp + mov bp,sp + push es + push ds + push dx + push bx + + mov ax,DGROUP + mov ds,ax + + mov ax,4300h ; is there a xms driver installed? + int 2fh + cmp al,80h + jne umbt_error + + mov ax,4310h + int 2fh + + push es ; save driver entry point + push bx + + mov dx,0xffff ; go for broke! + mov ax,1000h ; get the umb's + push cs ; setup far return + push word umbt1 + push es ; push the driver entry point + push bx + retf ; Call the driver +umbt1: +; +; bl = 0xB0 and ax = 0 so do it again. +; + cmp bl,0xb0 ; fail safe + je umbtb + add sp,4 + jmp umbt_error +umbtb: + and dx,dx ; if it returns a size of zero. + jne umbtc + add sp,4 + jmp umbt_error + +umbtc: + pop bx ; restore driver entry + pop es + + mov ax,1000h ; dx set with largest size + push cs + push word umbt2 + push es + push bx + retf +umbt2: + cmp ax,1 + jne umbt_error + + mov word [_umb_start], bx ; save the segment + mov word [_UMB_top], dx ; and the true size + +umbt_error: dec ax + + pop bx + pop dx + pop ds + pop es + pop bp + retf ; this was called FAR. diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c index 3bf0bc4..55b8930 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -36,6 +36,9 @@ BYTE *RcsId = "$Id$"; /* * $Log$ + * Revision 1.9 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.8 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * @@ -194,12 +197,15 @@ static VOID StartTrace(VOID); static bTraceNext = FALSE; #endif +#if 0 /* Very suspicious, passing structure by value?? + Deactivated -- 2000/06/16 ska*/ /* Special entry for far call into the kernel */ #pragma argsused VOID FAR int21_entry(iregs UserRegs) { int21_handler(UserRegs); } +#endif /* Normal entry. This minimizes user stack usage by avoiding local */ /* variables needed for the rest of the handler. */ @@ -342,25 +348,7 @@ dispatch: r->FLAGS |= FLG_CARRY; break; -#if 0 - /* Moved to simulate a 0x4c00 -- 1999/04/21 ska */ - /* Terminate Program */ - case 0x00: - if (cu_psp == RootPsp) - break; - else if (((psp FAR *) (MK_FP(cu_psp, 0)))->ps_parent == cu_psp) - break; - tsr = FALSE; - return_mode = break_flg ? 1 : 0; - return_code = r->AL; - if (DosMemCheck() != SUCCESS) - panic("MCB chain corrupted"); -#ifdef TSC - StartTrace(); -#endif - return_user(); - break; -#endif + /* case 0x00: --> Simulate a DOS-4C-00 */ /* Read Keyboard with Echo */ case 0x01: @@ -862,11 +850,11 @@ dispatch: if (0xffff == r->DX) { /* Set Country Code */ - if((rc = setCountryCode(cntry)) < 0) + if((rc = DosSetCountry(cntry)) < 0) goto error_invalid; } else { /* Get Country Information */ - if((rc = getCountryInformation(cntry, MK_FP(r->DS, r->DX))) < 0) + if((rc = DosGetCountryInformation(cntry, MK_FP(r->DS, r->DX))) < 0) goto error_invalid; r->AX = r->BX = cntry; } @@ -1277,23 +1265,35 @@ dispatch: break; case 0x01: -/* if (((COUNT) r->BX) < 0 || r->BX > 2) - goto error_invalid; - else - { */ + { + switch (r->BX) + { + case LAST_FIT: + case LAST_FIT_U: + case LAST_FIT_UO: + case LARGEST: + case BEST_FIT: + case BEST_FIT_U: + case BEST_FIT_UO: + case FIRST_FIT: + case FIRST_FIT_U: + case FIRST_FIT_UO: + mem_access_mode = r->BX; + break; - mem_access_mode = r->BX; + default: + goto error_invalid; + } + } r->FLAGS &= ~FLG_CARRY; - -/* }*/ - break; + break; case 0x02: r->AL = uppermem_link; break; case 0x03: - uppermem_link = r->BL; + DosUmbLink(r->BL); break; default: @@ -1510,31 +1510,39 @@ dispatch: case 0x65: switch(r->AL) { case 0x20: /* upcase single character */ - r->DL = upChar(r->DL); + r->DL = DosUpChar(r->DL); break; case 0x21: /* upcase memory area */ - upMem(MK_FP(r->DS, r->DX), r->CX); + DosUpMem(MK_FP(r->DS, r->DX), r->CX); break; case 0x22: /* upcase ASCIZ */ - upString(MK_FP(r->DS, r->DX)); + DosUpString(MK_FP(r->DS, r->DX)); break; case 0xA0: /* upcase single character of filenames */ - r->DL = upFChar(r->DL); + r->DL = DosUpFChar(r->DL); break; case 0xA1: /* upcase memory area of filenames */ - upFMem(MK_FP(r->DS, r->DX), r->CX); + DosUpFMem(MK_FP(r->DS, r->DX), r->CX); break; case 0xA2: /* upcase ASCIZ of filenames */ - upFString(MK_FP(r->DS, r->DX)); + DosUpFString(MK_FP(r->DS, r->DX)); break; case 0x23: /* check Yes/No response */ - r->AX = yesNo(r->DL); + r->AX = DosYesNo(r->DL); break; default: - if ((rc = extCtryInfo( + if ((rc = DosGetData( r->AL, r->BX, r->DX, r->CX, - MK_FP(r->ES, r->DI))) < 0) - goto error_exit; + MK_FP(r->ES, r->DI))) < 0) { +#ifdef NLS_DEBUG + printf("DosGetData() := %d\n", rc); +#endif + goto error_exit; + } +#ifdef NLS_DEBUG + printf("DosGetData() returned successfully\n", rc); +#endif + break; } r->FLAGS &= ~FLG_CARRY; @@ -1546,10 +1554,10 @@ dispatch: switch (r->AL) { case 1: - rc = getCodePage(&r->BX, &r->DX); + rc = DosGetCodepage(&r->BX, &r->DX); break; case 2: - rc = setCodePage(r->BX, r->DX); + rc = DosSetCodepage(r->BX, r->DX); break; default: diff --git a/kernel/kernel.asm b/kernel/kernel.asm index 63eec19..9cfba57 100644 --- a/kernel/kernel.asm +++ b/kernel/kernel.asm @@ -28,6 +28,9 @@ ; $Id$ ; ; $Log$ +; Revision 1.5 2000/08/06 05:50:17 jimtabor +; Add new files and update cvs with patches and changes +; ; Revision 1.4 2000/06/21 18:16:46 jimtabor ; Add UMB code, patch, and code fixes ; @@ -307,7 +310,8 @@ deblock_seg dw 0 ; 0056 (offset always zero) times 3 db 0 ; 0058 unknown dw 0 ; 005B unknown db 0, 0FFh, 0 ; 005D unknown - db 0 ; 0060 unknown + global _VgaSet +_VgaSet db 0 ; 0060 unknown dw 0 ; 0061 unknown global _uppermem_link _uppermem_link db 0 ; 0063 upper memory link flag @@ -315,7 +319,8 @@ _uppermem_link db 0 ; 0063 upper memory link flag _UMB_top dw 0 ; 0064 unknown UMB_top will do for now global _uppermem_root _uppermem_root dw 0FFFFh ; 0066 dmd_upper_root - dw 0 ; 0068 para of last mem search + global _umb_start +_umb_start dw 0 ; 0068 para of last mem search SysVarEnd: diff --git a/kernel/kernel.mak b/kernel/kernel.mak index 75f4996..10988f6 100644 --- a/kernel/kernel.mak +++ b/kernel/kernel.mak @@ -5,6 +5,9 @@ # # $Log$ +# Revision 1.4 2000/08/06 05:50:17 jimtabor +# Add new files and update cvs with patches and changes +# # Revision 1.3 2000/05/25 20:56:21 jimtabor # Fixed project history # @@ -119,10 +122,10 @@ INCLUDEPATH = ..\HDR #AFLAGS = /Mx /DSTANDALONE=1 /I..\HDR NASMFLAGS = -i../hdr/ LIBS =..\LIB\DEVICE.LIB ..\LIB\LIBM.LIB -CFLAGS = -1- -O -Z -d -I..\hdr -I. \ - -D__STDC__=0;DEBUG;KERNEL;I86;PROTO;ASMSUPT #CFLAGS = -1- -O -Z -d -I..\hdr -I. \ -# -D__STDC__=0;KERNEL;I86;PROTO;ASMSUPT +# -D__STDC__=0;DEBUG;KERNEL;I86;PROTO;ASMSUPT +CFLAGS = -1- -O -Z -d -I..\hdr -I. \ + -D__STDC__=0;KERNEL;I86;PROTO;ASMSUPT INITCFLAGS = $(CFLAGS) -zAINIT -zCINIT_TEXT -zPIGROUP HDR=../hdr/ @@ -244,6 +247,8 @@ io.obj: io.asm segs.inc irqstack.obj: irqstack.asm +nls_hc.obj: nls_hc.asm segs.inc + nlssupt.obj: nlssupt.asm segs.inc procsupt.obj: procsupt.asm segs.inc $(HDR)stacks.inc @@ -399,10 +404,10 @@ nls.obj: nls.c $(HDR)portab.h globals.h $(HDR)device.h $(HDR)mcb.h \ $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h $(HDR)fcb.h \ $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h $(HDR)cds.h \ $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h $(HDR)file.h \ - $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h $(HDR)version.h proto.h \ - 001-437.nls + $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h $(HDR)version.h proto.h -nls_hc.obj: nls_hc.c globals.h $(HDR)portab.h $(HDR)nls.h +# \ +# 001-437.nls prf.obj: prf.c $(HDR)portab.h diff --git a/kernel/main.c b/kernel/main.c index c23bc6d..026012b 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -39,6 +39,9 @@ static BYTE *mainRcsId = "$Id$"; /* * $Log$ + * Revision 1.7 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.6 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * @@ -193,8 +196,8 @@ INIT static VOID init_kernel(void) /* Init oem hook - returns memory size in KB */ ram_top = init_oem(); - - UMB_top = 3; /* testing for now* + UMB_top = 0; + umb_start = 0; /* Fake int 21h stack frame */ user_r = (iregs FAR *) DOS_PSP + 0xD0; diff --git a/kernel/memmgr.c b/kernel/memmgr.c index f80e8dc..4994273 100644 --- a/kernel/memmgr.c +++ b/kernel/memmgr.c @@ -35,6 +35,9 @@ static BYTE *memmgrRcsId = "$Id$"; /* * $Log$ + * Revision 1.5 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.4 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * @@ -185,8 +188,15 @@ COUNT DosMemAlloc(UWORD size, COUNT mode, seg FAR * para, UWORD FAR * asize) /* Initialize */ p = para2far(first_mcb); + biggestSeg = foundSeg = NULL; + if((mode & (FIRST_FIT_UO | FIRST_FIT_U)) && uppermem_link) { + if(uppermem_root) + p = para2far(uppermem_root); + + } + /* Search through memory blocks */ FOREVER { @@ -196,7 +206,7 @@ COUNT DosMemAlloc(UWORD size, COUNT mode, seg FAR * para, UWORD FAR * asize) if (mcbFree(p)) { /* unused block, check if it applies to the rule */ - if (joinMCBs(p) != SUCCESS) /* join following unused blocks */ + if (joinMCBs(p) != SUCCESS) /* join following unused blocks */ return DE_MCBDESTRY; /* error */ if (!biggestSeg || biggestSeg->m_size < p->m_size) @@ -208,6 +218,8 @@ COUNT DosMemAlloc(UWORD size, COUNT mode, seg FAR * para, UWORD FAR * asize) switch (mode) { case LAST_FIT: /* search for last possible */ + case LAST_FIT_U: + case LAST_FIT_UO: default: foundSeg = p; break; @@ -218,14 +230,19 @@ COUNT DosMemAlloc(UWORD size, COUNT mode, seg FAR * para, UWORD FAR * asize) break; case BEST_FIT: /* first, but smallest block */ + case BEST_FIT_U: + case BEST_FIT_UO: if (!foundSeg || foundSeg->m_size > p->m_size) /* better match found */ foundSeg = p; break; - case FIRST_FIT: /* first possible */ + case FIRST_FIT: /* first possible */ + case FIRST_FIT_U: + case FIRST_FIT_UO: foundSeg = p; goto stopIt; /* OK, rest of chain can be ignored */ + } } } @@ -254,7 +271,8 @@ stopIt: /* reached from FIRST_FIT on match */ /* foundSeg := pointer to allocated block p := pointer to MCB that will form the rest of the block */ - if (mode == LAST_FIT) + if ( + (mode == LAST_FIT)||(mode == LAST_FIT_UO)||(mode == LAST_FIT_U)) { /* allocate the block from the end of the found block */ p = foundSeg; @@ -310,7 +328,6 @@ COUNT FAR init_call_DosMemAlloc(UWORD size, COUNT mode, seg FAR * para, UWORD FA COUNT DosMemLargest(UWORD FAR * size) { REG mcb FAR *p; - mcb FAR *q; COUNT found; /* Initialize */ @@ -376,6 +393,7 @@ COUNT DosMemFree(UWORD para) #if 0 /* Moved into allocating functions -- 1999/04/21 ska */ /* Now merge free blocks */ + for (p = (mcb FAR *) (MK_FP(first_mcb, 0)); p->m_type != MCB_LAST; p = q) { /* make q a pointer to the next block */ @@ -469,6 +487,7 @@ COUNT DosMemChange(UWORD para, UWORD size, UWORD * maxSize) COUNT DosMemCheck(void) { REG mcb FAR *p; + REG mcb FAR *u; /* Initialize */ p = para2far(first_mcb); @@ -483,13 +502,13 @@ COUNT DosMemCheck(void) /* not corrupted - but not end, bump the pointer */ p = nxtMCB(p); } - return SUCCESS; } COUNT FreeProcessMem(UWORD ps) { - mcb FAR *p; + mcb FAR *p, FAR *u; + COUNT x = 0; /* Initialize */ p = para2far(first_mcb); @@ -501,12 +520,14 @@ COUNT FreeProcessMem(UWORD ps) DosMemFree(FP_SEG(p)); /* not corrupted - if last we're OK! */ - if (p->m_type == MCB_LAST) - return SUCCESS; + if (p->m_type == MCB_LAST){ + if(x) + return DE_MCBDESTRY; + return SUCCESS; + } p = nxtMCB(p); } - return DE_MCBDESTRY; } @@ -536,7 +557,6 @@ COUNT DosGetLargestBlock(UWORD FAR * block) if (p->m_type == MCB_LAST) break; p = nxtMCB(p); - } *block = sz; return SUCCESS; @@ -545,7 +565,8 @@ COUNT DosGetLargestBlock(UWORD FAR * block) VOID show_chain(void) { - mcb FAR *p = para2far(first_mcb); + mcb FAR *p, FAR *u; + p = para2far(first_mcb); for (;;) { @@ -579,4 +600,49 @@ VOID _fmemcpy(BYTE FAR * d, BYTE FAR * s, REG COUNT n) *d++ = *s++; } + +VOID DosUmbLink(BYTE n) +{ + REG mcb FAR *p; + REG mcb FAR *q; + + if(uppermem_root){ + + q = p = para2far(first_mcb); + + if(uppermem_link){ + + while ( p != (mcb FAR *) para2far(0x9fff) ) + { + + if (!mcbValid(p)) + goto DUL_exit; + q = p; + p = nxtMCB(p); + } + + printf("M end at 0x%04x:0x%04x\n", FP_SEG(q), FP_OFF(q)); + + if(q->m_type == MCB_NORMAL) + q->m_type = MCB_LAST; + } + else + { + while( q->m_type != MCB_LAST) + { + if (!mcbValid(q)) + goto DUL_exit; + q = nxtMCB(q); + } + + printf("Z end at 0x%04x:0x%04x\n", FP_SEG(q), FP_OFF(q)); + + if(q->m_type == MCB_LAST) + q->m_type = MCB_NORMAL; + } + uppermem_link = n; + } +DUL_exit: + return; +} #endif diff --git a/kernel/network.c b/kernel/network.c index 3a433e9..55d79c2 100644 --- a/kernel/network.c +++ b/kernel/network.c @@ -36,6 +36,9 @@ static BYTE *RcsId = "$Id$"; /* * $Log$ + * Revision 1.7 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.6 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * @@ -118,7 +121,7 @@ UCOUNT Remote_RW(UWORD func, UCOUNT n, BYTE FAR * bp, sft FAR * s, COUNT FAR * e COUNT Remote_find(UWORD func, BYTE FAR * name, REG dmatch FAR * dmp ) { COUNT i, x; - char FAR *p, *q; + char FAR *p, FAR *q; VOID FAR * test; struct dirent FAR *SDp = (struct dirent FAR *) &SearchDir; diff --git a/kernel/newstuff.c b/kernel/newstuff.c index c5e2bd7..459d3f8 100644 --- a/kernel/newstuff.c +++ b/kernel/newstuff.c @@ -31,6 +31,9 @@ static BYTE *mainRcsId = "$Id$"; /* * $Log$ + * Revision 1.8 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.7 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * @@ -217,7 +220,7 @@ COUNT get_verify_drive(char FAR *src) } else drive = default_drive; - if ((drive < 0) || (drive > (lastdrive - 1))) { + if ((drive < 0) || (drive > lastdrive)) { drive = DE_INVLDDRV; } return drive; @@ -233,9 +236,10 @@ COUNT get_verify_drive(char FAR *src) COUNT truename(char FAR * src, char FAR * dest, COUNT t) { static char buf[128] = "A:\\\0\0\0\0\0\0\0\0\0"; - static char Name[8] = " "; + /* /// Changed to FNAME_SIZE from 8 for cleanliness. - Ron Cemer */ + static char Name[FNAME_SIZE]; char *bufp = buf + 3; - COUNT i, n, x = 2; + COUNT i, n, rootEndPos = 2; /* renamed x to rootEndPos - Ron Cemer */ struct cds FAR *cdsp; struct dhdr FAR *dhp; BYTE FAR *froot; @@ -251,7 +255,7 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t) { buf[0] = (src[0] | 0x20) + 'A' - 'a'; - if (buf[0] > (lastdrive - 1) + 'A') + if (buf[0] > lastdrive + 'A') return DE_PATHNOTFND; src += 2; @@ -259,6 +263,16 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t) else buf[0] = default_drive + 'A'; +/* /// Added to adjust for filenames which begin with ".\" + The problem was manifesting itself in the inability + to run an program whose filename (without the extension) + was longer than six characters and the PATH variable + contained ".", unless you explicitly specified the full + path to the executable file. + Jun 11, 2000 - rbc */ +/* /// Changed to "while" from "if". - Ron Cemer */ + while ( (src[0] == '.') && (src[1] == '\\') ) src += 2; + i = buf[0] - 'A'; /* Code repoff from dosfns.c @@ -277,23 +291,50 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t) for (; d < FNAME_SIZE; d++) Name[d] = ' '; + /* /// Bugfix: NUL.LST is the same as NUL. This is true for all + devices. On a device name, the extension is irrelevant + as long as the name matches. + - Ron Cemer */ +#if (0) /* if we have an extension, can't be a device */ if (*froot != '.') { +#endif for (dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp->dh_next) { if (fnmatch((BYTE FAR *) &Name, (BYTE FAR *) dhp->dh_name, FNAME_SIZE, FALSE)) { buf[2] ='/'; - for (d = 0; d < FNAME_SIZE; d++){ - if(Name[d] == 0x20) - goto exit_tn; + /* /// Bug: should be only copying up to first space. + - Ron Cemer + for (d = 0; d < FNAME_SIZE || Name[d] == ' '; d++) */ + for (d = 0; ( (d < FNAME_SIZE) && (Name[d] != ' ') ); d++) *bufp++ = Name[d]; + /* /// DOS will return C:/NUL.LST if you pass NUL.LST in. + DOS will also return C:/NUL.??? if you pass NUL.* in. + Code added here to support this. + - Ron Cemer */ + while ( (*froot != '.') && (*froot != '\0') ) froot++; + if (*froot) froot++; + if (*froot) { + *bufp++ = '.'; + for (i = 0; i < FEXT_SIZE; i++) { + if ( (*froot == '\0') || (*froot == '.') ) + break; + if (*froot == '*') { + for (; i < FEXT_SIZE; i++) *bufp++ = '?'; + break; + } + *bufp++ = *froot++; + } } + /* /// End of code additions. - Ron Cemer */ goto exit_tn; } } +#if (0) } +#endif cdsp = &CDSp->cds_table[i]; current_ldt = cdsp; @@ -309,7 +350,7 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t) { fsncopy((BYTE FAR *) & cdsp->cdsCurrentPath[0], (BYTE FAR *) & buf[0], cdsp->cdsJoinOffset); bufp = buf + cdsp->cdsJoinOffset; - x = cdsp->cdsJoinOffset; + rootEndPos = cdsp->cdsJoinOffset; /* renamed x to rootEndPos - Ron Cemer */ *bufp++ = '\\'; } @@ -327,6 +368,19 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t) src++; move_name: + + /* /// The block inside the "#if (0) ... #endif" is + seriously broken. New code added below to replace it. + This eliminates many serious bugs, specifically + with FreeCOM where truename is required to work + according to the DOS specification in order for + the COPY and other file-related commands to work + properly. + This should be a major improvement to all apps which + use truename. + - Ron Cemer */ + +#if (0) /* * The code here is brain dead. It works long as the calling * function are operating with in normal parms. @@ -384,7 +438,7 @@ move_name: for (bufp -= 2; *bufp != '\\'; bufp--) { - if (bufp < buf + x) /* '..' illegal in root dir */ + if (bufp < buf + rootEndPos) /* '..' illegal in root dir */ return DE_PATHNOTFND; } src++; @@ -413,9 +467,115 @@ move_name: break; } } + /* remove trailing backslashes */ while (bufp[-1] == '\\') --bufp; +#endif + +/* /// Beginning of new code. - Ron Cemer */ + bufp--; + { + char c, *bufend = buf+(sizeof(buf)-1); + int gotAnyWildcards = 0; + int seglen, copylen, state; + while ( (*src) && (bufp < bufend) ) { + /* Skip duplicated slashes. */ + while ( (*src == '/') || (*src == '\\') ) src++; + if (!(*src)) break; + /* Find the end of this segment in the source string. */ + for (seglen = 0; ; seglen++) { + c = src[seglen]; + if ( (c == '\0') || (c == '/') || (c == '\\') ) + break; + } + if (seglen > 0) { + /* Ignore all ".\" or "\." path segments. */ + if ( (seglen != 1) || (*src != '.') ) { + /* Apply ".." to the path by removing + last path segment from buf. */ + if ( (seglen==2) && (src[0] == '.') && (src[1] == '.') ) { + if (bufp > (buf+rootEndPos)) { + bufp--; + while ( (bufp > (buf+rootEndPos)) + && (*bufp != '/') + && (*bufp != '\\') ) + bufp--; + } + } else { + /* New segment. If any wildcards in previous + segment(s), this is an invalid path. */ + if (gotAnyWildcards) return DE_PATHNOTFND; + /* Append current path segment to result. */ + *(bufp++) = '\\'; + if (bufp >= bufend) break; + copylen = state = 0; + for (i=0; ( (i < seglen) && (bufp < bufend) ); i++) { + c = src[i]; + gotAnyWildcards |= ( (c == '?') || (c == '*') ); + switch (state) { + case 0: /* Copying filename (excl. extension) */ + if (c == '*') { + while (copylen < FNAME_SIZE) { + *(bufp++) = '?'; + if (bufp >= bufend) break; + copylen++; + } + copylen = 0; + state = 1; /* Go wait for dot */ + break; + } + if (c == '.') { + *(bufp++) = '.'; + copylen = 0; + state = 2; /* Copy extension next */ + break; + } + *(bufp++) = c; + copylen++; + if (copylen >= FNAME_SIZE) { + copylen = 0; + state = 1; /* Go wait for dot */ + break; + } + break; + case 1: /* Looking for dot so we can copy exten */ + if (src[i] == '.') { + *(bufp++) = '.'; + state = 2; + } + break; + case 2: /* Copying extension */ + if (c == '*') { + while (copylen < FEXT_SIZE) { + *(bufp++) = '?'; + if (bufp >= bufend) break; + copylen++; + } + i = seglen; /* Done with segment */ + break; + } + if (c == '.') { + i = seglen; /* Done with segment */ + break; + } + *(bufp++) = c; + copylen++; + if (copylen >= FEXT_SIZE) { + i = seglen; /* Done with segment */ + break; + } + break; + } + } + } + } + } /* if (seglen > 0) */ + src += seglen; + if (*src) src++; + } /* while ( (*src) && (bufp < bufend) ) */ + } +/* /// End of new code. - Ron Cemer */ if (bufp == buf + 2) ++bufp; @@ -425,7 +585,7 @@ exit_tn: *bufp++ = 0; /* finally, uppercase everything */ - upString(buf); + DosUpString(buf); /* copy to user's buffer */ fbcopy(buf, dest, bufp - buf); diff --git a/kernel/nls.c b/kernel/nls.c index a909c78..a8b21a3 100644 --- a/kernel/nls.c +++ b/kernel/nls.c @@ -5,7 +5,7 @@ /* */ /* National Languge Support functions and data structures */ /* */ -/* Copyright (c) 1995, 1996, 2000 */ +/* Copyright (c) 2000 */ /* Steffen Kaiser */ /* All Rights Reserved */ /* */ @@ -27,10 +27,16 @@ /* Cambridge, MA 02139, USA. */ /****************************************************************/ +/* + * Note 1: Some code assume certains prerequisites to be matched, + * e.g. character tables exactly 128 bytes long; I try to keep\ + * track of these conditions within comments marked with: + * ==ska*/ + #include "portab.h" #include "globals.h" -#include "intr.h" -#include "nls.h" +#include "pcb.h" +#include #ifdef VERSION_STRINGS static BYTE *RcsId = "$Id$"; @@ -38,134 +44,173 @@ static BYTE *RcsId = "$Id$"; /* * $Log$ - * Revision 1.3 2000/05/25 20:56:21 jimtabor - * Fixed project history + * Revision 1.4 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes * - * Revision 1.2 2000/05/08 04:30:00 jimtabor - * Update CVS to 2020 - * - * Revision 1.1.1.1 2000/05/06 19:34:53 jhall1 - * The FreeDOS Kernel. A DOS kernel that aims to be 100% compatible with - * MS-DOS. Distributed under the GNU GPL. - * - * Revision 1.8 2000/03/17 22:59:04 kernel - * Steffen Kaiser's NLS changes + * Revision 1.1 2000/03/23 02:44:21 ska + * Initial revision * */ -#ifdef NLS_REORDER_POINTERS -#define getTable2 (&nlsInfo.actPkg->nlsPointer[0].pointer) -#define getTable4 (&nlsInfo.actPkg->nlsPointer[1].pointer) +/* + * assertDSeqSS() - test if DS == SS + * Otherwise pointers to local variables (that ones on the stack) will + * be referenced via DS, which will cause to use wrong values. + */ +#ifdef NLS_DEBUG +#define assertDSeqSS() if(_DS != _SS) assertDSneSS(); +void assertDSneSS(void) +{ panic("DS unequal to SS"); +} +#define log(a) printf a +#define log1(a) printf a #else -#define getTable2 getTable(2) -#define getTable4 getTable(4) +#define assertDSeqSS() +#define log(a) +#ifdef NDEBUG +#define log1(a) +#else +#define log1(a) printf a +#endif +#endif + + +struct nlsInfoBlock nlsInfo = { + (char FAR *)0 /* filename to COUNTRY.SYS */ + ,437 /* system code page */ + /* Implementation flags */ + ,0 +#ifdef NLS_MODIFYABLE_DATA + | NLS_CODE_MODIFYABLE_DATA +#endif +#ifdef NLS_REORDER_POINTERS + | NLS_CODE_REORDER_POINTERS +#endif + ,&nlsPackageHardcoded /* hardcoded first package */ + ,&nlsPackageHardcoded /* first item in chain */ +}; + + + /* getTableX return the pointer to the X'th table; X==subfct */ + /* subfct 2: normal upcase table; 4: filename upcase table */ +#ifdef NLS_REORDER_POINTERS +#define getTable2(nls) ((nls)->nlsPointers[0].pointer) +#define getTable4(nls) ((nls)->nlsPointers[1].pointer) +#else +#define getTable2(nls) getTable(2, (nls)) +#define getTable4(nls) getTable(4, (nls)) #define NEED_GET_TABLE #endif - -#ifdef NLS_CACHE_POINTERS -#define normalCh nlsInfo.upTable -#define fileCh nlsInfo.fnamUpTable -#else -#define normalCh getTable2 -#define fileCh getTable4 -#endif -#define yesChar nlsInfo.actPkg->yeschar -#define noChar nlsInfo.actPkg->nochar + /*== both chartables must be 128 bytes long and lower range is + identical to 7bit-US-ASCII ==ska*/ +#define getCharTbl2(nls) \ + (((struct nlsCharTbl FAR*)getTable2(nls))->tbl - 0x80) +#define getCharTbl4(nls) \ + (((struct nlsCharTbl FAR*)getTable4(nls))->tbl - 0x80) -#define NLS_MUX_COUNTRY_INFO(nls) ((nls)->muxCallingFlags & NLS_FLAG_INFO) -#define NLS_MUX_POINTERS(nls) ((nls)->muxCallingFlags & NLS_FLAG_POINTERS) -#define NLS_MUX_YESNO(nls) ((nls)->muxCallingFlags & NLS_FLAG_YESNO) -#define NLS_MUX_EXTERNAL_UP(nls) ((nls)->muxCallingFlags & NLS_FLAG_UP) -#define NLS_MUX_EXTERNAL_FUP(nls) ((nls)->muxCallingFlags & NLS_FLAG_FUP) +/******************************************************************** + ***** MUX calling functions **************************************** + ********************************************************************/ - - -static COUNT muxGo(int subfct, struct REGPACK *rp) -{ rp->r_si = FP_OFF(&nlsInfo); - rp->r_ds = FP_SEG(&nlsInfo); - rp->r_ax = 0x1400 | subfct; +/*== DS:SI _always_ points to global NLS info structure <-> no + * subfct can use these registers for anything different. ==ska*/ +static COUNT muxGo(int subfct, iregs *rp) +{ +log( ("NLS: muxGo(): subfct=%x, cntry=%u, cp=%u, ES:DI=%04x:%04x\n", subfct + , rp->DX, rp->BX, rp->ES, rp->DI) ); + rp->SI = FP_OFF(&nlsInfo); + rp->DS = FP_SEG(&nlsInfo); + rp->AX = 0x1400 | subfct; intr(0x2f, rp); - return rp->r_ax; +log( ("NLS: muxGo(): return value = %d\n", rp->AX) ); + return rp->AX; } /* * Call NLSFUNC to load the NLS package */ COUNT muxLoadPkg(UWORD cp, UWORD cntry) -{ struct REGPACK r; +{ iregs r; + + assertDSeqSS(); /* because "&r" */ - /* Return the al register as sign extended: */ /* 0x1400 == not installed, ok to install */ /* 0x1401 == not installed, not ok to install */ /* 0x14FF == installed */ - r.r_bx = 0; /* make sure the NLSFUNC ID is updated */ + r.BX = 0; /* make sure the NLSFUNC ID is updated */ if(muxGo(0, &r) != 0x14ff) return DE_FILENOTFND; /* No NLSFUNC --> no load */ - if(r.r_bx != NLS_FREEDOS_NLSFUNC_ID) - return DE_INVLDACC; + if(r.BX != NLS_FREEDOS_NLSFUNC_ID) /* FreeDOS NLSFUNC will return */ + return DE_INVLDACC; /* This magic number */ /* OK, the correct NLSFUNC is available --> load pkg */ - r.r_dx = cntry; - r.r_bx = cp; - return muxGo(NLS_NLSFUNC_LOAD_PKG, &r); + /* If BX == -1 on entry, NLSFUNC updates BX to the codepage loaded + into memory. The system must then change to this one later */ + r.DX = cntry; + r.BX = cp; + return muxGo(NLSFUNC_LOAD_PKG, &r); } static int muxBufGo(int subfct, int bp, UWORD cp, UWORD cntry, UWORD bufsize - , BYTE FAR *buf) -{ struct REGPACK r; + , VOID FAR *buf) +{ iregs r; - r.r_bx = cntry; - r.r_dx = cp; - r.r_es = FP_SEG(*buf); - r.r_di = FP_OFF(*buf); - r.r_cx = bufsize; - r.r_bp = bp; + assertDSeqSS(); /* because "&r" */ + +log( ("NLS: muxBufGo(): subfct=%x, BP=%u, cp=%u, cntry=%u, len=%u, buf=%04x:%04x\n", + subfct, bp, cp, cntry, bufsize, FP_SEG(buf), FP_OFF(buf)) ); + + r.DX = cntry; + r.BX = cp; + r.ES = FP_SEG(buf); + r.DI = FP_OFF(buf); + r.CX = bufsize; + r.BP = bp; return muxGo(subfct, &r); } -#define mux38(cp,cc,bs,b) muxBufGo(4, 0, (cp), (cc), (bs), (b)) #define mux65(s,cp,cc,bs,b) muxBufGo(2, (s), (cp), (cc), (bs), (b)) -#define muxUpMem(s,l,f) muxBufGo((f), 0, NLS_DEFAULT, NLS_DEFAULT, l, s) +#define mux38(cp,cc,bs,b) muxBufGo(4, 0, (cp), (cc), (bs), (b)) +#define muxYesNo(ch) muxBufGo(NLSFUNC_YESNO,0, NLS_DEFAULT, NLS_DEFAULT, (ch), 0) +#define muxUpMem(s,b,bs) muxBufGo((s),0, NLS_DEFAULT,NLS_DEFAULT, (bs), (b)) -static int muxYesNo(int ch) -{ struct REGPACK r; - - r.r_cx = ch; - return muxGo(NLS_NLSFUNC_YESNO, &r); -} +/******************************************************************** + ***** Helper functions********************************************** + ********************************************************************/ /* - * Search the NLS package within the chain - * Also resolves the default values (-1) into the current + * Search for the NLS package within the chain + * Also resolves the default values (-1) into the currently * active codepage/country code. */ -struct nlsPackage FAR *searchPackage(UWORD *cp, UWORD *cntry) +static struct nlsPackage FAR *searchPackage(UWORD cp, UWORD cntry) { struct nlsPackage FAR *nls; - if(*cp == NLS_DEFAULT) - *cp = nlsInfo.actPkg->cntryInfo.codePage; - if(*cntry == NLS_DEFAULT) - *cntry = nlsInfo.actPkg->cntryInfo.countryCode; + if(cp == NLS_DEFAULT) + cp = nlsInfo.actPkg->cp; + if(cntry == NLS_DEFAULT) + cntry = nlsInfo.actPkg->cntry; - nls = &nlsInfo.chain; - while((nls->cntryInfo.codePage != *cp - || nls->cntryInfo.countryCode != *cntry) + nls = nlsInfo.chain; + while((nls->cp != cp || nls->cntry != cntry) && (nls = nls->nxt) != NULL); return nls; } -struct nlsPointerInf FAR *locateSubfct(struct nlsPackage FAR *nls - , UBYTE subfct) +/* For various robustnesses reasons and to simplify the implementation + at other places, locateSubfct() returns NULL (== "not found"), + if nls == NULL on entry. */ +static VOID FAR *locateSubfct(struct nlsPackage FAR *nls, int subfct) { int cnt; - struct nlsPointerInf FAR *p; + struct nlsPointer FAR *p; - for(cnt = nls->numSubfct, p = &nls->nlsPointer[0] + if(nls) for(cnt = nls->numSubfct, p = &nls->nlsPointers[0] ; cnt--; ++p) - if(p->subfct == subfct) + if(p->subfct == (UBYTE)subfct) return p; return NULL; @@ -173,18 +218,23 @@ struct nlsPointerInf FAR *locateSubfct(struct nlsPackage FAR *nls #ifdef NEED_GET_TABLE /* search the table (from a subfct) from the active package */ -struct nlsPointerInf FAR *getTable(UBYTE subfct) -{ struct nlsPointerInf FAR *poi; +/* Note: Because this table returns the pointers for stuff of + *internal* purpose, it seems to be more comfortable that this + function is guaranteed to return valid pointers, rather than + to let the user (some kernel function) deal with non-existing + tables -- 2000/02/26 ska*/ +static VOID FAR *getTable(UBYTE subfct, struct nlsPackage FAR *nls) +{ struct nlsPointer FAR *poi; - if((poi = locateSubfct(nlsInfo.actPkg, subfct)) != NULL) + if((poi = locateSubfct(nls, subfct)) != NULL) return poi; /* Failed --> return the hardcoded table */ switch(subfct) { case 2: return &nlsUpHardcodedTable; case 4: return &nlsFnameUpHardcodedTable; - case 5: return &nlsFnameTermHardcodedTable; - case 6: return &nlsCollHardcodedTable; + /* case 5: return &nlsFnameTermHardcodedTable; */ + /* case 6: return &nlsCollHardcodedTable; */ } } #endif @@ -192,94 +242,312 @@ struct nlsPointerInf FAR *getTable(UBYTE subfct) /* * Copy a buffer and test the size of the buffer * Returns SUCCESS on success; DE_INVLDFUNC on failure + * + * Efficiency note: This function is used as: + * return cpyBuf(buf, bufsize, ...) + * three times. If the code optimizer is some good, it can re-use + * the code to push bufsize, buf, call cpyBuf() and return its result. + * The parameter were ordered to allow this code optimization. */ -static COUNT cpyBuf(UBYTE FAR *dst, UBYTE FAR *src - , UWORD srclen, UWORD dstlen) +static COUNT cpyBuf(VOID FAR *dst, UWORD dstlen + , VOID FAR *src, UWORD srclen) { if(srclen <= dstlen) { - _fmemcpy((BYTE FAR*)dst, (BYTE FAR*)src, srclen); + _fmemcpy(dst, src, srclen); return SUCCESS; } return DE_INVLDFUNC; /* buffer too small */ } + + +/* + * This function assumes that 'map' is adjusted such that + * map[0x80] is the uppercase of character 0x80. + *== 128 byte chartables, lower range conform to 7bit-US-ASCII ==ska*/ +static VOID upMMem(UBYTE FAR *map, UBYTE FAR * str, unsigned len) +{ + REG unsigned c; + +#ifdef NLS_DEBUG + UBYTE FAR *oldStr; + unsigned oldLen; + + oldStr = str; + oldLen = len; +log( ("NLS: upMMem(): len=%u, %04x:%04x=\"", len, FP_SEG(str), FP_OFF(str)) ); + for(c = 0; c < len; ++c) + printf("%c", str[c] > 32? str[c]: '.'); + printf("\"\n"); +#endif + if (len) + do + { + if ((c = *str) >= 'a' && c <= 'z') + *str += 'A' - 'a'; + else if (c > 0x7f) + *str = map[c]; + ++str; + } + while (--len); +#ifdef NLS_DEBUG +printf("NLS: upMMem(): result=\""); + for(c = 0; c < oldLen; ++c) + printf("%c", oldStr[c] > 32? oldStr[c]: '.'); + printf("\"\n"); +#endif +} + + +/******************************************************************** + ***** Lowlevel interface ******************************************* + ********************************************************************/ + +/* GetData function used by both the MUX-callback function and + the direct-access interface. + subfct == NLS_DOS_38 is a value > 0xff in order to not clash + with subfunctions valid to be passed as DOS-65-XX. */ +static int nlsGetData(struct nlsPackage FAR *nls, int subfct, UBYTE FAR *buf + , unsigned bufsize) +{ VOID FAR *poi; + +log( ("NLS: nlsGetData(): subfct=%x, bufsize=%u, cp=%u, cntry=%u\n", + subfct, bufsize, nls->cp, nls->cntry) ); + + /* Theoretically tables 1 and, if NLS_REORDER_POINTERS is enabled, + 2 and 4 could be hard-coded, because their + data is located at predictable (calculatable) locations. + However, 1 and subfct NLS_DOS_38 are to handle the same + data and the "locateSubfct()" call has to be implemented anyway, + in order to handle all subfunctions. + Also, NLS is often NOT used in any case, so this code is more + size than speed optimized. */ + if((poi = locateSubfct(nls, subfct)) != NULL) { +log( ("NLS: nlsGetData(): subfunction found\n") ); + switch(subfct) { + case 1: /* Extended Country Information */ + return cpyBuf(buf, bufsize, poi + , ((struct nlsExtCntryInfo FAR*)poi)->size + 3); + case NLS_DOS_38: /* Normal Country Information */ + return cpyBuf(buf, bufsize + , &(((struct nlsExtCntryInfo FAR*)poi)->dateFmt) + , 34); /* standard cinfo has no more 34 _used_ bytes */ + default: + /* All other subfunctions just return the found nlsPoinerInf + structure */ + return cpyBuf(buf, bufsize, poi, sizeof(struct nlsPointer)); + } + } + + /* The requested subfunction could not been located within the + NLS pkg --> error. Because the data corresponds to the subfunction + number passed to the API, the failure is the same as that a wrong + API function has been called. */ +log( ("NLS: nlsGetData(): Subfunction not found\n") ); + return DE_INVLDFUNC; +} + +VOID nlsCPchange(UWORD cp) +{ printf("\7\nSorry, to change the codepage is not implemented, yet.\n\ +Hope it's OK to proceed ignoring this call.\n-- 2000/02/26 ska\n"); +} + +/* + * Changes the current active codepage or cntry + * + * Note: Usually any call sees a value of -1 (0xFFFF) as "the current + * country/CP". When a new NLS pkg is loaded, there is however a little + * difference, because one could mean that when switching to country XY + * the system may change to any codepage required. + * Example: + * MODE has prepared codepages 437 and 850. + * The user loaded a 2nd NLS pkg via CONFIG.SYS with: + * COUNTRY=49,850,C:\COUNTRY.SYS + * By default, the kernel maintains the hardcoded 001,437 (U.S.A./CP437) + * After the Country statement the system switches to codepage 850. + * But when the user invokes DOS-38-01/DX=FFFF (Set Country ID to 1) + * the system _must_ switch to codepage 437, because this is the only + * NLS pkg loaded. + * Therefore, setPackage() will substitute the current country ID, if + * cntry==-1, but leaves cp==-1 in order to let NLSFUNC choose the most + * appropriate codepage on its own. + */ + +static COUNT nlsSetPackage(struct nlsPackage FAR *nls) +{ + if(nls->cp != nlsInfo.actPkg->cp) /* Codepage gets changed --> + inform all character drivers thereabout. + If this fails, it would be possible that the old + NLS pkg had been removed from memory by NLSFUNC. */ + nlsCPchange(nls->cp); + + nlsInfo.actPkg = nls; + + return SUCCESS; +} +static COUNT DosSetPackage(UWORD cp, UWORD cntry) +{ struct nlsPackage FAR*nls; /* NLS package to use to return the info from */ + + /* nls := NLS package of cntry/codepage */ + if((nls = searchPackage(cp, cntry)) != NULL) + /* OK the NLS pkg is loaded --> activate it */ + return nlsSetPackage(nls); + + /* not loaded --> invoke NLSFUNC to load it */ + return muxLoadPkg(cp, cntry); +} + +static void nlsUpMem(struct nlsPackage FAR *nls, VOID FAR *str, int len) +{ +log( ("NLS: nlsUpMem()\n") ); + upMMem(getCharTbl2(nls), (UBYTE FAR*)str, len); +} +static void nlsFUpMem(struct nlsPackage FAR *nls, VOID FAR *str, int len) +{ +log( ("NLS: nlsFUpMem()\n") ); + upMMem(getCharTbl4(nls), (UBYTE FAR*)str, len); +} + +static VOID xUpMem(struct nlsPackage FAR *nls, VOID FAR * str, unsigned len) +/* upcase a memory area */ +{ +log( ("NLS: xUpMem(): cp=%u, cntry=%u\n", nls->cp, nls->cntry) ); + + if(nls->flags & NLS_FLAG_DIRECT_UPCASE) + nlsUpMem(nls, str, len); + else + muxBufGo(NLSFUNC_UPMEM, 0, nls->cp, nls->cntry, len, str); +} + +static int nlsYesNo(struct nlsPackage FAR *nls, unsigned char ch) +{ + assertDSeqSS(); /* because "&ch" */ + +log( ("NLS: nlsYesNo(): in ch=%u (%c)\n", ch, ch>32? ch: ' ') ); + + xUpMem(nls, &ch, 1); /* Upcase character */ + /* Cannot use DosUpChar(), because + maybe: nls != current NLS pkg + However: Upcase character within lowlevel + function to allow a yesNo() function + catched by external MUX-14 handler, which + does NOT upcase character. */ +log( ("NLS: nlsYesNo(): upcased ch=%u (%c)\n", ch, ch>32? ch: ' ') ); + if(ch == nls->yeschar) + return 1; + if(ch == nls->nochar) + return 0; + return 2; +} + + +/******************************************************************** + ***** DOS API ****************************************************** + ********************************************************************/ + +BYTE DosYesNo(unsigned char ch) +/* returns: 0: ch == "No", 1: ch == "Yes", 2: ch crap */ +{ + if(nlsInfo.actPkg->flags & NLS_FLAG_DIRECT_YESNO) + return nlsYesNo(nlsInfo.actPkg, ch); + else + return muxYesNo(ch); +} + + +#ifndef DosUpMem +VOID DosUpMem(VOID FAR * str, unsigned len) +{ xUpMem(nlsInfo.actPkg, str, len); +} +#endif + +/* + * This function is also called by the backdoor entry specified by + * the "upCaseFct" member of the Country Information structure. Therefore + * the HiByte of the first argument must remain unchanged. + * See NLSSUPT.ASM -- 2000/03/30 ska + */ +unsigned char DosUpChar(unsigned char ch) + /* upcase a single character */ +{ + assertDSeqSS(); /* because "&ch" */ +log( ("NLS: DosUpChar(): in ch=%u (%c)\n", ch, ch>32? ch: ' ') ); + DosUpMem((UBYTE FAR*)&ch, 1); +log( ("NLS: DosUpChar(): upcased ch=%u (%c)\n", ch, ch>32? ch: ' ') ); + return ch; +} + +VOID DosUpString(char FAR *str) +/* upcase a string */ +{ + DosUpMem(str, fstrlen(str)); +} + +VOID DosUpFMem(VOID FAR *str, unsigned len) +/* upcase a memory area for file names */ +{ +#ifdef NLS_DEBUG + unsigned c; +log( ("NLS: DosUpFMem(): len=%u, %04x:%04x=\"", len, FP_SEG(str), FP_OFF(str)) ); + for(c = 0; c < len; ++c) + printf("%c", str[c] > 32? str[c]: '.'); + printf("\"\n"); +#endif + if(nlsInfo.actPkg->flags & NLS_FLAG_DIRECT_FUPCASE) + nlsFUpMem(nlsInfo.actPkg, str, len); + else + muxUpMem(NLSFUNC_FILE_UPMEM, str, len); +} + +unsigned char DosUpFChar(unsigned char ch) + /* upcase a single character for file names */ +{ + assertDSeqSS(); /* because "&ch" */ + DosUpFMem((UBYTE FAR*)&ch, 1); + return ch; +} + +VOID DosUpFString(char FAR *str) +/* upcase a string for file names */ +{ + DosUpFMem(str, fstrlen(str)); +} + /* * Called for all subfunctions other than 0x20-0x23,& 0xA0-0xA2 * of DOS-65 + * + * If the requested NLS pkg specified via cntry and cp is _not_ + * loaded, MUX-14 is invoked; otherwise the pkg's NLS_Fct_buf + * function is invoked. */ -COUNT extCtryInfo(int subfct, UWORD codepage - , UWORD cntry, UWORD bufsize, UBYTE FAR * buf) +COUNT DosGetData(int subfct, UWORD cp, UWORD cntry + , UWORD bufsize, VOID FAR * buf) { struct nlsPackage FAR*nls; /* NLS package to use to return the info from */ - int rc; - int muxOnCntryInfo, muxOnPointer; - struct nlsPointerInf FAR *poi; - if(!buf) +log( ("NLS: GetData(): subfct=%x, cp=%u, cntry=%u, bufsize=%u\n", + subfct, cp, cntry, bufsize) ); + + if(!buf || !bufsize) return DE_INVLDDATA; if(subfct == 0) /* Currently not supported */ return DE_INVLDFUNC; /* nls := NLS package of cntry/codepage */ - if((nls = searchPackage(&codepage, &cntry)) == NULL) - /* requested NLS package is not loaded --> - pass the request to NLSFUNC */ - muxOnCntryInfo = muxOnPointer = TRUE; - else { - muxOnCntryInfo = NLS_MUX_COUNTRY_INFO(nls); - muxOnPointer = NLS_MUX_POINTERS(nls); + if((nls = searchPackage(cp, cntry)) == NULL + || (nls->flags & NLS_FLAG_DIRECT_GETDATA) == 0) { + /* If the NLS pkg is not loaded into memory or the + direct-access flag is disabled, the request must + be passed through MUX */ + return (subfct == NLS_DOS_38) + ? mux38(nls->cp, nls->cntry, bufsize, buf) + : mux65(subfct, nls->cp, nls->cntry, bufsize, buf); } - if(subfct == 1) { /* return Extended Country Information */ - if(muxOnCntryInfo) - return mux65(1, codepage, cntry, bufsize, buf); - return cpyBuf(buf, (BYTE FAR*)&nls->cntryInfo - , nls->cntryInfo.size + 3, bufsize); - } - if(subfct == NLS_DOS_38) { /* return Country Information */ - if(muxOnCntryInfo) - return mux38(codepage, cntry, bufsize, buf); - return cpyBuf(buf, (BYTE FAR*)&nls->cntryInfo.dateFmt - , nls->cntryInfo.size - 4, bufsize); - } - - if(muxOnPointer) - return mux65(subfct, codepage, cntry, bufsize, buf); - - /* any other subfunction returns a pointer to any sort - of data; the pointer is located within the nlsPointers - array */ - if((poi = locateSubfct(nls, subfct)) != NULL) - return cpyBuf(buf, (UBYTE FAR *)poi - , sizeof(struct nlsPointerInf), bufsize); - - return DE_INVLDFUNC; + /* Direct access to the data */ + return nlsGetData(nls, subfct, buf, bufsize); } -/* - * Changes the current active codepage or cntry - */ -static COUNT setPackage(UWORD cp, UWORD cntry) -{ struct nlsPackage FAR*nls; /* NLS package to use to return the info from */ - int rc; - - /* nls := NLS package of cntry/codepage */ - if((nls = searchPackage(&cp, &cntry)) == NULL) { - /* not loaded --> invoke NLSFUNC to load it */ - if((rc = muxLoadPkg(cp, cntry)) != SUCCESS) - return rc; - if((nls = searchPackage(&cp, &cntry)) == NULL) - /* something went wrong */ - return DE_INVLDFUNC; - } - - nlsInfo.actPkg = nls; -#ifdef NLS_CACHE_POINTERS - /* Fill the quick-access pointers */ - nlsInfo.fnamUpTable = getTable4->pointer - 0x80; - nlsInfo.upTable = getTable2->pointer - 0x80; -#endif - return SUCCESS; -} /* * Called for DOS-38 get info @@ -288,121 +556,100 @@ static COUNT setPackage(UWORD cp, UWORD cntry) * it is assumed the buffer is large enough as described in RBIL, * which is 34 bytes _hardcoded_. */ -COUNT getCountryInformation(UWORD cntry, BYTE FAR *buf) -{ return extCtryInfo(NLS_DOS_38, NLS_DEFAULT, cntry, 34, buf); +#ifndef DosGetCountryInformation +COUNT DosGetCountryInformation(UWORD cntry, VOID FAR *buf) +{ return DosGetData(NLS_DOS_38, NLS_DEFAULT, cntry, 34, buf); } +#endif /* * Called for DOS-38 set country code */ -COUNT setCountryCode(UWORD cntry) -{ return setPackage(NLS_DEFAULT, cntry); +#ifndef DosSetCountry +COUNT DosSetCountry(UWORD cntry) +{ return DosSetPackage(NLS_DEFAULT, cntry); } +#endif /* * Called for DOS-66-01 get CP */ -COUNT getCodePage(UWORD FAR* actCP, UWORD FAR*sysCP) +COUNT DosGetCodepage(UWORD FAR* actCP, UWORD FAR* sysCP) { *sysCP = nlsInfo.sysCodePage; - *actCP = nlsInfo.actPkg->cntryInfo.codePage; + *actCP = nlsInfo.actPkg->cp; return SUCCESS; } + /* * Called for DOS-66-02 set CP * Note: One cannot change the system CP. Why it is necessary * to specify it, is lost to me. (2000/02/13 ska) */ -COUNT setCodePage(UWORD actCP, UWORD sysCP) +COUNT DosSetCodepage(UWORD actCP, UWORD sysCP) { if(sysCP == NLS_DEFAULT || sysCP == nlsInfo.sysCodePage) - return setPackage(actCP, NLS_DEFAULT); + return DosSetPackage(actCP, NLS_DEFAULT); return DE_INVLDDATA; } +/******************************************************************** + ***** MUX-14 API *************************************************** + ********************************************************************/ +/* Registers: + AH == 14 + AL == subfunction + BX == codepage + DX == country code + DS:SI == internal global nlsInfo + ES:DI == user block -static VOID upMMem(unsigned char FAR *map, unsigned char FAR * str - , unsigned len) -{ - REG unsigned c; + Return value: AL register to be returned + if AL == 0, Carry must be cleared, otherwise set +*/ +#pragma argsused +UWORD syscall_MUX14(DIRECT_IREGS) +{ struct nlsPackage FAR*nls; /* addressed NLS package */ - if (len) - do - { - if ((c = *str) >= 'a' && c <= 'z') - *str += 'A' - 'a'; - else if (c > 0x7f) - *str = map[c & 0x7f]; - ++str; - } - while (--len); +log( ("NLS: MUX14(): subfct=%x, cp=%u, cntry=%u\n", + AL, BX, DX) ); + + if((nls = searchPackage(BX, DX)) == NULL) + return DE_INVLDFUNC; /* no such package */ + +log( ("NLS: MUX14(): NLS pkg found\n") ); + + switch(AL) { + case NLSFUNC_INSTALL_CHECK: + BX = NLS_FREEDOS_NLSFUNC_ID; + return SUCCESS; /* kernel just simulates default functions */ + case NLSFUNC_DOS38: + return nlsGetData(nls, NLS_DOS_38, MK_FP(ES, DI), 34); + case NLSFUNC_GETDATA: + return nlsGetData(nls, BP, MK_FP(ES, DI), CX); + case NLSFUNC_DRDOS_GETDATA: + /* Does not pass buffer length */ + return nlsGetData(nls, CL, MK_FP(ES, DI), 512); + case NLSFUNC_LOAD_PKG: + case NLSFUNC_LOAD_PKG2: + return nlsSetPackage(nls); + case NLSFUNC_YESNO: + return nlsYesNo(nls, CL); + case NLSFUNC_UPMEM: + nlsUpMem(nls, MK_FP(ES, DI), CX); + return SUCCESS; + case NLSFUNC_FILE_UPMEM: +#ifdef NLS_DEBUG +{ unsigned j; + BYTE FAR *p; +log( ("NLS: MUX14(FILE_UPMEM): len=%u, %04x:%04x=\"", CX, ES, DI) ); + for(j = 0, p = MK_FP(ES, DI); j < CX; ++j) + printf("%c", p[j] > 32? p[j]: '.'); + printf("\"\n"); } - - -BYTE yesNo(unsigned char ch) -/* returns: 0: ch == "No", 1: ch == "Yes", 2: ch crap */ -{ - if(NLS_MUX_YESNO(nlsInfo.actPkg)) - return muxYesNo(ch); - - ch = upChar(ch); - if (ch == noChar) - return 0; - if (ch == yesChar) - return 1; - return 2; -} - -VOID upMem(unsigned char FAR * str, unsigned len) -/* upcase a memory area */ -{ -#ifndef NLS_CACHE_POINTERS - if(NLS_MUX_EXTERNAL_UP(nlsInfo.actPkg)) { - muxUpMem(str, len, NLS_NLSFUNC_UP); - return; - } #endif - upMMem(normalCh, str, len); -} - -unsigned char upChar(unsigned char ch) - /* upcase a single character */ -{ unsigned char buf[1]; - *buf = ch; - upMem((BYTE FAR*)buf, 1); - return *buf; -} - -VOID upString(unsigned char FAR * str) -/* upcase a string */ -{ - upMem(str, fstrlen(str)); -} - -VOID upFMem(unsigned char FAR * str, unsigned len) -/* upcase a memory area for file names */ -{ -#ifndef NLS_CACHE_POINTERS - if(NLS_MUX_EXTERNAL_FUP(nlsInfo.actPkg)) { - muxUpMem(str, len, NLS_NLSFUNC_FUP); - return; + nlsFUpMem(nls, MK_FP(ES, DI), CX); + return SUCCESS; } -#endif - upMMem(fileCh, str, len); +log( ("NLS: MUX14(): Invalid function %x\n", AL) ); + return DE_INVLDFUNC; /* no such function */ } - -unsigned char upFChar(unsigned char ch) - /* upcase a single character for file names */ -{ unsigned char buf[1]; - - *buf = ch; - upFMem((BYTE FAR*)buf, 1); - return *buf; -} - -VOID upFString(unsigned char FAR * str) -/* upcase a string for file names */ -{ - upFMem(str, fstrlen(str)); -} - - diff --git a/kernel/nls_hc.asm b/kernel/nls_hc.asm new file mode 100644 index 0000000..087c9e7 --- /dev/null +++ b/kernel/nls_hc.asm @@ -0,0 +1,109 @@ +; Hardcoded DOS-NLS information for country = 1, codepage = 437 +; This is an automatically generated file! +; Any modifications will be lost! + +; Prerequisites: +;; ==> Assuming that data of tables remains constant all the time +;; ==> Reordering tables 1, 2, 4 and 5 + + %include "segs.inc" +segment _DATA + + GLOBAL _nlsPackageHardcoded +_nlsPackageHardcoded: + DB 000h, 000h, 000h, 000h, 001h, 000h, 0b5h, 001h + DB 00fh, 000h, 059h, 04eh, 006h, 000h + DB 002h + DW ?table2, SEG ?table2 + DB 004h + DW ?table4, SEG ?table4 + DB 005h + DW ?table5, SEG ?table5 + DB 006h + DW ?table6, SEG ?table6 + DB 007h + DW ?table7, SEG ?table7 + GLOBAL _nlsCountryInfoHardcoded +_nlsCountryInfoHardcoded: + DB 001h +?table1: + DB 01ch, 000h, 001h, 000h, 0b5h, 001h, 000h, 000h + DB 024h, 000h, 000h, 000h, 000h, 02ch, 000h, 02eh + DB 000h, 02dh, 000h, 03ah, 000h, 000h, 002h, 000h + DB 0e8h, 058h, 000h, 000h, 02ch, 000h + GLOBAL _hcTablesStart +_hcTablesStart: + GLOBAL _nlsFUpcaseHardcoded +_nlsFUpcaseHardcoded: +?table4: + GLOBAL _nlsUpcaseHardcoded +_nlsUpcaseHardcoded: +?table2: + DB 080h, 000h, 080h, 09ah, 045h, 041h, 08eh, 041h + DB 08fh, 080h, 045h, 045h, 045h, 049h, 049h, 049h + DB 08eh, 08fh, 090h, 092h, 092h, 04fh, 099h, 04fh + DB 055h, 055h, 059h, 099h, 09ah, 09bh, 09ch, 09dh + DB 09eh, 09fh, 041h, 049h, 04fh, 055h, 0a5h, 0a5h + DB 0a6h, 0a7h, 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh + DB 0aeh, 0afh, 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h + DB 0b6h, 0b7h, 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh + DB 0beh, 0bfh, 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h + DB 0c6h, 0c7h, 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh + DB 0ceh, 0cfh, 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h + DB 0d6h, 0d7h, 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh + DB 0deh, 0dfh, 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h + DB 0e6h, 0e7h, 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh + DB 0eeh, 0efh, 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h + DB 0f6h, 0f7h, 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh + DB 0feh, 0ffh + GLOBAL _nlsFnameTermHardcoded +_nlsFnameTermHardcoded: +?table5: + DB 016h, 000h, 08eh, 000h, 0ffh, 041h, 000h, 020h + DB 0eeh, 00eh, 02eh, 022h, 02fh, 05ch, 05bh, 05dh + DB 03ah, 07ch, 03ch, 03eh, 02bh, 03dh, 03bh, 02ch + GLOBAL _nlsCollHardcoded +_nlsCollHardcoded: +?table6: + DB 000h, 001h, 000h, 001h, 002h, 003h, 004h, 005h + DB 006h, 007h, 008h, 009h, 00ah, 00bh, 00ch, 00dh + DB 00eh, 00fh, 010h, 011h, 012h, 013h, 014h, 015h + DB 016h, 017h, 018h, 019h, 01ah, 01bh, 01ch, 01dh + DB 01eh, 01fh, 020h, 021h, 022h, 023h, 024h, 025h + DB 026h, 027h, 028h, 029h, 02ah, 02bh, 02ch, 02dh + DB 02eh, 02fh, 030h, 031h, 032h, 033h, 034h, 035h + DB 036h, 037h, 038h, 039h, 03ah, 03bh, 03ch, 03dh + DB 03eh, 03fh, 040h, 041h, 042h, 043h, 044h, 045h + DB 046h, 047h, 048h, 049h, 04ah, 04bh, 04ch, 04dh + DB 04eh, 04fh, 050h, 051h, 052h, 053h, 054h, 055h + DB 056h, 057h, 058h, 059h, 05ah, 05bh, 05ch, 05dh + DB 05eh, 05fh, 060h, 041h, 042h, 043h, 044h, 045h + DB 046h, 047h, 048h, 049h, 04ah, 04bh, 04ch, 04dh + DB 04eh, 04fh, 050h, 051h, 052h, 053h, 054h, 055h + DB 056h, 057h, 058h, 059h, 05ah, 07bh, 07ch, 07dh + DB 07eh, 07fh, 043h, 055h, 045h, 041h, 041h, 041h + DB 041h, 043h, 045h, 045h, 045h, 049h, 049h, 049h + DB 041h, 041h, 045h, 041h, 041h, 04fh, 04fh, 04fh + DB 055h, 055h, 059h, 04fh, 055h, 024h, 024h, 024h + DB 024h, 024h, 041h, 049h, 04fh, 055h, 04eh, 04eh + DB 0a6h, 0a7h, 03fh, 0a9h, 0aah, 0abh, 0ach, 021h + DB 022h, 022h, 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h + DB 0b6h, 0b7h, 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh + DB 0beh, 0bfh, 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h + DB 0c6h, 0c7h, 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh + DB 0ceh, 0cfh, 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h + DB 0d6h, 0d7h, 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh + DB 0deh, 0dfh, 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h + DB 0e6h, 0e7h, 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh + DB 0eeh, 0efh, 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h + DB 0f6h, 0f7h, 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh + DB 0feh, 0ffh + GLOBAL _nlsDBCSHardcoded +_nlsDBCSHardcoded: +?table7: + DB 000h, 000h, 000h, 000h + GLOBAL _hcTablesEnd +_hcTablesEnd: + + +END diff --git a/kernel/nls_hc.c b/kernel/nls_hc.c deleted file mode 100644 index 1d20071..0000000 --- a/kernel/nls_hc.c +++ /dev/null @@ -1,194 +0,0 @@ -/****************************************************************/ -/* */ -/* nls_hc.c */ -/* FreeDOS */ -/* */ -/* National Languge Support hardcoded NLS package */ -/* */ -/* Copyright (c) 2000 */ -/* Steffen Kaiser */ -/* All Rights Reserved */ -/* */ -/* This file is part of DOS-C. */ -/* */ -/* DOS-C is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version */ -/* 2, or (at your option) any later version. */ -/* */ -/* DOS-C is distributed in the hope that it will be useful, but */ -/* WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ -/* the GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public */ -/* License along with DOS-C; see the file COPYING. If not, */ -/* write to the Free Software Foundation, 675 Mass Ave, */ -/* Cambridge, MA 02139, USA. */ -/****************************************************************/ - -#include "portab.h" -#include "globals.h" -#define NLS_NO_VARS -#include "nls.h" - -#undef NLS_NO_VARS -#define NLS_HARDCODED US -#define NLS_POINTERS 5 -#define NLS_FNAMSEPS 14 -#define NLS_DBCSENTR 1 -#include "nls.h" - - -/* - * Hardcoded NLS package for U.S.A. CP437 - */ -struct nlsCharTbl128 nlsUpHardcodedTable = { - 128, /* upcase table */ - { - '\x80' ,'\x9a' ,'E' ,'A' ,'\x8e' ,'A' ,'\x8f' ,'\x80' /* 0 - 7 */ - ,'E' ,'E' ,'E' ,'I' ,'I' ,'I' ,'\x8e' ,'\x8f' /* 8 - 15 */ - ,'\x90' ,'\x92' ,'\x92' ,'O' ,'\x99' ,'O' ,'U' ,'U' /* 16 - 23 */ - ,'Y' ,'\x99' ,'\x9a' ,'\x9b' ,'\x9c' ,'\x9d' ,'\x9e' ,'\x9f' /* 24 - 31 */ - ,'A' ,'I' ,'O' ,'U' ,'\xa5' ,'\xa5' ,'\xa6' ,'\xa7' /* 32 - 39 */ - ,'\xa8' ,'\xa9' ,'\xaa' ,'\xab' ,'\xac' ,'\xad' ,'\xae' ,'\xaf' /* 40 - 47 */ - ,'\xb0' ,'\xb1' ,'\xb2' ,'\xb3' ,'\xb4' ,'\xb5' ,'\xb6' ,'\xb7' /* 48 - 55 */ - ,'\xb8' ,'\xb9' ,'\xba' ,'\xbb' ,'\xbc' ,'\xbd' ,'\xbe' ,'\xbf' /* 56 - 63 */ - ,'\xc0' ,'\xc1' ,'\xc2' ,'\xc3' ,'\xc4' ,'\xc5' ,'\xc6' ,'\xc7' /* 64 - 71 */ - ,'\xc8' ,'\xc9' ,'\xca' ,'\xcb' ,'\xcc' ,'\xcd' ,'\xce' ,'\xcf' /* 72 - 79 */ - ,'\xd0' ,'\xd1' ,'\xd2' ,'\xd3' ,'\xd4' ,'\xd5' ,'\xd6' ,'\xd7' /* 80 - 87 */ - ,'\xd8' ,'\xd9' ,'\xda' ,'\xdb' ,'\xdc' ,'\xdd' ,'\xde' ,'\xdf' /* 88 - 95 */ - ,'\xe0' ,'\xe1' ,'\xe2' ,'\xe3' ,'\xe4' ,'\xe5' ,'\xe6' ,'\xe7' /* 96 - 103 */ - ,'\xe8' ,'\xe9' ,'\xea' ,'\xeb' ,'\xec' ,'\xed' ,'\xee' ,'\xef' /* 104 - 111 */ - ,'\xf0' ,'\xf1' ,'\xf2' ,'\xf3' ,'\xf4' ,'\xf5' ,'\xf6' ,'\xf7' /* 112 - 119 */ - ,'\xf8' ,'\xf9' ,'\xfa' ,'\xfb' ,'\xfc' ,'\xfd' ,'\xfe' ,'\xff' /* 120 - 127 */ - } -}; -struct nlsCharTbl128 nlsFnameUpHardcodedTable = { - 128, /* file name upcase table */ - { - '\x80' ,'\x9a' ,'E' ,'A' ,'\x8e' ,'A' ,'\x8f' ,'\x80' /* 0 - 7 */ - ,'E' ,'E' ,'E' ,'I' ,'I' ,'I' ,'\x8e' ,'\x8f' /* 8 - 15 */ - ,'\x90' ,'\x92' ,'\x92' ,'O' ,'\x99' ,'O' ,'U' ,'U' /* 16 - 23 */ - ,'Y' ,'\x99' ,'\x9a' ,'\x9b' ,'\x9c' ,'\x9d' ,'\x9e' ,'\x9f' /* 24 - 31 */ - ,'A' ,'I' ,'O' ,'U' ,'\xa5' ,'\xa5' ,'\xa6' ,'\xa7' /* 32 - 39 */ - ,'\xa8' ,'\xa9' ,'\xaa' ,'\xab' ,'\xac' ,'\xad' ,'\xae' ,'\xaf' /* 40 - 47 */ - ,'\xb0' ,'\xb1' ,'\xb2' ,'\xb3' ,'\xb4' ,'\xb5' ,'\xb6' ,'\xb7' /* 48 - 55 */ - ,'\xb8' ,'\xb9' ,'\xba' ,'\xbb' ,'\xbc' ,'\xbd' ,'\xbe' ,'\xbf' /* 56 - 63 */ - ,'\xc0' ,'\xc1' ,'\xc2' ,'\xc3' ,'\xc4' ,'\xc5' ,'\xc6' ,'\xc7' /* 64 - 71 */ - ,'\xc8' ,'\xc9' ,'\xca' ,'\xcb' ,'\xcc' ,'\xcd' ,'\xce' ,'\xcf' /* 72 - 79 */ - ,'\xd0' ,'\xd1' ,'\xd2' ,'\xd3' ,'\xd4' ,'\xd5' ,'\xd6' ,'\xd7' /* 80 - 87 */ - ,'\xd8' ,'\xd9' ,'\xda' ,'\xdb' ,'\xdc' ,'\xdd' ,'\xde' ,'\xdf' /* 88 - 95 */ - ,'\xe0' ,'\xe1' ,'\xe2' ,'\xe3' ,'\xe4' ,'\xe5' ,'\xe6' ,'\xe7' /* 96 - 103 */ - ,'\xe8' ,'\xe9' ,'\xea' ,'\xeb' ,'\xec' ,'\xed' ,'\xee' ,'\xef' /* 104 - 111 */ - ,'\xf0' ,'\xf1' ,'\xf2' ,'\xf3' ,'\xf4' ,'\xf5' ,'\xf6' ,'\xf7' /* 112 - 119 */ - ,'\xf8' ,'\xf9' ,'\xfa' ,'\xfb' ,'\xfc' ,'\xfd' ,'\xfe' ,'\xff' /* 120 - 127 */ - } -}; -struct nlsFnamTermUS nlsFnameTermHardcodedTable = { - 22, /* size of permittable character structure */ - 1, /* reserved */ - '\x00' ,'\xff', /* first/last permittable character */ - 0, /* reserved */ - '\x00' ,' ', /* first/last excluded character */ - 2, /* reserved */ - 14, /* number of separators */ - { /* separators */ - '.' ,'"' ,'/' ,'\\','[' ,']' ,':' ,'|', /* 0 - 7 */ - '<' ,'>' ,'+' ,'=' ,';' ,',' /* 8 - 13 */ - } -}; -struct nlsCharTbl256 nlsCollHardcodedTable = { - 256, /* collating sequence table */ - { - '\x00' ,'\x01' ,'\x02' ,'\x03' ,'\x04' ,'\x05' ,'\x06' ,'\x07' /* 0 - 7 */ - ,'\x08' ,'\x09' ,'\x0a' ,'\x0b' ,'\x0c' ,'\x0d' ,'\x0e' ,'\x0f' /* 8 - 15 */ - ,'\x10' ,'\x11' ,'\x12' ,'\x13' ,'\x14' ,'\x15' ,'\x16' ,'\x17' /* 16 - 23 */ - ,'\x18' ,'\x19' ,'\x1a' ,'\x1b' ,'\x1c' ,'\x1d' ,'\x1e' ,'\x1f' /* 24 - 31 */ - ,' ' ,'!' ,'"' ,'#' ,'$' ,'%' ,'&' ,'\'' /* 32 - 39 */ - ,'(' ,')' ,'*' ,'+' ,',' ,'-' ,'.' ,'/' /* 40 - 47 */ - ,'0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' /* 48 - 55 */ - ,'8' ,'9' ,':' ,';' ,'<' ,'=' ,'>' ,'?' /* 56 - 63 */ - ,'@' ,'A' ,'B' ,'C' ,'D' ,'E' ,'F' ,'G' /* 64 - 71 */ - ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O' /* 72 - 79 */ - ,'P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' /* 80 - 87 */ - ,'X' ,'Y' ,'Z' ,'[' ,'\\',']' ,'^' ,'_' /* 88 - 95 */ - ,'`' ,'A' ,'B' ,'C' ,'D' ,'E' ,'F' ,'G' /* 96 - 103 */ - ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O' /* 104 - 111 */ - ,'P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' /* 112 - 119 */ - ,'X' ,'Y' ,'Z' ,'{' ,'|' ,'}' ,'~' ,'\x7f' /* 120 - 127 */ - ,'C' ,'U' ,'E' ,'A' ,'A' ,'A' ,'A' ,'C' /* 128 - 135 */ - ,'E' ,'E' ,'E' ,'I' ,'I' ,'I' ,'A' ,'A' /* 136 - 143 */ - ,'E' ,'A' ,'A' ,'O' ,'O' ,'O' ,'U' ,'U' /* 144 - 151 */ - ,'Y' ,'O' ,'U' ,'$' ,'$' ,'$' ,'$' ,'$' /* 152 - 159 */ - ,'A' ,'I' ,'O' ,'U' ,'N' ,'N' ,'\xa6' ,'\xa7' /* 160 - 167 */ - ,'?' ,'\xa9' ,'\xaa' ,'\xab' ,'\xac' ,'!' ,'"' ,'"' /* 168 - 175 */ - ,'\xb0' ,'\xb1' ,'\xb2' ,'\xb3' ,'\xb4' ,'\xb5' ,'\xb6' ,'\xb7' /* 176 - 183 */ - ,'\xb8' ,'\xb9' ,'\xba' ,'\xbb' ,'\xbc' ,'\xbd' ,'\xbe' ,'\xbf' /* 184 - 191 */ - ,'\xc0' ,'\xc1' ,'\xc2' ,'\xc3' ,'\xc4' ,'\xc5' ,'\xc6' ,'\xc7' /* 192 - 199 */ - ,'\xc8' ,'\xc9' ,'\xca' ,'\xcb' ,'\xcc' ,'\xcd' ,'\xce' ,'\xcf' /* 200 - 207 */ - ,'\xd0' ,'\xd1' ,'\xd2' ,'\xd3' ,'\xd4' ,'\xd5' ,'\xd6' ,'\xd7' /* 208 - 215 */ - ,'\xd8' ,'\xd9' ,'\xda' ,'\xdb' ,'\xdc' ,'\xdd' ,'\xde' ,'\xdf' /* 216 - 223 */ - ,'\xe0' ,'S' ,'\xe2' ,'\xe3' ,'\xe4' ,'\xe5' ,'\xe6' ,'\xe7' /* 224 - 231 */ - ,'\xe8' ,'\xe9' ,'\xea' ,'\xeb' ,'\xec' ,'\xed' ,'\xee' ,'\xef' /* 232 - 239 */ - ,'\xf0' ,'\xf1' ,'\xf2' ,'\xf3' ,'\xf4' ,'\xf5' ,'\xf6' ,'\xf7' /* 240 - 247 */ - ,'\xf8' ,'\xf9' ,'\xfa' ,'\xfb' ,'\xfc' ,'\xfd' ,'\xfe' ,'\xff' /* 248 - 255 */ - } -}; -struct nlsDBCSUS nlsDBCSHardcodedTable = { - 0, /* no DBC support */ - 0, /* DBC end marker */ -}; - -struct nlsInfoBlockUS nlsInfo = { - (char FAR*)NULL /*fname*/ - ,437 /*sysCodePage*/ - ,(struct nlsPackage FAR*)&nlsInfo.chain /* actPkg */ -#ifdef NLS_CACHE_DATA - ,(struct nlsCharTbl FAR*)&nlsFnameUpHardcodedTable - ,(struct nlsCharTbl FAR*)&nlsUpHardcodedTable -#endif - , /* hardcoded nlsPackageUS */ { - (struct nlsPackage FAR*)NULL /* nxt */ - ,0 /* MUX calling flags */ - , /* Extended Country Information */ { - 1, /* subfct */ - 0x26, /* size */ - 1, /* country code */ - 437, /* code page */ - 0, /* date format */ - { - /* currency string */ - '$','\x00','\x00','\x00','\x00', /* 0 - 4 */ - }, - { /* thousand separator */ - ',' ,'\x00' /* 0 - 1 */ - }, - { /* decimal point */ - '.' ,'\x00' /* 0 - 1 */ - }, - { /* date separator */ - '-' ,'\x00' /* 0 - 1 */ - }, - { /* time separator */ - ':' ,'\x00' /* 0 - 1 */ - }, - 0, /* currency format */ - 2, /* currency prescision */ - 0, /* time format */ - CharMapSrvc, /* upcase function */ - { /* data separator */ - ',','\x00' /* 0 - 1 */ - } - } - , 'Y', 'N' /* yes / no */ - , 5 /* num of subfunctions */ - , /* subfunctions */ { - { 2, (VOID FAR*)&nlsUpHardcodedTable } /* #0 */ - , { 4, (VOID FAR*)&nlsFnameUpHardcodedTable } /* #1 */ - , { 5, (VOID FAR*)&nlsFnameTermHardcodedTable } /* #2 */ - , { 6, (VOID FAR*)&nlsCollHardcodedTable } /* #3 */ - , { 7, (VOID FAR*)&nlsDBCSHardcodedTable } /* #4 */ - } - } -}; diff --git a/kernel/nls_load.c b/kernel/nls_load.c new file mode 100644 index 0000000..f3bf199 --- /dev/null +++ b/kernel/nls_load.c @@ -0,0 +1,388 @@ +/****************************************************************/ +/* */ +/* nls_load.c */ +/* FreeDOS */ +/* */ +/* National Languge Support functions and data structures */ +/* Load an entry from FreeDOS COUNTRY.SYS file. */ +/* */ +/* Copyright (c) 2000 */ +/* Steffen Kaiser */ +/* All Rights Reserved */ +/* */ +/* This file is part of FreeDOS. */ +/* */ +/* DOS-C is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version */ +/* 2, or (at your option) any later version. */ +/* */ +/* DOS-C is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ +/* the GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public */ +/* License along with DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + + +#include "portab.h" +#include "globals.h" +//#include "pcb.h" +#include + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * + */ + +#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, int size, COUNT fd) +{ if(dos_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(dos_lseek(fd, fct->csys_rpos, 0) >= 0) + return readStructure(buf, fct->csys_length, fd); + return err(); +} + +#define seek(n) rseek((LONG)(n), fd) +static rseek(LONG rpos, COUNT fd) +{ if(dos_lseek(fd, rpos, 1) >= 0) + return 1; + + return err(); +} + + +COUNT csysOpen(void) +{ COUNT fd; + struct nlsCSys_fileHeader header; + + if((fd = dos_open((BYTE FAR*)filename, 0)) < 0) { + printf("Cannot open: \"%s\"\n", filename); + return 1; + } + + if(dos_read(fd, &header, sizeof(header)) != sizeof(header); + || strcmp(header.csys_idstring, CSYS_FD_IDSTRING) != 0 + || dos_lseek(fd, (LONG)sizeof(csys_completeFileHeader), 0) + != (LONG)sizeof(csys_completeFileHeader)) { + printf("No valid COUNTRY.SYS: \"%s\"\n\nTry NLSFUNC /i %s\n" + , filename, filename); + dos_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 */ + memcpy(&hfct, fct, sizeof(hfct)); + memcpy(fct, &fcts[idx], sizeof(hfct)); + memcpy(&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 < numFcts && 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 += dos_ltell(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(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; +} + +INIT BOOL LoadCountryInfo(char *fnam) +{ COUNT fd; + int rc; + + if(strlen(fnam) < sizeof(filename)) { + strcpy(filename, fnam); + if((fd = csysOpen()) >= 0) { + rc = csysLoadPackage(fd); + dos_close(fd); + return rc; + } + } else + printf("Filename too long\n"); + return 0; +} diff --git a/kernel/nlssupt.asm b/kernel/nlssupt.asm index 6c9d9c4..b188c98 100644 --- a/kernel/nlssupt.asm +++ b/kernel/nlssupt.asm @@ -29,6 +29,9 @@ ; $Id$ ; ; $Log$ +; Revision 1.4 2000/08/06 05:50:17 jimtabor +; Add new files and update cvs with patches and changes +; ; Revision 1.3 2000/05/25 20:56:21 jimtabor ; Fixed project history ; @@ -95,10 +98,10 @@ _CharMapSrvc: push cx push bx - mov dx, DGROUP - mov ds, dx + push ax ; arg of _upChar + mov ax, DGROUP + mov ds, ax - push ax call _upChar ;add sp, byte 2 // next POP retrieves orig AX diff --git a/kernel/proto.h b/kernel/proto.h index cb3b9fd..b755496 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -34,8 +34,8 @@ static BYTE *Proto_hRcsId = "$Id$"; /* * $Log$ - * Revision 1.5 2000/06/21 18:16:46 jimtabor - * Add UMB code, patch, and code fixes + * Revision 1.6 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes * * Revision 1.4 2000/05/26 19:25:19 jimtabor * Read History file for Change info @@ -374,6 +374,7 @@ COUNT DosMemCheck(void); COUNT FreeProcessMem(UWORD ps); COUNT DosGetLargestBlock(UWORD FAR * block); VOID show_chain(void); +VOID DosUmbLink(BYTE n); VOID mcb_print(mcb FAR * mcbp); VOID _fmemcpy(BYTE FAR * d, BYTE FAR * s, REG COUNT n); @@ -385,19 +386,26 @@ VOID bcopy(REG BYTE * s, REG BYTE * d, REG COUNT n); __FAR_WRAPPER(VOID, fbcopy, (REG VOID FAR * s, REG VOID FAR * d, REG COUNT n)) /* nls.c */ -COUNT extCtryInfo(int subfct, UWORD codepage, - UWORD cntry, UWORD bufsize, UBYTE FAR * buf); -BYTE yesNo(unsigned char ch); -unsigned char upChar(unsigned char ch); -VOID upString(unsigned char FAR * str); -VOID upMem(unsigned char FAR * str, unsigned len); -unsigned char upFChar(unsigned char ch); -VOID upFString(unsigned char FAR * str); -VOID upFMem(unsigned char FAR * str, unsigned len); -COUNT setCountryCode(UWORD cntry); -COUNT getCountryInformation(UWORD cntry, BYTE FAR *buf); -COUNT getCodePage(UWORD FAR* actCP, UWORD FAR*sysCP); -COUNT setCodePage(UWORD actCP, UWORD sysCP); +BYTE DosYesNo(unsigned char ch); +#ifndef DosUpMem +VOID DosUpMem(VOID FAR * str, unsigned len); +#endif +unsigned char DosUpChar(unsigned char ch); +VOID DosUpString(char FAR *str); +VOID DosUpFMem(VOID FAR *str, unsigned len); +unsigned char DosUpFChar(unsigned char ch); +VOID DosUpFString(char FAR *str); +COUNT DosGetData(int subfct, UWORD cp, UWORD cntry + , UWORD bufsize, VOID FAR * buf); +#ifndef DosGetCountryInformation +COUNT DosGetCountryInformation(UWORD cntry, VOID FAR *buf); +#endif +#ifndef DosSetCountry +COUNT DosSetCountry(UWORD cntry); +#endif +COUNT DosGetCodepage(UWORD FAR* actCP, UWORD FAR* sysCP); +COUNT DosSetCodepage(UWORD actCP, UWORD sysCP); +UWORD syscall_MUX14(DIRECT_IREGS); /* prf.c */ VOID put_console(COUNT c); @@ -460,6 +468,8 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t); COUNT int2f_Remote_call(UWORD func, UWORD b, UCOUNT n, UWORD d, VOID FAR * s, UWORD i, VOID FAR * data); COUNT QRemote_Fn(char FAR * s, char FAR * d); +COUNT FAR Umb_Test(void); + UWORD get_machine_name(BYTE FAR * netname); VOID set_machine_name(BYTE FAR * netname, UWORD name_num); UCOUNT Remote_RW(UWORD func, UCOUNT n, BYTE FAR * bp, sft FAR * s, COUNT FAR * err); @@ -467,6 +477,9 @@ COUNT Remote_find(UWORD func, BYTE FAR * name, REG dmatch FAR * dmp); /* procsupt.asm */ VOID INRPT FAR exec_user(iregs FAR * irp); +#define strcpy(d, s) scopy(s, d) + +/* detect.c */ +unsigned long FAR is_dosemu(void); -#define strcpy(d, s) scopy(s, d) diff --git a/kernel/task.c b/kernel/task.c index 671e6b4..447e238 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -35,6 +35,9 @@ static BYTE *RcsId = "$Id$"; /* * $Log$ + * Revision 1.5 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.4 2000/05/26 19:25:19 jimtabor * Read History file for Change info * @@ -661,8 +664,14 @@ static COUNT DosExeLoader(BYTE FAR * namep, exec_blk FAR * exp, COUNT mode) /* + long2para((LONG) sizeof(psp)); ?? -- 1999/04/21 ska */ if (exe_size > asize) exe_size = asize; - } - +/* /// Removed closing curly brace. We should not attempt to allocate + memory if we are overlaying the current process, because the new + process will simply re-use the block we already have allocated. + This was causing execl() to fail in applications which use it to + overlay (replace) the current exe file with a new one. + Jun 11, 2000 - rbc + } */ + /* Allocate our memory and pass back any errors */ /* We can still get an error on first fit if the above */ /* returned size was a bet fit case */ @@ -694,6 +703,18 @@ static COUNT DosExeLoader(BYTE FAR * namep, exec_blk FAR * exp, COUNT mode) else /* with no error, we got exactly what we asked for */ asize = exe_size; + +/* /// Added open curly brace and "else" clause. We should not attempt + to allocate memory if we are overlaying the current process, because + the new process will simply re-use the block we already have allocated. + This was causing execl() to fail in applications which use it to + overlay (replace) the current exe file with a new one. + Jun 11, 2000 - rbc */ + } + else + asize = exe_size; +/* /// End of additions. Jun 11, 2000 - rbc */ + if (mode != OVERLAY) { /* memory found large enough - continue processing */ diff --git a/sys/sys.c b/sys/sys.c index 8cd699d..d14d060 100644 --- a/sys/sys.c +++ b/sys/sys.c @@ -27,6 +27,9 @@ ***************************************************************/ /* $Log$ + * Revision 1.4 2000/08/06 05:50:17 jimtabor + * Add new files and update cvs with patches and changes + * * Revision 1.3 2000/05/25 20:56:23 jimtabor * Fixed project history *