Browse Source

Error reporting in arifmetic and Get<> functions.

Replace 0 on nullptr.
ObjPtr
Michael Uleysky 8 years ago
parent
commit
da0c897a95
  1. 50
      include/builtin.h
  2. 32
      include/common.h
  3. 42
      src/deptree.cpp
  4. 31
      src/globals.cpp
  5. 2
      src/init.cpp
  6. 4
      src/main.cpp
  7. 4
      src/object.cpp

50
include/builtin.h

@ -10,7 +10,7 @@ struct Valued
template<>
struct Valued<ObjectString>
{
double operator ()(const ObjectString* q, bool* isok) {double d=0; *isok=str2double(q->Value(),&d); return d;}
double operator ()(const ObjectString* q, bool* isok) {double d=0; if(!str2double(q->Value(),&d)) *isok=false; return d;}
};
template<class O>
@ -22,7 +22,7 @@ struct Valuei
template<>
struct Valuei<ObjectString>
{
int64_t operator ()(const ObjectString* q, bool* isok) {int64_t i=0; *isok=str2int(q->Value(),&i); return i;}
int64_t operator ()(const ObjectString* q, bool* isok) {int64_t i=0; if(!str2int(q->Value(),&i)) *isok=false; return i;}
};
@ -37,36 +37,52 @@ template<class T> class OpPos {public: static T V(T a) {return +a;}};
template<template<typename> class Op, bool intArifm=true>
ObjectBase* Arifm2(const ObjectList* input)
{
if(input->Size()!=2) return 0;
if(input->Size()!=2) return new ObjectError("Arifmetic binary operator","incorrect number of arguments");
const ObjectBase *arg1=input->At(0),*arg2=input->At(1);
OBTypeM<Valuei,ObjectInt,ObjectString> i1(arg1), i2(arg2);
OBTypeM<Valued,ObjectReal,ObjectInt,ObjectString> r1(arg1), r2(arg2);
bool isok;
bool isok1=true, isok2=true;
// Integer arifmetic
isok=true;
if(i1 && i2 && intArifm)
{
int64_t v1=i1(&isok),v2=i2(&isok);
if(isok) return new ObjectInt(Op<int64_t>::V(v1,v2));
int64_t v1=i1(&isok1),v2=i2(&isok2);
if(isok1 && isok2) return new ObjectInt(Op<int64_t>::V(v1,v2));
}
isok1=isok2=true;
// Real arifmetic
isok=true;
if(r1 && r2)
{
double v1=r1(&isok),v2=r2(&isok);
if(isok) return new ObjectReal(Op<double>::V(v1,v2));
double v1=r1(&isok1),v2=r2(&isok2);
if(isok1 && isok2) return new ObjectReal(Op<double>::V(v1,v2));
}
// Analyze error
// Check first argument
switch(r1.Error())
{
case(OBTypeErr::OK): if(!isok1) return new ObjectError("Arifmetic binary operator","failed conversion of first argument to double"); else break;
case(OBTypeErr::NULLPTR): return new ObjectError("Arifmetic binary operator","first argument is nullptr"); // Impossible case
case(OBTypeErr::TYPEMISMATCH): return new ObjectError("Arifmetic binary operator","first argument has incorrect type");
}
return 0;
// Firs argument is ok, check second
switch(r2.Error())
{
case(OBTypeErr::OK): if(!isok2) return new ObjectError("Arifmetic binary operator","failed conversion of second argument to double"); else break;
case(OBTypeErr::NULLPTR): return new ObjectError("Arifmetic binary operator","second argument is nullptr"); // Impossible case
case(OBTypeErr::TYPEMISMATCH): return new ObjectError("Arifmetic binary operator","second argument has incorrect type");
}
return new ObjectError("Arifmetic binary operator","unknown error"); // Impossible case
}
template<template<typename> class Op, bool intArifm=true>
ObjectBase* Arifm1(const ObjectList* input)
{
if(input->Size()!=1) return 0;
if(input->Size()!=1) return new ObjectError("Arifmetic unary operator","incorrect number of arguments");
const ObjectBase *arg=input->At(0);
OBTypeM<Valuei,ObjectInt,ObjectString> i(arg);
OBTypeM<Valued,ObjectReal,ObjectString> r(arg);
@ -88,5 +104,13 @@ ObjectBase* Arifm1(const ObjectList* input)
if(isok) return new ObjectReal(Op<double>::V(v));
}
return 0;
// Analyze error
switch(r.Error())
{
case(OBTypeErr::OK): if(!isok) return new ObjectError("Arifmetic unary operator","failed conversion of argument to double"); else break;
case(OBTypeErr::NULLPTR): return new ObjectError("Arifmetic unary operator","argument is nullptr"); // Impossible case
case(OBTypeErr::TYPEMISMATCH): return new ObjectError("Arifmetic unary operator","argument has incorrect type");
}
return new ObjectError("Arifmetic unary operator","unknown error"); // Impossible case
}

32
include/common.h

@ -39,7 +39,7 @@ class EXPORT ObjectBase
protected:
bool err;
// No save by default
virtual const int8_t* Blob(size_t* size) const { *size=0; return 0; }
virtual const int8_t* Blob(size_t* size) const { *size=0; return nullptr; }
virtual void DeallocBlob(const int8_t* ptr) const {};
ObjectBase():err(false) {}
public:
@ -57,6 +57,7 @@ class EXPORT ObjectBase
virtual std::string Dump() const {return "%"+Type()+"%";}
};
enum class OBTypeErr {OK,NULLPTR,TYPEMISMATCH};
// Template for checking and using ObjectBase derivative classes
// Checking if arg is non-zero: if(OBType<Derived>(arg).Exist())
@ -71,11 +72,12 @@ class OBType
OBType() = delete;
OBType(OBType&&) = delete;
OBType(OBType&) = delete;
OBType(const ObjectBase* arg):iszero(0==arg) {if(0==arg) p=0; else if(typeid(*arg)==typeid(O)) p=dynamic_cast<const O*>(arg); else p=0;}
OBType(const ObjectBase* arg):iszero(nullptr==arg) {if(nullptr==arg) p=nullptr; else if(typeid(*arg)==typeid(O)) p=dynamic_cast<const O*>(arg); else p=nullptr;}
const O* operator->() const {return p;}
operator bool() const {return 0!=p;}
operator bool() const {return nullptr!=p;}
operator const O*() const {return p;}
bool Exist() const {return !iszero;}
OBTypeErr Error() const {if(iszero) return OBTypeErr::NULLPTR; else if(nullptr==p) return OBTypeErr::TYPEMISMATCH; else return OBTypeErr::OK;}
};
@ -110,7 +112,7 @@ class OBTypeM<Func,O1,O...>: public OBTypeM<Func,O...>
else return OBTypeM<Func,O...>::template F<Res,Args...>(args...);
}
public:
OBTypeM(const ObjectBase* arg):OBTypeM<Func,O...>(arg) {if(0==arg) right=false; else right=(typeid(*arg)==typeid(O1));}
OBTypeM(const ObjectBase* arg):OBTypeM<Func,O...>(arg) {if(nullptr==arg) right=false; else right=(typeid(*arg)==typeid(O1));}
operator bool() const {return right || OBTypeM<Func,O...>::operator bool();}
template<class Res, class... Args>
bool Apply(Res& res, Args... args) const
@ -127,6 +129,7 @@ class OBTypeM<Func,O1,O...>: public OBTypeM<Func,O...>
else return OBTypeM<Func,O...>::template F<T,Args...>(args...);
}
bool Exist() const {return OBTypeM<Func,O...>::Exist();}
OBTypeErr Error() const {if(!Exist()) return OBTypeErr::NULLPTR; else if(!operator bool()) return OBTypeErr::TYPEMISMATCH; else return OBTypeErr::OK;}
};
// Partial instantiation of the bottom of recursion
@ -147,7 +150,7 @@ class OBTypeM<Func>
void operator ()(Args... args) const {}
template<class Res, class... Args>
Res F(Args... args) const {return Res();}
bool Exist() const {return 0!=p;}
bool Exist() const {return nullptr!=p;}
};
@ -261,17 +264,17 @@ public:
std::string Dump() const override { return Name()+"="+val->Dump(); }
// Own functions
bool Exist() const {return 0!=val.get();}
bool Exist() const {return nullptr!=val.get();}
ObjectBase* Get(const std::string& gname) const
{
if(gname==name) return val->Copy();
else return 0;
else return new ObjectError("ObjectPair Get","pair has name "+name+" not "+gname);
}
// This function is same as Get but return pointer on constant object
const ObjectBase* Find(const std::string& gname) const
{
if(gname==name) return val.get();
else return 0;
else return nullptr;
}
std::string Name() const {return name;}
void SetPair(const std::string& n, ObjectBase* v) {if(!Exist()) {name=n; val.reset(v);}}
@ -321,7 +324,7 @@ public:
ObjectBase* Get(const std::string& gname) const
{
const ObjectBase* p=Find(gname);
return (0==p)?0:p->Copy();
return (nullptr==p)?new ObjectError("ObjectList Get","name "+gname+" not found in list"):p->Copy();
}
// This function is same as Get but return pointer on constant object
const ObjectBase* Find(const std::string& gname) const
@ -329,14 +332,14 @@ public:
const ObjectBase* p;
for(auto& i: *vals)
{
p=0;
p=nullptr;
OBType<ObjectPair> pair(i);
OBType<ObjectList> list(i);
if(pair) p=pair->Find(gname);
else if(list) p=list->Find(gname);
if(0!=p) return p;
if(nullptr!=p) return p;
}
return 0;
return nullptr;
}
ListValues::size_type Size() const {return vals->size();}
ObjectList* PushBack(ObjectBase* p) {vals->push_back(p); return this;}
@ -354,10 +357,11 @@ EXPORT int LoadModule(const std::string& name, const void* p, const std::string&
template<class T>
ObjectBase* Get(const ObjectList* input)
{
if(input->Size()!=2) return 0;
if(input->Size()!=2) return new ObjectError("GET","incorrect number of arguments");
OBType<T> ob(input->At(0));
OBType<ObjectString> name(input->At(1));
if(!(ob && name)) return 0;
if(!name) return new ObjectError("GET","second argument is not ObjectString");
if(!ob) return new ObjectError("GET","incorrect type of first argument");
return ob->Get(name->Value());
}

42
src/deptree.cpp

@ -281,14 +281,14 @@ void* TreeEvaluateM(void* arg)
// Begin critical section (access to root)
pthread_mutex_lock(&p->root_mtx);
// Check, if all done, or error happens?
if(0==p->root->childrens.size() || 0!=p->exitcode) {pthread_mutex_unlock(&p->root_mtx); return 0;}
if(0==p->root->childrens.size() || 0!=p->exitcode) {pthread_mutex_unlock(&p->root_mtx); return nullptr;}
// End critical section
pthread_mutex_unlock(&p->root_mtx);
// Begin critical section (access to leafs)
pthread_mutex_lock(&p->leaf_mtx);
// Check, if some work available?
if(0==p->leafs.size()) {pthread_mutex_unlock(&p->leaf_mtx); nanosleep(&skip,0); continue;}
if(0==p->leafs.size()) {pthread_mutex_unlock(&p->leaf_mtx); nanosleep(&skip,nullptr); continue;}
// Select working node
leaf=*(p->leafs.begin());
// and remove its from list
@ -307,12 +307,12 @@ void* TreeEvaluateM(void* arg)
COUT(ERROR)<<" in instruction save at line "<<loc.first_line<<", position "<<loc.first_column<<std::endl;
for(const auto& inc: loc.incstack) COUT(ERROR)<<" included from "<<inc.filename<<" at line "<<inc.line<<", position "<<inc.column<<std::endl;
p->exitcode=1;
return 0;
return nullptr;
}
if(!Save(ol.get()))
{
p->exitcode=1;
return 0;
return nullptr;
}
// This leaf can have only one parent - root
// Begin critical section (access to root)
@ -333,12 +333,12 @@ void* TreeEvaluateM(void* arg)
COUT(ERROR)<<" in instruction print at line "<<loc.first_line<<", position "<<loc.first_column<<std::endl;
for(const auto& inc: loc.incstack) COUT(ERROR)<<" included from "<<inc.filename<<" at line "<<inc.line<<", position "<<inc.column<<std::endl;
p->exitcode=1;
return 0;
return nullptr;
}
if(!Print(ol.get()))
{
p->exitcode=1;
return 0;
return nullptr;
}
// Begin critical section (access to root)
@ -363,7 +363,7 @@ void* TreeEvaluateM(void* arg)
COUT(ERROR)<<" in definition of variable "<<leaf->name<<" at line "<<loc.first_line<<", position "<<loc.first_column<<std::endl;
for(const auto& inc: loc.incstack) COUT(ERROR)<<" included from "<<inc.filename<<" at line "<<inc.line<<", position "<<inc.column<<std::endl;
p->exitcode=1;
return 0;
return nullptr;
}
// Begin critical section (access to tree structure)
@ -390,7 +390,7 @@ void* TreeEvaluateM(void* arg)
leaf->parents.clear();
delete leaf;
}
return 0;
return nullptr;
}
@ -419,13 +419,13 @@ void* TreeEvaluate(void* arg)
COUT(ERROR)<<" in instruction save at line "<<loc.first_line<<", position "<<loc.first_column<<std::endl;
for(const auto& inc: loc.incstack) COUT(ERROR)<<" included from "<<inc.filename<<" at line "<<inc.line<<", position "<<inc.column<<std::endl;
p->exitcode=1;
return 0;
return nullptr;
}
// eob is evaluated object
if(!Save(ol.get()))
{
p->exitcode=1;
return 0;
return nullptr;
}
// This leaf can have only one parent - root
(*leaf->parents.begin())->childrens.erase(leaf);
@ -442,12 +442,12 @@ void* TreeEvaluate(void* arg)
COUT(ERROR)<<" in instruction print at line "<<loc.first_line<<", position "<<loc.first_column<<std::endl;
for(const auto& inc: loc.incstack) COUT(ERROR)<<" included from "<<inc.filename<<" at line "<<inc.line<<", position "<<inc.column<<std::endl;
p->exitcode=1;
return 0;
return nullptr;
}
if(!Print(ol.get()))
{
p->exitcode=1;
return 0;
return nullptr;
}
// This leaf can have only one parent - root
(*leaf->parents.begin())->childrens.erase(leaf);
@ -466,7 +466,7 @@ void* TreeEvaluate(void* arg)
COUT(ERROR)<<" in definition of variable "<<leaf->name<<" at line "<<loc.first_line<<", position "<<loc.first_column<<std::endl;
for(const auto& inc: loc.incstack) COUT(ERROR)<<" included from "<<inc.filename<<" at line "<<inc.line<<", position "<<inc.column<<std::endl;
p->exitcode=1;
return 0;
return nullptr;
}
for(auto& i:leaf->parents)
@ -483,7 +483,7 @@ void* TreeEvaluate(void* arg)
leaf->parents.clear();
delete leaf;
}
return 0;
return nullptr;
}
@ -499,16 +499,16 @@ int DepTree::EvaluateTree(unsigned int nthreads)
{
pthread_t* threads=new pthread_t[nthreads-1];
p.root=this;
pthread_mutex_init(&p.leaf_mtx,0);
pthread_mutex_init(&p.root_mtx,0);
pthread_mutex_init(&p.vars_mtx,0);
pthread_mutex_init(&p.prsv_mtx,0);
pthread_mutex_init(&p.tree_mtx,0);
pthread_mutex_init(&p.leaf_mtx,nullptr);
pthread_mutex_init(&p.root_mtx,nullptr);
pthread_mutex_init(&p.vars_mtx,nullptr);
pthread_mutex_init(&p.prsv_mtx,nullptr);
pthread_mutex_init(&p.tree_mtx,nullptr);
while(0!=p.root->parents.size()) p.root=*(p.root->parents.begin());
for(unsigned int i=0;i<nthreads-1;++i) pthread_create(threads+i,0,&TreeEvaluateM,&p);
for(unsigned int i=0;i<nthreads-1;++i) pthread_create(threads+i,nullptr,&TreeEvaluateM,&p);
TreeEvaluateM(&p);
for(unsigned int i=0;i<nthreads-1;++i) pthread_join(threads[i],0);
for(unsigned int i=0;i<nthreads-1;++i) pthread_join(threads[i],nullptr);
delete[] threads;
pthread_mutex_destroy(&p.leaf_mtx);
pthread_mutex_destroy(&p.root_mtx);

31
src/globals.cpp

@ -6,24 +6,9 @@ G_funcsType G_funcs;
// Loaded modules
G_libsType G_libs;
/*
// Variables definitions
G_VarType G_Vars;
// List of objects to save
G_ExecType G_ToSave;
// List of objects to print
G_ExecType G_ToPrint;
*/
void ClearGlobals()
{
for(auto& it:G_libs) dlclose(it);
//G_Vars.clear();
//G_ToPrint.clear();
//G_ToSave.clear();
}
@ -47,20 +32,20 @@ int LoadModule(const std::string& name, const void* p, const std::string& modnam
initname+="_module_init";
// Check if module is statically linked or already loaded: dlopen'ed the main program
handle=dlopen(0,RTLD_LAZY|RTLD_GLOBAL);
if(0==handle)
handle=dlopen(nullptr,RTLD_LAZY|RTLD_GLOBAL);
if(nullptr==handle)
{
COUT(ERROR)<<std::endl<<"Something wrong: can't dlopen the main program"<<std::endl;
return 1;
}
initfunc=dlsym(handle,initname.c_str());
if(0==initfunc) // We not find it
if(nullptr==initfunc) // We not find it
{
if('/'==name[0]) // Absolute path
{
handle=dlopen(name.c_str(),RTLD_LAZY|RTLD_GLOBAL);
if(0==handle) handle=dlopen((name+".so").c_str(),RTLD_LAZY|RTLD_GLOBAL);
if(nullptr==handle) handle=dlopen((name+".so").c_str(),RTLD_LAZY|RTLD_GLOBAL);
}
else // Relative path
{
@ -72,13 +57,13 @@ int LoadModule(const std::string& name, const void* p, const std::string& modnam
epos=spath.find(':',bpos);
curpath=spath.substr(bpos,(std::string::npos==epos)?epos:(epos-bpos));
handle=dlopen((curpath+name).c_str(),RTLD_LAZY|RTLD_GLOBAL);
if(0!=handle) break;
if(nullptr!=handle) break;
handle=dlopen((curpath+name+".so").c_str(),RTLD_LAZY|RTLD_GLOBAL);
if(0!=handle) break;
if(nullptr!=handle) break;
bpos=epos+1;
} while(std::string::npos!=epos);
}
if(0==handle)
if(nullptr==handle)
{
COUT(ERROR)<<std::endl<<"Can't dlopen module "<<name<<std::endl;
return 1;
@ -87,7 +72,7 @@ int LoadModule(const std::string& name, const void* p, const std::string& modnam
initfunc=dlsym(handle,initname.c_str());
}
if(0==initfunc)
if(nullptr==initfunc)
{
COUT(ERROR)<<std::endl<<"Can't find initialising function "<<initname<<" in module "<<name<<std::endl;
return 1;

2
src/init.cpp

@ -25,7 +25,7 @@ int ParseConfigFile(const char* config, ExecType& tosave, ExecType& toprint, Var
int ret;
conffd=fopen(config,"r");
if(conffd==0)
if(nullptr==conffd)
{
COUT(ERROR)<<"Can't open file "<<config<<std::endl;
return 1;

4
src/main.cpp

@ -22,11 +22,11 @@ int main(int argc, char** argv)
options.threads=1;
options.help=options.dump=false;
options.dl=NORMAL;
options.config=0;
options.config=nullptr;
// Parse options
ret=ParseOptions(argc,argv,options);
if(ret!=0 || options.config==0) {usage(argv[0]); return 1;}
if(ret!=0 || nullptr==options.config) {usage(argv[0]); return 1;}
if(options.help) {usage(argv[0]); return 0;}
SetDebugLevel(options.dl);

4
src/object.cpp

@ -213,13 +213,13 @@ bool ObjectBase::Save(const char* fname) const
fd=fopen(fname,"w");
serrno=errno;
if(0==fd)
if(nullptr==fd)
{
COUT(ERROR)<<"Can't open file "<<fname<<" for writing: "<<strerror(serrno)<<std::endl;
return false;
}
dptr=Blob(&size);
if(0==dptr)
if(nullptr==dptr)
{
COUT(ERROR)<<"Can't get blob for writing to "<<fname<<std::endl;
fclose(fd);

Loading…
Cancel
Save