Merge pull request #239 from louisrubet/#218/enhanced_gcc_warnings

Add enhanced gcc warnings
This commit is contained in:
Louis Rubet 2022-02-28 10:25:47 +01:00 committed by GitHub
commit db0e7f6ebb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 134 additions and 110 deletions

View file

@ -46,16 +46,6 @@ set(RPN_LICENSE "LGPLv3")
set(RPN_LICENSE_FILE "${PROJECT_SOURCE_DIR}/LICENSE")
set(RPN_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
# compiler options
if(CMAKE_COMPILER_IS_GNUCXX)
message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}")
# TODO still up to date?
set(BASE_COMPILER_OPTIONS "-std=c++17 -Wl,--no-as-needed")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILER_OPTIONS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${BASE_COMPILER_OPTIONS} -O0 -g")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${BASE_COMPILER_OPTIONS} -O3 -s")
endif()
# custom linenoise-ng
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/linenoise-ng/.git")
execute_process(command git submodule init ${PROJECT_SOURCE_DIR}/linenoise-ng)
@ -73,32 +63,47 @@ endif()
# includes
include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/linenoise-ng/include ${PROJECT_SOURCE_DIR}/mpreal)
# build
add_executable(
rpn
${PROJECT_SOURCE_DIR}/src/main.cc
${PROJECT_SOURCE_DIR}/src/object.cc
${PROJECT_SOURCE_DIR}/src/mpreal-out.cc
${PROJECT_SOURCE_DIR}/src/program.cc
${PROJECT_SOURCE_DIR}/src/lexer.cc
${PROJECT_SOURCE_DIR}/src/input.cc
${PROJECT_SOURCE_DIR}/src/rpn-branch.cc
${PROJECT_SOURCE_DIR}/src/rpn-complex.cc
${PROJECT_SOURCE_DIR}/src/rpn-general.cc
${PROJECT_SOURCE_DIR}/src/rpn-logs.cc
${PROJECT_SOURCE_DIR}/src/rpn-program.cc
${PROJECT_SOURCE_DIR}/src/rpn-real.cc
${PROJECT_SOURCE_DIR}/src/rpn-stack.cc
${PROJECT_SOURCE_DIR}/src/rpn-store.cc
${PROJECT_SOURCE_DIR}/src/rpn-string.cc
${PROJECT_SOURCE_DIR}/src/rpn-test.cc
${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cc
${PROJECT_SOURCE_DIR}/src/rpn-time.cc
${PROJECT_SOURCE_DIR}/src/rpn-trig.cc
${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp
${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp
${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp
)
# src
set(RPN_SRC_FILES
${PROJECT_SOURCE_DIR}/src/main.cc
${PROJECT_SOURCE_DIR}/src/object.cc
${PROJECT_SOURCE_DIR}/src/mpreal-out.cc
${PROJECT_SOURCE_DIR}/src/program.cc
${PROJECT_SOURCE_DIR}/src/lexer.cc
${PROJECT_SOURCE_DIR}/src/input.cc
${PROJECT_SOURCE_DIR}/src/rpn-branch.cc
${PROJECT_SOURCE_DIR}/src/rpn-complex.cc
${PROJECT_SOURCE_DIR}/src/rpn-general.cc
${PROJECT_SOURCE_DIR}/src/rpn-logs.cc
${PROJECT_SOURCE_DIR}/src/rpn-program.cc
${PROJECT_SOURCE_DIR}/src/rpn-real.cc
${PROJECT_SOURCE_DIR}/src/rpn-stack.cc
${PROJECT_SOURCE_DIR}/src/rpn-store.cc
${PROJECT_SOURCE_DIR}/src/rpn-string.cc
${PROJECT_SOURCE_DIR}/src/rpn-test.cc
${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cc
${PROJECT_SOURCE_DIR}/src/rpn-time.cc
${PROJECT_SOURCE_DIR}/src/rpn-trig.cc)
set(LINENOISE_NG_SRC_FILES
${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp
${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp
${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp)
# compiler options
set_source_files_properties(${RPN_SRC_FILES} COMPILE_FLAGS # some harder warnings
"-Wall -Wextra -pedantic -Wno-missing-field-initializers")
if(CMAKE_COMPILER_IS_GNUCXX)
message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}")
# TODO still up to date?
set(BASE_COMPILER_OPTIONS "-std=c++17 -Wl,--no-as-needed")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILER_OPTIONS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${BASE_COMPILER_OPTIONS} -O0 -g")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${BASE_COMPILER_OPTIONS} -O3 -s")
endif()
add_executable(rpn ${RPN_SRC_FILES} ${LINENOISE_NG_SRC_FILES})
target_link_libraries(rpn mpfr)
target_link_libraries(rpn gmp)

View file

@ -2,8 +2,11 @@
#include "lexer.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic" // allow designated initializers
bool Lexer::Analyse(string& entry, map<string, ReservedWord>& keywords, vector<SynElement>& elements,
vector<SynError>& errors) {
vector<SynError>& errors) {
size_t jump;
for (size_t i = 0; i < entry.size(); i++) {
if (isspace(entry[i])) continue;
@ -49,7 +52,7 @@ void Lexer::Trim(string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
}
bool Lexer::ParseString(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
bool Lexer::ParseString(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
vector<SynElement>& elements) {
// here we are sure that entry[0] is at least '"'
for (size_t i = idx + 1; i < entry.size(); i++) {
@ -66,7 +69,7 @@ bool Lexer::ParseString(string& entry, size_t idx, size_t& next_idx, vector<SynE
return true;
}
bool Lexer::ParseSymbol(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
bool Lexer::ParseSymbol(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
vector<SynElement>& elements) {
// here we are sure that entry[0] is at least '\''
for (size_t i = idx + 1; i < entry.size(); i++) {
@ -81,7 +84,7 @@ bool Lexer::ParseSymbol(string& entry, size_t idx, size_t& next_idx, vector<SynE
return true;
}
bool Lexer::ParseProgram(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
bool Lexer::ParseProgram(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
vector<SynElement>& elements) {
// here we are sure that entry is at least "<<"
// find last ">>" or "»"
@ -153,7 +156,6 @@ int Lexer::GetBaseAt(string& entry, size_t& next_idx, bool& positive) {
bool Lexer::GetNUmberAt(string& entry, size_t idx, size_t& next_idx, int& base, mpreal** r, char delim) {
stringstream ss;
int idxNumber = 0;
string token;
bool positive = true;
@ -193,7 +195,7 @@ bool Lexer::ParseNumber(string& entry, size_t idx, size_t& next_idx, vector<SynE
}
}
bool Lexer::ParseComplex(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
bool Lexer::ParseComplex(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
vector<SynElement>& elements) {
mpreal* re = nullptr;
mpreal* im = nullptr;
@ -253,3 +255,5 @@ bool Lexer::ParseUnknown(string& entry, size_t idx, size_t& next_idx, vector<Syn
next_idx = token.size() + idx;
return true;
}
#pragma GCC diagnostic pop

View file

@ -52,13 +52,16 @@ static void EnterInteractive() {
/// @param siginfo signal info, see POSIX sigaction
/// @param context see POSIX sigaction
///
static void CtrlHandler(int sig, siginfo_t* siginfo, void* context) { ExitInteractive(); }
static void CtrlHandler(int sig __attribute__((unused)), siginfo_t* siginfo __attribute__((unused)),
void* context __attribute__((unused))) {
ExitInteractive();
}
/// @brief setup signals handlers to stop with honours
///
/// @param prog the prog to catch the signals to, must be checked not nullptr by user
///
static void CatchSignals(program* prog) {
static void CatchSignals() {
struct sigaction act = {0};
act.sa_sigaction = &CtrlHandler;
@ -85,6 +88,9 @@ int main(int argc, char* argv[]) {
// init history
EnterInteractive();
// user could stop prog with CtrlC
CatchSignals();
// entry loop
heap heap;
rpnstack stack;
@ -95,8 +101,6 @@ int main(int argc, char* argv[]) {
string entry;
switch (Input(entry, program::GetAutocompletionWords()).status) {
case Input::InputStatus::kOk:
// user could stop prog with CtrlC
CatchSignals(&prog);
// run it
if (prog.Parse(entry) == kOk && prog.Run() == kGoodbye)
go_on = false;
@ -127,7 +131,7 @@ int main(int argc, char* argv[]) {
ret = prog.Parse(entry);
if (ret == kOk) {
// user could stop prog with CtrlC
CatchSignals(&prog);
CatchSignals();
// run it
ret = prog.Run();

View file

@ -184,7 +184,7 @@ ostream& _out_number(ostream& out, int base, const mpreal& value) {
if (digits > 0) {
out << '.';
int remaining = MIN(strlen(print_from) - nexp - 1, digits) + 1;
int remaining = MIN(static_cast<int>(strlen(print_from)) - nexp - 1, digits) + 1;
for (int i = nexp; i < remaining + nexp; i++) out << print_from[i];
for (int i = 0; i < nexp + digits - len; i++) out << '0';
}

View file

@ -172,8 +172,8 @@ struct Symbol : Object {
virtual Object* Clone() { return new Symbol(value, auto_eval); }
virtual string Name() { return string("symbol"); }
virtual ostream& Show(ostream& out) { return out << "'" << value << "'"; }
bool auto_eval;
string value;
bool auto_eval;
};
struct Keyword : Object {
@ -187,19 +187,19 @@ struct Keyword : Object {
struct Branch : Object {
Branch() : Object(kBranch) {}
explicit Branch(branch_fn_t fn__, const string& value__) : Object(kBranch) {
fn = fn__;
explicit Branch(branch_fn_t fn__, const string& value__) : Object(kBranch), fn(fn__), value(value__) {
arg1 = static_cast<size_t>(-1);
arg2 = static_cast<size_t>(-1);
arg3 = static_cast<size_t>(-1);
arg_bool = 0;
value = value__;
}
explicit Branch(Branch& other) : Object(kBranch) {
fn = other.fn;
arg1 = other.arg1;
arg2 = other.arg2;
arg3 = other.arg3;
first_index = other.first_index;
last_index = other.last_index;
arg_bool = other.arg_bool;
value = other.value;
}

View file

@ -3,6 +3,8 @@
#include "program.h"
//< language reserved keywords (allowed types are kKeyword, kBranch or kUndef)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type" // allow casting kBranch callbacks
vector<program::keyword_t> program::keywords_{
// GENERAL
{kUndef, "", nullptr, "\nGENERAL"},
@ -129,8 +131,7 @@ vector<program::keyword_t> program::keywords_{
{kBranch, "else", (program_fn_t)&program::RpnElse, "used with if"},
{kBranch, "end", (program_fn_t)&program::RpnEnd, "used with various branch instructions"},
{kBranch, "start", (program_fn_t)&program::RpnStart, "<start> <end> start <instructions> next|<step> step"},
{kBranch, "for", (program_fn_t)&program::RpnFor,
"<start> <end> for <variable> <instructions> next|<step> step"},
{kBranch, "for", (program_fn_t)&program::RpnFor, "<start> <end> for <variable> <instructions> next|<step> step"},
{kBranch, "next", (program_fn_t)&program::RpnNext, "used with start and for"},
{kBranch, "step", (program_fn_t)&program::RpnStep, "used with start and for"},
{kKeyword, "ift", &program::RpnIft, "similar to if-then-end, <test-instruction> <true-instruction> ift"},
@ -202,6 +203,7 @@ vector<program::keyword_t> program::keywords_{
{kKeyword, "date", &program::RpnDate, "date in local format"},
{kKeyword, "ticks", &program::RpnTicks, "system tick in µs"},
};
#pragma GCC diagnostic pop
/// autocompletion vector for linenoise autocompletion
vector<string>& program::GetAutocompletionWords() {
@ -219,7 +221,6 @@ vector<string>& program::GetAutocompletionWords() {
RetValue program::Run() {
bool go_out = false;
RetValue ret = kOk;
ObjectType type;
err_ = kOk;
err_context_ = "";
@ -598,7 +599,10 @@ RetValue program::Parse(string& entry) {
push_back(new Keyword(element.fn, element.value));
break;
case kBranch:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type" // allow casting kBranch callbacks
push_back(new Branch((branch_fn_t)element.fn, element.value));
#pragma GCC diagnostic pop
break;
default:
ShowError(kUnknownError, "error creating program from entry");
@ -637,8 +641,10 @@ RetValue program::ShowError() {
case kInternalError:
case kDeadlyError:
ret = kDeadlyError;
break;
default:
ret = kOk;
break;
}
return ret;

View file

@ -213,7 +213,7 @@ class program : public deque<Object*>, public Lexer {
// test-core
void RpnTest();
void RunTestFile(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps,
int& total_steps_failed);
int& total_steps_failed);
// test
void RpnSup(void);
@ -248,42 +248,42 @@ class program : public deque<Object*>, public Lexer {
// convenience macros for rpn_xx function
// carefull : some of these macros modify program flow
#define ERROR_CONTEXT(err) \
#define ERROR_CONTEXT(err) \
do { \
err_ = (err); \
err_context_ = __FUNCTION__; \
} while (0)
#define MIN_ARGUMENTS(num) \
do { \
if ((num) >= 0 && stack_.size() < (num)) { \
ERROR_CONTEXT(kMissingOperand); \
return; \
} \
#define MIN_ARGUMENTS(num) \
do { \
if (stack_.size() < (num)) { \
ERROR_CONTEXT(kMissingOperand); \
return; \
} \
} while (0)
#define MIN_ARGUMENTS_RET(num, ret) \
do { \
if ((num) >= 0 && stack_.size() < (num)) { \
ERROR_CONTEXT(kMissingOperand); \
return (ret); \
} \
#define MIN_ARGUMENTS_RET(num, ret) \
do { \
if (stack_.size() < (num)) { \
ERROR_CONTEXT(kMissingOperand); \
return (ret); \
} \
} while (0)
#define ARG_MUST_BE_OF_TYPE(num, type) \
do { \
if ((num) >= 0 && stack_.at(num)->_type != (type)) { \
ERROR_CONTEXT(kBadOperandType); \
return; \
} \
#define ARG_MUST_BE_OF_TYPE(num, type) \
do { \
if (stack_.at(num)->_type != (type)) { \
ERROR_CONTEXT(kBadOperandType); \
return; \
} \
} while (0)
#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \
do { \
if ((num) >= 0 && stack_.at(num)->_type != (type)) { \
ERROR_CONTEXT(kBadOperandType); \
return (ret); \
} \
#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \
do { \
if (stack_.at(num)->_type != (type)) { \
ERROR_CONTEXT(kBadOperandType); \
return (ret); \
} \
} while (0)
#endif // SRC_PROGRAM_HPP_

View file

@ -83,7 +83,7 @@ size_t program::RpnEnd(Branch& myobj) {
size_t ret = kStepOut;
// arg1 = index of do+1 in case of do..unti..end
if (myobj.arg1 != -1) {
if (myobj.arg1 != kStepOut) {
// in a template do..until..end
MIN_ARGUMENTS_RET(1, kRtError);
ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError);
@ -106,7 +106,7 @@ size_t program::RpnEnd(Branch& myobj) {
/// @return kStepOut next object to run in the current program is current + 1
/// @return kRtError something went wrong with preprocess, abort branch
///
size_t program::RpnDo(Branch& myobj) {
size_t program::RpnDo(Branch& myobj __attribute__((unused))) {
// nothing
return kStepOut;
}
@ -118,7 +118,7 @@ size_t program::RpnDo(Branch& myobj) {
/// @return kStepOut next object to run in the current program is current + 1
/// @return kRtError something went wrong with preprocess, abort Branch
///
size_t program::RpnUntil(Branch& myobj) {
size_t program::RpnUntil(Branch& myobj __attribute__((unused))) {
// nothing
return kStepOut;
}
@ -170,7 +170,7 @@ void program::RpnIfte(void) {
/// @return kStepOut next object to run in the current program is current + 1
/// @return kRtError something went wrong with preprocess, abort branch
///
size_t program::RpnWhile(Branch& myobj) {
size_t program::RpnWhile(Branch& myobj __attribute__((unused))) {
// nothing
return kStepOut;
}
@ -298,8 +298,7 @@ size_t program::RpnNext(Branch& myobj) {
mpfr_add(myobj.first_index.mpfr_ptr(), myobj.first_index.mpfr_srcptr(), mpreal(1).mpfr_srcptr(), MPFR_RNDD);
// for command: increment symbol too
if (start_or_for->arg1 != -1) {
Object* obj;
if (start_or_for->arg1 != kStepOut) {
Symbol* var;
if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != kSymbol) {
ERROR_CONTEXT(kMissingOperand);
@ -318,7 +317,7 @@ size_t program::RpnNext(Branch& myobj) {
return kStepOut;
} else {
// for command: next instruction will be after symbol variable
if (start_or_for->arg1 != -1) return start_or_for->arg1 + 1;
if (start_or_for->arg1 != kStepOut) return start_or_for->arg1 + 1;
// start command: next instruction will be after start command
else
return myobj.arg1 + 1;
@ -361,8 +360,7 @@ size_t program::RpnStep(Branch& myobj) {
// carefull: round toward minus infinity to avoid missing last boundary (because growing step)
mpfr_add(myobj.first_index.mpfr_ptr(), myobj.first_index.mpfr_srcptr(), step.mpfr_srcptr(), MPFR_RNDD);
if (start_or_for->arg1 != -1) {
Object* obj;
if (start_or_for->arg1 != kStepOut) {
Symbol* var;
// for command: increment symbol too
@ -382,7 +380,7 @@ size_t program::RpnStep(Branch& myobj) {
ret = kStepOut;
} else {
// for command: next instruction will be after symbol variable
if (start_or_for->arg1 != -1) ret = start_or_for->arg1 + 1;
if (start_or_for->arg1 != kStepOut) ret = start_or_for->arg1 + 1;
// start command: next instruction will be after start command
else
ret = myobj.arg1 + 1;

View file

@ -54,7 +54,6 @@ void program::RpnHelp() {
cout << _syntax << endl;
// keywords
unsigned int i = 0;
for (auto& kw : keywords_)
if (!kw.comment.empty()) {
// titles in bold

View file

@ -82,10 +82,10 @@ void program::RpnEval(void) {
///
int program::RpnInprog(Branch& inprog_obj) {
string context("->"); // for showing errors
int count_symbols = 0;
size_t count_symbols = 0;
bool prog_found = false;
if (inprog_obj.arg1 == -1) {
if (inprog_obj.arg1 == kStepOut) {
ERROR_CONTEXT(kUnknownError);
return -1;
}
@ -132,7 +132,7 @@ int program::RpnInprog(Branch& inprog_obj) {
}
// load variables
for (unsigned int i = inprog_obj.arg1 + count_symbols; i > inprog_obj.arg1; i--) {
for (size_t i = inprog_obj.arg1 + count_symbols; i > inprog_obj.arg1; i--) {
local_heap_[reinterpret_cast<Symbol*>(at(i))->value] = stack_.at(0)->Clone();
stack_.pop();
}

View file

@ -31,7 +31,7 @@ void program::RpnDropn(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, kNumber);
int args = static_cast<int>(stack_.value<Number>(0).toLong());
size_t args = stack_.value<Number>(0).toULong();
MIN_ARGUMENTS(args + 1);
stack_.erase(0, args + 1);
}
@ -53,11 +53,15 @@ void program::RpnDupn(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, kNumber);
int args = static_cast<int>(stack_.value<Number>(0).toLong());
size_t args = stack_.value<Number>(0).toULong();
stack_.pop();
if (args == 0) {
ERROR_CONTEXT(kOutOfRange);
return;
}
MIN_ARGUMENTS(args);
for (int i = 0; i < args; i++) stack_.push_front(stack_.at(args - 1)->Clone());
for (size_t i = 0; i < args; i++) stack_.push_front(stack_.at(args - 1)->Clone());
}
/// @brief dup2 keyword implementation
@ -74,7 +78,7 @@ void program::RpnPick(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, kNumber);
int to_pick = static_cast<int>(stack_.value<Number>(0).toLong());
size_t to_pick = static_cast<int>(stack_.value<Number>(0).toLong());
stack_.pop();
// treat stack_ depth errors
@ -105,9 +109,13 @@ void program::RpnRoll(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, kNumber);
int args = static_cast<int>(stack_.value<Number>(0).toLong());
size_t args = static_cast<int>(stack_.value<Number>(0).toLong());
stack_.pop();
MIN_ARGUMENTS(args);
if (args == 0) {
ERROR_CONTEXT(kOutOfRange);
return;
}
Object* tmp = stack_.at(args - 1);
stack_.erase(args - 1, 1, false);
@ -120,9 +128,13 @@ void program::RpnRolld(void) {
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, kNumber);
int args = static_cast<int>(stack_.value<Number>(0).toLong());
size_t args = static_cast<int>(stack_.value<Number>(0).toLong());
stack_.pop();
MIN_ARGUMENTS(args);
if (args == 0) {
ERROR_CONTEXT(kOutOfRange);
return;
}
Object* tmp = stack_.at(0);
stack_.erase(0, 1, false);

View file

@ -193,7 +193,6 @@ void program::RpnPurge(void) {
/// @brief vars keyword implementation
///
void program::RpnVars(void) {
Object* obj;
program* parent = parent_;
string name;
int index = 1;
@ -214,7 +213,7 @@ void program::RpnVars(void) {
while (parent != nullptr) {
for (auto i : parent->local_heap_) {
cout << "parent var " << index++ << ": name '" << i.first << "', type " << i.second->Name() << ", value ";
obj->Show(cout) << endl;
i.second->Show(cout) << endl;
}
parent = parent->parent_;
}

View file

@ -117,9 +117,9 @@ void program::RunTestFile(string test_filename, int& total_tests, int& total_tes
rpnstack stk;
heap hp;
bool failed = false;
bool is_first_step;
bool is_test_error_shown;
int last_err;
bool is_first_step = true;
bool is_test_error_shown = false;
int last_err = static_cast<int>(kOk);
stringstream cerr_buffer;
streambuf* cerr_old_buffer;

View file

@ -144,7 +144,7 @@ void program::RpnTestXor(void) {
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, kNumber);
ARG_MUST_BE_OF_TYPE(1, kNumber);
if (stack_.value<Number>(0) != 0 ^ stack_.value<Number>(1) != 0)
if ((stack_.value<Number>(0) != 0) ^ (stack_.value<Number>(1) != 0))
stack_.push(new Number(1));
else
stack_.push(new Number(0));

View file

@ -44,9 +44,6 @@ void program::RpnDate() {
// date format = (M)M.DDYYYY
date = static_cast<double>(tm->tm_mon + 1) * 1000000.0 + static_cast<double>(tm->tm_mday) * 10000.0 +
static_cast<double>(tm->tm_year + 1900);
// push it
Number* num;
// division after push for real precision
stack_.push(new Number(date));
stack_.value<Number>(0) /= 1000000.0;