#214: doxy comments

This commit is contained in:
Louis Rubet 2018-08-13 00:15:20 +02:00
parent 7e19b195f0
commit e5dd31560e
19 changed files with 995 additions and 304 deletions

View file

@ -15,7 +15,8 @@ static heap s_global_heap;
static stack s_global_stack; static stack s_global_stack;
static program* s_prog_to_interrupt = NULL; static program* s_prog_to_interrupt = NULL;
// actions to be done at rpn exit /// @brief actions to be done at rpn exit
///
void exit_interactive_rpn() { void exit_interactive_rpn() {
struct passwd* pw = getpwuid(getuid()); struct passwd* pw = getpwuid(getuid());
if (pw != NULL) { if (pw != NULL) {
@ -32,7 +33,8 @@ void exit_interactive_rpn() {
} }
} }
// actions to be done at rpn exit /// @brief actions to be done at rpn exit
///
void init_interactive_rpn() { void init_interactive_rpn() {
struct passwd* pw = getpwuid(getuid()); struct passwd* pw = getpwuid(getuid());
if (pw != NULL) { if (pw != NULL) {
@ -45,7 +47,12 @@ void init_interactive_rpn() {
} }
} }
// handle CtrlC signal /// @brief handle CtrlC signal (sigaction handler): exit rpn
///
/// @param sig signal, see POSIX sigaction
/// @param siginfo signal info, see POSIX sigaction
/// @param context see POSIX sigaction
///
static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) { static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) {
if (s_prog_to_interrupt != NULL) { if (s_prog_to_interrupt != NULL) {
s_prog_to_interrupt->stop(); s_prog_to_interrupt->stop();
@ -55,13 +62,22 @@ static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) {
exit_interactive_rpn(); exit_interactive_rpn();
} }
// handle SIGSEGV signal /// @brief handle SIGSEGV signal (sigaction handler): stop and exit rpn
///
/// @param sig signal, see POSIX sigaction
/// @param siginfo signal info, see POSIX sigaction
/// @param context see POSIX sigaction
///
static void segv_handler(int sig, siginfo_t* siginfo, void* context) { static void segv_handler(int sig, siginfo_t* siginfo, void* context) {
fprintf(stderr, "Internal error\n"); fprintf(stderr, "Internal error\n");
s_prog_to_interrupt->stop(); s_prog_to_interrupt->stop();
s_prog_to_interrupt = NULL; s_prog_to_interrupt = NULL;
} }
/// @brief setup signals handlers to stop with honours
///
/// @param prog the prog to catch the signals to, must be checked not NULL by user
///
static void catch_signals(program* prog) { static void catch_signals(program* prog) {
struct sigaction act; struct sigaction act;
@ -78,7 +94,12 @@ static void catch_signals(program* prog) {
(void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']", errno, strerror(errno)); (void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']", errno, strerror(errno));
} }
// /// @brief rpn entry point
///
/// @param argc command line args nb
/// @param argv command line args nb
/// @return int 0=ok
///
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
int ret = 0; int ret = 0;
bool go_on = true; bool go_on = true;

View file

@ -20,6 +20,14 @@ string number::s_mpfr_printf_format = string(MPFR_DEFAULT_FORMAT);
// //
const char* object::s_cmd_type_string[cmd_max] = CMD_TYPE_STRINGS; const char* object::s_cmd_type_string[cmd_max] = CMD_TYPE_STRINGS;
/// @brief return if a mpfr is higher to a given precision
/// this function is directly copied from mpfr
///
/// @param p the mpfr to test
/// @param prec the precision
/// @return true p is higher than 10^prec
/// @return false p is lower than 10^prec
///
static bool is_min(mpfr_t p, mpfr_prec_t prec) { static bool is_min(mpfr_t p, mpfr_prec_t prec) {
// see mpfr_vasprintf code // see mpfr_vasprintf code
bool ret; bool ret;
@ -64,6 +72,14 @@ static bool is_min(mpfr_t p, mpfr_prec_t prec) {
return ret; return ret;
} }
/// @brief print a mpfr in fixed format according to a base
/// this function is based copied on mpfr library
///
/// @param stream the stream to write to
/// @param real the real to print
/// @param base the base to print the real
/// @param write_after_sign substring to write between the sign and the real
///
static void print_fix(FILE* stream, mpfr_t real, int base, const char* write_after_sign = NULL) { static void print_fix(FILE* stream, mpfr_t real, int base, const char* write_after_sign = NULL) {
// see mpfr_vasprintf code // see mpfr_vasprintf code
mpfr_exp_t exp = mpfr_get_exp(real); mpfr_exp_t exp = mpfr_get_exp(real);
@ -142,6 +158,10 @@ static void print_fix(FILE* stream, mpfr_t real, int base, const char* write_aft
} }
} }
/// @brief show an object representation according to its type
///
/// @param stream the stream to write to
///
void object::show(FILE* stream) { void object::show(FILE* stream) {
int digits; int digits;
char* str; char* str;

View file

@ -24,8 +24,8 @@ class branch;
typedef void (program::*program_fn_t)(void); typedef void (program::*program_fn_t)(void);
typedef int (program::*branch_fn_t)(branch&); typedef int (program::*branch_fn_t)(branch&);
// MPFR object /// @brief MPFR (floating point) object
//// ///
struct floating_t { struct floating_t {
mpfr_prec_t mpfr_prec; // precision in bits mpfr_prec_t mpfr_prec; // precision in bits
unsigned int mpfr_prec_bytes; // significand storing length in bytes unsigned int mpfr_prec_bytes; // significand storing length in bytes
@ -67,8 +67,8 @@ struct floating_t {
static const char* s_mpfr_rnd_str[5]; static const char* s_mpfr_rnd_str[5];
}; };
// object - a generic stack object /// @brief object - a generic stack object
//// ///
struct object { struct object {
// object type // object type
cmd_type_t _type; cmd_type_t _type;
@ -83,8 +83,8 @@ struct object {
static const char* s_cmd_type_string[cmd_max]; static const char* s_cmd_type_string[cmd_max];
}; };
// stack objects derived from object /// @brief stack objects derived from object
//// ///
struct number : public object { struct number : public object {
// members // members
enum { dec, hex, bin, base } _representation; enum { dec, hex, bin, base } _representation;
@ -122,8 +122,8 @@ struct number : public object {
static string s_mpfr_printf_format; static string s_mpfr_printf_format;
}; };
// stack objects derived from object /// @brief stack objects derived from object
//// ///
struct complex : public object { struct complex : public object {
enum { dec, hex } _representation; enum { dec, hex } _representation;
// mind that re float value is at the end of the object // mind that re float value is at the end of the object
@ -153,6 +153,8 @@ struct complex : public object {
} }
}; };
/// @brief object string
///
struct ostring : public object { struct ostring : public object {
// ostring may first have been allocated with len+1 bytes // ostring may first have been allocated with len+1 bytes
void set(const char* value, unsigned int len) { void set(const char* value, unsigned int len) {
@ -172,6 +174,8 @@ struct ostring : public object {
char _value[0]; char _value[0];
}; };
/// @brief object program
///
struct oprogram : public object { struct oprogram : public object {
// oprogram may first have been allocated with len+1 bytes // oprogram may first have been allocated with len+1 bytes
void set(const char* value, unsigned int len) { void set(const char* value, unsigned int len) {
@ -191,6 +195,8 @@ struct oprogram : public object {
char _value[0]; char _value[0];
}; };
/// @brief object symbol
///
struct symbol : public object { struct symbol : public object {
// symbol may first have been allocated with len+1 bytes // symbol may first have been allocated with len+1 bytes
void set(const char* value, unsigned int len, bool auto_eval) { void set(const char* value, unsigned int len, bool auto_eval) {
@ -214,6 +220,8 @@ struct symbol : public object {
char _value[0]; char _value[0];
}; };
/// @brief object keyword
///
struct keyword : public object { struct keyword : public object {
// keyword may first have been allocated with len+1 bytes // keyword may first have been allocated with len+1 bytes
void set(program_fn_t fn, const char* value, unsigned int len) { void set(program_fn_t fn, const char* value, unsigned int len) {
@ -236,6 +244,8 @@ struct keyword : public object {
char _value[0]; char _value[0];
}; };
/// @brief object branch
///
struct branch : public object { struct branch : public object {
// //
void set(branch_fn_t fn, const char* value, unsigned int len) { void set(branch_fn_t fn, const char* value, unsigned int len) {

View file

@ -1,5 +1,11 @@
#include "program.hpp" #include "program.hpp"
/// @brief completion callback as asked by linenoise-ng
/// this is called by linenoise-ng whenever the user enters TAB
///
/// @param text the text after wich the user entered TAB
/// @param lc the completion object to add strings with linenoiseAddCompletion()
///
void program::entry_completion_generator(const char* text, linenoiseCompletions* lc) { void program::entry_completion_generator(const char* text, linenoiseCompletions* lc) {
int i = 0; int i = 0;
int text_len = strnlen(text, 6); int text_len = strnlen(text, 6);
@ -26,7 +32,11 @@ void program::entry_completion_generator(const char* text, linenoiseCompletions*
} }
} }
// interactive entry and decoding /// @brief interactive entry and decoding
///
/// @param prog the program to add entered objects
/// @return ret_value see this type
///
ret_value program::entry(program& prog) { ret_value program::entry(program& prog) {
string entry_str; string entry_str;
char* entry; char* entry;
@ -63,7 +73,7 @@ ret_value program::entry(program& prog) {
ret = parse(entry_str.c_str(), prog); ret = parse(entry_str.c_str(), prog);
// keep history // keep history
if (entry[0] != 0) linenoiseHistoryAdd(entry_str.c_str()); if (entry[0] != 0) (void)linenoiseHistoryAdd(entry_str.c_str());
} else } else
ret = ret_internal; ret = ret_internal;
} }
@ -74,6 +84,13 @@ ret_value program::entry(program& prog) {
return ret; return ret;
} }
/// @brief return function pointer from function name
///
/// @param fn_name function name
/// @param fn function pointer
/// @param type the function type (cmd_keyword or cmd_branch)
/// @return ret_value see this type
///
ret_value program::get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type) { ret_value program::get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type) {
unsigned int i = 0; unsigned int i = 0;
while (s_keywords[i].type != cmd_max) { while (s_keywords[i].type != cmd_max) {
@ -87,6 +104,14 @@ ret_value program::get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& typ
return ret_unknown_err; return ret_unknown_err;
} }
/// @brief get a keyword object from entry and add it to a program
///
/// @param entry the entry
/// @param prog the program
/// @param remaining_entry the remaining entry after the object was added
/// @return true an object was added
/// @return false no object was added
///
static bool get_keyword(const string& entry, program& prog, string& remaining_entry) { static bool get_keyword(const string& entry, program& prog, string& remaining_entry) {
program_fn_t fn; program_fn_t fn;
unsigned int obj_len; unsigned int obj_len;
@ -113,6 +138,330 @@ static bool get_keyword(const string& entry, program& prog, string& remaining_en
return ret; return ret;
} }
/// @brief get a symbol object from entry and add it to a program
///
/// @param entry the entry
/// @param prog the program
/// @param remaining_entry the remaining entry after the object was added
/// @return true an object was added
/// @return false no object was added
///
static bool get_symbol(const string& entry, program& prog, string& remaining_entry) {
bool ret = false;
int entry_len = entry.size();
unsigned int obj_len;
if (entry_len >= 1 && entry[0] == '\'') {
if (entry_len == 1) {
// void symbol entry, like '
// total object length
obj_len = sizeof(symbol) + 1;
// allocate and set object
// symbol beginning with ' is not autoevaluated
symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol);
new_obj->set("", 0, false);
} else {
// symbol entry, like 'toto' or 'toto
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 and set object
// symbol beginning with ' is not autoevaluated
symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol);
new_obj->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len, false);
}
ret = true;
}
return ret;
}
/// @brief get an object other from known ones from entry and add it to a program
///
/// @param entry the entry
/// @param prog the program
/// @param remaining_entry the remaining entry after the object was added
/// @return true an object was added
/// @return false no object was added
///
static bool get_other(const string& entry, program& prog, string& remaining_entry) {
bool ret = false;
int entry_len = entry.size();
unsigned int obj_len;
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 and set object
// symbol not beginning with ' is autoevaluated (ie is evaluated when pushed
// on stack)
symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol);
new_obj->set(entry.c_str(), naked_entry_len, true);
ret = true;
}
return ret;
}
/// @brief get a string object from entry and add it to a program
///
/// @param entry the entry
/// @param prog the program
/// @param remaining_entry the remaining entry after the object was added
/// @return true an object was added
/// @return false no object was added
///
static bool get_string(const string& entry, program& prog, string& remaining_entry) {
bool ret = false;
unsigned int obj_len;
int entry_len = entry.size();
if (entry_len >= 1 && entry[0] == '"') {
if (entry_len == 1) {
// total object length
obj_len = sizeof(ostring) + 1;
// allocate and set object
ostring* new_obj = (ostring*)prog.allocate_back(obj_len, cmd_string);
new_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 and set object
ostring* new_obj = (ostring*)prog.allocate_back(obj_len, cmd_string);
new_obj->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len);
}
ret = true;
}
return ret;
}
/// @brief get a program object from entry and add it to a program
///
/// @param entry the entry
/// @param prog the program
/// @param remaining_entry the remaining entry after the object was added
/// @return true an object was added
/// @return false no object was added
///
static bool get_program(string& entry, program& prog, string& remaining_entry) {
bool ret = false;
unsigned int obj_len;
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 and set object
oprogram* new_obj = (oprogram*)prog.allocate_back(obj_len, cmd_program);
new_obj->set(&entry[2], naked_entry_len);
ret = true;
}
return ret;
}
/// @brief get a number object from entry and add it to a program
///
/// @param entry the entry
/// @param prog the program
/// @param remaining_entry the remaining entry after the object was added
/// @return true an object was added
/// @return false no object was added
///
static bool get_number(string& entry, program& prog, string& remaining_entry) {
char* endptr;
bool ret = false;
if (entry.size() > 0) {
// pre parse to avoid doing a useless allocation
// detect the begining of a number including nan, inf, @nan@, @inf@
if (entry.find_first_of("+-0123456789.ni@", 0) == 0) {
// detect an arbitrary base entry like 3bXXX or 27bYYY
int base = 0;
size_t base_detect = entry.find_first_of("b", 0);
if (base_detect == 1 || base_detect == 2)
if (sscanf(entry.c_str(), "%db", &base) == 1 && base >= 2 && base <= 62)
entry = entry.substr(base_detect + 1);
else
base = 0;
number* num = (number*)prog.allocate_back(number::calc_size(), cmd_number);
int mpfr_ret = mpfr_strtofr(num->_value.mpfr, entry.c_str(), &endptr, base, MPFR_DEFAULT_RND);
if (endptr != NULL && endptr != entry.c_str()) {
// determine representation
if (base != 0) {
num->_representation = number::base;
num->_base = base;
} else {
string beg = entry.substr(0, 2);
if (beg == "0x" || beg == "0X")
num->_representation = number::hex;
else if (beg == "0b" || beg == "0B")
num->_representation = number::bin;
else
num->_representation = number::dec;
}
ret = true;
// remaining string if any
remaining_entry = endptr;
} else
(void)prog.pop_back();
}
}
return ret;
}
/// @brief get a complex object from entry and add it to a program
///
/// @param entry the entry
/// @param prog the program
/// @param remaining_entry the remaining entry after the object was added
/// @return true an object was added
/// @return false no object was added
///
static bool get_complex(const string& entry, program& prog, string& remaining_entry) {
char* endptr;
bool ret = false;
if (entry.size() > 0) {
size_t comma = entry.find(',');
if (comma != string::npos) {
complex* cplx;
// pre parse RE to avoid doing a useless allocation
// detect the begining of a number, including nan, inf, @nan@, @inf@
string re_str = entry.substr(1, comma - 1).c_str();
if (re_str.find_first_of(" +-0123456789.ni@", 0) == 0) {
cplx = (complex*)prog.allocate_back(complex::calc_size(), cmd_complex);
int mpfr_ret = mpfr_strtofr(cplx->re()->mpfr, re_str.c_str(), &endptr, 0, MPFR_DEFAULT_RND);
if (endptr != NULL && endptr != re_str.c_str()) {
// determine representation
string beg = re_str.substr(0, 2);
if (beg == "0x" || beg == "0X")
cplx->_representation = complex::hex;
else
cplx->_representation = complex::dec;
ret = true;
} else
(void)prog.pop_back();
}
// pre parse IM to avoid doing a useless allocation
// detect the begining of a number, including nan, inf, @nan@, @inf@
string im_str = entry.substr(comma + 1).c_str();
if (ret == true && im_str.find_first_of(" +-0123456789.ni@", 0) == 0) {
ret = false;
int mpfr_ret = mpfr_strtofr(cplx->im()->mpfr, im_str.c_str(), &endptr, 0, MPFR_DEFAULT_RND);
if (endptr != NULL && endptr != im_str.c_str()) {
// determine representation
string beg = im_str.substr(0, 2);
if (beg == "0x" || beg == "0X")
cplx->_representation = complex::hex;
else
cplx->_representation = complex::dec;
ret = true;
} else
(void)prog.pop_back();
}
}
}
return ret;
}
/// @brief recognize a comment object from entry
///
/// @param entry the entry
/// @param remaining_entry the remaining entry after the comment was found
/// @return true a comment was found
/// @return false no comment was found
///
static bool get_comment(string& entry, string& remaining_entry) {
bool ret = false;
unsigned int obj_len;
int entry_len = entry.size();
if (entry_len >= 1 && entry[0] == '#') {
// entry (complete line) is ignored
ret = true;
}
return ret;
}
/// @brief get an object from an entry string and add it to a program
///
/// @param entry the entry string
/// @param prog the program
/// @param remaining_entry the remaining entry after the object was added
/// @return true an object was added to the prog
/// @return false no object was added to the prog
///
static bool _obj_from_string(string& entry, program& prog, string& remaining_entry) {
bool ret = false;
remaining_entry.erase();
if (get_number(entry, prog, remaining_entry))
ret = true;
else if (get_symbol(entry, prog, remaining_entry))
ret = true;
else if (get_string(entry, prog, remaining_entry))
ret = true;
else if (get_program(entry, prog, remaining_entry))
ret = true;
else if (get_keyword(entry, prog, remaining_entry))
ret = true;
else if (get_complex(entry, prog, remaining_entry))
ret = true;
else if (get_comment(entry, remaining_entry))
ret = true;
else
// nothing, considered as an auto-evaluated symbol
if (get_other(entry, prog, remaining_entry))
ret = true;
return ret;
}
/// @brief cut an entry string into entry chunks with respect of types separators
///
/// @param entry the entry
/// @param entries the cut entriy vector
/// @return true entries not vempty
/// @return false entries empty
///
static bool _cut(const char* entry, vector<string>& entries) { static bool _cut(const char* entry, vector<string>& entries) {
string tmp; string tmp;
int len = strlen(entry); int len = strlen(entry);
@ -245,260 +594,12 @@ static bool _cut(const char* entry, vector<string>& entries) {
return entries.size() > 0; return entries.size() > 0;
} }
static bool get_symbol(const string& entry, program& prog, string& remaining_entry) { /// @brief parse an entry string: cut it into objects chunks and add them to a program
bool ret = false; ///
int entry_len = entry.size(); /// @param entry the entry string
unsigned int obj_len; /// @param prog the program
/// @return ret_value see this type
if (entry_len >= 1 && entry[0] == '\'') { ///
if (entry_len == 1) {
// void symbol entry, like '
// total object length
obj_len = sizeof(symbol) + 1;
// allocate and set object
// symbol beginning with ' is not autoevaluated
symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol);
new_obj->set("", 0, false);
} else {
// symbol entry, like 'toto' or 'toto
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 and set object
// symbol beginning with ' is not autoevaluated
symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol);
new_obj->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len, false);
}
ret = true;
}
return ret;
}
static bool get_other(const string& entry, program& prog, string& remaining_entry) {
bool ret = false;
int entry_len = entry.size();
unsigned int obj_len;
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 and set object
// symbol not beginning with ' is autoevaluated (ie is evaluated when pushed
// on stack)
symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol);
new_obj->set(entry.c_str(), naked_entry_len, true);
ret = true;
}
return ret;
}
static bool get_string(const string& entry, program& prog, string& remaining_entry) {
bool ret = false;
unsigned int obj_len;
int entry_len = entry.size();
if (entry_len >= 1 && entry[0] == '"') {
if (entry_len == 1) {
// total object length
obj_len = sizeof(ostring) + 1;
// allocate and set object
ostring* new_obj = (ostring*)prog.allocate_back(obj_len, cmd_string);
new_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 and set object
ostring* new_obj = (ostring*)prog.allocate_back(obj_len, cmd_string);
new_obj->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len);
}
ret = true;
}
return ret;
}
static bool get_program(string& entry, program& prog, string& remaining_entry) {
bool ret = false;
unsigned int obj_len;
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 and set object
oprogram* new_obj = (oprogram*)prog.allocate_back(obj_len, cmd_program);
new_obj->set(&entry[2], naked_entry_len);
ret = true;
}
return ret;
}
static bool get_number(string& entry, program& prog, string& remaining_entry) {
char* endptr;
bool ret = false;
if (entry.size() > 0) {
// pre parse to avoid doing a useless allocation
// detect the begining of a number including nan, inf, @nan@, @inf@
if (entry.find_first_of("+-0123456789.ni@", 0) == 0) {
// detect an arbitrary base entry like 3bXXX or 27bYYY
int base = 0;
size_t base_detect = entry.find_first_of("b", 0);
if (base_detect == 1 || base_detect == 2)
if (sscanf(entry.c_str(), "%db", &base) == 1 && base >= 2 && base <= 62)
entry = entry.substr(base_detect + 1);
else
base = 0;
number* num = (number*)prog.allocate_back(number::calc_size(), cmd_number);
int mpfr_ret = mpfr_strtofr(num->_value.mpfr, entry.c_str(), &endptr, base, MPFR_DEFAULT_RND);
if (endptr != NULL && endptr != entry.c_str()) {
// determine representation
if (base != 0) {
num->_representation = number::base;
num->_base = base;
} else {
string beg = entry.substr(0, 2);
if (beg == "0x" || beg == "0X")
num->_representation = number::hex;
else if (beg == "0b" || beg == "0B")
num->_representation = number::bin;
else
num->_representation = number::dec;
}
ret = true;
// remaining string if any
remaining_entry = endptr;
} else
(void)prog.pop_back();
}
}
return ret;
}
static bool get_complex(const string& entry, program& prog, string& remaining_entry) {
char* endptr;
bool ret = false;
if (entry.size() > 0) {
size_t comma = entry.find(',');
if (comma != string::npos) {
complex* cplx;
// pre parse RE to avoid doing a useless allocation
// detect the begining of a number, including nan, inf, @nan@, @inf@
string re_str = entry.substr(1, comma - 1).c_str();
if (re_str.find_first_of(" +-0123456789.ni@", 0) == 0) {
cplx = (complex*)prog.allocate_back(complex::calc_size(), cmd_complex);
int mpfr_ret = mpfr_strtofr(cplx->re()->mpfr, re_str.c_str(), &endptr, 0, MPFR_DEFAULT_RND);
if (endptr != NULL && endptr != re_str.c_str()) {
// determine representation
string beg = re_str.substr(0, 2);
if (beg == "0x" || beg == "0X")
cplx->_representation = complex::hex;
else
cplx->_representation = complex::dec;
ret = true;
} else
(void)prog.pop_back();
}
// pre parse IM to avoid doing a useless allocation
// detect the begining of a number, including nan, inf, @nan@, @inf@
string im_str = entry.substr(comma + 1).c_str();
if (ret == true && im_str.find_first_of(" +-0123456789.ni@", 0) == 0) {
ret = false;
int mpfr_ret = mpfr_strtofr(cplx->im()->mpfr, im_str.c_str(), &endptr, 0, MPFR_DEFAULT_RND);
if (endptr != NULL && endptr != im_str.c_str()) {
// determine representation
string beg = im_str.substr(0, 2);
if (beg == "0x" || beg == "0X")
cplx->_representation = complex::hex;
else
cplx->_representation = complex::dec;
ret = true;
} else
(void)prog.pop_back();
}
}
}
return ret;
}
static bool get_comment(string& entry, program& prog, string& remaining_entry) {
bool ret = false;
unsigned int obj_len;
int entry_len = entry.size();
if (entry_len >= 1 && entry[0] == '#') {
// entry (complete line) is ignored
ret = true;
}
return ret;
}
static bool _obj_from_string(string& entry, program& prog, string& remaining_entry) {
bool ret = false;
remaining_entry.erase();
if (get_number(entry, prog, remaining_entry))
ret = true;
else if (get_symbol(entry, prog, remaining_entry))
ret = true;
else if (get_string(entry, prog, remaining_entry))
ret = true;
else if (get_program(entry, prog, remaining_entry))
ret = true;
else if (get_keyword(entry, prog, remaining_entry))
ret = true;
else if (get_complex(entry, prog, remaining_entry))
ret = true;
else if (get_comment(entry, prog, remaining_entry))
ret = true;
else
// nothing, considered as an auto-evaluated symbol
if (get_other(entry, prog, remaining_entry))
ret = true;
return ret;
}
ret_value program::parse(const char* entry, program& prog) { ret_value program::parse(const char* entry, program& prog) {
vector<string> entries; vector<string> entries;
ret_value ret = ret_ok; ret_value ret = ret_ok;

View file

@ -1,9 +1,9 @@
#include "program.hpp" #include "program.hpp"
// //< return type strings
const char* program::s_ret_value_string[ret_max] = RET_VALUE_STRINGS; const char* program::s_ret_value_string[ret_max] = RET_VALUE_STRINGS;
// //< kanguage reserved keywords (allowed types are cmd_keyword, cmd_branch or cmd_undef)
program::keyword_t program::s_keywords[] = { program::keyword_t program::s_keywords[] = {
// GENERAL // GENERAL
{cmd_undef, "", NULL, "\nGENERAL"}, {cmd_undef, "", NULL, "\nGENERAL"},
@ -206,6 +206,12 @@ program::keyword_t program::s_keywords[] = {
{cmd_max, "", NULL, ""}, {cmd_max, "", NULL, ""},
}; };
/// @brief run a program on a stack and a heap
///
/// @param stk the stack, storing prog result
/// @param hp the heap, storing variables
/// @return ret_value see this type
///
ret_value program::run(stack& stk, heap& hp) { ret_value program::run(stack& stk, heap& hp) {
bool go_out = false; bool go_out = false;
ret_value ret = ret_ok; ret_value ret = ret_ok;
@ -298,15 +304,19 @@ ret_value program::run(stack& stk, heap& hp) {
return ret; return ret;
} }
/// @brief stop a program
///
///
void program::stop() { interrupt_now = true; } void program::stop() { interrupt_now = true; }
bool program::compare_keyword(keyword* k, const char* str_to_compare, int len) { /// @brief return whether a branch object has a given name
if (k->_len >= len) ///
return strncmp(k->_value, str_to_compare, len) == 0; /// @param b the branch object
else /// @param str_to_compare the name
return false; /// @param len the name length
} /// @return true the branch name is str_to_compare
/// @return false the branch name is NOT str_to_compare
///
bool program::compare_branch(branch* b, const char* str_to_compare, int len) { bool program::compare_branch(branch* b, const char* str_to_compare, int len) {
if (b->_len >= len) if (b->_len >= len)
return strncasecmp(b->_value, str_to_compare, len) == 0; return strncasecmp(b->_value, str_to_compare, len) == 0;
@ -314,6 +324,13 @@ bool program::compare_branch(branch* b, const char* str_to_compare, int len) {
return false; return false;
} }
/// @brief prepare a program for execution
/// this is needed before a program can be run
/// inner members of branch or keyword objects are filled by this function
/// these inner members store for example the index of the next keyword to execute etc.
///
/// @return ret_value see this type
///
ret_value program::preprocess(void) { ret_value program::preprocess(void) {
// for if-then-else-end // for if-then-else-end
vector<struct if_layout_t> vlayout; vector<struct if_layout_t> vlayout;
@ -540,6 +557,10 @@ ret_value program::preprocess(void) {
return ret_ok; return ret_ok;
} }
/// @brief show the last error set
///
/// @return ret_value see this type
///
ret_value program::show_error() { ret_value program::show_error() {
ret_value ret; ret_value ret;
@ -556,6 +577,12 @@ ret_value program::show_error() {
return ret; return ret;
} }
/// @brief record an error as the last error set and show it
///
/// @param err the error to record
/// @param context a context string
/// @return ret_value see this type
///
ret_value program::show_error(ret_value err, string& context) { ret_value program::show_error(ret_value err, string& context) {
// record error // record error
_err = err; _err = err;
@ -563,6 +590,12 @@ ret_value program::show_error(ret_value err, string& context) {
return show_error(); return show_error();
} }
/// @brief record an error as the last error set and show it
///
/// @param err the error to record
/// @param context a context string
/// @return ret_value see this type
///
ret_value program::show_error(ret_value err, const char* context) { ret_value program::show_error(ret_value err, const char* context) {
// record error // record error
_err = err; _err = err;
@ -570,6 +603,12 @@ ret_value program::show_error(ret_value err, const char* context) {
return show_error(); return show_error();
} }
/// @brief set the last error as being a syntax error and show it
///
/// @param err the error to record
/// @param context a context string
/// @return ret_value see this type
///
void program::show_syntax_error(const char* context) { void program::show_syntax_error(const char* context) {
// record error // record error
_err = ret_syntax; _err = ret_syntax;
@ -577,8 +616,18 @@ void program::show_syntax_error(const char* context) {
(void)show_error(); (void)show_error();
} }
/// @brief return the last error set
///
/// @return ret_value see this type
///
ret_value program::get_err(void) { return _err; } ret_value program::get_err(void) { return _err; }
/// @brief show a stack (show its different objects)
/// generally a stack is associated to a running program
///
/// @param st the stack to show
/// @param show_separator whether to show a stack level prefix or not
///
void program::show_stack(stack& st, bool show_separator) { void program::show_stack(stack& st, bool show_separator) {
if (st.size() == 1) { if (st.size() == 1) {
((object*)st.back())->show(); ((object*)st.back())->show();
@ -592,6 +641,8 @@ void program::show_stack(stack& st, bool show_separator) {
} }
} }
/// @brief apply default precision mode and digits
///
void program::apply_default() { void program::apply_default() {
// default float precision, float mode // default float precision, float mode
number::s_mode = DEFAULT_MODE; number::s_mode = DEFAULT_MODE;

View file

@ -27,7 +27,7 @@ using namespace std;
#include "stack.hpp" #include "stack.hpp"
#include "version.h" #include "version.h"
// //< convinient structure to preprocess a program
struct if_layout_t { struct if_layout_t {
if_layout_t() if_layout_t()
: index_then_or_unti_or_repeat(-1), index_else(-1), index_end(-1), is_do_unti(false), is_while_repeat(false) {} : index_then_or_unti_or_repeat(-1), index_else(-1), index_end(-1), is_do_unti(false), is_while_repeat(false) {}
@ -39,7 +39,7 @@ struct if_layout_t {
bool is_while_repeat; bool is_while_repeat;
}; };
// program //< program class: the class containing a string parser, all the programs keywords, a stack for running the program
class program : public stack { class program : public stack {
public: public:
program(program* parent_prog = NULL) { program(program* parent_prog = NULL) {

View file

@ -1,6 +1,11 @@
#include "program.hpp" #include "program.hpp"
// /// @brief if keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_if(branch& myobj) { int program::rpn_if(branch& myobj) {
// myobj.arg1 = 'if' condition evaluation value // myobj.arg1 = 'if' condition evaluation value
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
@ -14,6 +19,11 @@ int program::rpn_if(branch& myobj) {
return -1; return -1;
} }
/// @brief then keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
///
int program::rpn_then(branch& myobj) { int program::rpn_then(branch& myobj) {
// myobj.arg1 = index of then + 1 // myobj.arg1 = index of then + 1
// myobj.arg2 = index of else + 1 or end + 1 // myobj.arg2 = index of else + 1 or end + 1
@ -27,6 +37,12 @@ int program::rpn_then(branch& myobj) {
return myobj.arg2; return myobj.arg2;
} }
/// @brief else keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_else(branch& myobj) { int program::rpn_else(branch& myobj) {
// myobj.arg1 = index of else + 1 // myobj.arg1 = index of else + 1
// myobj.arg2 = index of end + 1 // myobj.arg2 = index of end + 1
@ -40,6 +56,12 @@ int program::rpn_else(branch& myobj) {
return myobj.arg1; return myobj.arg1;
} }
/// @brief end keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_end(branch& myobj) { int program::rpn_end(branch& myobj) {
int ret = -1; int ret = -1;
@ -60,17 +82,34 @@ int program::rpn_end(branch& myobj) {
return ret; return ret;
} }
/// @brief do keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_do(branch& myobj) { int program::rpn_do(branch& myobj) {
// nothing // nothing
return -1; return -1;
} }
/// @brief until keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_until(branch& myobj) { int program::rpn_until(branch& myobj) {
// nothing // nothing
return -1; return -1;
} }
// /// @brief ift keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
void program::rpn_ift(void) { void program::rpn_ift(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(1, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number);
@ -89,6 +128,12 @@ void program::rpn_ift(void) {
(void)_stack->pop_back(2); (void)_stack->pop_back(2);
} }
/// @brief ifte keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
void program::rpn_ifte(void) { void program::rpn_ifte(void) {
MIN_ARGUMENTS(3); MIN_ARGUMENTS(3);
ARG_MUST_BE_OF_TYPE(2, cmd_number); ARG_MUST_BE_OF_TYPE(2, cmd_number);
@ -108,12 +153,23 @@ void program::rpn_ifte(void) {
(void)_calc_stack.pop_back(); (void)_calc_stack.pop_back();
} }
// /// @brief while keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_while(branch& myobj) { int program::rpn_while(branch& myobj) {
// nothing // nothing
return -1; return -1;
} }
/// @brief repeat keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_repeat(branch& myobj) { int program::rpn_repeat(branch& myobj) {
int ret = -1; int ret = -1;
@ -128,6 +184,12 @@ int program::rpn_repeat(branch& myobj) {
return ret; return ret;
} }
/// @brief start keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_start(branch& myobj) { int program::rpn_start(branch& myobj) {
int ret = -1; int ret = -1;
@ -155,6 +217,12 @@ int program::rpn_start(branch& myobj) {
return ret; return ret;
} }
/// @brief for keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_for(branch& myobj) { int program::rpn_for(branch& myobj) {
int ret; int ret;
@ -190,6 +258,12 @@ int program::rpn_for(branch& myobj) {
return ret; return ret;
} }
/// @brief next keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_next(branch& myobj) { int program::rpn_next(branch& myobj) {
// arg1 = index of start or for command in program // arg1 = index of start or for command in program
// farg1 = current count // farg1 = current count
@ -228,6 +302,12 @@ int program::rpn_next(branch& myobj) {
} }
} }
/// @brief step keyword (branch) implementation
///
/// @param myobj the current branch object
/// @return int index of the next object to run in the current program
/// @return -1 the next object index to run in the current program is the current+1
///
int program::rpn_step(branch& myobj) { int program::rpn_step(branch& myobj) {
int ret; int ret;
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);

View file

@ -1,5 +1,8 @@
#include "program.hpp" #include "program.hpp"
/// @brief re keyword implementation
/// the result is stacked on current program stack
///
void program::rpn_re() { void program::rpn_re() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
@ -12,6 +15,9 @@ void program::rpn_re() {
_calc_stack.pop_back(); _calc_stack.pop_back();
} }
/// @brief im keyword implementation
/// the result is stacked on current program stack
///
void program::rpn_im() { void program::rpn_im() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
@ -24,6 +30,9 @@ void program::rpn_im() {
_calc_stack.pop_back(); _calc_stack.pop_back();
} }
/// @brief arg keyword implementation
/// the result is stacked on current program stack
///
void program::rpn_arg() { void program::rpn_arg() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
@ -38,6 +47,9 @@ void program::rpn_arg() {
_calc_stack.pop_back(); _calc_stack.pop_back();
} }
/// @brief conj keyword implementation
/// the result is stacked on current program stack
///
void program::rpn_conj() { void program::rpn_conj() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
@ -46,6 +58,9 @@ void program::rpn_conj() {
CHECK_MPFR(mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd));
} }
/// @brief r2c keyword implementation
/// the result is stacked on current program stack
///
void program::rpn_r2c() { void program::rpn_r2c() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -62,6 +77,9 @@ void program::rpn_r2c() {
_calc_stack.pop_back(2); _calc_stack.pop_back(2);
} }
/// @brief c2r keyword implementation
/// the result is stacked on current program stack
///
void program::rpn_c2r() { void program::rpn_c2r() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
@ -77,6 +95,9 @@ void program::rpn_c2r() {
_calc_stack.pop_back(); _calc_stack.pop_back();
} }
/// @brief r2p keyword implementation
/// the result is stacked on current program stack
///
void program::rpn_r2p() { void program::rpn_r2p() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
@ -96,6 +117,9 @@ void program::rpn_r2p() {
_stack->pop_back(); _stack->pop_back();
} }
/// @brief p2r keyword implementation
/// the result is stacked on current program stack
///
void program::rpn_p2r() { void program::rpn_p2r() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex); ARG_MUST_BE_OF_TYPE(0, cmd_complex);

View file

@ -1,12 +1,18 @@
#include "program.hpp" #include "program.hpp"
// /// @brief nop keyword implementation
///
void program::rpn_nop() { void program::rpn_nop() {
// nop // nop
} }
/// @brief quit keyword implementation
///
void program::rpn_good_bye() { ERR_CONTEXT(ret_good_bye); } void program::rpn_good_bye() { ERR_CONTEXT(ret_good_bye); }
/// @brief nop keyword implementation
/// the result is written on stdout
///
void program::rpn_help() { void program::rpn_help() {
// software name // software name
printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname); printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname);
@ -55,10 +61,22 @@ void program::rpn_help() {
printf("\n\n"); printf("\n\n");
} }
/// @brief calculate a number of digits for a given base from a precision in bits
///
/// @param base the base
/// @param bit_precision the precision in bits
/// @return int the number of digits
///
static int base_digits_from_bit_precision(int base, int bit_precision) { static int base_digits_from_bit_precision(int base, int bit_precision) {
return (int)ceil(bit_precision * log(2.0) / log((double)base)) - 1; return (int)ceil(bit_precision * log(2.0) / log((double)base)) - 1;
} }
/// @brief print a decimal digit in a given MPFR format
///
/// @param decimal_digits the number
/// @param printf_format the format
/// @return string the result string
///
static string make_digit_format(int decimal_digits, const char* printf_format) { static string make_digit_format(int decimal_digits, const char* printf_format) {
stringstream ss; stringstream ss;
ss << MPFR_FORMAT_BEG; ss << MPFR_FORMAT_BEG;
@ -67,6 +85,12 @@ static string make_digit_format(int decimal_digits, const char* printf_format) {
return ss.str(); return ss.str();
} }
/// @brief whether a precision is in the precision min/max
///
/// @param precision the precision in bits
/// @return true the precision is good
/// @return false the precision is not good
///
static bool check_decimal_digits(double precision) { static bool check_decimal_digits(double precision) {
bool ret = true; bool ret = true;
@ -80,6 +104,8 @@ static bool check_decimal_digits(double precision) {
return ret; return ret;
} }
/// @brief std keyword implementation
///
void program::rpn_std() { void program::rpn_std() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -95,6 +121,8 @@ void program::rpn_std() {
ERR_CONTEXT(ret_out_of_range); ERR_CONTEXT(ret_out_of_range);
} }
/// @brief fix keyword implementation
///
void program::rpn_fix() { void program::rpn_fix() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -110,6 +138,8 @@ void program::rpn_fix() {
ERR_CONTEXT(ret_out_of_range); ERR_CONTEXT(ret_out_of_range);
} }
/// @brief sci keyword implementation
///
void program::rpn_sci() { void program::rpn_sci() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -125,6 +155,8 @@ void program::rpn_sci() {
ERR_CONTEXT(ret_out_of_range); ERR_CONTEXT(ret_out_of_range);
} }
/// @brief version keyword implementation
///
void program::rpn_version() { void program::rpn_version() {
// allocate and set object // allocate and set object
unsigned int naked_entry_len = strlen(version); unsigned int naked_entry_len = strlen(version);
@ -132,6 +164,8 @@ void program::rpn_version() {
str->set(version, naked_entry_len); str->set(version, naked_entry_len);
} }
/// @brief uname keyword implementation
///
void program::rpn_uname() { void program::rpn_uname() {
// allocate and set object // allocate and set object
unsigned int naked_entry_len = strlen(uname); unsigned int naked_entry_len = strlen(uname);
@ -139,6 +173,8 @@ void program::rpn_uname() {
str->set(uname, naked_entry_len); str->set(uname, naked_entry_len);
} }
/// @brief history keyword implementation
///
void program::rpn_history() { void program::rpn_history() {
// see command history on stdout // see command history on stdout
int index = 0; int index = 0;
@ -150,6 +186,8 @@ void program::rpn_history() {
} }
} }
/// @brief type keyword implementation
///
void program::rpn_type() { void program::rpn_type() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -162,8 +200,12 @@ void program::rpn_type() {
typ->set(object::s_cmd_type_string[type], string_size); typ->set(object::s_cmd_type_string[type], string_size);
} }
/// @brief default keyword implementation
///
void program::rpn_default() { program::apply_default(); } void program::rpn_default() { program::apply_default(); }
/// @brief prec keyword implementation
///
void program::rpn_precision() { void program::rpn_precision() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -184,6 +226,8 @@ void program::rpn_precision() {
ERR_CONTEXT(ret_out_of_range); ERR_CONTEXT(ret_out_of_range);
} }
/// @brief round keyword implementation
///
void program::rpn_round() { void program::rpn_round() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string); ARG_MUST_BE_OF_TYPE(0, cmd_string);

View file

@ -1,11 +1,15 @@
#include "program.hpp" #include "program.hpp"
/// @brief e keyword implementation
///
void program::rpn_e(void) { void program::rpn_e(void) {
number* euler = (number*)_stack->allocate_back(number::calc_size(), cmd_number); number* euler = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
euler->_value = 1L; euler->_value = 1L;
CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd));
} }
/// @brief log10 keyword implementation
///
void program::rpn_log10() { void program::rpn_log10() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -21,6 +25,8 @@ void program::rpn_log10() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief alog10 keyword implementation
///
void program::rpn_alog10() { void program::rpn_alog10() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -34,6 +40,8 @@ void program::rpn_alog10() {
} }
} }
/// @brief log2 keyword implementation
///
void program::rpn_log2() { void program::rpn_log2() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -49,6 +57,8 @@ void program::rpn_log2() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief alog2 keyword implementation
///
void program::rpn_alog2() { void program::rpn_alog2() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -62,6 +72,8 @@ void program::rpn_alog2() {
} }
} }
/// @brief ln keyword implementation
///
void program::rpn_ln() { void program::rpn_ln() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -106,6 +118,8 @@ void program::rpn_ln() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief exp keyword implementation
///
void program::rpn_exp() { void program::rpn_exp() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -133,6 +147,8 @@ void program::rpn_exp() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief expm keyword implementation
///
void program::rpn_expm() { void program::rpn_expm() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -147,6 +163,8 @@ void program::rpn_expm() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief lnp1 keyword implementation
///
void program::rpn_lnp1() { void program::rpn_lnp1() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -161,6 +179,8 @@ void program::rpn_lnp1() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief sinh keyword implementation
///
void program::rpn_sinh() { void program::rpn_sinh() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -191,6 +211,8 @@ void program::rpn_sinh() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief asinh keyword implementation
///
void program::rpn_asinh() { void program::rpn_asinh() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -211,6 +233,8 @@ void program::rpn_asinh() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief cosh keyword implementation
///
void program::rpn_cosh() { void program::rpn_cosh() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -241,6 +265,8 @@ void program::rpn_cosh() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief acosh keyword implementation
///
void program::rpn_acosh() { void program::rpn_acosh() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -265,6 +291,8 @@ void program::rpn_acosh() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief tanh keyword implementation
///
void program::rpn_tanh() { void program::rpn_tanh() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -293,6 +321,8 @@ void program::rpn_tanh() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief atanh keyword implementation
///
void program::rpn_atanh() { void program::rpn_atanh() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);

View file

@ -1,11 +1,17 @@
#include "program.hpp" #include "program.hpp"
// /// @brief find variable by its name in local heap, parens heaps, global heap
///
/// @param variable the variable name to find
/// @param obj the variable object found
/// @param size its size
/// @return true variable was found
/// @return false variable was not found
///
bool program::find_variable(string& variable, object*& obj, unsigned int& size) { bool program::find_variable(string& variable, object*& obj, unsigned int& size) {
bool found = false; bool found = false;
program* parent = _parent_prog; program* parent = _parent_prog;
// find variable in local heap, parens heaps, global heap
if (_local_heap.get(variable, obj, size)) if (_local_heap.get(variable, obj, size))
found = true; found = true;
else { else {
@ -24,6 +30,8 @@ bool program::find_variable(string& variable, object*& obj, unsigned int& size)
return found; return found;
} }
/// @brief eval keyword implementation
///
void program::rpn_eval(void) { void program::rpn_eval(void) {
bool run_prog = false; bool run_prog = false;
string prog_text; string prog_text;
@ -67,7 +75,8 @@ void program::rpn_eval(void) {
} }
} }
// carefull, this not a command but a branch /// @brief -> keyword (branch) implementation
///
int program::rpn_inprog(branch& myobj) { int program::rpn_inprog(branch& myobj) {
string context("->"); // for showing errors string context("->"); // for showing errors
int count_symbols = 0; int count_symbols = 0;

View file

@ -1,5 +1,7 @@
#include "program.hpp" #include "program.hpp"
/// @brief + keyword implementation
///
void program::rpn_plus() { void program::rpn_plus() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -51,6 +53,8 @@ void program::rpn_plus() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief - keyword implementation
///
void program::rpn_minus() { void program::rpn_minus() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -83,6 +87,8 @@ void program::rpn_minus() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief * keyword implementation
///
void program::rpn_mul() { void program::rpn_mul() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -133,6 +139,9 @@ void program::rpn_mul() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief divide the 2 complexes on stack
/// result on the prog stack
///
void program::do_divide_complexes() { void program::do_divide_complexes() {
//(a+ib)/(x+iy)=(a+ib)(x-iy)/(x^2+y^2)=(ax+by+i(bx-ay))/(x^2+y^2) //(a+ib)/(x+iy)=(a+ib)(x-iy)/(x^2+y^2)=(ax+by+i(bx-ay))/(x^2+y^2)
complex* right = (complex*)_stack->get_obj(0); // x+iy complex* right = (complex*)_stack->get_obj(0); // x+iy
@ -177,6 +186,8 @@ void program::do_divide_complexes() {
_calc_stack.pop_back(4); _calc_stack.pop_back(4);
} }
/// @brief / keyword implementation
///
void program::rpn_div() { void program::rpn_div() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -224,6 +235,8 @@ void program::rpn_div() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief neg keyword implementation
///
void program::rpn_neg() { void program::rpn_neg() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -238,6 +251,8 @@ void program::rpn_neg() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief inv keyword implementation
///
void program::rpn_inv() { void program::rpn_inv() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -257,6 +272,8 @@ void program::rpn_inv() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief % (purcent) keyword implementation
///
void program::rpn_purcent() { void program::rpn_purcent() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -269,6 +286,8 @@ void program::rpn_purcent() {
CHECK_MPFR(mpfr_div_si(left->_value.mpfr, left->_value.mpfr, 100L, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_div_si(left->_value.mpfr, left->_value.mpfr, 100L, floating_t::s_mpfr_rnd));
} }
/// @brief %CH keyword implementation
///
void program::rpn_purcentCH() { void program::rpn_purcentCH() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -281,6 +300,8 @@ void program::rpn_purcentCH() {
CHECK_MPFR(mpfr_div(left->_value.mpfr, right->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_div(left->_value.mpfr, right->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
} }
/// @brief power keyword implementation
///
void program::rpn_power() { void program::rpn_power() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
bool done_on_real = false; bool done_on_real = false;
@ -338,6 +359,8 @@ void program::rpn_power() {
} }
} }
/// @brief sqrt keyword implementation
///
void program::rpn_squareroot() { void program::rpn_squareroot() {
if (_stack->get_type(0) == cmd_number) { if (_stack->get_type(0) == cmd_number) {
number* left = (number*)_stack->back(); number* left = (number*)_stack->back();
@ -362,6 +385,8 @@ void program::rpn_squareroot() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief sq keyword implementation
///
void program::rpn_square() { void program::rpn_square() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -375,6 +400,8 @@ void program::rpn_square() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief mod keyword implementation
///
void program::rpn_modulo() { void program::rpn_modulo() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -386,6 +413,8 @@ void program::rpn_modulo() {
CHECK_MPFR(mpfr_fmod(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_fmod(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd));
} }
/// @brief abs keyword implementation
///
void program::rpn_abs() { void program::rpn_abs() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -416,6 +445,8 @@ void program::rpn_abs() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief hex keyword implementation
///
void program::rpn_hex() { void program::rpn_hex() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -423,18 +454,24 @@ void program::rpn_hex() {
number::s_decimal_digits = 0; number::s_decimal_digits = 0;
} }
/// @brief bin keyword implementation
///
void program::rpn_bin() { void program::rpn_bin() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
((number*)_stack->back())->_representation = number::bin; ((number*)_stack->back())->_representation = number::bin;
} }
/// @brief dec keyword implementation
///
void program::rpn_dec() { void program::rpn_dec() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
((number*)_stack->back())->_representation = number::dec; ((number*)_stack->back())->_representation = number::dec;
} }
/// @brief base keyword implementation
///
void program::rpn_base() { void program::rpn_base() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -448,6 +485,8 @@ void program::rpn_base() {
ERR_CONTEXT(ret_out_of_range); ERR_CONTEXT(ret_out_of_range);
} }
/// @brief fact (factorial) keyword implementation
///
void program::rpn_fact() { void program::rpn_fact() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -461,6 +500,8 @@ void program::rpn_fact() {
CHECK_MPFR(mpfr_gamma(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_gamma(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
} }
/// @brief sign keyword implementation
///
void program::rpn_sign() { void program::rpn_sign() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -478,6 +519,8 @@ void program::rpn_sign() {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief mant keyword implementation
///
void program::rpn_mant() { void program::rpn_mant() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -508,6 +551,8 @@ void program::rpn_mant() {
ERR_CONTEXT(ret_out_of_range); ERR_CONTEXT(ret_out_of_range);
} }
/// @brief xpon keyword implementation
///
void program::rpn_xpon() { void program::rpn_xpon() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -546,6 +591,8 @@ void program::rpn_xpon() {
ERR_CONTEXT(ret_out_of_range); ERR_CONTEXT(ret_out_of_range);
} }
/// @brief floor keyword implementation
///
void program::rpn_floor() { void program::rpn_floor() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -555,6 +602,8 @@ void program::rpn_floor() {
CHECK_MPFR(mpfr_floor(left->_value.mpfr, left->_value.mpfr)); CHECK_MPFR(mpfr_floor(left->_value.mpfr, left->_value.mpfr));
} }
/// @brief ceil keyword implementation
///
void program::rpn_ceil() { void program::rpn_ceil() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -564,6 +613,8 @@ void program::rpn_ceil() {
CHECK_MPFR(mpfr_ceil(left->_value.mpfr, left->_value.mpfr)); CHECK_MPFR(mpfr_ceil(left->_value.mpfr, left->_value.mpfr));
} }
/// @brief fp keyword implementation
///
void program::rpn_fp() { void program::rpn_fp() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -573,6 +624,8 @@ void program::rpn_fp() {
CHECK_MPFR(mpfr_frac(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_frac(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
} }
/// @brief ip keyword implementation
///
void program::rpn_ip() { void program::rpn_ip() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -582,6 +635,8 @@ void program::rpn_ip() {
CHECK_MPFR(mpfr_trunc(left->_value.mpfr, left->_value.mpfr)); CHECK_MPFR(mpfr_trunc(left->_value.mpfr, left->_value.mpfr));
} }
/// @brief min keyword implementation
///
void program::rpn_min() { void program::rpn_min() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -593,6 +648,8 @@ void program::rpn_min() {
CHECK_MPFR(mpfr_min(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_min(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd));
} }
/// @brief max keyword implementation
///
void program::rpn_max() { void program::rpn_max() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);

View file

@ -1,6 +1,7 @@
#include "program.hpp" #include "program.hpp"
// /// @brief swap keyword implementation
///
void program::rpn_swap(void) { void program::rpn_swap(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
@ -10,16 +11,23 @@ void program::rpn_swap(void) {
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
_calc_stack.pop_back(2); _calc_stack.pop_back(2);
} }
/// @brief drop keyword implementation
///
void program::rpn_drop(void) { void program::rpn_drop(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
(void)_stack->pop_back(); (void)_stack->pop_back();
} }
/// @brief drop2 keyword implementation
///
void program::rpn_drop2(void) { void program::rpn_drop2(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
(void)_stack->pop_back(2); (void)_stack->pop_back(2);
} }
/// @brief dropn keyword implementation
///
void program::rpn_dropn(void) { void program::rpn_dropn(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -30,19 +38,27 @@ void program::rpn_dropn(void) {
(void)_stack->pop_back(args + 1); (void)_stack->pop_back(args + 1);
} }
/// @brief erase / del keyword implementation
///
void program::rpn_erase(void) { (void)_stack->pop_back(_stack->size()); } void program::rpn_erase(void) { (void)_stack->pop_back(_stack->size()); }
/// @brief dup keyword implementation
///
void program::rpn_dup(void) { void program::rpn_dup(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
stack::copy_and_push_back(*_stack, _stack->size() - 1, *_stack); stack::copy_and_push_back(*_stack, _stack->size() - 1, *_stack);
} }
/// @brief dup2 keyword implementation
///
void program::rpn_dup2(void) { void program::rpn_dup2(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
} }
/// @brief dupn keyword implementation
///
void program::rpn_dupn(void) { void program::rpn_dupn(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -54,6 +70,8 @@ void program::rpn_dupn(void) {
for (int i = 0; i < args; i++) stack::copy_and_push_back(*_stack, _stack->size() - args, *_stack); for (int i = 0; i < args; i++) stack::copy_and_push_back(*_stack, _stack->size() - args, *_stack);
} }
/// @brief pick keyword implementation
///
void program::rpn_pick(void) { void program::rpn_pick(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -69,6 +87,8 @@ void program::rpn_pick(void) {
stack::copy_and_push_back(*_stack, _stack->size() - to_pick, *_stack); stack::copy_and_push_back(*_stack, _stack->size() - to_pick, *_stack);
} }
/// @brief rot keyword implementation
///
void program::rpn_rot(void) { void program::rpn_rot(void) {
MIN_ARGUMENTS(3); MIN_ARGUMENTS(3);
@ -82,12 +102,16 @@ void program::rpn_rot(void) {
_calc_stack.pop_back(3); _calc_stack.pop_back(3);
} }
/// @brief depth keyword implementation
///
void program::rpn_depth(void) { void program::rpn_depth(void) {
unsigned long depth = (unsigned long)_stack->size(); unsigned long depth = (unsigned long)_stack->size();
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
num->set(depth); num->set(depth);
} }
/// @brief roll keyword implementation
///
void program::rpn_roll(void) { void program::rpn_roll(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -107,6 +131,8 @@ void program::rpn_roll(void) {
_calc_stack.pop_back(args); _calc_stack.pop_back(args);
} }
/// @brief rolld keyword implementation
///
void program::rpn_rolld(void) { void program::rpn_rolld(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -127,6 +153,8 @@ void program::rpn_rolld(void) {
_calc_stack.pop_back(args); _calc_stack.pop_back(args);
} }
/// @brief over keyword implementation
///
void program::rpn_over(void) { void program::rpn_over(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);

View file

@ -1,6 +1,7 @@
#include "program.hpp" #include "program.hpp"
// /// @brief sto keyword implementation
///
void program::rpn_sto(void) { void program::rpn_sto(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_symbol); ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
@ -10,7 +11,8 @@ void program::rpn_sto(void) {
(void)_stack->pop_back(); (void)_stack->pop_back();
} }
// /// @brief sto+ keyword implementation
///
void program::rpn_stoadd(void) { void program::rpn_stoadd(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -41,6 +43,8 @@ void program::rpn_stoadd(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief sto- keyword implementation
///
void program::rpn_stosub(void) { void program::rpn_stosub(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -71,6 +75,8 @@ void program::rpn_stosub(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief sto* keyword implementation
///
void program::rpn_stomul(void) { void program::rpn_stomul(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -101,6 +107,8 @@ void program::rpn_stomul(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief sto/ keyword implementation
///
void program::rpn_stodiv(void) { void program::rpn_stodiv(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -131,6 +139,8 @@ void program::rpn_stodiv(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief stosneg keyword implementation
///
void program::rpn_stoneg(void) { void program::rpn_stoneg(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -147,6 +157,8 @@ void program::rpn_stoneg(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief sinv keyword implementation
///
void program::rpn_stoinv(void) { void program::rpn_stoinv(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -163,6 +175,8 @@ void program::rpn_stoinv(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief rcl keyword implementation
///
void program::rpn_rcl(void) { void program::rpn_rcl(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_symbol); ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
@ -180,6 +194,8 @@ void program::rpn_rcl(void) {
ERR_CONTEXT(ret_unknown_variable); ERR_CONTEXT(ret_unknown_variable);
} }
/// @brief edit keyword implementation
///
void program::rpn_edit(void) { void program::rpn_edit(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -206,7 +222,10 @@ void program::rpn_edit(void) {
ERR_CONTEXT(ret_runtime_error); ERR_CONTEXT(ret_runtime_error);
} }
// carefull : this is not a langage command /// @brief recall then eval a symbol variable if it is auto-evaluable
///
/// @param symb the smlbol to recall and autoeval
///
void program::auto_rcl(symbol* symb) { void program::auto_rcl(symbol* symb) {
if (symb->_auto_eval) { if (symb->_auto_eval) {
object* obj; object* obj;
@ -223,6 +242,8 @@ void program::auto_rcl(symbol* symb) {
stack::copy_and_push_back(symb, *_stack, symb->size()); stack::copy_and_push_back(symb, *_stack, symb->size());
} }
/// @brief purge keyword implementation
///
void program::rpn_purge(void) { void program::rpn_purge(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_symbol); ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
@ -231,6 +252,8 @@ void program::rpn_purge(void) {
if (!_heap->erase(name)) ERR_CONTEXT(ret_unknown_variable); if (!_heap->erase(name)) ERR_CONTEXT(ret_unknown_variable);
} }
/// @brief vars keyword implementation
///
void program::rpn_vars(void) { void program::rpn_vars(void) {
object* obj; object* obj;
unsigned int size; unsigned int size;
@ -266,4 +289,6 @@ void program::rpn_vars(void) {
} }
} }
/// @brief clusr keyword implementation
///
void program::rpn_clusr(void) { _heap->erase_all(); } void program::rpn_clusr(void) { _heap->erase_all(); }

View file

@ -1,5 +1,7 @@
#include "program.hpp" #include "program.hpp"
/// @brief ->str keyword implementation
///
void program::rpn_instr() { void program::rpn_instr() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -25,6 +27,8 @@ void program::rpn_instr() {
} }
} }
/// @brief str-> keyword implementation
///
void program::rpn_strout() { void program::rpn_strout() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string); ARG_MUST_BE_OF_TYPE(0, cmd_string);
@ -39,6 +43,8 @@ void program::rpn_strout() {
prog.run(*_stack, *_heap); prog.run(*_stack, *_heap);
} }
/// @brief chr keyword implementation
///
void program::rpn_chr() { void program::rpn_chr() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -55,6 +61,8 @@ void program::rpn_chr() {
str->_value[1] = 0; str->_value[1] = 0;
} }
/// @brief num keyword implementation
///
void program::rpn_num() { void program::rpn_num() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string); ARG_MUST_BE_OF_TYPE(0, cmd_string);
@ -64,6 +72,8 @@ void program::rpn_num() {
numb->_value = the_chr; numb->_value = the_chr;
} }
/// @brief size keyword implementation
///
void program::rpn_strsize() { void program::rpn_strsize() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string); ARG_MUST_BE_OF_TYPE(0, cmd_string);
@ -73,6 +83,8 @@ void program::rpn_strsize() {
numb->_value = len; numb->_value = len;
} }
/// @brief pos keyword implementation
///
void program::rpn_strpos() { void program::rpn_strpos() {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_string); ARG_MUST_BE_OF_TYPE(0, cmd_string);
@ -89,6 +101,8 @@ void program::rpn_strpos() {
numb->_value = pos; numb->_value = pos;
} }
/// @brief sub keyword implementation
///
void program::rpn_strsub() { void program::rpn_strsub() {
MIN_ARGUMENTS(3); MIN_ARGUMENTS(3);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);

View file

@ -1,7 +1,11 @@
#include "program.hpp" #include "program.hpp"
/// @brief write stack in a string, each entry separated between commas
///
/// @param stack_is the output string
/// @param stk the stack
///
void program::test_get_stack(string& stack_is, stack& stk) { void program::test_get_stack(string& stack_is, stack& stk) {
// write stack in a string, each entry separated between commas
for (int i = 0; i < (int)stk.size(); i++) { for (int i = 0; i < (int)stk.size(); i++) {
FILE* tmp_file = tmpfile(); FILE* tmp_file = tmpfile();
char* line = NULL; char* line = NULL;
@ -24,6 +28,14 @@ void program::test_get_stack(string& stack_is, stack& stk) {
} }
} }
/// @brief show the tests results
///
/// @param title test title
/// @param tests tests nb
/// @param tests_failed failed tests nb
/// @param steps steps nb
/// @param steps_failed failed steps nb
///
void program::test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed) { void program::test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed) {
printf("%s: run %d tests: %d passed, ", title.c_str(), tests, tests - tests_failed); printf("%s: run %d tests: %d passed, ", title.c_str(), tests, tests - tests_failed);
if (tests_failed > 0) printf(FG_RED); if (tests_failed > 0) printf(FG_RED);
@ -37,6 +49,8 @@ void program::test_show_result(string title, int tests, int tests_failed, int st
printf(")\n"); printf(")\n");
} }
/// @brief test keyword implementation
///
void program::rpn_test() { void program::rpn_test() {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string); ARG_MUST_BE_OF_TYPE(0, cmd_string);
@ -52,6 +66,14 @@ void program::rpn_test() {
test_show_result("Total", total_tests, total_tests_failed, total_steps, total_steps_failed); test_show_result("Total", total_tests, total_tests_failed, total_steps, total_steps_failed);
} }
/// @brief load a test file and run its tests
///
/// @param test_filename the test file filename
/// @param total_tests the total tests nb
/// @param total_tests_failed the total failed tests nb
/// @param total_steps the total steps nb
/// @param total_steps_failed the total failed steps nb
///
void program::test(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps, void program::test(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps,
int& total_steps_failed) { int& total_steps_failed) {
const string stack_size("-> stack size should be "); const string stack_size("-> stack size should be ");

View file

@ -1,5 +1,10 @@
#include "program.hpp" #include "program.hpp"
/// @brief compared 2 strings on top of the stack
///
/// @return 0 strings are equal
/// @return !0 strings are not equal (see strcmp output)
///
int program::cmp_strings_on_stack_top() { int program::cmp_strings_on_stack_top() {
// _stack sould have 2 strings at level 1 and 2 // _stack sould have 2 strings at level 1 and 2
// this function removes these 2 entries // this function removes these 2 entries
@ -8,6 +13,8 @@ int program::cmp_strings_on_stack_top() {
return strncmp(left->_value, right->_value, min(left->_len, right->_len)); return strncmp(left->_value, right->_value, min(left->_len, right->_len));
} }
/// @brief > keyword implementation
///
void program::rpn_sup(void) { void program::rpn_sup(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -30,6 +37,8 @@ void program::rpn_sup(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief >= keyword implementation
///
void program::rpn_sup_eq(void) { void program::rpn_sup_eq(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -52,6 +61,8 @@ void program::rpn_sup_eq(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief < keyword implementation
///
void program::rpn_inf(void) { void program::rpn_inf(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -74,6 +85,8 @@ void program::rpn_inf(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief <= keyword implementation
///
void program::rpn_inf_eq(void) { void program::rpn_inf_eq(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -96,6 +109,8 @@ void program::rpn_inf_eq(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief != keyword implementation
///
void program::rpn_diff(void) { void program::rpn_diff(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -133,6 +148,8 @@ void program::rpn_diff(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief == keyword implementation
///
void program::rpn_eq(void) { void program::rpn_eq(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
@ -170,6 +187,8 @@ void program::rpn_eq(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief and keyword implementation
///
void program::rpn_test_and(void) { void program::rpn_test_and(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -184,6 +203,8 @@ void program::rpn_test_and(void) {
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
} }
/// @brief or keyword implementation
///
void program::rpn_test_or(void) { void program::rpn_test_or(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -198,6 +219,8 @@ void program::rpn_test_or(void) {
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
} }
/// @brief xor keyword implementation
///
void program::rpn_test_xor(void) { void program::rpn_test_xor(void) {
MIN_ARGUMENTS(2); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -219,6 +242,8 @@ void program::rpn_test_xor(void) {
} }
} }
/// @brief not keyword implementation
///
void program::rpn_test_not(void) { void program::rpn_test_not(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -230,4 +255,6 @@ void program::rpn_test_not(void) {
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
} }
/// @brief test same implementation
///
void program::rpn_same(void) { rpn_eq(); } void program::rpn_same(void) { rpn_eq(); }

View file

@ -1,11 +1,14 @@
#include "program.hpp" #include "program.hpp"
// /// @brief pi keyword implementation
///
void program::rpn_pi(void) { void program::rpn_pi(void) {
number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number); number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd));
} }
/// @brief d->r keyword implementation
///
void program::rpn_d2r(void) { void program::rpn_d2r(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -20,6 +23,8 @@ void program::rpn_d2r(void) {
CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
} }
/// @brief r->d keyword implementation
///
void program::rpn_r2d(void) { void program::rpn_r2d(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
@ -34,6 +39,8 @@ void program::rpn_r2d(void) {
CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
} }
/// @brief sin keyword implementation
///
void program::rpn_sin(void) { void program::rpn_sin(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -64,6 +71,8 @@ void program::rpn_sin(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief asin keyword implementation
///
void program::rpn_asin(void) { void program::rpn_asin(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -101,6 +110,8 @@ void program::rpn_asin(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief cos keyword implementation
///
void program::rpn_cos(void) { void program::rpn_cos(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -132,6 +143,8 @@ void program::rpn_cos(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief acos keyword implementation
///
void program::rpn_acos(void) { void program::rpn_acos(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -151,6 +164,8 @@ void program::rpn_acos(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief tan keyword implementation
///
void program::rpn_tan(void) { void program::rpn_tan(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
@ -191,6 +206,8 @@ void program::rpn_tan(void) {
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
/// @brief atan keyword implementation
///
void program::rpn_atan(void) { void program::rpn_atan(void) {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);

View file

@ -8,7 +8,8 @@ using namespace std;
// allocation base size // allocation base size
#define ALLOC_STACK_CHUNK (64 * 1024) #define ALLOC_STACK_CHUNK (64 * 1024)
// /// @brief stack object, parens of program, storing execution stack values or programs
///
class stack { class stack {
public: public:
stack() { stack() {
@ -24,14 +25,20 @@ class stack {
if (_base_pointer != NULL) free(_base_pointer); if (_base_pointer != NULL) free(_base_pointer);
} }
/// @brief remove all the stack elements
///
void erase() { void erase() {
_current = _base; _current = _base;
_count = 0; _count = 0;
} }
// /// @brief copy a whole stack entry and push it back to another stack
///
/// @param from copy from
/// @param index_from index t ocopy from
/// @param to copy to
///
static void copy_and_push_back(stack& from, unsigned int index_from, stack& to) { static void copy_and_push_back(stack& from, unsigned int index_from, stack& to) {
// copy a whole stack entry and push it back to another stack
object* allocated = to.allocate_back(from.seq_len(index_from), from.seq_type(index_from)); object* allocated = to.allocate_back(from.seq_len(index_from), from.seq_type(index_from));
memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from)); memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from));
@ -41,9 +48,13 @@ class stack {
((complex*)allocated)->move(); ((complex*)allocated)->move();
} }
// /// @brief copy a whole stack entry and push it back to another stack
///
/// @param from copy from
/// @param index_from index t ocopy from
/// @param to copy to
///
static void copy_and_push_back(object* from, stack& to, unsigned int size) { static void copy_and_push_back(object* from, stack& to, unsigned int size) {
// copy a whole stack entry and push it back to another stack
object* allocated = to.allocate_back(size, from->_type); object* allocated = to.allocate_back(size, from->_type);
memcpy(allocated, from, size); memcpy(allocated, from, size);
@ -53,6 +64,14 @@ class stack {
((complex*)allocated)->move(); ((complex*)allocated)->move();
} }
/// @brief allocate one object back on an already populated (or not) stack
/// the object function move is called on every reallocated object on the stack
/// the object function init is called on the new allocated object if its type is cmd_number or cmd_complex
///
/// @param size the object size in bytes
/// @param type the object type
/// @return object* the allocated object
///
object* allocate_back(unsigned int size, cmd_type_t type) { object* allocate_back(unsigned int size, cmd_type_t type) {
object* allocated; object* allocated;
bool data_is_reallocated = false; bool data_is_reallocated = false;
@ -119,36 +138,77 @@ class stack {
return back; return back;
} }
/// @brief the number of objects on stack
///
/// @return unsigned int
///
unsigned int size() { return _count; } unsigned int size() { return _count; }
// stack access (stack_level=0=first out) /// @brief stack access (stack_level=0=first out)
///
/// @param stack_level the object stack level
/// @return object* pointer on object at this stack level
///
object* get_obj(unsigned int stack_level) { return seq_obj(_count - stack_level - 1); } object* get_obj(unsigned int stack_level) { return seq_obj(_count - stack_level - 1); }
/// @brief same as get_obj
///
/// @param stack_level the object stack level
/// @return object* pointer on object at this stack level
///
object* operator[](unsigned int stack_level) { return seq_obj(_count - stack_level - 1); } object* operator[](unsigned int stack_level) { return seq_obj(_count - stack_level - 1); }
/// @brief returns the last object on stack
///
/// @return object* the object
///
object* back() { object* back() {
object* obj = NULL; object* obj = NULL;
if (_count > 0) obj = _base_pointer[_count - 1]; if (_count > 0) obj = _base_pointer[_count - 1];
return obj; return obj;
} }
/// @brief get an object len
///
/// @param index the object stack level
/// @return unsigned int the length in bytes
///
unsigned int get_len(unsigned int index) { return seq_len(_count - index - 1); } unsigned int get_len(unsigned int index) { return seq_len(_count - index - 1); }
/// @brief get an object type
///
/// @param index the object stack level
/// @return cmd_type_t the object type
///
cmd_type_t get_type(unsigned int index) { return seq_type(_count - index - 1); } cmd_type_t get_type(unsigned int index) { return seq_type(_count - index - 1); }
// sequential access (index is counted from front) /// @brief sequential object access (index is counted from front)
///
/// @param index object index from front
/// @return object* the object pointer
///
object* seq_obj(unsigned int index) { object* seq_obj(unsigned int index) {
object* obj = NULL; object* obj = NULL;
if (index < _count) obj = _base_pointer[index]; if (index < _count) obj = _base_pointer[index];
return obj; return obj;
} }
/// @brief get an object len
///
/// @param index the object stack level from front
/// @return unsigned int the length in bytes
///
unsigned int seq_len(unsigned int index) { unsigned int seq_len(unsigned int index) {
unsigned int len = 0; unsigned int len = 0;
if (index < _count) len = _base_pointer[index]->_size; if (index < _count) len = _base_pointer[index]->_size;
return len; return len;
} }
/// @brief get an object len
///
/// @param index the object stack level from front
/// @return cmd_type_t the object type
///
cmd_type_t seq_type(unsigned int index) { cmd_type_t seq_type(unsigned int index) {
cmd_type_t type = cmd_undef; cmd_type_t type = cmd_undef;
if (index < _count) type = _base_pointer[index]->_type; if (index < _count) type = _base_pointer[index]->_type;
@ -160,17 +220,25 @@ class stack {
char* _current; char* _current;
object** _base_pointer; object** _base_pointer;
unsigned int _count; // stack count unsigned int _count; //< stack count
unsigned int _total_count_pointer; // total number of possible pointers unsigned int _total_count_pointer; //< total number of possible pointers
unsigned int _total_size; // total allocated data size in bytes unsigned int _total_size; //< total allocated data size in bytes
}; };
// /// @brief heap object, storing variables (=named object)
///
class heap : public stack { class heap : public stack {
public: public:
heap() {} heap() {}
virtual ~heap() {} virtual ~heap() {}
/// @brief add a variable on the heap
///
/// @param name the variable name
/// @param obj the variable content
/// @param size the variable size in bytes
/// @return object*
///
object* add(const string name, object* obj, unsigned int size) { object* add(const string name, object* obj, unsigned int size) {
map<string, unsigned int>::iterator i = _map.find(name); map<string, unsigned int>::iterator i = _map.find(name);
object* local = NULL; object* local = NULL;
@ -195,6 +263,14 @@ class heap : public stack {
return local; return local;
} }
/// @brief get a variable
///
/// @param name the variable name
/// @param obj the variable content
/// @param size the variable size in bytes
/// @return true the variable was found
/// @return false the variable was not found
///
bool get(const string name, object*& obj, unsigned int& size) { bool get(const string name, object*& obj, unsigned int& size) {
bool ret = false; bool ret = false;
map<string, unsigned int>::iterator i = _map.find(name); map<string, unsigned int>::iterator i = _map.find(name);
@ -207,6 +283,14 @@ class heap : public stack {
return ret; return ret;
} }
/// @brief replace a variable value by another
///
/// @param name the variable name
/// @param obj the new value
/// @param size the variable size in bytes
/// @return true the variable was found
/// @return false the variable was not found
///
bool replace_value(const string name, object* obj, unsigned int size) { bool replace_value(const string name, object* obj, unsigned int size) {
bool ret = false; bool ret = false;
map<string, unsigned int>::iterator i = _map.find(name); map<string, unsigned int>::iterator i = _map.find(name);
@ -224,8 +308,23 @@ class heap : public stack {
} }
} }
/// @brief whether a variable exists in heap or not
///
/// @param name the variable name
/// @return true the variable exists
/// @return false variable does not exist
///
bool exist(const string name) { return (_map.find(name) != _map.end()); } bool exist(const string name) { return (_map.find(name) != _map.end()); }
/// @brief get a variable by its index in heap
///
/// @param num the variable index
/// @param name the variable name
/// @param obj the variable content
/// @param size the variable size in bytes
/// @return true the variable was found
/// @return false the variable was not found
///
bool get_by_index(int num, string& name, object*& obj, unsigned int& size) { bool get_by_index(int num, string& name, object*& obj, unsigned int& size) {
if (num >= 0 && num < (int)_map.size()) { if (num >= 0 && num < (int)_map.size()) {
object* local; object* local;
@ -242,6 +341,12 @@ class heap : public stack {
return false; return false;
} }
/// @brief erase a variable
///
/// @param name the variable name
/// @return true the variable was found
/// @return false the variable was not found
///
bool erase(const string& name) { bool erase(const string& name) {
map<string, unsigned int>::iterator i = _map.find(name); map<string, unsigned int>::iterator i = _map.find(name);
bool ret = false; bool ret = false;
@ -256,6 +361,8 @@ class heap : public stack {
return ret; return ret;
} }
/// @brief erase all variables
///
void erase_all(void) { void erase_all(void) {
// map // map
_map.erase(_map.begin(), _map.end()); _map.erase(_map.begin(), _map.end());
@ -264,6 +371,10 @@ class heap : public stack {
((stack*)this)->erase(); ((stack*)this)->erase();
} }
/// @brief get the variables nb
///
/// @return unsigned int the variables nb
///
unsigned int count_vars() { return _map.size(); } unsigned int count_vars() { return _map.size(); }
private: private: