1
0

Fix FORMAT$

This commit is contained in:
otya128
2016-12-08 20:01:40 +09:00
parent 3de90d2f41
commit 0ce9b370ad
2 changed files with 129 additions and 36 deletions

View File

@@ -1364,6 +1364,19 @@ class BuiltinFunction
{ {
return cast(int)(p.console.console[y][x].character); return cast(int)(p.console.console[y][x].character);
} }
struct FixedBuffer(T, size_t S)
{
T[S] buffer = void;
size_t length;
void put(T v)
{
if (buffer.length <= length)
{
throw new StringTooLong("FORMAT$", 2);
}
buffer[length++] = v;
}
}
static wstring FORMAT(PetitComputer p, Value[] va_args) static wstring FORMAT(PetitComputer p, Value[] va_args)
{ {
alias retro!(Value[]) VaArgs; alias retro!(Value[]) VaArgs;
@@ -1371,58 +1384,120 @@ class BuiltinFunction
auto format = args[0].castString; auto format = args[0].castString;
import std.array : appender; import std.array : appender;
import std.format; import std.format;
auto w = appender!wstring(); FixedBuffer!(wchar, 1024) buffer;//String too long
int j = 1; int j = 1;
for(int i = 0; i < format.length; i++) for(int i = 0; i < format.length; i++)
{ {
auto f = format[i]; auto f = format[i];
if(f == '%') if(f == '%')
{ {
int d = cast(int)indexOf(format, 'D', CaseSensitive.yes); i = i + 1;
if(d != -1) bool sign = false;//+
bool left = false;//-
bool space = false;//' '
bool zero = false;
for(; i < format.length; i++)
{ {
auto spec = singleSpec(format[i .. d + 1]); auto c = format[i];
spec.spec = 'd'; if (c == '+')
formatValue(w, args[j].castInteger, spec); {
j++; sign = true;
i = d; }
continue; else if (c == ' ')
{
space = true;
}
else if (c == '-')
{
left = true;
}
else if (c == '0')
{
zero = true;
}
else
{
break;
}
} }
d = cast(int)indexOf(format, 'X', CaseSensitive.yes); int d1, d2 = 6;
if(d != -1) wstring a1 = format[i..$];
if (a1[0] >= '0' && a1[0] <= '9')
{ {
auto spec = singleSpec(format[i .. d + 1]); d1 = parse!(int, wstring)(a1);
spec.spec = cast(char)format[d];
formatValue(w, args[j].castInteger, spec);
j++;
i = d;
continue;
} }
d = cast(int)indexOf(format, 'S', CaseSensitive.yes); if (a1[0] == '.')
if(d != -1)
{ {
auto spec = singleSpec(format[i .. d + 1]); a1 = a1[1..$];
spec.spec = 's'; if (a1[0] >= '0' && a1[0] <= '9')
formatValue(w, args[j].castString, spec); {
j++; d2 = parse!(int, wstring)(a1);
i = d; }
continue;
} }
d = cast(int)indexOf(format, 'F', CaseSensitive.yes); wstring buf;
if(d != -1) FormatSpec!wchar spec;
switch (a1[0])
{ {
auto spec = singleSpec(format[i .. d + 1]); case 'S', 's':
spec.spec = 'f'; {
formatValue(w, args[j].castDouble, spec); auto val = args[j].castString;
j++; spec.width = d1;
i = d; spec.flDash = left;
continue; spec.flZero = zero;
spec.flPlus = sign;
spec.flSpace = space;
formatValue(&buffer, val, spec);
break;
}
case 'X', 'x':
spec.spec = 'X';
goto caseInteger;
case 'B', 'b':
spec.spec = 'b';
goto caseInteger;
case 'D', 'd':
spec.spec = 'd';
caseInteger:
{
auto val = args[j].castInteger;
spec.width = d1;
spec.precision = d2;
spec.flDash = left;
spec.flZero = zero;
spec.flPlus = sign;
spec.flSpace = space;
formatValue(&buffer, val, spec);
break;
}
case 'F', 'f':
{
spec.spec = 'f';
auto val = args[j].castDouble;
spec.width = d1;
if (d2 < 1022)
{
spec.precision = d2;
spec.flDash = left;
spec.flZero = zero;
spec.flPlus = sign;
spec.flSpace = space;
formatValue(&buffer, val, spec);
}
break;
}
default:
throw new IllegalFunctionCall("FORMAT$");
} }
j++;
i = 0;
format = a1;
continue;
} }
w ~= f; buffer.put(f);
} }
//プチコン互換FOMA wchar[] data = new wchar[buffer.length];
return cast(immutable)w.data(); data[] = buffer.buffer[0..buffer.length];
return cast(immutable)data;
} }
static wstring CHR(int code) static wstring CHR(int code)
{ {

View File

@@ -155,6 +155,24 @@ class SubscriptOutOfRange : SmileBasicError
super("Subscript out of range"); super("Subscript out of range");
} }
} }
class StringTooLong : SmileBasicError
{
this()
{
this.errnum = 41;
super("String too long");
}
this(string func)
{
this.errnum = 41;
super("String too long(" ~ func ~ ")");
}
this(string func, int arg)
{
this.errnum = 41;
super("String too long(" ~ func ~ ":" ~ arg.to!string ~ ")");
}
}
class CantUseFromDirectMode : SmileBasicError class CantUseFromDirectMode : SmileBasicError
{ {
this() this()