newrpl/firmware/sys/fsystem/fsconvert2shortentry.c
2016-06-14 20:20:05 -04:00

187 lines
3.4 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"
static int stringchr(char *string,char a)
{
while(*string) { if(*string==a) return 1; ++string; }
return 0;
}
// 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,flags;
int nlen,nchars;
unsigned char *ext,*tmp,*orgname=(unsigned char *)name;
ncase=ecase=flags=0;
nlen=(int)stringlen((char *)name)+1;
// FIND EXTENSION
ext=(unsigned char *)__fsfindcharrev(name,NULL,(char *)".");
if(!ext) ext=(unsigned char *)name+nlen-1; // POINT TO END-OF-STRING
// 1ST STAGE, ANALYZE NAME
tmp=(unsigned char *)name;
while((*tmp=='.') || (*tmp==' ')) ++tmp;
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 {
if((*tmp==0xe5) && (tmp==(unsigned char *)name)) *tmp=0x5;
}
++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(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;
}