mirror of
https://git.code.sf.net/p/newrpl/sources
synced 2024-11-16 19:51:25 +01:00
260 lines
6.9 KiB
C
260 lines
6.9 KiB
C
/*
|
|
* Copyright (c) 2014-2015, Claudio Lapilli and the newRPL Team
|
|
* All rights reserved.
|
|
* This file is released under the 3-clause BSD license.
|
|
* See the file LICENSE.txt that shipped with this distribution.
|
|
*/
|
|
|
|
#include "fsyspriv.h"
|
|
|
|
#ifndef CONFIG_NO_FSYSTEM
|
|
|
|
static int stringchr(char *string, char a)
|
|
{
|
|
while(*string) {
|
|
if(*string == a)
|
|
return 1;
|
|
++string;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
extern const int cp850toUnicode[128];
|
|
|
|
// CONVERT A LONG NAME INTO SHORT NAME
|
|
// BIT 0=1 --> tname INCLUDES TRAILING ~1
|
|
// ERROR= BIT 1=1 --> tname IS A LONG ENTRY
|
|
// BITS 3&4 = NT CASE FLAGS IF NAME IS NOT LONG ENTRY
|
|
|
|
int FSConvert2ShortEntry(char *name, int minnum)
|
|
{
|
|
int ncase, ecase, noext, flags;
|
|
int nlen, nchars;
|
|
unsigned char *ext, *tmp, *orgname = (unsigned char *)name, *ptr;
|
|
|
|
ncase = ecase = flags = 0;
|
|
|
|
// 1ST STAGE, ANALYZE NAME
|
|
tmp = (unsigned char *)name;
|
|
|
|
while((*tmp == '.') || (*tmp == ' '))
|
|
++tmp;
|
|
|
|
if(*tmp == 0)
|
|
return 0; // INVALID NAME IS EITHER ALL DOTS OR ALL SPACES
|
|
|
|
ptr = tmp;
|
|
// STRIP ALL ENDING SEMICOLONS, THEY DON'T ALTER THE SHORT NAME
|
|
while(*ptr != 0)
|
|
++ptr;
|
|
while(ptr > tmp) {
|
|
if(ptr[-1] == ';')
|
|
--ptr;
|
|
else
|
|
break;
|
|
}
|
|
*ptr = 0;
|
|
nlen = ptr - tmp + 1;
|
|
|
|
// FIND EXTENSION
|
|
ext = (unsigned char *)__fsfindcharrev((char *)tmp, NULL, (char *)".");
|
|
|
|
if(!ext) {
|
|
noext = 1; // POINT TO END-OF-STRING
|
|
ext = (unsigned char *)name + nlen - 1;
|
|
}
|
|
else
|
|
noext = 0;
|
|
|
|
if(tmp != (unsigned char *)name) {
|
|
// STRIP LEADING DOTS OR SPACES
|
|
flags |= 3; // MARK NAME WAS CONVERTED
|
|
memmoveb(name, tmp, nlen - (int)(tmp - (unsigned char *)name));
|
|
ext -= (int)(tmp - (unsigned char *)name);
|
|
nlen -= (int)(tmp - (unsigned char *)name);
|
|
tmp = (unsigned char *)name;
|
|
}
|
|
|
|
nchars = 8;
|
|
do {
|
|
|
|
do {
|
|
if(*tmp <= 127) // >127 IS PERMITTED
|
|
{
|
|
if(*tmp < 'A' || *tmp > 'Z') // UPPERCASE LETTERS ARE PERMITTED
|
|
{
|
|
if(!stringchr("0123456789$%'-_@~`!(){}^#&", *tmp)) // NUMBERS AND SYMBOLS PERMITTED
|
|
{
|
|
// IT HAS TO BE AN ILLEGAL CHARACTER
|
|
if(*tmp == ' ' || *tmp == '.') {
|
|
// REMOVE SPACES AND PERIODS
|
|
flags |= 3;
|
|
memmoveb(tmp, tmp + 1,
|
|
nlen - (int)(tmp - (unsigned char *)name));
|
|
ext--;
|
|
nlen--;
|
|
continue;
|
|
}
|
|
if(*tmp >= 'a' && *tmp <= 'z') {
|
|
// LOWERCASE LETTERS NEED CONVERSION
|
|
*tmp -= 32;
|
|
if(ecase != 1)
|
|
ecase = 2; // MARK NAME IS LOWERCASE
|
|
else
|
|
flags |= 2;
|
|
}
|
|
else {
|
|
// ANY OTHER CHARACTER IS INVALID
|
|
*tmp = '_';
|
|
flags |= 3;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if(ecase != 2)
|
|
ecase = 1; // MARK NAME IS UPPERCASE
|
|
else
|
|
flags |= 2;
|
|
}
|
|
}
|
|
else {
|
|
// DECODE A UTF-8 CHARACTER AND CONVERT TO CP850
|
|
int cp = utf82cp((char *)tmp, (char *)tmp + 4);
|
|
unsigned char *skiptmp =
|
|
(unsigned char *)utf8skip((char *)tmp, (char *)tmp + 4);
|
|
|
|
// MAKE SURE WE INCLUDE A LONG NAME, THE SHORT ONE MIGHT NOT MATCH DUE TO CP CONVERSION
|
|
flags |= 2;
|
|
|
|
int k;
|
|
for(k = 0; k < 128; ++k) {
|
|
if(cp850toUnicode[k] == cp) {
|
|
cp = 128 + k;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(cp > 0xff)
|
|
*tmp = '_'; // REPLACE ANY UNICODE CHARACTER OUTSIDE RANGE
|
|
else if((cp == 0xe5) && (tmp == (unsigned char *)name))
|
|
*tmp = 0x5;
|
|
else
|
|
*tmp = cp;
|
|
|
|
memmoveb(tmp + 1, skiptmp,
|
|
nlen - (int)(skiptmp - (unsigned char *)name));
|
|
ext -= skiptmp - (tmp + 1);
|
|
nlen -= skiptmp - (tmp + 1);
|
|
}
|
|
++tmp;
|
|
}
|
|
while((tmp != ext) && (tmp < (unsigned char *)name + nchars));
|
|
|
|
// NAME WAS PROCESSED
|
|
if(tmp != ext) {
|
|
// NAME IS LONGER THAN EXPECTED
|
|
flags |= 3;
|
|
|
|
// COPY EXTENSION AFTER NAME
|
|
memmoveb(tmp, ext, nlen - (int)(ext - (unsigned char *)name));
|
|
nlen -= (int)(ext - tmp);
|
|
ext -= (int)(ext - tmp);
|
|
}
|
|
if(*tmp == '.') {
|
|
ext = (unsigned char *)name + nlen - 1;
|
|
tmp++;
|
|
name = (char *)tmp; // SKIP DOT
|
|
// PREPARE TO PROCESS EXTENSION
|
|
nchars = 3;
|
|
ncase = ecase;
|
|
ecase = 0;
|
|
continue;
|
|
}
|
|
|
|
}
|
|
while(tmp < ext);
|
|
|
|
if(noext) {
|
|
ncase = ecase;
|
|
ecase = 0;
|
|
}
|
|
|
|
if(flags & 1 || minnum > 0) {
|
|
// ADD TAIL IF REQUIRED
|
|
// FIND EXTENSION
|
|
ext = (unsigned char *)__fsfindcharrev((char *)orgname, NULL,
|
|
(char *)".");
|
|
if(!ext)
|
|
ext = orgname + nlen - 1;
|
|
|
|
if(minnum <= 0)
|
|
minnum = 1;
|
|
|
|
int digits = 1;
|
|
if(minnum > 9999)
|
|
digits = 5;
|
|
else {
|
|
if(minnum > 999)
|
|
digits = 4;
|
|
else {
|
|
if(minnum > 99)
|
|
digits = 3;
|
|
else {
|
|
if(minnum > 9)
|
|
digits = 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
// EXPAND STRING
|
|
if(ext < orgname + 7 - digits)
|
|
tmp = ext;
|
|
else
|
|
tmp = orgname + 7 - digits;
|
|
memmoveb(tmp + digits + 1, ext, nlen - (int)(ext - orgname));
|
|
|
|
*tmp++ = '~';
|
|
|
|
memsetb(tmp, 48, digits);
|
|
|
|
while(minnum > 9999) {
|
|
*tmp += 1;
|
|
minnum -= 10000;
|
|
}
|
|
if(digits > 4)
|
|
++tmp;
|
|
|
|
while(minnum > 999) {
|
|
*tmp += 1;
|
|
minnum -= 1000;
|
|
}
|
|
if(digits > 3)
|
|
++tmp;
|
|
|
|
while(minnum > 99) {
|
|
*tmp += 1;
|
|
minnum -= 100;
|
|
}
|
|
if(digits > 2)
|
|
++tmp;
|
|
|
|
while(minnum > 9) {
|
|
*tmp += 1;
|
|
minnum -= 10;
|
|
}
|
|
if(digits > 1)
|
|
++tmp;
|
|
|
|
*tmp = minnum + '0';
|
|
flags |= 1;
|
|
|
|
}
|
|
|
|
if(flags)
|
|
return flags;
|
|
flags = (ncase & 2) << 2;
|
|
flags |= (ecase & 2) << 3;
|
|
return flags;
|
|
}
|
|
|
|
#endif
|