mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-22 11:19:32 -06:00
better error handling which always reports the right file name
This commit is contained in:
@@ -30,6 +30,35 @@ private:
|
||||
const char *msg;
|
||||
};
|
||||
|
||||
class PGF_INTERNAL_DECL pgf_systemerror : public std::runtime_error {
|
||||
public:
|
||||
pgf_systemerror(int code) : std::runtime_error("pgf_systemerror")
|
||||
{
|
||||
this->m_code = code;
|
||||
this->m_filepath = NULL;
|
||||
}
|
||||
|
||||
pgf_systemerror(int code, const char *filepath) : std::runtime_error("pgf_systemerror")
|
||||
{
|
||||
this->m_code = code;
|
||||
this->m_filepath = filepath;
|
||||
}
|
||||
|
||||
virtual int code() const
|
||||
{
|
||||
return m_code;
|
||||
}
|
||||
|
||||
const char *filepath() const
|
||||
{
|
||||
return m_filepath;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_code;
|
||||
const char *m_filepath;
|
||||
};
|
||||
|
||||
struct PGF_INTERNAL_DECL PgfFlag {
|
||||
PgfLiteral value;
|
||||
PgfText name;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <system_error>
|
||||
|
||||
#include "data.h"
|
||||
|
||||
@@ -270,30 +269,33 @@ struct malloc_state
|
||||
};
|
||||
|
||||
PGF_INTERNAL
|
||||
PgfDB::PgfDB(const char* pathname, int flags, int mode) {
|
||||
PgfDB::PgfDB(const char* filepath, int flags, int mode) {
|
||||
size_t file_size;
|
||||
bool is_new = false;
|
||||
|
||||
fd = -1;
|
||||
ms = NULL;
|
||||
|
||||
if (pathname == NULL) {
|
||||
if (filepath == NULL) {
|
||||
this->filepath = NULL;
|
||||
file_size = getpagesize();
|
||||
is_new = true;
|
||||
} else {
|
||||
fd = open(pathname, flags, mode);
|
||||
fd = open(filepath, flags, mode);
|
||||
if (fd < 0)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, filepath);
|
||||
|
||||
this->filepath = strdup(filepath);
|
||||
|
||||
file_size = lseek(fd, 0, SEEK_END);
|
||||
if (file_size == ((off_t) -1))
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, filepath);
|
||||
|
||||
is_new = false;
|
||||
if (file_size == 0) {
|
||||
file_size = getpagesize();
|
||||
if (ftruncate(fd, file_size) < 0)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, filepath);
|
||||
is_new = true;
|
||||
}
|
||||
}
|
||||
@@ -302,7 +304,7 @@ PgfDB::PgfDB(const char* pathname, int flags, int mode) {
|
||||
ms = (malloc_state*)
|
||||
mmap(NULL, file_size, PROT_READ | PROT_WRITE, mflags, fd, 0);
|
||||
if (ms == MAP_FAILED)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, filepath);
|
||||
|
||||
if (is_new) {
|
||||
init_state(file_size);
|
||||
@@ -310,7 +312,7 @@ PgfDB::PgfDB(const char* pathname, int flags, int mode) {
|
||||
|
||||
int res = pthread_rwlock_init(&rwlock, NULL);
|
||||
if (res != 0) {
|
||||
throw std::system_error(res, std::generic_category());
|
||||
throw pgf_systemerror(errno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,6 +329,8 @@ PgfDB::~PgfDB() {
|
||||
close(fd);
|
||||
|
||||
pthread_rwlock_destroy(&rwlock);
|
||||
|
||||
::free((void*) filepath);
|
||||
}
|
||||
|
||||
PGF_INTERNAL
|
||||
@@ -338,7 +342,7 @@ void PgfDB::sync()
|
||||
|
||||
int res = msync((void *) ms, size, MS_SYNC | MS_INVALIDATE);
|
||||
if (res != 0)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno);
|
||||
}
|
||||
|
||||
PGF_INTERNAL
|
||||
@@ -837,13 +841,13 @@ object PgfDB::malloc_internal(size_t bytes)
|
||||
|
||||
if (fd >= 0) {
|
||||
if (ftruncate(fd, new_size) < 0)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, filepath);
|
||||
}
|
||||
|
||||
malloc_state* new_ms =
|
||||
(malloc_state*) mremap(ms, old_size, new_size, MREMAP_MAYMOVE);
|
||||
if (new_ms == MAP_FAILED)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno);
|
||||
|
||||
ms = new_ms;
|
||||
current_base = (unsigned char*) ms;
|
||||
@@ -961,7 +965,7 @@ DB_scope::DB_scope(PgfDB *db, DB_scope_mode tp)
|
||||
(tp == READER_SCOPE) ? pthread_rwlock_rdlock(&db->rwlock)
|
||||
: pthread_rwlock_wrlock(&db->rwlock);
|
||||
if (res != 0)
|
||||
throw std::system_error(res, std::generic_category());
|
||||
throw pgf_systemerror(res);
|
||||
|
||||
save_db = current_db;
|
||||
current_db = db;
|
||||
@@ -978,7 +982,7 @@ DB_scope::~DB_scope()
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wterminate"
|
||||
if (res != 0)
|
||||
throw std::system_error(res, std::generic_category());
|
||||
throw pgf_systemerror(res);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
current_db = save_db;
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
class PgfDB {
|
||||
private:
|
||||
int fd;
|
||||
const char *filepath;
|
||||
malloc_state* ms;
|
||||
|
||||
pthread_rwlock_t rwlock;
|
||||
@@ -64,7 +65,7 @@ private:
|
||||
friend class PgfReader;
|
||||
|
||||
public:
|
||||
PGF_INTERNAL_DECL PgfDB(const char* pathname, int flags, int mode);
|
||||
PGF_INTERNAL_DECL PgfDB(const char* filepath, int flags, int mode);
|
||||
PGF_INTERNAL_DECL ~PgfDB();
|
||||
|
||||
template<class A>
|
||||
|
||||
@@ -23,16 +23,15 @@ PgfDB *pgf_read_pgf(const char* fpath,
|
||||
|
||||
try {
|
||||
db = new PgfDB(NULL, 0, 0);
|
||||
|
||||
std::ifstream in(fpath, std::ios::binary);
|
||||
if (in.fail()) {
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, fpath);
|
||||
}
|
||||
|
||||
{
|
||||
DB_scope scope(db, WRITER_SCOPE);
|
||||
|
||||
PgfReader rdr(&in);
|
||||
PgfReader rdr(&in, fpath);
|
||||
ref<PgfPGF> pgf = rdr.read_pgf();
|
||||
|
||||
PgfDB::set_root(pgf);
|
||||
@@ -40,14 +39,16 @@ PgfDB *pgf_read_pgf(const char* fpath,
|
||||
}
|
||||
|
||||
return db;
|
||||
} catch (std::system_error& e) {
|
||||
} catch (pgf_systemerror& e) {
|
||||
err->type = PGF_EXN_SYSTEM_ERROR;
|
||||
err->code = e.code().value();
|
||||
err->code = e.code();
|
||||
err->msg = e.filepath();
|
||||
} catch (pgf_error& e) {
|
||||
err->type = PGF_EXN_PGF_ERROR;
|
||||
err->msg = strdup(e.what());
|
||||
}
|
||||
|
||||
end:
|
||||
if (db != NULL)
|
||||
delete db;
|
||||
|
||||
@@ -68,13 +69,13 @@ PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path,
|
||||
|
||||
std::ifstream in(pgf_path, std::ios::binary);
|
||||
if (in.fail()) {
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, pgf_path);
|
||||
}
|
||||
|
||||
{
|
||||
DB_scope scope(db, WRITER_SCOPE);
|
||||
|
||||
PgfReader rdr(&in);
|
||||
PgfReader rdr(&in, pgf_path);
|
||||
ref<PgfPGF> pgf = rdr.read_pgf();
|
||||
|
||||
db->set_root<PgfPGF>(pgf);
|
||||
@@ -84,9 +85,10 @@ PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path,
|
||||
}
|
||||
|
||||
return db;
|
||||
} catch (std::system_error& e) {
|
||||
} catch (pgf_systemerror& e) {
|
||||
err->type = PGF_EXN_SYSTEM_ERROR;
|
||||
err->code = e.code().value();
|
||||
err->code = e.code();
|
||||
err->msg = e.filepath();
|
||||
} catch (pgf_error& e) {
|
||||
err->type = PGF_EXN_PGF_ERROR;
|
||||
err->msg = strdup(e.what());
|
||||
@@ -135,9 +137,10 @@ PgfDB *pgf_read_ngf(const char *fpath,
|
||||
}
|
||||
|
||||
return db;
|
||||
} catch (std::system_error& e) {
|
||||
} catch (pgf_systemerror& e) {
|
||||
err->type = PGF_EXN_SYSTEM_ERROR;
|
||||
err->code = e.code().value();
|
||||
err->code = e.code();
|
||||
err->msg = e.filepath();
|
||||
} catch (pgf_error& e) {
|
||||
err->type = PGF_EXN_PGF_ERROR;
|
||||
err->msg = strdup(e.what());
|
||||
@@ -431,9 +434,10 @@ PgfRevision pgf_clone_revision(PgfDB *db, PgfRevision revision,
|
||||
pgf->abstract.cats->ref_count++;
|
||||
|
||||
return new_pgf.as_object();
|
||||
} catch (std::system_error& e) {
|
||||
} catch (pgf_systemerror& e) {
|
||||
err->type = PGF_EXN_SYSTEM_ERROR;
|
||||
err->code = e.code().value();
|
||||
err->code = e.code();
|
||||
err->msg = e.filepath();
|
||||
} catch (pgf_error& e) {
|
||||
err->type = PGF_EXN_PGF_ERROR;
|
||||
err->msg = strdup(e.what());
|
||||
@@ -471,9 +475,10 @@ void pgf_create_function(PgfDB *db, PgfRevision revision,
|
||||
namespace_insert(pgf->abstract.funs, absfun);
|
||||
namespace_release(pgf->abstract.funs);
|
||||
pgf->abstract.funs = nmsp;
|
||||
} catch (std::system_error& e) {
|
||||
} catch (pgf_systemerror& e) {
|
||||
err->type = PGF_EXN_SYSTEM_ERROR;
|
||||
err->code = e.code().value();
|
||||
err->code = e.code();
|
||||
err->msg = e.filepath();
|
||||
} catch (pgf_error& e) {
|
||||
err->type = PGF_EXN_PGF_ERROR;
|
||||
err->msg = strdup(e.what());
|
||||
|
||||
@@ -55,6 +55,7 @@ typedef struct {
|
||||
* - If the exception was caused by external factors such as an error
|
||||
* from a system call, then type will be PGF_EXN_SYSTEM_ERROR and
|
||||
* the field code will contain the value of errno from the C runtime.
|
||||
* The field msg will be NULL or it may contain a file name.
|
||||
*
|
||||
* - If the exception was caused by factors related to the GF runtime
|
||||
* itself, then the error type is PGF_EXN_PGF_ERROR, and the field
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
PgfReader::PgfReader(std::istream *in)
|
||||
PgfReader::PgfReader(std::istream *in, const char *filepath)
|
||||
{
|
||||
this->in = in;
|
||||
this->filepath = filepath;
|
||||
}
|
||||
|
||||
uint8_t PgfReader::read_uint8()
|
||||
@@ -15,7 +16,7 @@ uint8_t PgfReader::read_uint8()
|
||||
if (in->eof())
|
||||
throw pgf_error("reached end of file while reading a grammar");
|
||||
if (in->fail())
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, filepath);
|
||||
|
||||
return b;
|
||||
}
|
||||
@@ -27,7 +28,7 @@ uint16_t PgfReader::read_u16be()
|
||||
if (in->eof())
|
||||
throw pgf_error("reached end of file while reading a grammar");
|
||||
if (in->fail())
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, filepath);
|
||||
|
||||
return (((uint16_t) buf[0]) << 8 | buf[1]);
|
||||
}
|
||||
@@ -39,7 +40,7 @@ uint64_t PgfReader::read_u64be()
|
||||
if (in->eof())
|
||||
throw pgf_error("reached end of file while reading a grammar");
|
||||
if (in->fail())
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, filepath);
|
||||
|
||||
return (((uint64_t) buf[0]) << 56 |
|
||||
((uint64_t) buf[1]) << 48 |
|
||||
@@ -95,7 +96,7 @@ object PgfReader::read_name_internal(size_t struct_size)
|
||||
if (in->eof())
|
||||
throw pgf_error("utf8 decoding error");
|
||||
if (in->fail())
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, filepath);
|
||||
|
||||
ptext->text[size] = 0;
|
||||
|
||||
@@ -131,7 +132,7 @@ object PgfReader::read_text_internal(size_t struct_size)
|
||||
if (in->eof())
|
||||
throw pgf_error("utf8 decoding error");
|
||||
if (in->fail())
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
throw pgf_systemerror(errno, filepath);
|
||||
|
||||
p += len;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
class PGF_INTERNAL_DECL PgfReader
|
||||
{
|
||||
public:
|
||||
PgfReader(std::istream *in);
|
||||
PgfReader(std::istream *in, const char *filepath);
|
||||
|
||||
uint8_t read_uint8();
|
||||
uint16_t read_u16be();
|
||||
@@ -74,6 +74,7 @@ public:
|
||||
|
||||
private:
|
||||
std::istream *in;
|
||||
const char* filepath;
|
||||
|
||||
object read_name_internal(size_t struct_size);
|
||||
object read_text_internal(size_t struct_size);
|
||||
|
||||
Reference in New Issue
Block a user