mirror of
https://github.com/ksherlock/mpw.git
synced 2024-10-03 17:54:29 +00:00
str2dec, dec2x (Pascal)
This commit is contained in:
parent
0dbb111b9b
commit
a436e91373
@ -16,9 +16,17 @@ set(TOOLBOX_SRC
|
||||
os_fileinfo.cpp
|
||||
qd.cpp
|
||||
sane.cpp
|
||||
saneparser.cpp
|
||||
utility.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT saneparser.cpp
|
||||
COMMAND ragel -p -G2 -o saneparser.cpp "${CMAKE_CURRENT_SOURCE_DIR}/saneparser.rl"
|
||||
MAIN_DEPENDENCY saneparser.rl
|
||||
)
|
||||
|
||||
|
||||
add_library(TOOLBOX_LIB ${TOOLBOX_SRC})
|
121
toolbox/sane.cpp
121
toolbox/sane.cpp
@ -1,5 +1,6 @@
|
||||
#include "qd.h"
|
||||
#include "toolbox.h"
|
||||
#include "sane.h"
|
||||
|
||||
#include <cpu/defs.h>
|
||||
#include <cpu/CpuModule.h>
|
||||
@ -7,6 +8,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
#include "stackframe.h"
|
||||
|
||||
@ -436,6 +438,61 @@ namespace SANE
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class DestType>
|
||||
uint16_t fdecimal(const char *name)
|
||||
{
|
||||
uint16_t op;
|
||||
uint32_t decimalPtr;
|
||||
uint32_t dest;
|
||||
|
||||
|
||||
StackFrame<10>(decimalPtr, dest, op);
|
||||
|
||||
uint16_t sgn = memoryReadByte(decimalPtr);
|
||||
uint16_t exp = memoryReadWord(decimalPtr + 2);
|
||||
std::string sig;
|
||||
sig = ToolBox::ReadPString(decimalPtr + 4, false);
|
||||
|
||||
Log(" %s({%c %s e%d}, %08x)\n",
|
||||
name,
|
||||
sgn ? '-' : ' ', sig.c_str(), exp,
|
||||
dest
|
||||
);
|
||||
|
||||
extended tmp = 0;
|
||||
if (sig.length())
|
||||
{
|
||||
if (sig[0] == 'I')
|
||||
{
|
||||
tmp = INFINITY;
|
||||
}
|
||||
else if (sig[0] == 'N')
|
||||
{
|
||||
tmp = NAN; // todo -- nan type
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = stold(sig);
|
||||
|
||||
while (exp > 0)
|
||||
{
|
||||
tmp = tmp * 10.0;
|
||||
exp--;
|
||||
}
|
||||
while (exp < 0)
|
||||
{
|
||||
tmp = tmp / 10.0;
|
||||
exp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sgn) tmp = -tmp;
|
||||
|
||||
writenum<DestType>((DestType)tmp, dest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void cpuSetFlagsAbs(UWO f);
|
||||
uint16_t fp68k(uint16_t trap)
|
||||
@ -540,6 +597,12 @@ namespace SANE
|
||||
break;
|
||||
|
||||
|
||||
case 0x0009:
|
||||
// fdec2x
|
||||
return fdecimal<extended>("FDEC2X");
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -625,10 +688,64 @@ namespace SANE
|
||||
|
||||
uint32_t fpstr2dec()
|
||||
{
|
||||
// void str2dec(const char *s,short *ix,decimal *d,short *vp);
|
||||
|
||||
#if 0
|
||||
#define SIGDIGLEN 20 /* significant decimal digits */
|
||||
#define DECSTROUTLEN 80 /* max length for dec2str output */
|
||||
|
||||
printf(stderr, "fpstr2dec is not yet supported.\n");
|
||||
exit(1);
|
||||
struct decimal {
|
||||
char sgn; /*sign 0 for +, 1 for -*/
|
||||
char unused;
|
||||
short exp; /*decimal exponent*/
|
||||
struct{
|
||||
unsigned char length;
|
||||
unsigned char text[SIGDIGLEN]; /*significant digits */
|
||||
unsigned char unused;
|
||||
}sig;
|
||||
};
|
||||
#endif
|
||||
|
||||
uint32_t stringPtr;
|
||||
uint32_t indexPtr;
|
||||
uint32_t decimalPtr;
|
||||
uint32_t validPtr;
|
||||
|
||||
uint16_t valid;
|
||||
uint16_t index;
|
||||
decimal d;
|
||||
|
||||
StackFrame<16>(stringPtr, indexPtr, decimalPtr, validPtr);
|
||||
|
||||
index = memoryReadWord(indexPtr);
|
||||
|
||||
std::string str = ToolBox::ReadPString(stringPtr, false);
|
||||
Log(" FPSTR2DEC(%s, %04x, %08x, %08x)\n",
|
||||
str.c_str(), index, decimalPtr, validPtr);
|
||||
|
||||
index--;
|
||||
str2dec(str, index, d, valid);
|
||||
index++;
|
||||
|
||||
memoryWriteWord(index, indexPtr);
|
||||
memoryWriteWord(valid, validPtr);
|
||||
|
||||
if (d.sig.length() > 20)
|
||||
{
|
||||
// truncate and adjust the exponent
|
||||
// 1234e0 -> 123e1 -> 12e2 -> 1e3
|
||||
// 1234e-1 -> 123e-0 -> 12e1
|
||||
int over = d.sig.length() - 20;
|
||||
d.sig.resize(20);
|
||||
d.exp += over;
|
||||
}
|
||||
|
||||
memoryWriteByte(d.sgn, decimalPtr);
|
||||
memoryWriteByte(0, decimalPtr + 1);
|
||||
memoryWriteWord(d.exp, decimalPtr + 2);
|
||||
ToolBox::WritePString(decimalPtr + 4, d.sig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t decstr68k(uint16_t trap)
|
||||
|
@ -2,9 +2,19 @@
|
||||
#define __mpw_sane_h__
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace SANE
|
||||
{
|
||||
struct decimal {
|
||||
decimal() : sgn(0), exp(0) {}
|
||||
int sgn;
|
||||
int exp;
|
||||
std::string sig;
|
||||
};
|
||||
|
||||
void str2dec(const std::string &s, uint16_t &index, decimal &d, uint16_t &vp);
|
||||
|
||||
uint32_t decstr68k(uint16_t trap);
|
||||
uint16_t fp68k(uint16_t trap);
|
||||
}
|
||||
|
268
toolbox/saneparser.rl
Normal file
268
toolbox/saneparser.rl
Normal file
@ -0,0 +1,268 @@
|
||||
|
||||
#include "sane.h"
|
||||
#include <string>
|
||||
|
||||
namespace SANE {
|
||||
|
||||
/*
|
||||
* %{} is a final transition. fpc points to the next character
|
||||
* %!{} is a final transition to an error state. fpc " " " "
|
||||
*
|
||||
*/
|
||||
%%{
|
||||
|
||||
machine fpstr;
|
||||
|
||||
|
||||
action check { checkpoint = fpc; }
|
||||
|
||||
nantype =
|
||||
'('
|
||||
digit* ${ nantype = nantype * 10 + fc - '0'; }
|
||||
')'
|
||||
$!{ nantype = 0; }
|
||||
%check
|
||||
;
|
||||
|
||||
nan = 'NAN'i
|
||||
>{ nan = true; }
|
||||
%check
|
||||
%!check
|
||||
nantype?
|
||||
;
|
||||
|
||||
infinity = 'INF'i
|
||||
>{ nan = true; }
|
||||
%{ nan = false; infinity = true; checkpoint = fpc; }
|
||||
%!{ nan = false; infinity = true; checkpoint = fpc; };
|
||||
|
||||
exponent =
|
||||
[eE]
|
||||
[+\-]? ${ if (fc == '-') negative_exp = true; }
|
||||
digit+ ${ exp = exp * 10 + fc - '0'; }
|
||||
%check
|
||||
%!check
|
||||
;
|
||||
|
||||
significand =
|
||||
(
|
||||
(
|
||||
digit+ ${
|
||||
// don't push leading 0s
|
||||
if (fc != '0' || siga.size())
|
||||
siga.push_back(fc);
|
||||
}
|
||||
( '.' digit* ${ sigb.push_back(fc); })?
|
||||
)
|
||||
|
|
||||
(
|
||||
'.'
|
||||
digit+ ${ sigb.push_back(fc); }
|
||||
)
|
||||
)
|
||||
%check
|
||||
%!check
|
||||
;
|
||||
|
||||
finite_number = significand exponent?;
|
||||
|
||||
unsigned_decimal = finite_number | infinity | nan;
|
||||
|
||||
left_decimal =
|
||||
[+\-]? ${ if (fc == '-') negative = true; }
|
||||
unsigned_decimal
|
||||
;
|
||||
|
||||
decimal_number = [ \t]* left_decimal;
|
||||
|
||||
main := decimal_number;
|
||||
|
||||
}%%
|
||||
|
||||
|
||||
std::string normalize(std::string &a, std::string &b, int &exponent)
|
||||
{
|
||||
int pos;
|
||||
|
||||
// 1 = 1e0 10 = 1e1
|
||||
// 12 = 12e0
|
||||
// 123 = 123e0
|
||||
|
||||
// 1.1 = 11e-1
|
||||
// 0.1 = 1e-1
|
||||
|
||||
// remove trailing 0s
|
||||
while (b.size() && b.back() == '0')
|
||||
b.pop_back();
|
||||
|
||||
int bits = 0;
|
||||
if (a.length()) bits |= 0x01;
|
||||
if (b.length()) bits |= 0x02;
|
||||
|
||||
std::string out;
|
||||
switch(bits)
|
||||
{
|
||||
case 0x00:
|
||||
// should never happen...
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
// a only.
|
||||
// remove trailing 0s and add 1 exp for each.
|
||||
while (a.length() && a.back() == '0')
|
||||
{
|
||||
a.pop_back();
|
||||
exponent++;
|
||||
}
|
||||
out = a;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
// b only.
|
||||
//.001 = e1-3
|
||||
exponent -= b.length();
|
||||
pos = b.find_first_not_of('0');
|
||||
out = b.substr(pos);
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
// a and b
|
||||
// 10.01 = 1001e-2
|
||||
exponent -= b.length();
|
||||
out = a;
|
||||
out += b;
|
||||
break;
|
||||
|
||||
}
|
||||
if (out.empty()) out = "0";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void str2dec(const std::string &s, uint16_t &index, decimal &d, uint16_t &vp)
|
||||
{
|
||||
%%write data;
|
||||
|
||||
bool infinity = false;
|
||||
bool nan = false;
|
||||
int nantype = 0;
|
||||
bool negative = false;
|
||||
bool negative_exp = false;
|
||||
int exp = 0;
|
||||
std::string siga, sigb;
|
||||
|
||||
if (index >= s.size()) return;
|
||||
|
||||
/*
|
||||
char *p = s.c_str();
|
||||
char *pe = p + s.size();
|
||||
char *eof = pe;
|
||||
char *checkpoint = p;
|
||||
*/
|
||||
auto p = s.begin();
|
||||
auto checkpoint = s.begin();
|
||||
|
||||
auto pe = s.end();
|
||||
auto eof = s.end();
|
||||
|
||||
int cs;
|
||||
|
||||
p += index;
|
||||
|
||||
%%write init;
|
||||
|
||||
%%write exec;
|
||||
|
||||
d.sgn = negative ? 1 : 0;
|
||||
|
||||
if (infinity)
|
||||
{
|
||||
d.sig = "I";
|
||||
}
|
||||
else if (nan)
|
||||
{
|
||||
d.sig = "N";
|
||||
if (nantype)
|
||||
{
|
||||
const char *hexstr = "0123456789abcdef";
|
||||
// 4-byte hex
|
||||
d.sig.push_back(hexstr[(nantype >> 24) & 0xff]);
|
||||
d.sig.push_back(hexstr[(nantype >> 16) & 0xff]);
|
||||
d.sig.push_back(hexstr[(nantype >> 8) & 0xff]);
|
||||
d.sig.push_back(hexstr[(nantype >> 0) & 0xff]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
d.sig = normalize(siga, sigb, exp);
|
||||
d.exp = negative_exp ? -exp : exp;
|
||||
}
|
||||
|
||||
vp = cs != fpstr_error;
|
||||
index = checkpoint - s.begin();
|
||||
|
||||
return;
|
||||
#if 0
|
||||
|
||||
|
||||
printf("%s\n", str);
|
||||
|
||||
bool valid = cs != fpstr_error;
|
||||
int index = checkpoint - str;
|
||||
|
||||
printf("infinity: %d\n", infinity);
|
||||
printf(" nan: %d\n", nan);
|
||||
printf(" nantype: %d\n", nantype);
|
||||
|
||||
if (negative_exp) exp = -exp;
|
||||
|
||||
printf(" exp: %d\n", exp);
|
||||
printf("negative: %d\n", negative);
|
||||
printf(" sig: %s.%s\n", siga.c_str(), sigb.c_str());
|
||||
printf(" valid: %d\n", valid);
|
||||
printf(" index: %d\n", index);
|
||||
printf("\n");
|
||||
|
||||
|
||||
/*
|
||||
* now we need to normalize the significand / exponent
|
||||
* 1.2 e0 -> 12 e-1
|
||||
* 1000 e0 -> 1 e 3
|
||||
*/
|
||||
|
||||
std::string sig = normalize(siga, sigb, exp);
|
||||
|
||||
printf("normalized: %s e %d\n", sig.c_str(), exp);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifdef MAIN
|
||||
#include <cstdio>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string s = argv[i];
|
||||
SANE::decimal d;
|
||||
short index = 0;
|
||||
short valid = 0;
|
||||
|
||||
SANE::str2dec(s, index, d, valid);
|
||||
|
||||
printf("index: %d\n", index);
|
||||
printf("valid: %d\n", valid);
|
||||
printf(" sign: %d\n", d.sgn);
|
||||
printf(" exp: %d\n", d.exp);
|
||||
printf(" sig: %s\n", d.sig.c_str());
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user