mirror of
https://github.com/louisrubet/rpn
synced 2025-01-01 18:20:06 +01:00
Merge branch 'c_strings'
Conflicts: src/rpn.cpp
This commit is contained in:
commit
14ea7d2b74
16 changed files with 779 additions and 320 deletions
259
README
259
README
|
@ -24,39 +24,202 @@ Language extensions will soon be included:
|
|||
========================================================================
|
||||
Here is a list of HP28s reserved words.
|
||||
|
||||
New commands (nonexistent in RPL) are tagged with (+).
|
||||
Already implemented commands are tagged with (*).
|
||||
New commands (nonexistent in RPL) are tagged with * in column new.
|
||||
Already implemented commands are tagged with * in column impl.
|
||||
Tested commands are tagged with * in column tested.
|
||||
|
||||
GENERAL OPERATIONS
|
||||
+(*), -(*), neg(*), *(*), /(*), inv(*)(+), %(*), %CH(*), ^(*),
|
||||
sqrt(*)(+), sq(*)(+), test(*)(+)
|
||||
category command new impl. tested
|
||||
|
||||
GENERAL (some are 'CURSOR' commands)
|
||||
verbose(*)(+), std(*), fix(*), sci(*), version(*)(+), uname(*)(+)
|
||||
GENERAL + *
|
||||
GENERAL - *
|
||||
GENERAL neg *
|
||||
GENERAL * *
|
||||
GENERAL / *
|
||||
GENERAL inv *
|
||||
GENERAL % *
|
||||
GENERAL %CH *
|
||||
GENERAL ^ *
|
||||
GENERAL sqrt * *
|
||||
GENERAL sq * *
|
||||
GENERAL test * *
|
||||
GENERAL verbose * *
|
||||
GENERAL std *
|
||||
GENERAL fix *
|
||||
GENERAL sci *
|
||||
GENERAL version * *
|
||||
GENERAL uname * *
|
||||
|
||||
STACK
|
||||
drop(*), swap(*), roll, dup(*), over, dup2(*), drop2(*), rot(*),
|
||||
list->, rolld, pick(*), dupn, dropn, depth(*), ->list, load_stack(+),
|
||||
save_stack(+)
|
||||
STACK drop *
|
||||
STACK swap *
|
||||
STACK roll
|
||||
STACK dup *
|
||||
STACK over
|
||||
STACK dup2 *
|
||||
STACK drop2 *
|
||||
STACK rot *
|
||||
STACK list->
|
||||
STACK rolld
|
||||
STACK pick *
|
||||
STACK dupn
|
||||
STACK dropn
|
||||
STACK depth *
|
||||
STACK ->list
|
||||
STACK load_stack * *
|
||||
STACK save_stack * *
|
||||
|
||||
STORE
|
||||
sto(*), rcl(*), purge(*), sto+, sto-, sto*, sto/, sneg, sinv, sconj,
|
||||
erase(*)(+), vars(*)(+), include(+), load_vars(+), save_vars(+)
|
||||
STORE sto *
|
||||
STORE rcl *
|
||||
STORE purge *
|
||||
STORE sto+
|
||||
STORE sto-
|
||||
STORE sto*
|
||||
STORE sto/
|
||||
STORE sneg
|
||||
STORE sinv
|
||||
STORE sconj
|
||||
STORE erase * *
|
||||
STORE vars * *
|
||||
STORE include *
|
||||
STORE load_vars *
|
||||
STORE save_vars *
|
||||
|
||||
PROGRAM(+)
|
||||
eval(*), load_prog(+), save_prog(+)
|
||||
PROGRAM eval *
|
||||
PROGRAM load_prog *
|
||||
PROGRAM save_prog *
|
||||
|
||||
ALGEBRA neg * *
|
||||
ALGEBRA colct
|
||||
ALGEBRA expan
|
||||
ALGEBRA size
|
||||
ALGEBRA form
|
||||
ALGEBRA obsub
|
||||
ALGEBRA exsub
|
||||
ALGEBRA taylr
|
||||
ALGEBRA isol
|
||||
ALGEBRA quad,
|
||||
ALGEBRA show
|
||||
ALGEBRA obget
|
||||
ALGEBRA exget
|
||||
|
||||
BINARY + *
|
||||
BINARY - *
|
||||
BINARY * *
|
||||
BINARY / *
|
||||
BINARY dec *
|
||||
BINARY hex *
|
||||
BINARY oct *
|
||||
BINARY bin *
|
||||
BINARY stws
|
||||
BINARY rcws
|
||||
BINARY rl
|
||||
BINARY rr
|
||||
BINARY rlb
|
||||
BINARY rrb
|
||||
BINARY r->b *
|
||||
BINARY b->r *
|
||||
BINARY sl
|
||||
BINARY sr
|
||||
BINARY slb
|
||||
BINARY srb
|
||||
BINARY asr
|
||||
BINARY and
|
||||
BINARY or
|
||||
BINARY xor
|
||||
BINARY not
|
||||
|
||||
STRING + *
|
||||
STRING ->str *
|
||||
STRING str-> *
|
||||
STRING chr
|
||||
STRING num
|
||||
STRING ->lcd
|
||||
STRING lcd->
|
||||
STRING pos
|
||||
STRING sub
|
||||
STRING size
|
||||
STRING disp
|
||||
|
||||
BRANCH
|
||||
BRANCH if *
|
||||
BRANCH then *
|
||||
BRANCH else *
|
||||
BRANCH end *
|
||||
BRANCH start *
|
||||
BRANCH for *
|
||||
BRANCH next *
|
||||
BRANCH step *
|
||||
BRANCH ift
|
||||
BRANCH ifte
|
||||
BRANCH do
|
||||
BRANCH until
|
||||
BRANCH end
|
||||
BRANCH while
|
||||
BRANCH repeat
|
||||
BRANCH end
|
||||
|
||||
TEST
|
||||
TEST != *
|
||||
TEST > *
|
||||
TEST >= *
|
||||
TEST < *
|
||||
TEST <= *
|
||||
TEST sf
|
||||
TEST cf
|
||||
TEST fs?
|
||||
TEST fc?
|
||||
TEST fs?c
|
||||
TEST fc?c
|
||||
TEST and *
|
||||
TEST or *
|
||||
TEST xor *
|
||||
TEST not *
|
||||
TEST same *
|
||||
TEST == *
|
||||
TEST stof
|
||||
TEST rclf
|
||||
TEST type
|
||||
|
||||
TRIG
|
||||
TRIG pi * *
|
||||
TRIG sin *
|
||||
TRIG asin *
|
||||
TRIG cos *
|
||||
TRIG acos *
|
||||
TRIG tan *
|
||||
TRIG atan *
|
||||
TRIG p→r
|
||||
TRIG r→p
|
||||
TRIG r→c
|
||||
TRIG c→r
|
||||
TRIG arg
|
||||
TRIG →hms
|
||||
TRIG hms→
|
||||
TRIG hms+
|
||||
TRIG hms-
|
||||
TRIG d→r *
|
||||
TRIG r→d *
|
||||
|
||||
LOGS
|
||||
LOGS log *
|
||||
LOGS alog *
|
||||
LOGS ln *
|
||||
LOGS exp *
|
||||
LOGS lnp1
|
||||
LOGS expm
|
||||
LOGS sinh *
|
||||
LOGS asinh *
|
||||
LOGS cosh *
|
||||
LOGS acosh *
|
||||
LOGS tanh *
|
||||
LOGS atanh *
|
||||
|
||||
|
||||
Not yet
|
||||
=======
|
||||
|
||||
MEMORY
|
||||
mem, menu, order, path, home, crdir, vars, clusr
|
||||
|
||||
ALGEBRA
|
||||
neg(*)(+), colct, expan, size, form, obsub, exsub, taylr, isol, quad,
|
||||
show, obget, exget
|
||||
|
||||
BINARY
|
||||
+(*), -(*), *(*), /(*), dec(*), hex(*), oct(*), bin(*), stws, rcws,
|
||||
rl, rr, rlb, rrb, r->b(*), b->r(*), sl, sr, slb, srb, asr, and, or,
|
||||
xor, not
|
||||
mem, menu, order, path, home, crdir, vars, clusr,
|
||||
|
||||
STAT
|
||||
∑dat, ∑par, ∑+, ∑-, n∑, cl∑, sto∑, rcl∑, tot, mean, sdev, var, max∑,
|
||||
|
@ -65,39 +228,6 @@ STAT
|
|||
PRINT
|
||||
pr1, prst, prvar, prlcd, cr, trac, prstc, prusr, prmd
|
||||
|
||||
STRING
|
||||
+(*), ->str, str->, chr, num, ->lcd, lcd->, pos, sub, size, disp
|
||||
|
||||
CONTRL
|
||||
sst, halt, abort, kill, wait, key, bepp, cllcd, disp, clmf, errn,
|
||||
errm
|
||||
|
||||
BRANCH
|
||||
if(*), iferr, then(*), else(*), end(*), start(*), for(*), next(*),
|
||||
step(*), ift, ifte, do, until, end, while, repeat, end
|
||||
|
||||
TEST
|
||||
!=(*), >(*), >=(*), <(*), <=(*), sf, cf, fs?, fc?, fs?c, fc?c, and(*),
|
||||
or(*), xor(*), not(*), same(*), ==(*), stof, rclf, type
|
||||
|
||||
CATALOG
|
||||
next, prev, scan, use, fetch, quit
|
||||
|
||||
UNITS
|
||||
convert
|
||||
|
||||
CURSOR (some of these functions can be found in GENERAL)
|
||||
ins, del, ← → ↑ ↓, std, fix, sci, eng, deg, rad, cmd, undo, last, ml,
|
||||
rdx, prmd
|
||||
|
||||
TRIG
|
||||
pi(*)(+), sin(*), asin(*), cos(*), acos(*), tan(*), atan(*), p→r, r→p,
|
||||
r→c, c→r, arg, →hms, hms→, hms+, hms-, (*)d→r, (*)r→d
|
||||
|
||||
LOGS
|
||||
log(*), alog(*), ln(*), exp(*), lnp1, expm, sinh(*), asinh(*), cosh(*),
|
||||
acosh(*), tanh(*), atanh(*)
|
||||
|
||||
SOLV
|
||||
steq, rceq, isol, quad, show, root,
|
||||
|
||||
|
@ -105,6 +235,19 @@ PLOT
|
|||
ppar, steq, rceq, pmin, pmax, indep, draw, res, axes, centr, *w, *h,
|
||||
sto∑, rcl∑, col∑, scl∑, drw∑, cllcd, digtiz
|
||||
|
||||
CURSOR
|
||||
ins, del, ← → ↑ ↓, cmd, undo, last, ml, rdx, prmd
|
||||
|
||||
CONTRL
|
||||
sst, halt, abort, kill, wait, key, bepp, cllcd, disp, clmf, errn,
|
||||
errm
|
||||
|
||||
CATALOG
|
||||
next, prev, scan, use, fetch, quit
|
||||
|
||||
UNITS
|
||||
convert
|
||||
|
||||
CUSTOM
|
||||
menu, custom
|
||||
|
||||
|
|
41
src/debug.h
Normal file
41
src/debug.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
static void dump8(unsigned char* to_dump, unsigned long offset,
|
||||
unsigned long size)
|
||||
{
|
||||
const int block_size = 1;
|
||||
const int block_per_line = 16;
|
||||
int max_line = size / block_size;
|
||||
unsigned char mychar;
|
||||
int i;
|
||||
int j;
|
||||
for (i = 0; i < max_line; i++)
|
||||
{
|
||||
if ((i % block_per_line) == 0)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
printf(" ");
|
||||
for (j = i - block_per_line; j < i; j++)
|
||||
{
|
||||
mychar = *(to_dump + j);
|
||||
if ((mychar < 32) || (mychar >= 127))
|
||||
mychar = '.';
|
||||
printf("%c", mychar);
|
||||
}
|
||||
}
|
||||
printf("\n%08lX:", offset + i * block_size);
|
||||
}
|
||||
printf(" %02hhX", *(to_dump + i));
|
||||
}
|
||||
if (i > 0)
|
||||
{
|
||||
printf(" ");
|
||||
for (j = (i >= block_per_line) ? (i - block_per_line) : 0; j < i; j++)
|
||||
{
|
||||
mychar = *(to_dump + j);
|
||||
if ((mychar < 32) || (mychar >= 127))
|
||||
mychar = '.';
|
||||
printf("%c", mychar);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
333
src/parse.h
333
src/parse.h
|
@ -1,15 +1,43 @@
|
|||
static bool _cut(const string& entry, vector<string>& entries)
|
||||
// keywords declaration
|
||||
struct keyword_t
|
||||
{
|
||||
cmd_type_t type;
|
||||
char name[24];
|
||||
program_fn_t fn;
|
||||
string comment;
|
||||
};
|
||||
static const int g_max_commands = 128;
|
||||
static keyword_t _keywords[g_max_commands];
|
||||
|
||||
static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type)
|
||||
{
|
||||
for(unsigned int i=0; (i<sizeof(_keywords)/sizeof(_keywords[0])) && (_keywords[i].type != cmd_max); i++)
|
||||
{
|
||||
if ((strnlen(_keywords[i].name, sizeof(_keywords[i].name))>0)
|
||||
&& (strncmp(fn_name, _keywords[i].name, sizeof(_keywords[i].name)) == 0))
|
||||
{
|
||||
fn = _keywords[i].fn;
|
||||
type = _keywords[i].type;
|
||||
return ret_ok;
|
||||
}
|
||||
}
|
||||
return ret_unknown_err;
|
||||
}
|
||||
|
||||
static bool _cut(const char* entry, vector<string>& entries)
|
||||
{
|
||||
string tmp;
|
||||
//TODO borner
|
||||
int len = strlen(entry);
|
||||
|
||||
for (int i=0; i<entry.size(); i++)
|
||||
for (int i=0; i < len; i++)
|
||||
{
|
||||
switch(entry.at(i))
|
||||
switch(entry[i])
|
||||
{
|
||||
//symbol
|
||||
case '\'':
|
||||
//push prec entry if exists
|
||||
if (tmp.size()>0)
|
||||
if (tmp.size() > 0)
|
||||
{
|
||||
entries.push_back(tmp);
|
||||
tmp.clear();
|
||||
|
@ -17,10 +45,10 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
//get symbol
|
||||
tmp='\'';
|
||||
i++;
|
||||
while((i<entry.size()) && (isalnum(entry.at(i)) || entry.at(i)=='_'))
|
||||
tmp+=entry.at(i++);
|
||||
if ((i<entry.size()) && entry.at(i)=='\'')
|
||||
tmp+='\'';
|
||||
while((i < len) && (isalnum(entry[i]) || entry[i]=='_'))
|
||||
tmp += entry[i++];
|
||||
if ((i < len) && entry[i] == '\'')
|
||||
tmp += '\'';
|
||||
entries.push_back(tmp);
|
||||
tmp.clear();
|
||||
break;
|
||||
|
@ -28,7 +56,7 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
//string
|
||||
case '"':
|
||||
//push prec entry if exists
|
||||
if (tmp.size()>0)
|
||||
if (tmp.size() > 0)
|
||||
{
|
||||
entries.push_back(tmp);
|
||||
tmp.clear();
|
||||
|
@ -36,10 +64,10 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
//get expression
|
||||
tmp='"';
|
||||
i++;
|
||||
while(i<entry.size() && entry.at(i)>=' ')
|
||||
while(i < len && entry[i] >= ' ')
|
||||
{
|
||||
tmp+=entry.at(i);
|
||||
if (entry.at(i++) == '"')
|
||||
tmp += entry[i];
|
||||
if (entry[i++] == '"')
|
||||
break;
|
||||
}
|
||||
entries.push_back(tmp);
|
||||
|
@ -55,35 +83,37 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
tmp.clear();
|
||||
}
|
||||
|
||||
if (entry.substr(i, 2) == "<<")
|
||||
if (strncmp(&entry[i], "<<", 2) == 0)
|
||||
{
|
||||
int up = 1;
|
||||
|
||||
// found a program begin
|
||||
i+=2;
|
||||
tmp="<< ";
|
||||
i += 2;
|
||||
tmp = "<< ";
|
||||
|
||||
// trim leading spaces
|
||||
while (i<entry.size() && (entry.at(i)==' ' || entry.at(i)=='\t'))
|
||||
while (i < len && (entry[i]==' ' || entry[i]=='\t'))
|
||||
i++;
|
||||
|
||||
while(i<entry.size())
|
||||
while(i < len)
|
||||
{
|
||||
if (entry.substr(i, 2) == "<<")
|
||||
if (strncmp(&entry[i], "<<", 2) == 0)
|
||||
{
|
||||
up++;
|
||||
i+=2;
|
||||
tmp+=" << ";
|
||||
i += 2;
|
||||
tmp += " << ";
|
||||
// trim leading spaces
|
||||
while (i<entry.size() && (entry.at(i)==' ' || entry.at(i)=='\t'))
|
||||
while (i < len && (entry[i] == ' ' || entry[i] == '\t'))
|
||||
i++;
|
||||
}
|
||||
else if (entry.substr(i, 2) == ">>")
|
||||
else if (strncmp(&entry[i], ">>", 2) == 0)
|
||||
{
|
||||
up--;
|
||||
i+=2;
|
||||
tmp+=" >>";
|
||||
i += 2;
|
||||
tmp += " >>";
|
||||
|
||||
// trim trailing spaces
|
||||
while (i<entry.size() && (entry.at(i)==' ' || entry.at(i)=='\t'))
|
||||
while (i < len && (entry[i] == ' ' || entry[i] == '\t'))
|
||||
i++;
|
||||
// found end
|
||||
if (up == 0)
|
||||
|
@ -91,7 +121,7 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
}
|
||||
else
|
||||
{
|
||||
tmp+=entry[i];
|
||||
tmp += entry[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -114,9 +144,9 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
|
||||
//other
|
||||
default:
|
||||
if (entry.at(i)!=' ' && entry.at(i)!='\t')
|
||||
if (entry[i] != ' ' && entry[i] != '\t')
|
||||
{
|
||||
tmp+=entry.at(i);
|
||||
tmp += entry[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -147,14 +177,18 @@ static bool get_keyword(const string& entry, object*& obj, unsigned int& obj_siz
|
|||
{
|
||||
if (type == cmd_keyword)
|
||||
{
|
||||
obj = new keyword(fn, (string&)entry);
|
||||
obj_size = sizeof(keyword);
|
||||
// allocate keyword object
|
||||
obj_size = sizeof(keyword)+entry.size()+1;
|
||||
obj = (object*)malloc(obj_size);
|
||||
((keyword*)obj)->set(fn, entry.c_str(), entry.size());
|
||||
ret = true;
|
||||
}
|
||||
else if (type == cmd_branch)
|
||||
{
|
||||
obj = new branch((branch_fn_t)fn, (string&)entry);
|
||||
obj_size = sizeof(branch);
|
||||
// allocate branch object
|
||||
obj_size = sizeof(branch)+entry.size()+1;
|
||||
obj = (object*)malloc(obj_size);
|
||||
((branch*)obj)->set((branch_fn_t)fn, entry.c_str(), entry.size());
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
@ -162,53 +196,147 @@ static bool get_keyword(const string& entry, object*& obj, unsigned int& obj_siz
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool get_symbol(const string& entry, object*& obj)
|
||||
static bool get_symbol(const string& entry, object*& obj, unsigned int& obj_len)
|
||||
{
|
||||
bool ret = false;
|
||||
int len = entry.size();
|
||||
if (len>1 && entry[0]=='\'')
|
||||
{
|
||||
int last = entry[len-1]=='\''?(len-2):(len-1);
|
||||
obj = new symbol(entry.substr(1, last).c_str());
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int entry_len = entry.size();
|
||||
|
||||
static bool get_string(const string& entry, object*& obj)
|
||||
{
|
||||
bool ret = false;
|
||||
int len = entry.size();
|
||||
if (len>1 && entry[0]=='\"')
|
||||
if (entry_len>=1 && entry[0]=='\'')
|
||||
{
|
||||
int last = entry[len-1]=='\"'?(len-2):(len-1);
|
||||
obj = new ostring(entry.substr(1, last).c_str());
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
// symbol entry, like 'toto'
|
||||
if (entry_len == 1)
|
||||
{
|
||||
// total object length
|
||||
obj_len = sizeof(symbol)+1;
|
||||
|
||||
static bool get_program(const string& entry, object*& obj)
|
||||
{
|
||||
bool ret = false;
|
||||
int len = entry.size();
|
||||
if (len>=2 && entry[0]=='<' && entry[1]=='<')
|
||||
{
|
||||
int last;
|
||||
if (len>=4 && entry[len-1]=='>' && entry[len-2]=='>')
|
||||
last = len-4;
|
||||
// allocate object
|
||||
obj = (symbol*)malloc(obj_len);
|
||||
|
||||
//set it
|
||||
((symbol*)obj)->set("", 0);
|
||||
}
|
||||
else
|
||||
last = len-2;
|
||||
obj = new oprogram(entry.substr(2, last).c_str());
|
||||
{
|
||||
int naked_entry_len;
|
||||
|
||||
// entry length without prefix / postfix
|
||||
naked_entry_len = entry[entry_len-1]=='\''?(entry_len-2):(entry_len-1);
|
||||
// total object length
|
||||
obj_len = sizeof(symbol)+naked_entry_len+1;
|
||||
|
||||
// allocate object
|
||||
obj = (symbol*)malloc(obj_len);
|
||||
|
||||
// set it
|
||||
((symbol*)obj)->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len);
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool get_other(const string& entry, object*& obj, unsigned int& obj_len, cmd_type_t& type)
|
||||
{
|
||||
bool ret = false;
|
||||
int entry_len = entry.size();
|
||||
|
||||
if (entry_len>=1)
|
||||
{
|
||||
// entry which is nothing is considered as an auto-evaluated symbol
|
||||
int naked_entry_len;
|
||||
|
||||
// entry length without prefix / postfix
|
||||
naked_entry_len = entry[entry_len-1]=='\''?(entry_len-1):(entry_len);
|
||||
// total object length
|
||||
obj_len = sizeof(symbol)+naked_entry_len+1;
|
||||
|
||||
// allocate object
|
||||
obj = (symbol*)malloc(obj_len);
|
||||
|
||||
// set it
|
||||
((symbol*)obj)->set(entry.c_str(), naked_entry_len);
|
||||
((symbol*)obj)->_auto_eval = true;
|
||||
type = cmd_symbol;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool get_string(const string& entry, object*& obj, unsigned int& obj_len)
|
||||
{
|
||||
bool ret = false;
|
||||
int entry_len = entry.size();
|
||||
if (entry_len>=1 && entry[0]=='"')
|
||||
{
|
||||
if (entry_len == 1)
|
||||
{
|
||||
// total object length
|
||||
obj_len = sizeof(ostring)+1;
|
||||
|
||||
// allocate object
|
||||
obj = (ostring*)malloc(obj_len);
|
||||
|
||||
//set it
|
||||
((ostring*)obj)->set("", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int naked_entry_len;
|
||||
|
||||
// entry length without prefix / postfix
|
||||
naked_entry_len = entry[entry_len-1]=='"'?(entry_len-2):(entry_len-1);
|
||||
|
||||
// total object length
|
||||
obj_len = sizeof(ostring)+naked_entry_len+1;
|
||||
|
||||
// allocate object
|
||||
obj = (ostring*)malloc(obj_len);
|
||||
|
||||
// set it
|
||||
((ostring*)obj)->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len);
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool get_program(const string& entry, object*& obj, unsigned int& obj_len)
|
||||
{
|
||||
bool ret = false;
|
||||
int entry_len = entry.size();
|
||||
if (entry_len>=2 && entry[0]=='<' && entry[1]=='<')
|
||||
{
|
||||
int naked_entry_len;
|
||||
|
||||
// entry length without prefix / postfix
|
||||
if (entry_len>=4 && entry[entry_len-1]=='>' && entry[entry_len-2]=='>')
|
||||
naked_entry_len = entry_len-4;
|
||||
else
|
||||
naked_entry_len = entry_len-2;
|
||||
|
||||
// total object length
|
||||
obj_len = sizeof(oprogram)+naked_entry_len+1;
|
||||
|
||||
// allocate object
|
||||
obj = (object*)malloc(obj_len);
|
||||
|
||||
// set it
|
||||
((oprogram*)obj)->set(&entry[2], naked_entry_len);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool get_float(const string& entry, object*& obj)
|
||||
// care: not threadsafe
|
||||
static bool get_float(const string& entry, object*& obj, unsigned int& obj_size)
|
||||
{
|
||||
stringstream token;
|
||||
static number new_number;
|
||||
floating_t val;
|
||||
stringstream token;
|
||||
bool ret = false;
|
||||
|
||||
token<<entry;
|
||||
|
@ -216,17 +344,22 @@ static bool get_float(const string& entry, object*& obj)
|
|||
|
||||
if ( (!token.fail()) && (!token.bad()) )
|
||||
{
|
||||
obj = new number(val);
|
||||
new_number.set(val);
|
||||
obj = &new_number;
|
||||
obj_size = sizeof(number);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool get_binary(const string& entry, object*& obj)
|
||||
// care: not threadsafe
|
||||
static bool get_binary(const string& entry, object*& obj, unsigned int& obj_size)
|
||||
{
|
||||
static binary new_binary;
|
||||
integer_t val;
|
||||
bool ret = false;
|
||||
|
||||
if ((entry.size() >= 2) && (entry[0] == '#'))
|
||||
{
|
||||
stringstream token;
|
||||
|
@ -255,7 +388,9 @@ static bool get_binary(const string& entry, object*& obj)
|
|||
token>>val;
|
||||
if(syntax && !token.fail())
|
||||
{
|
||||
obj = new binary(val);
|
||||
new_binary.set(val);
|
||||
obj = &new_binary;
|
||||
obj_size = sizeof(binary);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
@ -263,8 +398,10 @@ static bool get_binary(const string& entry, object*& obj)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool get_binary_bin(const string& entry, object*& obj)
|
||||
// care: not threadsafe
|
||||
static bool get_binary_bin(const string& entry, object*& obj, unsigned int& obj_size)
|
||||
{
|
||||
static binary new_binary;
|
||||
integer_t val;
|
||||
int len = entry.size();
|
||||
bool ret = false;
|
||||
|
@ -281,7 +418,9 @@ static bool get_binary_bin(const string& entry, object*& obj)
|
|||
exponent/=2;
|
||||
}
|
||||
}
|
||||
obj = new binary(val);
|
||||
new_binary.set(val);
|
||||
obj = &new_binary;
|
||||
obj_size = sizeof(binary);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
|
@ -292,40 +431,34 @@ static bool _obj_from_string(const string& entry, object*& obj, unsigned int& ob
|
|||
{
|
||||
bool ret = false;
|
||||
|
||||
if (get_float(entry, obj))
|
||||
if (get_float(entry, obj, obj_size))
|
||||
{
|
||||
type = cmd_number;
|
||||
obj_size = sizeof(number);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_binary(entry, obj))
|
||||
else if (get_binary(entry, obj, obj_size))
|
||||
{
|
||||
type = cmd_binary;
|
||||
obj_size = sizeof(binary);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_binary_bin(entry, obj))
|
||||
else if (get_binary_bin(entry, obj, obj_size))
|
||||
{
|
||||
type = cmd_binary;
|
||||
obj_size = sizeof(binary);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_symbol(entry, obj))
|
||||
else if (get_symbol(entry, obj, obj_size))
|
||||
{
|
||||
type = cmd_symbol;
|
||||
obj_size = sizeof(symbol);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_string(entry, obj))
|
||||
else if (get_string(entry, obj, obj_size))
|
||||
{
|
||||
type = cmd_string;
|
||||
obj_size = sizeof(ostring);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_program(entry, obj))
|
||||
else if (get_program(entry, obj, obj_size))
|
||||
{
|
||||
type = cmd_program;
|
||||
obj_size = sizeof(oprogram);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_keyword(entry, obj, obj_size, type))
|
||||
|
@ -335,16 +468,31 @@ static bool _obj_from_string(const string& entry, object*& obj, unsigned int& ob
|
|||
else
|
||||
{
|
||||
// nothing, considered as an auto-evaluated symbol
|
||||
obj = new symbol((string&)entry);
|
||||
((symbol*)obj)->_auto_eval = true;
|
||||
obj_size = sizeof(symbol);
|
||||
type = cmd_symbol;
|
||||
ret = true;
|
||||
if (get_other(entry, obj, obj_size, type))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _delete_obj_from_string(object* obj)
|
||||
{
|
||||
if (obj != NULL)
|
||||
{
|
||||
switch (obj->_type)
|
||||
{
|
||||
case cmd_number:
|
||||
case cmd_binary:
|
||||
break;
|
||||
default:
|
||||
free(obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char* entry_completion_generator(const char* text, int state)
|
||||
{
|
||||
static int list_index, len, too_far;
|
||||
|
@ -386,7 +534,7 @@ static char* entry_completion_dupstr(char* s)
|
|||
return r;
|
||||
}
|
||||
|
||||
static ret_value parse(const string& entry, program& prog)
|
||||
static ret_value parse(const char* entry, program& prog)
|
||||
{
|
||||
vector<string> entries;
|
||||
ret_value ret = ret_ok;
|
||||
|
@ -403,6 +551,7 @@ static ret_value parse(const string& entry, program& prog)
|
|||
if(_obj_from_string((*it), obj, obj_size, type))
|
||||
{
|
||||
prog.push_back(obj, obj_size, type);
|
||||
_delete_obj_from_string(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -417,7 +566,7 @@ static ret_value parse(const string& entry, program& prog)
|
|||
// interactive entry and decoding
|
||||
static ret_value entry(program& prog)
|
||||
{
|
||||
char *buf;
|
||||
char* buf;
|
||||
ret_value ret;
|
||||
|
||||
// declare completion fn (bound to '\t' by default)
|
||||
|
@ -427,10 +576,8 @@ static ret_value entry(program& prog)
|
|||
buf = readline(prompt);
|
||||
if (buf != NULL)
|
||||
{
|
||||
string entry(buf);
|
||||
|
||||
// parse it
|
||||
ret = parse(entry, prog);
|
||||
ret = parse(buf, prog);
|
||||
|
||||
// keep history
|
||||
if (buf[0]!=0)
|
||||
|
|
|
@ -16,7 +16,9 @@ void plus()
|
|||
//TODO really too slow
|
||||
putb(getb() + getb());
|
||||
}
|
||||
// string
|
||||
//TODO
|
||||
#if 0
|
||||
// string
|
||||
else if (IS_ARG_TYPE(0, cmd_string))
|
||||
{
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_string);
|
||||
|
@ -24,6 +26,7 @@ void plus()
|
|||
_stack->pop_back();
|
||||
*((ostring*)_stack->back())->_value += second;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
|
|
@ -23,8 +23,9 @@ void rtob()
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
binary bin((integer_t)getf());
|
||||
_stack->push_back(&bin, sizeof(binary), cmd_binary);
|
||||
binary bin;
|
||||
bin.set(((integer_t)getf()));
|
||||
_stack->push_back(&bin, bin.size(), cmd_binary);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -70,8 +70,9 @@ int rpn_for(branch& myobj)
|
|||
myobj.farg1 = getf();
|
||||
|
||||
// store symbol with first value
|
||||
number num(myobj.farg1);
|
||||
_heap->add(*sym->_value, &num, sizeof(number), cmd_number);
|
||||
number num;
|
||||
num.set(myobj.farg1);
|
||||
_heap->add(string(sym->_value), &num, num.size(), cmd_number);
|
||||
|
||||
return myobj.arg1 + 1;
|
||||
}
|
||||
|
@ -98,7 +99,7 @@ int rpn_next(branch& myobj)
|
|||
int type;
|
||||
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
||||
// check symbol variable is a number, then increase
|
||||
if (_heap->get(*var->_value, obj, size, type) && (type == cmd_number))
|
||||
if (_heap->get(string(var->_value), obj, size, type) && (type == cmd_number))
|
||||
((number*)obj)->_value = myobj.farg1;
|
||||
}
|
||||
|
||||
|
@ -143,7 +144,7 @@ int rpn_step(branch& myobj)
|
|||
int type;
|
||||
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
||||
// check symbol variable is a number, then increase
|
||||
if (_heap->get(*var->_value, obj, size, type) && (type == cmd_number))
|
||||
if (_heap->get(string(var->_value), obj, size, type) && (type == cmd_number))
|
||||
((number*)obj)->_value = myobj.farg1;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ void eval(void)
|
|||
void* obj;
|
||||
unsigned int size;
|
||||
int type;
|
||||
string& variable = *((symbol*)_stack->back())->_value;
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
if (_heap->get(variable, obj, size, type))
|
||||
{
|
||||
_stack->pop_back();
|
||||
|
@ -20,13 +20,13 @@ void eval(void)
|
|||
else if (IS_ARG_TYPE(0, cmd_program))
|
||||
{
|
||||
// eval a program
|
||||
string& entry = *((oprogram*)_stack->back())->_value;
|
||||
string entry(((oprogram*)_stack->back())->_value);
|
||||
_stack->pop_back();
|
||||
|
||||
program prog;
|
||||
|
||||
// make program from entry
|
||||
if (program::parse(entry, prog) == ret_ok)
|
||||
if (program::parse(entry.c_str(), prog) == ret_ok)
|
||||
{
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
|
@ -100,16 +100,16 @@ int inprog(branch& myobj)
|
|||
// load variables
|
||||
for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--)
|
||||
{
|
||||
_heap->add(*((symbol*)seq_obj(i))->_value, _stack->get_obj(0), _stack->get_len(0), _stack->get_type(0));
|
||||
_heap->add(string(((symbol*)seq_obj(i))->_value), _stack->get_obj(0), _stack->get_len(0), _stack->get_type(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
|
||||
// run the program
|
||||
string& entry = *((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value;
|
||||
string entry(((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value);
|
||||
program prog;
|
||||
|
||||
// make the program from entry
|
||||
if (program::parse(entry, prog) == ret_ok)
|
||||
if (program::parse(entry.c_str(), prog) == ret_ok)
|
||||
{
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
|
|
|
@ -76,6 +76,7 @@ void rot(void)
|
|||
|
||||
void depth(void)
|
||||
{
|
||||
number num((floating_t)_stack->size());
|
||||
_stack->push_back(&num, sizeof(number), cmd_number);
|
||||
number num;
|
||||
num.set((floating_t)_stack->size());
|
||||
_stack->push_back(&num, num.size(), cmd_number);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ void sto(void)
|
|||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||
|
||||
string name = getn();
|
||||
string name(((symbol*)_stack->get_obj(0))->_value);
|
||||
_stack->pop_back();
|
||||
_heap->add(name, _stack->get_obj(0), _stack->get_len(0), _stack->get_type(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
|
@ -18,7 +19,7 @@ void rcl(void)
|
|||
void* obj;
|
||||
unsigned int size;
|
||||
int type;
|
||||
string& variable = *((symbol*)_stack->back())->_value;
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
if (_heap->get(variable, obj, size, type))
|
||||
{
|
||||
_stack->pop_back();
|
||||
|
@ -36,13 +37,13 @@ void auto_rcl(symbol* symb)
|
|||
void* obj;
|
||||
unsigned int size;
|
||||
int type;
|
||||
if (_heap->get(*symb->_value, obj, size, type))
|
||||
if (_heap->get(string(symb->_value), obj, size, type))
|
||||
_stack->push_back(obj, size, type);
|
||||
else
|
||||
_stack->push_back(symb, sizeof(symbol), cmd_symbol);
|
||||
_stack->push_back(symb, symb->size(), cmd_symbol);
|
||||
}
|
||||
else
|
||||
_stack->push_back(symb, sizeof(symbol), cmd_symbol);
|
||||
_stack->push_back(symb, symb->size(), cmd_symbol);
|
||||
}
|
||||
|
||||
void purge(void)
|
||||
|
@ -50,8 +51,11 @@ void purge(void)
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||
|
||||
if (!_heap->erase(getn()))
|
||||
string name(((symbol*)_stack->back())->_value);
|
||||
if (!_heap->erase(name))
|
||||
ERR_CONTEXT(ret_unknown_variable);
|
||||
else
|
||||
_stack->pop_back();
|
||||
}
|
||||
|
||||
void vars(void)
|
||||
|
|
|
@ -9,23 +9,24 @@ void instr()
|
|||
((object*)_stack->back())->show(out);
|
||||
_stack->pop_back();
|
||||
|
||||
ostring* str = new ostring(out.str().c_str());
|
||||
_stack->push_back(str, sizeof(ostring), cmd_string);
|
||||
ostring str;
|
||||
str.set(out.str().c_str(), out.str().size());
|
||||
_stack->push_back(&str, str.size(), cmd_string);
|
||||
}
|
||||
}
|
||||
|
||||
void strout()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
string& entry = *((ostring*)_stack->back())->_value;
|
||||
string entry(((ostring*)_stack->back())->_value);
|
||||
_stack->pop_back();
|
||||
|
||||
program prog;
|
||||
|
||||
// make program from string in stack level 1
|
||||
if (program::parse(entry, prog) == ret_ok)
|
||||
if (program::parse(entry.c_str(), prog) == ret_ok)
|
||||
{
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
|
|
|
@ -115,7 +115,7 @@ void program::test()
|
|||
{
|
||||
// parse entry and run line
|
||||
program prog;
|
||||
ret = program::parse(entry, prog);
|
||||
ret = program::parse(entry.c_str(), prog);
|
||||
if (ret == ret_ok)
|
||||
{
|
||||
// run it
|
||||
|
|
|
@ -63,11 +63,14 @@ void eq(void)
|
|||
putf(getf() == first);
|
||||
}
|
||||
break;
|
||||
//TODO
|
||||
#if 0
|
||||
case cmd_symbol:
|
||||
{
|
||||
string first = getn();
|
||||
putf(getn() == first);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
_stack->pop_back();
|
||||
|
|
364
src/rpn.cpp
364
src/rpn.cpp
|
@ -43,11 +43,6 @@ using namespace std;
|
|||
|
||||
#include "stack.h"
|
||||
|
||||
//TODO faut-il que ces variables soient globales ?
|
||||
static const char g_cursor[] = "> ";
|
||||
static const string g_show_stack_separator = ":\t";
|
||||
static const int g_max_commands = 128;
|
||||
|
||||
//
|
||||
static int g_verbose = 0;
|
||||
|
||||
|
@ -106,22 +101,28 @@ typedef union
|
|||
typedef int (program::*branch_fn_t)(branch&);
|
||||
|
||||
//
|
||||
class object
|
||||
struct object
|
||||
{
|
||||
public:
|
||||
cmd_type_t _type;// object type
|
||||
object(cmd_type_t type = cmd_undef):_type(type) { }
|
||||
// object type
|
||||
cmd_type_t _type;
|
||||
|
||||
//
|
||||
void show(ostream& stream = cout);
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
class number : public object
|
||||
struct number : public object
|
||||
{
|
||||
public:
|
||||
number(floating_t value) : object(cmd_number) { _value = value; }
|
||||
floating_t _value;
|
||||
|
||||
// representation mode
|
||||
//
|
||||
void set(floating_t value)
|
||||
{
|
||||
_type = cmd_number;
|
||||
_value = value;
|
||||
}
|
||||
unsigned int size() { return sizeof(number); }
|
||||
|
||||
// representation mode
|
||||
typedef enum {
|
||||
std,
|
||||
fix,
|
||||
|
@ -133,18 +134,24 @@ public:
|
|||
// precision
|
||||
static int s_default_precision;
|
||||
static int s_current_precision;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
number::mode_enum number::s_default_mode = number::std;
|
||||
number::mode_enum number::s_mode = number::s_default_mode;
|
||||
int number::s_default_precision = 20;
|
||||
int number::s_current_precision = number::s_default_precision;
|
||||
|
||||
class binary : public object
|
||||
struct binary : public object
|
||||
{
|
||||
public:
|
||||
binary(integer_t value) : object(cmd_binary) { _value = value; }
|
||||
integer_t _value;
|
||||
|
||||
//
|
||||
void set(integer_t value)
|
||||
{
|
||||
_type = cmd_binary;
|
||||
_value = value;
|
||||
}
|
||||
unsigned int size() { return sizeof(binary); }
|
||||
|
||||
// representation mode
|
||||
typedef enum {
|
||||
dec,
|
||||
|
@ -154,61 +161,190 @@ public:
|
|||
} binary_enum;
|
||||
static binary_enum s_default_mode;
|
||||
static binary_enum s_mode;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
binary::binary_enum binary::s_default_mode = binary::dec;
|
||||
binary::binary_enum binary::s_mode = binary::s_default_mode;
|
||||
|
||||
class ostring : public object
|
||||
struct ostring : public object
|
||||
{
|
||||
public:
|
||||
ostring(string& value, cmd_type_t type = cmd_string) : object(type)
|
||||
{
|
||||
_value = new string(value);
|
||||
}
|
||||
ostring(const char* value, cmd_type_t type = cmd_string) : object(type)
|
||||
{
|
||||
_value = new string(value);
|
||||
}
|
||||
string* _value;
|
||||
};
|
||||
//
|
||||
void set(const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_string;
|
||||
if (value != NULL)
|
||||
{
|
||||
if (len>0)
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
int size() { return sizeof(ostring)+_len+1; }
|
||||
|
||||
class oprogram : public ostring
|
||||
{
|
||||
public:
|
||||
oprogram(string& value, cmd_type_t type = cmd_program) : ostring(value, type) { }
|
||||
oprogram(const char* value, cmd_type_t type = cmd_program) : ostring(value, type) { }
|
||||
};
|
||||
//
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
class symbol : public ostring
|
||||
struct oprogram : public object
|
||||
{
|
||||
public:
|
||||
symbol(string& value, cmd_type_t type = cmd_symbol) : ostring(value, type), _auto_eval(false) { }
|
||||
symbol(const char* value, cmd_type_t type = cmd_symbol) : ostring(value, type), _auto_eval(false) { }
|
||||
bool _auto_eval;
|
||||
};
|
||||
//
|
||||
void set(const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_program;
|
||||
if (value != NULL)
|
||||
{
|
||||
if (len>0)
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
int size() { return sizeof(oprogram)+_len+1; }
|
||||
|
||||
class keyword : public symbol
|
||||
{
|
||||
public:
|
||||
keyword(program_fn_t fn, string& value, cmd_type_t type = cmd_keyword) : symbol(value, type) { _fn = fn; }
|
||||
program_fn_t _fn;
|
||||
};
|
||||
//
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
class branch : public keyword
|
||||
struct symbol : public object
|
||||
{
|
||||
public:
|
||||
branch(branch_fn_t fn, string& value) : keyword(NULL, value, cmd_branch), arg1(-1), arg2(-1), arg3(-1), arg_bool(false)
|
||||
{
|
||||
_type = cmd_branch;
|
||||
_fn = fn;
|
||||
}
|
||||
// branch function
|
||||
branch_fn_t _fn;
|
||||
// args used by cmd_branch cmds
|
||||
int arg1, arg2, arg3;
|
||||
floating_t farg1, farg2;
|
||||
bool arg_bool;
|
||||
};
|
||||
//
|
||||
void set(const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_symbol;
|
||||
_auto_eval = false;
|
||||
if (value != NULL)
|
||||
{
|
||||
if (len>0)
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
int size() { return sizeof(symbol)+_len+1; }
|
||||
|
||||
//
|
||||
bool _auto_eval;
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct keyword : public object
|
||||
{
|
||||
//
|
||||
void set(program_fn_t fn, const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_keyword;
|
||||
_fn = fn;
|
||||
if (value != NULL)
|
||||
{
|
||||
if (len>0)
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
int size() { return sizeof(keyword)+_len+1; }
|
||||
|
||||
//
|
||||
program_fn_t _fn;
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct branch : public object
|
||||
{
|
||||
//
|
||||
void set(branch_fn_t fn, const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_branch;
|
||||
_fn = fn;
|
||||
arg1 = -1;
|
||||
arg2 = -1;
|
||||
arg3 = -1;
|
||||
farg1 = 0;
|
||||
farg2 = 0;
|
||||
arg_bool = 0;
|
||||
if (value != NULL)
|
||||
{
|
||||
if (len>0)
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
int size() { return sizeof(branch)+_len+1; }
|
||||
|
||||
// branch function
|
||||
branch_fn_t _fn;
|
||||
// args used by cmd_branch cmds
|
||||
int arg1, arg2, arg3;
|
||||
floating_t farg1, farg2;
|
||||
bool arg_bool;
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
void object::show(ostream& stream)
|
||||
{
|
||||
switch(_type)
|
||||
{
|
||||
case cmd_number:
|
||||
stream << ((number*)this)->_value;
|
||||
break;
|
||||
case cmd_binary:
|
||||
{
|
||||
cout << "# ";
|
||||
switch(((binary*)this)->s_mode)
|
||||
{
|
||||
case binary::dec: cout<<std::right<<std::setw(8)<<std::dec<<((binary*)this)->_value<<" d"; break;
|
||||
case binary::hex: cout<<std::right<<std::setw(16)<<std::hex<<((binary*)this)->_value<<" h"; break;
|
||||
case binary::oct: cout<<std::right<<std::setw(16)<<std::oct<<((binary*)this)->_value<<" o"; break;
|
||||
case binary::bin:
|
||||
{
|
||||
string mybin;
|
||||
for (int i = (int)(log((floating_t)((binary*)this)->_value) / log(2.)); i>=0; i--)
|
||||
{
|
||||
if (((binary*)this)->_value & (1 << i))
|
||||
mybin+='1';
|
||||
else
|
||||
mybin+='0';
|
||||
}
|
||||
cout<<std::right<<std::setw(20)<<std::oct<<mybin<<" b";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cmd_string:
|
||||
stream << "\"" << ((ostring*)this)->_value << "\"";
|
||||
break;
|
||||
case cmd_program:
|
||||
stream << "<< " << ((oprogram*)this)->_value << " >>";
|
||||
break;
|
||||
case cmd_symbol:
|
||||
stream << "'" << ((symbol*)this)->_value << "'";
|
||||
break;
|
||||
case cmd_keyword:
|
||||
case cmd_branch:
|
||||
stream << ((keyword*)this)->_value;
|
||||
break;
|
||||
default:
|
||||
stream << "< unknown object representation >";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void object::show(ostream& stream)
|
||||
{
|
||||
|
@ -305,9 +441,9 @@ public:
|
|||
}
|
||||
|
||||
// could be an auto-evaluated symbol
|
||||
if (type == cmd_symbol)
|
||||
if (type == cmd_symbol)
|
||||
{
|
||||
auto_rcl((symbol*)seq_obj(i));
|
||||
auto_rcl((symbol*)seq_obj(i));
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -364,7 +500,23 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret_value preprocess(void)
|
||||
bool compare_keyword(keyword* k, const char* str_to_compare, int len)
|
||||
{
|
||||
if (k->_len >= len)
|
||||
return strncmp(k->_value, str_to_compare, len) == 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool compare_branch(branch* b, const char* str_to_compare, int len)
|
||||
{
|
||||
if (b->_len >= len)
|
||||
return strncmp(b->_value, str_to_compare, len) == 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
ret_value preprocess(void)
|
||||
{
|
||||
// for if-then-else-end
|
||||
vector<struct if_layout_t> vlayout;
|
||||
|
@ -380,9 +532,9 @@ public:
|
|||
if (type == cmd_keyword)
|
||||
{
|
||||
keyword* k = (keyword*)seq_obj(i);
|
||||
if (k->_value->compare("end") == 0)
|
||||
if (compare_keyword(k, "end", 3))
|
||||
{
|
||||
int next = i + 1;
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
next = -1;
|
||||
|
||||
|
@ -410,16 +562,16 @@ public:
|
|||
else if (type == cmd_branch)
|
||||
{
|
||||
branch* k = (branch*)seq_obj(i);
|
||||
if (k->_value->compare("if") == 0)
|
||||
if (compare_branch(k, "if", 2))
|
||||
{
|
||||
if_layout_t layout;
|
||||
layout.index_if = i;
|
||||
layout.index_if = i;
|
||||
vlayout.push_back(layout);
|
||||
layout_index++;
|
||||
}
|
||||
else if (k->_value->compare("then") == 0)
|
||||
else if (compare_branch(k, "then", 4))
|
||||
{
|
||||
int next = i + 1;
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
next = -1;
|
||||
|
||||
|
@ -446,9 +598,9 @@ public:
|
|||
k->arg1 = next;
|
||||
k->arg3 = vlayout[layout_index].index_if;
|
||||
}
|
||||
else if (k->_value->compare("else") == 0)
|
||||
else if (compare_branch(k, "else", 4))
|
||||
{
|
||||
int next = i + 1;
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
next = -1;
|
||||
|
||||
|
@ -482,16 +634,16 @@ public:
|
|||
k->arg3 = vlayout[layout_index].index_if;
|
||||
((branch*)seq_obj(vlayout[layout_index].index_then))->arg2 = next;// fill branch2 (if was false) of 'then'
|
||||
}
|
||||
else if (k->_value->compare("start") == 0)
|
||||
else if (compare_branch(k, "start", 5))
|
||||
{
|
||||
vstartindex.push_back(i);
|
||||
}
|
||||
else if (k->_value->compare("for") == 0)
|
||||
else if (compare_branch(k, "for", 3))
|
||||
{
|
||||
vstartindex.push_back(i);
|
||||
k->arg1 = i + 1;// arg1 points on symbol variable
|
||||
}
|
||||
else if(k->_value->compare("next") == 0)
|
||||
else if(compare_branch(k, "next", 4))
|
||||
{
|
||||
if (vstartindex.size() == 0)
|
||||
{
|
||||
|
@ -502,7 +654,7 @@ public:
|
|||
k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'next' branch1 = 'start' index
|
||||
vstartindex.pop_back();
|
||||
}
|
||||
else if (k->_value->compare("step") == 0)
|
||||
else if (compare_branch(k, "step", 4))
|
||||
{
|
||||
if (vstartindex.size() == 0)
|
||||
{
|
||||
|
@ -513,7 +665,7 @@ public:
|
|||
k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'step' branch1 = 'start' index
|
||||
vstartindex.pop_back();
|
||||
}
|
||||
else if (k->_value->compare("->") == 0)
|
||||
else if (compare_branch(k, "->", 2))
|
||||
{
|
||||
k->arg1 = i;// arg1 is '->' command index in program
|
||||
}
|
||||
|
@ -558,31 +710,6 @@ public:
|
|||
cerr<<"syntax error: "<<context<<endl;
|
||||
}
|
||||
|
||||
// keywords declaration
|
||||
struct keyword_t
|
||||
{
|
||||
cmd_type_t type;
|
||||
char name[24];
|
||||
program_fn_t fn;
|
||||
string comment;
|
||||
};
|
||||
static keyword_t _keywords[g_max_commands];
|
||||
|
||||
static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type)
|
||||
{
|
||||
for(unsigned int i=0; (i<sizeof(_keywords)/sizeof(_keywords[0])) && (_keywords[i].type != cmd_max); i++)
|
||||
{
|
||||
if ((strnlen(_keywords[i].name, sizeof(_keywords[i].name))>0)
|
||||
&& (strncmp(fn_name, _keywords[i].name, sizeof(_keywords[i].name)) == 0))
|
||||
{
|
||||
fn = _keywords[i].fn;
|
||||
type = _keywords[i].type;
|
||||
return ret_ok;
|
||||
}
|
||||
}
|
||||
return ret_unknown_err;
|
||||
}
|
||||
|
||||
ret_value get_err(void) { return _err; }
|
||||
|
||||
#include "parse.h"
|
||||
|
@ -625,8 +752,9 @@ private:
|
|||
void putf(floating_t value)
|
||||
{
|
||||
/* warning, caller must check object type before */
|
||||
number num(value);
|
||||
_stack->push_back(&num, sizeof(number), cmd_number);
|
||||
number num;
|
||||
num.set(value);
|
||||
_stack->push_back(&num, num.size(), cmd_number);
|
||||
}
|
||||
|
||||
integer_t getb()
|
||||
|
@ -640,26 +768,12 @@ private:
|
|||
void putb(integer_t value)
|
||||
{
|
||||
/* warning, caller must check object type before */
|
||||
binary num(value);
|
||||
_stack->push_back(&num, sizeof(binary), cmd_binary);
|
||||
binary num;
|
||||
num.set(value);
|
||||
_stack->push_back(&num, num.size(), cmd_binary);
|
||||
}
|
||||
|
||||
string getn()
|
||||
{
|
||||
/* warning, caller must check object type before */
|
||||
string* a = ((symbol*)_stack->back())->_value;
|
||||
_stack->pop_back();
|
||||
return *a;
|
||||
}
|
||||
|
||||
void putn(string& a)
|
||||
{
|
||||
/* warning, caller must check object type before */
|
||||
symbol sym(a);
|
||||
_stack->push_back(&sym, sizeof(symbol), cmd_symbol);
|
||||
}
|
||||
|
||||
int stack_size()
|
||||
int stack_size()
|
||||
{
|
||||
return _stack->size();
|
||||
}
|
||||
|
@ -748,7 +862,7 @@ int _tmain(int argc, _TCHAR* argv[])
|
|||
}
|
||||
|
||||
// make program
|
||||
ret = program::parse(entry, prog);
|
||||
ret = program::parse(entry.c_str(), prog);
|
||||
if (ret == ret_ok)
|
||||
{
|
||||
string separator = "";
|
||||
|
|
15
src/stack.h
15
src/stack.h
|
@ -8,6 +8,8 @@
|
|||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define ALLOC_BLOB (128*1024)
|
||||
#define LOCAL_COPY_PLACES 3
|
||||
#define LOCAL_COPY_SIZE 128
|
||||
|
@ -147,6 +149,11 @@ public:
|
|||
push_back(&local->blob, local->length, local->type);
|
||||
}
|
||||
|
||||
void dump(void)
|
||||
{
|
||||
dump8((unsigned char*)_base, 0, (unsigned long)(_current - _base));
|
||||
}
|
||||
|
||||
private:
|
||||
char* _base;
|
||||
char* _current;
|
||||
|
@ -186,13 +193,13 @@ public:
|
|||
//TODO gerer les pbs de memoire
|
||||
blob = (struct local_var*)malloc(size + sizeof(local_var));
|
||||
_map[name] = blob;
|
||||
}
|
||||
}
|
||||
else if (size != blob->length)
|
||||
{
|
||||
//TODO gerer les pbs de memoire
|
||||
blob = (struct local_var*)realloc(blob, size + sizeof(local_var));
|
||||
_map[name] = blob;
|
||||
}
|
||||
}
|
||||
blob->length = size;
|
||||
blob->type= type;
|
||||
memcpy(&blob->blob, obj, size);
|
||||
|
@ -244,12 +251,12 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool erase(const string name)
|
||||
bool erase(const string& name)
|
||||
{
|
||||
map<string, struct local_var*>::iterator i = _map.find(name);
|
||||
if (i != _map.end())
|
||||
{
|
||||
free(i->second);
|
||||
free(i->second);
|
||||
_map.erase(i->first);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
static const char version[] = "1.4-beta";
|
||||
static const char uname[] = "rpn v1.4-beta, (c) 2015 <louis@rubet.fr>";
|
||||
|
||||
static const char g_cursor[] = "> ";
|
||||
static const string g_show_stack_separator = "> ";
|
||||
|
||||
// syntax
|
||||
static const char* syntax[] = {
|
||||
"Reverse Polish Notation language, based on hewlett-Packard RPL",
|
||||
|
|
|
@ -42,21 +42,11 @@ drop2
|
|||
drop2
|
||||
|
||||
# test symbol entry 3
|
||||
'2 3'
|
||||
-> stack should be '2 3'
|
||||
drop
|
||||
|
||||
# test symbol entry 4
|
||||
'2 3
|
||||
-> stack should be '2 3'
|
||||
drop
|
||||
|
||||
# test symbol entry 5
|
||||
''
|
||||
-> stack should be ''
|
||||
drop
|
||||
|
||||
# test symbol entry 6
|
||||
# test symbol entry 4
|
||||
'
|
||||
-> stack should be ''
|
||||
drop
|
||||
|
@ -216,9 +206,9 @@ drop
|
|||
drop
|
||||
|
||||
# if-then-else-end test 8
|
||||
0 if then 0 if then 'ok' else 0 end else 'OK !' end
|
||||
0 if then 0 if then 'ok' else 0 end else 'OK' end
|
||||
-> stack size should be 1
|
||||
-> stack should be 'OK !'
|
||||
-> stack should be 'OK'
|
||||
drop
|
||||
|
||||
# start-next-step test 1
|
||||
|
|
Loading…
Reference in a new issue