diff --git a/src/main.cpp b/src/main.cpp index 2b07ca4..a3f5b58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,7 +15,8 @@ static heap s_global_heap; static stack s_global_stack; 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() { struct passwd* pw = getpwuid(getuid()); 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() { struct passwd* pw = getpwuid(getuid()); 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) { if (s_prog_to_interrupt != NULL) { s_prog_to_interrupt->stop(); @@ -55,13 +62,22 @@ static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) { 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) { fprintf(stderr, "Internal error\n"); s_prog_to_interrupt->stop(); 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) { 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)); } -// +/// @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 ret = 0; bool go_on = true; diff --git a/src/object.cpp b/src/object.cpp index e3dd3be..785e260 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -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; +/// @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) { // see mpfr_vasprintf code bool ret; @@ -64,6 +72,14 @@ static bool is_min(mpfr_t p, mpfr_prec_t prec) { 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) { // see mpfr_vasprintf code 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) { int digits; char* str; diff --git a/src/object.hpp b/src/object.hpp index 4878b9d..ec0d7d2 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -24,8 +24,8 @@ class branch; typedef void (program::*program_fn_t)(void); typedef int (program::*branch_fn_t)(branch&); -// MPFR object -//// +/// @brief MPFR (floating point) object +/// struct floating_t { mpfr_prec_t mpfr_prec; // precision in bits 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]; }; -// object - a generic stack object -//// +/// @brief object - a generic stack object +/// struct object { // object type cmd_type_t _type; @@ -83,8 +83,8 @@ struct object { static const char* s_cmd_type_string[cmd_max]; }; -// stack objects derived from object -//// +/// @brief stack objects derived from object +/// struct number : public object { // members enum { dec, hex, bin, base } _representation; @@ -122,8 +122,8 @@ struct number : public object { static string s_mpfr_printf_format; }; -// stack objects derived from object -//// +/// @brief stack objects derived from object +/// struct complex : public object { enum { dec, hex } _representation; // 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 { // ostring may first have been allocated with len+1 bytes void set(const char* value, unsigned int len) { @@ -172,6 +174,8 @@ struct ostring : public object { char _value[0]; }; +/// @brief object program +/// struct oprogram : public object { // oprogram may first have been allocated with len+1 bytes void set(const char* value, unsigned int len) { @@ -191,6 +195,8 @@ struct oprogram : public object { char _value[0]; }; +/// @brief object symbol +/// struct symbol : public object { // symbol may first have been allocated with len+1 bytes void set(const char* value, unsigned int len, bool auto_eval) { @@ -214,6 +220,8 @@ struct symbol : public object { char _value[0]; }; +/// @brief object keyword +/// struct keyword : public object { // keyword may first have been allocated with len+1 bytes void set(program_fn_t fn, const char* value, unsigned int len) { @@ -236,6 +244,8 @@ struct keyword : public object { char _value[0]; }; +/// @brief object branch +/// struct branch : public object { // void set(branch_fn_t fn, const char* value, unsigned int len) { diff --git a/src/parse.cpp b/src/parse.cpp index d6d3d59..a130bc7 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -1,5 +1,11 @@ #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) { int i = 0; 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) { string entry_str; char* entry; @@ -63,7 +73,7 @@ ret_value program::entry(program& prog) { ret = parse(entry_str.c_str(), prog); // keep history - if (entry[0] != 0) linenoiseHistoryAdd(entry_str.c_str()); + if (entry[0] != 0) (void)linenoiseHistoryAdd(entry_str.c_str()); } else ret = ret_internal; } @@ -74,6 +84,13 @@ ret_value program::entry(program& prog) { 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) { unsigned int i = 0; 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; } +/// @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) { program_fn_t fn; unsigned int obj_len; @@ -113,6 +138,330 @@ static bool get_keyword(const string& entry, program& prog, string& remaining_en 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& entries) { string tmp; int len = strlen(entry); @@ -245,260 +594,12 @@ static bool _cut(const char* entry, vector& entries) { return entries.size() > 0; } -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; -} - -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; -} - +/// @brief parse an entry string: cut it into objects chunks and add them to a program +/// +/// @param entry the entry string +/// @param prog the program +/// @return ret_value see this type +/// ret_value program::parse(const char* entry, program& prog) { vector entries; ret_value ret = ret_ok; diff --git a/src/program.cpp b/src/program.cpp index 0e15b9d..4bc3809 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -1,9 +1,9 @@ #include "program.hpp" -// +//< return type 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[] = { // GENERAL {cmd_undef, "", NULL, "\nGENERAL"}, @@ -206,6 +206,12 @@ program::keyword_t program::s_keywords[] = { {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) { bool go_out = false; ret_value ret = ret_ok; @@ -298,15 +304,19 @@ ret_value program::run(stack& stk, heap& hp) { return ret; } +/// @brief stop a program +/// +/// void program::stop() { interrupt_now = true; } -bool program::compare_keyword(keyword* k, const char* str_to_compare, int len) { - if (k->_len >= len) - return strncmp(k->_value, str_to_compare, len) == 0; - else - return false; -} - +/// @brief return whether a branch object has a given name +/// +/// @param b the branch object +/// @param str_to_compare the name +/// @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) { if (b->_len >= len) 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; } +/// @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) { // for if-then-else-end vector vlayout; @@ -540,6 +557,10 @@ ret_value program::preprocess(void) { return ret_ok; } +/// @brief show the last error set +/// +/// @return ret_value see this type +/// ret_value program::show_error() { ret_value ret; @@ -556,6 +577,12 @@ ret_value program::show_error() { 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) { // record error _err = err; @@ -563,6 +590,12 @@ ret_value program::show_error(ret_value err, string& context) { 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) { // record error _err = err; @@ -570,6 +603,12 @@ ret_value program::show_error(ret_value err, const char* context) { 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) { // record error _err = ret_syntax; @@ -577,8 +616,18 @@ void program::show_syntax_error(const char* context) { (void)show_error(); } +/// @brief return the last error set +/// +/// @return ret_value see this type +/// 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) { if (st.size() == 1) { ((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() { // default float precision, float mode number::s_mode = DEFAULT_MODE; diff --git a/src/program.hpp b/src/program.hpp index 8550891..e94ef73 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -27,7 +27,7 @@ using namespace std; #include "stack.hpp" #include "version.h" -// +//< convinient structure to preprocess a program struct 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) {} @@ -39,7 +39,7 @@ struct if_layout_t { 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 { public: program(program* parent_prog = NULL) { diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index c51428f..d52a700 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -1,6 +1,11 @@ #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) { // myobj.arg1 = 'if' condition evaluation value MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); @@ -14,6 +19,11 @@ int program::rpn_if(branch& myobj) { 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) { // myobj.arg1 = index of then + 1 // myobj.arg2 = index of else + 1 or end + 1 @@ -27,6 +37,12 @@ int program::rpn_then(branch& myobj) { 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) { // myobj.arg1 = index of else + 1 // myobj.arg2 = index of end + 1 @@ -40,6 +56,12 @@ int program::rpn_else(branch& myobj) { 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 ret = -1; @@ -60,17 +82,34 @@ int program::rpn_end(branch& myobj) { 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) { // nothing 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) { // nothing 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) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(1, cmd_number); @@ -89,6 +128,12 @@ void program::rpn_ift(void) { (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) { MIN_ARGUMENTS(3); ARG_MUST_BE_OF_TYPE(2, cmd_number); @@ -108,12 +153,23 @@ void program::rpn_ifte(void) { (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) { // nothing 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 ret = -1; @@ -128,6 +184,12 @@ int program::rpn_repeat(branch& myobj) { 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 ret = -1; @@ -155,6 +217,12 @@ int program::rpn_start(branch& myobj) { 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 ret; @@ -190,6 +258,12 @@ int program::rpn_for(branch& myobj) { 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) { // arg1 = index of start or for command in program // 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 ret; MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index e3bd22f..27e031e 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -1,5 +1,8 @@ #include "program.hpp" +/// @brief re keyword implementation +/// the result is stacked on current program stack +/// void program::rpn_re() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); @@ -12,6 +15,9 @@ void program::rpn_re() { _calc_stack.pop_back(); } +/// @brief im keyword implementation +/// the result is stacked on current program stack +/// void program::rpn_im() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); @@ -24,6 +30,9 @@ void program::rpn_im() { _calc_stack.pop_back(); } +/// @brief arg keyword implementation +/// the result is stacked on current program stack +/// void program::rpn_arg() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); @@ -38,6 +47,9 @@ void program::rpn_arg() { _calc_stack.pop_back(); } +/// @brief conj keyword implementation +/// the result is stacked on current program stack +/// void program::rpn_conj() { MIN_ARGUMENTS(1); 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)); } +/// @brief r2c keyword implementation +/// the result is stacked on current program stack +/// void program::rpn_r2c() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -62,6 +77,9 @@ void program::rpn_r2c() { _calc_stack.pop_back(2); } +/// @brief c2r keyword implementation +/// the result is stacked on current program stack +/// void program::rpn_c2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); @@ -77,6 +95,9 @@ void program::rpn_c2r() { _calc_stack.pop_back(); } +/// @brief r2p keyword implementation +/// the result is stacked on current program stack +/// void program::rpn_r2p() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); @@ -96,6 +117,9 @@ void program::rpn_r2p() { _stack->pop_back(); } +/// @brief p2r keyword implementation +/// the result is stacked on current program stack +/// void program::rpn_p2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index 9cba5f0..e038a9b 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -1,12 +1,18 @@ #include "program.hpp" -// +/// @brief nop keyword implementation +/// void program::rpn_nop() { // nop } +/// @brief quit keyword implementation +/// void program::rpn_good_bye() { ERR_CONTEXT(ret_good_bye); } +/// @brief nop keyword implementation +/// the result is written on stdout +/// void program::rpn_help() { // software name printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname); @@ -55,10 +61,22 @@ void program::rpn_help() { 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) { 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) { stringstream ss; ss << MPFR_FORMAT_BEG; @@ -67,6 +85,12 @@ static string make_digit_format(int decimal_digits, const char* printf_format) { 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) { bool ret = true; @@ -80,6 +104,8 @@ static bool check_decimal_digits(double precision) { return ret; } +/// @brief std keyword implementation +/// void program::rpn_std() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -95,6 +121,8 @@ void program::rpn_std() { ERR_CONTEXT(ret_out_of_range); } +/// @brief fix keyword implementation +/// void program::rpn_fix() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -110,6 +138,8 @@ void program::rpn_fix() { ERR_CONTEXT(ret_out_of_range); } +/// @brief sci keyword implementation +/// void program::rpn_sci() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -125,6 +155,8 @@ void program::rpn_sci() { ERR_CONTEXT(ret_out_of_range); } +/// @brief version keyword implementation +/// void program::rpn_version() { // allocate and set object unsigned int naked_entry_len = strlen(version); @@ -132,6 +164,8 @@ void program::rpn_version() { str->set(version, naked_entry_len); } +/// @brief uname keyword implementation +/// void program::rpn_uname() { // allocate and set object unsigned int naked_entry_len = strlen(uname); @@ -139,6 +173,8 @@ void program::rpn_uname() { str->set(uname, naked_entry_len); } +/// @brief history keyword implementation +/// void program::rpn_history() { // see command history on stdout int index = 0; @@ -150,6 +186,8 @@ void program::rpn_history() { } } +/// @brief type keyword implementation +/// void program::rpn_type() { MIN_ARGUMENTS(1); @@ -162,8 +200,12 @@ void program::rpn_type() { typ->set(object::s_cmd_type_string[type], string_size); } +/// @brief default keyword implementation +/// void program::rpn_default() { program::apply_default(); } +/// @brief prec keyword implementation +/// void program::rpn_precision() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -184,6 +226,8 @@ void program::rpn_precision() { ERR_CONTEXT(ret_out_of_range); } +/// @brief round keyword implementation +/// void program::rpn_round() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index 6eda691..78b2819 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -1,11 +1,15 @@ #include "program.hpp" +/// @brief e keyword implementation +/// void program::rpn_e(void) { number* euler = (number*)_stack->allocate_back(number::calc_size(), cmd_number); euler->_value = 1L; CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd)); } +/// @brief log10 keyword implementation +/// void program::rpn_log10() { MIN_ARGUMENTS(1); @@ -21,6 +25,8 @@ void program::rpn_log10() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief alog10 keyword implementation +/// void program::rpn_alog10() { MIN_ARGUMENTS(1); @@ -34,6 +40,8 @@ void program::rpn_alog10() { } } +/// @brief log2 keyword implementation +/// void program::rpn_log2() { MIN_ARGUMENTS(1); @@ -49,6 +57,8 @@ void program::rpn_log2() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief alog2 keyword implementation +/// void program::rpn_alog2() { MIN_ARGUMENTS(1); @@ -62,6 +72,8 @@ void program::rpn_alog2() { } } +/// @brief ln keyword implementation +/// void program::rpn_ln() { MIN_ARGUMENTS(1); @@ -106,6 +118,8 @@ void program::rpn_ln() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief exp keyword implementation +/// void program::rpn_exp() { MIN_ARGUMENTS(1); @@ -133,6 +147,8 @@ void program::rpn_exp() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief expm keyword implementation +/// void program::rpn_expm() { MIN_ARGUMENTS(1); @@ -147,6 +163,8 @@ void program::rpn_expm() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief lnp1 keyword implementation +/// void program::rpn_lnp1() { MIN_ARGUMENTS(1); @@ -161,6 +179,8 @@ void program::rpn_lnp1() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief sinh keyword implementation +/// void program::rpn_sinh() { MIN_ARGUMENTS(1); @@ -191,6 +211,8 @@ void program::rpn_sinh() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief asinh keyword implementation +/// void program::rpn_asinh() { MIN_ARGUMENTS(1); @@ -211,6 +233,8 @@ void program::rpn_asinh() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief cosh keyword implementation +/// void program::rpn_cosh() { MIN_ARGUMENTS(1); @@ -241,6 +265,8 @@ void program::rpn_cosh() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief acosh keyword implementation +/// void program::rpn_acosh() { MIN_ARGUMENTS(1); @@ -265,6 +291,8 @@ void program::rpn_acosh() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief tanh keyword implementation +/// void program::rpn_tanh() { MIN_ARGUMENTS(1); @@ -293,6 +321,8 @@ void program::rpn_tanh() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief atanh keyword implementation +/// void program::rpn_atanh() { MIN_ARGUMENTS(1); diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index 979f395..0a970e3 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -1,11 +1,17 @@ #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 found = false; program* parent = _parent_prog; - // find variable in local heap, parens heaps, global heap if (_local_heap.get(variable, obj, size)) found = true; else { @@ -24,6 +30,8 @@ bool program::find_variable(string& variable, object*& obj, unsigned int& size) return found; } +/// @brief eval keyword implementation +/// void program::rpn_eval(void) { bool run_prog = false; 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) { string context("->"); // for showing errors int count_symbols = 0; diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index b441c93..35dcc39 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -1,5 +1,7 @@ #include "program.hpp" +/// @brief + keyword implementation +/// void program::rpn_plus() { MIN_ARGUMENTS(2); @@ -51,6 +53,8 @@ void program::rpn_plus() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief - keyword implementation +/// void program::rpn_minus() { MIN_ARGUMENTS(2); @@ -83,6 +87,8 @@ void program::rpn_minus() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief * keyword implementation +/// void program::rpn_mul() { MIN_ARGUMENTS(2); @@ -133,6 +139,9 @@ void program::rpn_mul() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief divide the 2 complexes on stack +/// result on the prog stack +/// 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) complex* right = (complex*)_stack->get_obj(0); // x+iy @@ -177,6 +186,8 @@ void program::do_divide_complexes() { _calc_stack.pop_back(4); } +/// @brief / keyword implementation +/// void program::rpn_div() { MIN_ARGUMENTS(2); @@ -224,6 +235,8 @@ void program::rpn_div() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief neg keyword implementation +/// void program::rpn_neg() { MIN_ARGUMENTS(1); @@ -238,6 +251,8 @@ void program::rpn_neg() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief inv keyword implementation +/// void program::rpn_inv() { MIN_ARGUMENTS(1); @@ -257,6 +272,8 @@ void program::rpn_inv() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief % (purcent) keyword implementation +/// void program::rpn_purcent() { MIN_ARGUMENTS(2); 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)); } +/// @brief %CH keyword implementation +/// void program::rpn_purcentCH() { MIN_ARGUMENTS(2); 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)); } +/// @brief power keyword implementation +/// void program::rpn_power() { MIN_ARGUMENTS(2); bool done_on_real = false; @@ -338,6 +359,8 @@ void program::rpn_power() { } } +/// @brief sqrt keyword implementation +/// void program::rpn_squareroot() { if (_stack->get_type(0) == cmd_number) { number* left = (number*)_stack->back(); @@ -362,6 +385,8 @@ void program::rpn_squareroot() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief sq keyword implementation +/// void program::rpn_square() { MIN_ARGUMENTS(1); @@ -375,6 +400,8 @@ void program::rpn_square() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief mod keyword implementation +/// void program::rpn_modulo() { MIN_ARGUMENTS(2); 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)); } +/// @brief abs keyword implementation +/// void program::rpn_abs() { MIN_ARGUMENTS(1); @@ -416,6 +445,8 @@ void program::rpn_abs() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief hex keyword implementation +/// void program::rpn_hex() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -423,18 +454,24 @@ void program::rpn_hex() { number::s_decimal_digits = 0; } +/// @brief bin keyword implementation +/// void program::rpn_bin() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); ((number*)_stack->back())->_representation = number::bin; } +/// @brief dec keyword implementation +/// void program::rpn_dec() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); ((number*)_stack->back())->_representation = number::dec; } +/// @brief base keyword implementation +/// void program::rpn_base() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -448,6 +485,8 @@ void program::rpn_base() { ERR_CONTEXT(ret_out_of_range); } +/// @brief fact (factorial) keyword implementation +/// void program::rpn_fact() { MIN_ARGUMENTS(1); 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)); } +/// @brief sign keyword implementation +/// void program::rpn_sign() { MIN_ARGUMENTS(1); @@ -478,6 +519,8 @@ void program::rpn_sign() { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief mant keyword implementation +/// void program::rpn_mant() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -508,6 +551,8 @@ void program::rpn_mant() { ERR_CONTEXT(ret_out_of_range); } +/// @brief xpon keyword implementation +/// void program::rpn_xpon() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -546,6 +591,8 @@ void program::rpn_xpon() { ERR_CONTEXT(ret_out_of_range); } +/// @brief floor keyword implementation +/// void program::rpn_floor() { MIN_ARGUMENTS(1); 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)); } +/// @brief ceil keyword implementation +/// void program::rpn_ceil() { MIN_ARGUMENTS(1); 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)); } +/// @brief fp keyword implementation +/// void program::rpn_fp() { MIN_ARGUMENTS(1); 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)); } +/// @brief ip keyword implementation +/// void program::rpn_ip() { MIN_ARGUMENTS(1); 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)); } +/// @brief min keyword implementation +/// void program::rpn_min() { MIN_ARGUMENTS(2); 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)); } +/// @brief max keyword implementation +/// void program::rpn_max() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index 3918527..e55febc 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -1,6 +1,7 @@ #include "program.hpp" -// +/// @brief swap keyword implementation +/// void program::rpn_swap(void) { MIN_ARGUMENTS(2); 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); _calc_stack.pop_back(2); } + +/// @brief drop keyword implementation +/// void program::rpn_drop(void) { MIN_ARGUMENTS(1); (void)_stack->pop_back(); } +/// @brief drop2 keyword implementation +/// void program::rpn_drop2(void) { MIN_ARGUMENTS(2); (void)_stack->pop_back(2); } +/// @brief dropn keyword implementation +/// void program::rpn_dropn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -30,19 +38,27 @@ void program::rpn_dropn(void) { (void)_stack->pop_back(args + 1); } +/// @brief erase / del keyword implementation +/// void program::rpn_erase(void) { (void)_stack->pop_back(_stack->size()); } +/// @brief dup keyword implementation +/// void program::rpn_dup(void) { MIN_ARGUMENTS(1); stack::copy_and_push_back(*_stack, _stack->size() - 1, *_stack); } +/// @brief dup2 keyword implementation +/// void program::rpn_dup2(void) { MIN_ARGUMENTS(2); 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) { MIN_ARGUMENTS(1); 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); } +/// @brief pick keyword implementation +/// void program::rpn_pick(void) { MIN_ARGUMENTS(1); 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); } +/// @brief rot keyword implementation +/// void program::rpn_rot(void) { MIN_ARGUMENTS(3); @@ -82,12 +102,16 @@ void program::rpn_rot(void) { _calc_stack.pop_back(3); } +/// @brief depth keyword implementation +/// void program::rpn_depth(void) { unsigned long depth = (unsigned long)_stack->size(); number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); num->set(depth); } +/// @brief roll keyword implementation +/// void program::rpn_roll(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -107,6 +131,8 @@ void program::rpn_roll(void) { _calc_stack.pop_back(args); } +/// @brief rolld keyword implementation +/// void program::rpn_rolld(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -127,6 +153,8 @@ void program::rpn_rolld(void) { _calc_stack.pop_back(args); } +/// @brief over keyword implementation +/// void program::rpn_over(void) { MIN_ARGUMENTS(2); diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index e2f3605..244ec4e 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -1,6 +1,7 @@ #include "program.hpp" -// +/// @brief sto keyword implementation +/// void program::rpn_sto(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); @@ -10,7 +11,8 @@ void program::rpn_sto(void) { (void)_stack->pop_back(); } -// +/// @brief sto+ keyword implementation +/// void program::rpn_stoadd(void) { MIN_ARGUMENTS(2); @@ -41,6 +43,8 @@ void program::rpn_stoadd(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief sto- keyword implementation +/// void program::rpn_stosub(void) { MIN_ARGUMENTS(2); @@ -71,6 +75,8 @@ void program::rpn_stosub(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief sto* keyword implementation +/// void program::rpn_stomul(void) { MIN_ARGUMENTS(2); @@ -101,6 +107,8 @@ void program::rpn_stomul(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief sto/ keyword implementation +/// void program::rpn_stodiv(void) { MIN_ARGUMENTS(2); @@ -131,6 +139,8 @@ void program::rpn_stodiv(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief stosneg keyword implementation +/// void program::rpn_stoneg(void) { MIN_ARGUMENTS(1); @@ -147,6 +157,8 @@ void program::rpn_stoneg(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief sinv keyword implementation +/// void program::rpn_stoinv(void) { MIN_ARGUMENTS(1); @@ -163,6 +175,8 @@ void program::rpn_stoinv(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief rcl keyword implementation +/// void program::rpn_rcl(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); @@ -180,6 +194,8 @@ void program::rpn_rcl(void) { ERR_CONTEXT(ret_unknown_variable); } +/// @brief edit keyword implementation +/// void program::rpn_edit(void) { MIN_ARGUMENTS(1); @@ -206,7 +222,10 @@ void program::rpn_edit(void) { 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) { if (symb->_auto_eval) { object* obj; @@ -223,6 +242,8 @@ void program::auto_rcl(symbol* symb) { stack::copy_and_push_back(symb, *_stack, symb->size()); } +/// @brief purge keyword implementation +/// void program::rpn_purge(void) { MIN_ARGUMENTS(1); 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); } +/// @brief vars keyword implementation +/// void program::rpn_vars(void) { object* obj; unsigned int size; @@ -266,4 +289,6 @@ void program::rpn_vars(void) { } } +/// @brief clusr keyword implementation +/// void program::rpn_clusr(void) { _heap->erase_all(); } diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index 49bc574..8b36654 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -1,5 +1,7 @@ #include "program.hpp" +/// @brief ->str keyword implementation +/// void program::rpn_instr() { MIN_ARGUMENTS(1); @@ -25,6 +27,8 @@ void program::rpn_instr() { } } +/// @brief str-> keyword implementation +/// void program::rpn_strout() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); @@ -39,6 +43,8 @@ void program::rpn_strout() { prog.run(*_stack, *_heap); } +/// @brief chr keyword implementation +/// void program::rpn_chr() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); @@ -55,6 +61,8 @@ void program::rpn_chr() { str->_value[1] = 0; } +/// @brief num keyword implementation +/// void program::rpn_num() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); @@ -64,6 +72,8 @@ void program::rpn_num() { numb->_value = the_chr; } +/// @brief size keyword implementation +/// void program::rpn_strsize() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); @@ -73,6 +83,8 @@ void program::rpn_strsize() { numb->_value = len; } +/// @brief pos keyword implementation +/// void program::rpn_strpos() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_string); @@ -89,6 +101,8 @@ void program::rpn_strpos() { numb->_value = pos; } +/// @brief sub keyword implementation +/// void program::rpn_strsub() { MIN_ARGUMENTS(3); ARG_MUST_BE_OF_TYPE(0, cmd_number); diff --git a/src/rpn-test-core.cpp b/src/rpn-test-core.cpp index 4b95975..fae6ea1 100644 --- a/src/rpn-test-core.cpp +++ b/src/rpn-test-core.cpp @@ -1,7 +1,11 @@ #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) { - // write stack in a string, each entry separated between commas for (int i = 0; i < (int)stk.size(); i++) { FILE* tmp_file = tmpfile(); 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) { printf("%s: run %d tests: %d passed, ", title.c_str(), tests, tests - tests_failed); 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"); } +/// @brief test keyword implementation +/// void program::rpn_test() { MIN_ARGUMENTS(1); 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); } +/// @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, int& total_steps_failed) { const string stack_size("-> stack size should be "); diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 7fef8b9..8294a65 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -1,5 +1,10 @@ #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() { // _stack sould have 2 strings at level 1 and 2 // 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)); } +/// @brief > keyword implementation +/// void program::rpn_sup(void) { MIN_ARGUMENTS(2); @@ -30,6 +37,8 @@ void program::rpn_sup(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief >= keyword implementation +/// void program::rpn_sup_eq(void) { MIN_ARGUMENTS(2); @@ -52,6 +61,8 @@ void program::rpn_sup_eq(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief < keyword implementation +/// void program::rpn_inf(void) { MIN_ARGUMENTS(2); @@ -74,6 +85,8 @@ void program::rpn_inf(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief <= keyword implementation +/// void program::rpn_inf_eq(void) { MIN_ARGUMENTS(2); @@ -96,6 +109,8 @@ void program::rpn_inf_eq(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief != keyword implementation +/// void program::rpn_diff(void) { MIN_ARGUMENTS(2); @@ -133,6 +148,8 @@ void program::rpn_diff(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief == keyword implementation +/// void program::rpn_eq(void) { MIN_ARGUMENTS(2); @@ -170,6 +187,8 @@ void program::rpn_eq(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief and keyword implementation +/// void program::rpn_test_and(void) { MIN_ARGUMENTS(2); 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); } +/// @brief or keyword implementation +/// void program::rpn_test_or(void) { MIN_ARGUMENTS(2); 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); } +/// @brief xor keyword implementation +/// void program::rpn_test_xor(void) { MIN_ARGUMENTS(2); 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) { MIN_ARGUMENTS(1); 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); } +/// @brief test same implementation +/// void program::rpn_same(void) { rpn_eq(); } diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index 61a4819..32e32be 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -1,11 +1,14 @@ #include "program.hpp" -// +/// @brief pi keyword implementation +/// void program::rpn_pi(void) { number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number); CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd)); } +/// @brief d->r keyword implementation +/// void program::rpn_d2r(void) { MIN_ARGUMENTS(1); 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)); } +/// @brief r->d keyword implementation +/// void program::rpn_r2d(void) { MIN_ARGUMENTS(1); 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)); } +/// @brief sin keyword implementation +/// void program::rpn_sin(void) { MIN_ARGUMENTS(1); @@ -64,6 +71,8 @@ void program::rpn_sin(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief asin keyword implementation +/// void program::rpn_asin(void) { MIN_ARGUMENTS(1); @@ -101,6 +110,8 @@ void program::rpn_asin(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief cos keyword implementation +/// void program::rpn_cos(void) { MIN_ARGUMENTS(1); @@ -132,6 +143,8 @@ void program::rpn_cos(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief acos keyword implementation +/// void program::rpn_acos(void) { MIN_ARGUMENTS(1); @@ -151,6 +164,8 @@ void program::rpn_acos(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief tan keyword implementation +/// void program::rpn_tan(void) { MIN_ARGUMENTS(1); @@ -191,6 +206,8 @@ void program::rpn_tan(void) { ERR_CONTEXT(ret_bad_operand_type); } +/// @brief atan keyword implementation +/// void program::rpn_atan(void) { MIN_ARGUMENTS(1); diff --git a/src/stack.hpp b/src/stack.hpp index 3d3d7ef..bea54aa 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -8,7 +8,8 @@ using namespace std; // allocation base size #define ALLOC_STACK_CHUNK (64 * 1024) -// +/// @brief stack object, parens of program, storing execution stack values or programs +/// class stack { public: stack() { @@ -24,14 +25,20 @@ class stack { if (_base_pointer != NULL) free(_base_pointer); } + /// @brief remove all the stack elements + /// void erase() { _current = _base; _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) { - // 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)); memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from)); @@ -41,9 +48,13 @@ class stack { ((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) { - // copy a whole stack entry and push it back to another stack object* allocated = to.allocate_back(size, from->_type); memcpy(allocated, from, size); @@ -53,6 +64,14 @@ class stack { ((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* allocated; bool data_is_reallocated = false; @@ -119,36 +138,77 @@ class stack { return back; } + /// @brief the number of objects on stack + /// + /// @return unsigned int + /// 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); } + /// @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); } + /// @brief returns the last object on stack + /// + /// @return object* the object + /// object* back() { object* obj = NULL; if (_count > 0) obj = _base_pointer[_count - 1]; 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); } + /// @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); } - // 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* obj = NULL; if (index < _count) obj = _base_pointer[index]; 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 len = 0; if (index < _count) len = _base_pointer[index]->_size; 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 type = cmd_undef; if (index < _count) type = _base_pointer[index]->_type; @@ -160,17 +220,25 @@ class stack { char* _current; object** _base_pointer; - unsigned int _count; // stack count - unsigned int _total_count_pointer; // total number of possible pointers - unsigned int _total_size; // total allocated data size in bytes + unsigned int _count; //< stack count + unsigned int _total_count_pointer; //< total number of possible pointers + unsigned int _total_size; //< total allocated data size in bytes }; -// +/// @brief heap object, storing variables (=named object) +/// class heap : public stack { public: 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) { map::iterator i = _map.find(name); object* local = NULL; @@ -195,6 +263,14 @@ class heap : public stack { 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 ret = false; map::iterator i = _map.find(name); @@ -207,6 +283,14 @@ class heap : public stack { 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 ret = false; map::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()); } + /// @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) { if (num >= 0 && num < (int)_map.size()) { object* local; @@ -242,6 +341,12 @@ class heap : public stack { 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) { map::iterator i = _map.find(name); bool ret = false; @@ -256,6 +361,8 @@ class heap : public stack { return ret; } + /// @brief erase all variables + /// void erase_all(void) { // map _map.erase(_map.begin(), _map.end()); @@ -264,6 +371,10 @@ class heap : public stack { ((stack*)this)->erase(); } + /// @brief get the variables nb + /// + /// @return unsigned int the variables nb + /// unsigned int count_vars() { return _map.size(); } private: