From cf9f8b2d3e53a770325a1be230515e0a705ba570 Mon Sep 17 00:00:00 2001 From: Peter Veenstra Date: Fri, 2 Oct 2015 20:13:57 +0000 Subject: [PATCH] -Add DOS_ToUpper which seems closer than just toupper, we might need to use it at more places than just the driveletter, but it is a big change. -Rework FCB_ParseName: -- Remove special code for . and .. as it was wrong -- Continue reading the input string, when the max length of the field has been reached (123456789.12345 is read and returned as 12345678.123) -- strip spaces before and after reading the separators. -- The drive is always parsed (if present), it doesn't depend on the existence of said drive. -- Fix parsing of .EXE and other extension only names -- Always clear out current block and record size. Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3940 --- src/dos/dos_files.cpp | 120 +++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 48 deletions(-) diff --git a/src/dos/dos_files.cpp b/src/dos/dos_files.cpp index a37b4cf8..3cdac4bf 100644 --- a/src/dos/dos_files.cpp +++ b/src/dos/dos_files.cpp @@ -774,7 +774,21 @@ bool DOS_CreateTempFile(char * const name,Bit16u * entry) { return true; } -#define FCB_SEP ":.;,=+" +char DOS_ToUpper(char c) { + unsigned char uc = *reinterpret_cast(&c); + if (uc > 0x60 && uc < 0x7B) uc -= 0x20; + else if (uc > 0x7F && uc < 0xA5) { + const unsigned char t[0x25] = { + 0x00, 0x9a, 0x45, 0x41, 0x8E, 0x41, 0x8F, 0x80, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x4F, 0x99, 0x4F, 0x55, 0x55, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x49, 0x4F, 0x55, 0xA5}; + if (t[uc - 0x80]) uc = t[uc-0x80]; + } + char sc = *reinterpret_cast(&uc); + return sc; +} + +#define FCB_SEP ":;,=+" #define ILLEGAL ":.;,=+ \t/\"[]<>|" static bool isvalid(const char in){ @@ -822,77 +836,87 @@ Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u * fcb.GetName(fcb_name.full); fcb_name.part.drive[0]-='A'-1;fcb_name.part.drive[1]=0; fcb_name.part.name[8]=0;fcb_name.part.ext[3]=0; - /* Strip of the leading sepetaror */ - if((parser & PARSE_SEP_STOP) && *string) { //ignore leading seperator - char sep[] = FCB_SEP;char a[2]; - a[0]= *string;a[1]='\0'; - if (strcspn(a,sep)==0) string++; - } /* strip leading spaces */ while((*string==' ')||(*string=='\t')) string++; + + /* Strip of the leading separator */ + if((parser & PARSE_SEP_STOP) && *string) { + char sep[] = FCB_SEP;char a[2]; + a[0] = *string;a[1] = '\0'; + if (strcspn(a,sep) == 0) string++; + } + + /* Skip following spaces as well */ + while((*string==' ')||(*string=='\t')) string++; + /* Check for a drive */ if (string[1]==':') { + unsigned char d = *reinterpret_cast(&string[0]); + if (!isvalid(toupper(d))) {string += 2; goto savefcb;} //TODO check (for ret value) fcb_name.part.drive[0]=0; hasdrive=true; - if (isalpha(string[0]) && Drives[toupper(string[0])-'A']) { - fcb_name.part.drive[0]=(char)(toupper(string[0])-'A'+1); + if (isalpha(d) && Drives[toupper(d)-'A']) { //Floppies under dos always exist, but don't bother with that at this level + ; //THIS* was here } else ret=0xff; + fcb_name.part.drive[0]=DOS_ToUpper(string[0])-'A'+1; //Always do THIS* and continue parsing, just return the right code string+=2; } - /* Special checks for . and .. */ - if (string[0]=='.') { - string++; - if (!string[0]) { - hasname=true; - ret=PARSE_RET_NOWILD; - strcpy(fcb_name.part.name,". "); - goto savefcb; - } - if (string[1]=='.' && !string[1]) { - string++; - hasname=true; - ret=PARSE_RET_NOWILD; - strcpy(fcb_name.part.name,".. "); - goto savefcb; - } - goto checkext; - } - /* Copy the name */ + + /* Check for extension only file names */ + if (string[0] == '.') {string++;goto checkext;} + + /* do nothing if not a valid name */ + if(!isvalid(string[0])) goto savefcb; + hasname=true;finished=false;fill=' ';index=0; - while (index<8) { - if (!finished) { - if (string[0]=='*') {fill='?';fcb_name.part.name[index]='?';if (!ret) ret=1;finished=true;} - else if (string[0]=='?') {fcb_name.part.name[index]='?';if (!ret) ret=1;} - else if (isvalid(string[0])) {fcb_name.part.name[index]=(char)(toupper(string[0]));} - else { finished=true;continue; } - string++; - } else { - fcb_name.part.name[index]=fill; + /* Copy the name */ + while (true) { + unsigned char nc = *reinterpret_cast(&string[0]); + char ncs = (char)toupper(nc); //Should use DOS_ToUpper, but then more calls need to be changed. + if (ncs == '*') { //Handle * + fill = '?'; + ncs = '?'; } - index++; + if (ncs == '?' && !ret && index < 8) ret = 1; //Don't override bad drive + if (!isvalid(ncs)) { //Fill up the name. + while(index < 8) + fcb_name.part.name[index++] = fill; + break; + } + if (index < 8) { + fcb_name.part.name[index++] = (fill == '?')?fill:ncs; + } + string++; } if (!(string[0]=='.')) goto savefcb; string++; checkext: /* Copy the extension */ hasext=true;finished=false;fill=' ';index=0; - while (index<3) { - if (!finished) { - if (string[0]=='*') {fill='?';fcb_name.part.ext[index]='?';finished=true;} - else if (string[0]=='?') {fcb_name.part.ext[index]='?';if (!ret) ret=1;} - else if (isvalid(string[0])) {fcb_name.part.ext[index]=(char)(toupper(string[0]));} - else { finished=true;continue; } - string++; - } else { - fcb_name.part.ext[index]=fill; + while (true) { + unsigned char nc = *reinterpret_cast(&string[0]); + char ncs = (char)toupper(nc); + if (ncs == '*') { //Handle * + fill = '?'; + ncs = '?'; } - index++; + if (ncs == '?' && !ret && index < 3) ret = 1; + if (!isvalid(ncs)) { //Fill up the name. + while(index < 3) + fcb_name.part.ext[index++] = fill; + break; + } + if (index < 3) { + fcb_name.part.ext[index++] = (fill=='?')?fill:ncs; + } + string++; } savefcb: if (!hasdrive & !(parser & PARSE_DFLT_DRIVE)) fcb_name.part.drive[0] = 0; if (!hasname & !(parser & PARSE_BLNK_FNAME)) strcpy(fcb_name.part.name," "); if (!hasext & !(parser & PARSE_BLNK_FEXT)) strcpy(fcb_name.part.ext," "); fcb.SetName(fcb_name.part.drive[0],fcb_name.part.name,fcb_name.part.ext); + fcb.ClearBlockRecsize(); //Undocumented bonus work. *change=(Bit8u)(string-string_begin); return ret; }