Added error handling

This commit is contained in:
2025-08-29 00:02:45 +02:00
parent f93c463647
commit df4e7777de
17 changed files with 144 additions and 17 deletions

View File

@ -15,6 +15,7 @@ set(FSH_SOURCE_FILES
src/ast/ast_print.cpp
src/util/input.cpp
src/util/text.cpp
src/util/error.cpp
src/cmd/arg.cpp
src/cmd/cmd_base.cpp
)

View File

@ -7,6 +7,7 @@
#include "lexer.hpp"
#include "util/text.hpp"
#include "util/error.hpp"
namespace fsh {
@ -67,9 +68,29 @@ namespace fsh {
private:
};
class AstBuildError : public std::runtime_error {
class AstBuildError : public util::LazyError {
public:
AstBuildError(std::string err) : std::runtime_error(err) {}
AstBuildError() {}
};
class AstUnexpectedTypeError : public AstBuildError {
public:
AstUnexpectedTypeError(Lexer::TokenType type) : type(type){};
private:
Lexer::TokenType type;
std::string build_msg() const noexcept override {
return (std::string) "Unexpected " + util::tokens[type];
};
};
class AstNoRedirectError : public AstBuildError {
private:
std::string build_msg() const noexcept override {
return "No redirects provided";
};
};
}

View File

@ -27,7 +27,7 @@ namespace fsh {
}
Command& get(const std::string n) {
if (cmds.find(n) == cmds.end()) { throw std::runtime_error("Command not found " + n); }
if (cmds.find(n) == cmds.end()) { throw util::CmdNotFoundError(n); }
return *(cmds[n]);
}

View File

@ -8,6 +8,7 @@
#include "ast/ast.hpp"
#include "cmd/args/arg.hpp"
#include "util/error.hpp"
namespace fsh {

View File

@ -17,7 +17,7 @@ namespace fsh {
virtual void run(std::istream& in, std::ostream& out, ArgManager& args) override {
if(std::remove(args.get<std::string>(0).value().c_str())) {
throw std::runtime_error("Could not delete file");
throw util::FileDeleteError();
}
}

View File

@ -15,7 +15,7 @@ namespace fsh {
virtual void run(std::istream& in, std::ostream& out, ArgManager& args) override {
auto name = *(args.get<std::string>(0));
if (std::ifstream(name, std::ios::in).good() || !std::ofstream(name, std::ios::out).is_open()) {
throw std::runtime_error("File exists");
throw util::FileExistsError();
}
}
};

View File

@ -33,7 +33,7 @@ namespace fsh {
protected:
std::string replace_all(std::string str,const std::string &what,const std::string &with) {
if(what == "") throw std::runtime_error("\"\" cannot be used as what");
if(what == "") throw util::CmdError("What cannot be empty string");
unsigned long long pos = str.find(what);

View File

@ -21,11 +21,11 @@ namespace fsh {
std::string filename = args.get<std::string>(0).value();
if(!std::ifstream(filename, std::ios_base::in)) {
throw std::runtime_error("File does not exist");
throw util::FileExistsError();
}
if(!std::ofstream(filename, std::ios_base::out)) {
throw std::runtime_error("Failed to truncate");
throw util::CmdError("Failed to truncate");
}
}

76
include/util/error.hpp Normal file
View File

@ -0,0 +1,76 @@
#pragma once
#include <stdexcept>
#include <optional>
namespace fsh::util {
// Generates msg only once what has been called
// Usefull for errors meant to be silently discarded frequently
class LazyError : public std::exception {
public:
LazyError() {}
LazyError(const std::string& msg_) : msg_(msg_) {}
LazyError(const char* msg_) : msg_(msg_) {}
const char* what() const noexcept override;
protected:
mutable std::optional<std::string> msg_;
virtual std::string build_msg() const noexcept;
};
class CmdNotFoundError : public LazyError {
public:
CmdNotFoundError(std::string cmd_) : cmd_(cmd_) {}
protected:
std::string build_msg() const noexcept override;
private:
std::string cmd_;
};
class CmdError : public LazyError {
public:
CmdError(const std::string& msg_) : LazyError(msg_) {}
CmdError(const char* msg_) : LazyError(msg_) {}
};
class RuntimeError : public std::exception {
public:
const char* msg_;
RuntimeError() = delete;
RuntimeError(const char* msg_) : msg_(msg_) {}
const char* what() const noexcept override;
};
class FileDeleteError : public RuntimeError {
public:
FileDeleteError() : RuntimeError("Error deleting file") {}
};
class FileExistsError : public RuntimeError {
public:
FileExistsError() : RuntimeError("File already exists") {}
};
class FileOpenError : public RuntimeError {
public:
FileOpenError() : RuntimeError("Failed to open file") {}
};
class DoubleInputError : public RuntimeError {
public:
DoubleInputError() : RuntimeError("Tried to set input twice") {}
};
class LexerError : public LazyError {
public:
LexerError(const std::string& msg_) : LazyError(msg_) {}
LexerError(const char* msg_) : LazyError(msg_) {}
};
}

View File

@ -4,6 +4,7 @@
#include <optional>
#include <fstream>
#include <stdexcept>
#include "error.hpp"
// Razlicite pomocne funkcije za tekstove
namespace fsh::util {
@ -25,19 +26,19 @@ namespace fsh::util {
static inline std::ifstream input(const std::string& x) {
std::ifstream in(x, std::ios::in);
if (!in) { throw std::runtime_error("Can't open file"); }
if (!in) { throw FileOpenError(); }
return in;
}
static inline std::ofstream output(const std::string& x) {
std::ofstream out(x, std::ios::out);
if (!out.is_open()) { throw std::runtime_error("Can't open file"); }
if (!out.is_open()) { throw FileOpenError(); }
return out;
}
static inline std::ofstream output_append(const std::string& x) {
std::ofstream out(x, std::ios::app | std::ios::out);
if (!out.is_open()) { throw std::runtime_error("Can't open file"); }
if (!out.is_open()) { throw FileOpenError(); }
return out;
}

View File

@ -14,6 +14,7 @@ fsh_source_files = [
'src/ast/ast_print.cpp',
'src/util/input.cpp',
'src/util/text.cpp',
'src/util/error.cpp',
'src/cmd/arg.cpp',
'src/cmd/cmd_base.cpp'
]

View File

@ -21,7 +21,7 @@ namespace fsh {
it++;
return std::shared_ptr<TokenNode<T>>(new TokenNode<T>(value));
} else {
throw AstBuildError(std::string("Got unexcpected: ") + util::tokens[token_type]);
throw AstUnexpectedTypeError(token_type);
}
return nullptr;
}
@ -56,7 +56,7 @@ namespace fsh {
auto Rr = Optional<RRedirectNode>(it);
if (!Lr) Lr = Optional<LRedirectNode>(it);
if (!Lr && !Rr) throw AstBuildError("No redirects where provided");
if (!Lr && !Rr) throw AstNoRedirectError();
return std::shared_ptr<RedirectsNode>(new RedirectsNode(Lr, Rr));
}

View File

@ -1,5 +1,6 @@
#include "cmd/args/arg.hpp"
#include "cmd/args/arg_generic.hpp"
#include "util/error.hpp"
#include <iostream>
#include <string>
@ -12,7 +13,7 @@ namespace fsh {
str = std::stringstream(txt);
} else {
file = std::ifstream(txt, std::ios::in);
if (!*file) { throw std::runtime_error("Failed to open file"); }
if (!*file) { throw util::FileOpenError(); }
}
}

View File

@ -1,6 +1,7 @@
#include "cmd/cmd_base.hpp"
#include "cmd/args/arg.hpp"
#include "util/input.hpp"
#include "util/error.hpp"
namespace fsh {
@ -13,7 +14,7 @@ namespace fsh {
arg_factory.parse(args, vec, flag);
if (arg_factory.ghas_input()) {
if (&args.get_input(0) != &util::cin && &in != &util::cin) {
throw std::runtime_error("Tried to set input to command twice");
throw util::DoubleInputError();
}
if (&args.get_input(0) != &util::cin) run(args.get_input(0), out, args);
else

View File

@ -4,6 +4,7 @@
#include <string>
#include "lexer.hpp"
#include "util/text.hpp"
#include "util/error.hpp"
namespace fsh {
@ -57,7 +58,7 @@ namespace fsh {
LexerStateMachine::State LexerStateMachine::handle_string_literal() {
const int c = parser.peek();
if (c == std::char_traits<char>::eof()) {
throw std::runtime_error("Excpected \" before \\n");
throw util::LexerError("Excpected \" before \\n");
} else if (c == '\"') {
parser.consume();
return set_type(Lexer::TokenType::STRING_LITERAL);
@ -72,7 +73,7 @@ namespace fsh {
if (util::contains(c, "\t><| ") || c == std::char_traits<char>::eof()) {
return set_type(type);
} else if (c == '\"') {
throw std::runtime_error("Invalid \"");
throw util::LexerError("Invalid \"");
} else {
token += parser.consume();
return state;

22
src/util/error.cpp Normal file
View File

@ -0,0 +1,22 @@
#include <util/error.hpp>
namespace fsh::util {
const char* LazyError::what() const noexcept {
if(!msg_) {
msg_.emplace(build_msg());
}
return msg_->c_str();
}
std::string CmdNotFoundError::build_msg() const noexcept {
return "Command not found " + cmd_;
}
std::string LazyError::build_msg() const noexcept { return ""; }
const char* RuntimeError::what() const noexcept {
return msg_;
}
}

View File

@ -14,6 +14,7 @@ set(FSH_SOURCE_FILES
src/ast/ast_print.cpp
src/util/input.cpp
src/util/text.cpp
src/util/error.cpp
src/cmd/arg.cpp
src/cmd/cmd_base.cpp
)