Merge branch 'c_strings'

Conflicts:
	src/rpn.cpp
This commit is contained in:
louis 2015-03-01 23:33:20 +01:00
commit 14ea7d2b74
16 changed files with 779 additions and 320 deletions

259
README
View file

@ -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
View 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");
}

View file

@ -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)

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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)

View file

@ -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);

View file

@ -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

View file

@ -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();

View file

@ -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 = "";

View file

@ -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;
}

View file

@ -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",

View file

@ -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