Daily update

This commit is contained in:
Андреев Григорий 2024-08-12 00:12:30 +03:00
parent 581a4620de
commit 9f7903cae8
9 changed files with 206 additions and 119 deletions

View File

@ -34,6 +34,7 @@ struct CAWebChat {
BuildUnitsArray runlevel_2; BuildUnitsArray runlevel_2;
std::string build_type; std::string build_type;
bool build_tests = false;
std::vector<std::string> warning_flags = {"-Wall", "-Wno-unused-variable", "-Werror=return-type","-pedantic", std::vector<std::string> warning_flags = {"-Wall", "-Wno-unused-variable", "-Werror=return-type","-pedantic",
"-Wno-unused-but-set-variable", "-Wno-reorder"}; "-Wno-unused-but-set-variable", "-Wno-reorder"};
@ -57,8 +58,8 @@ struct CAWebChat {
return my_flag_collection; return my_flag_collection;
} }
CAWebChat(std::string _build_type, const NormalCBuildSystemCommandMeaning& cmd) CAWebChat(const std::string& _build_type, bool _build_tests, const NormalCBuildSystemCommandMeaning& cmd)
: build_type(std::move(_build_type)) : build_type(_build_type), build_tests(_build_tests)
{ {
ASSERT(build_type == "release" || build_type == "debug", "Unknown build type"); ASSERT(build_type == "release" || build_type == "debug", "Unknown build type");
@ -162,7 +163,9 @@ int main(int argc, char** argv) {
} }
NormalCBuildSystemCommandMeaning cmd; NormalCBuildSystemCommandMeaning cmd;
regular_bs_cli_cmd_interpret(args, cmd); regular_bs_cli_cmd_interpret(args, cmd);
CAWebChat bs("debug", cmd); const char* BS_SCRIPT_TYPE = getenv("BS_SCRIPT_TYPE");
const char* BS_SCRIPT_TESTS = getenv("BS_SCRIPT_TESTS");
CAWebChat bs(BS_SCRIPT_TYPE ? BS_SCRIPT_TYPE : "release", (bool)BS_SCRIPT_TESTS, cmd);
if (cmd.need_to_build) if (cmd.need_to_build)
complete_tasks_of_build_units(bs.runlevel_1); complete_tasks_of_build_units(bs.runlevel_1);
umask(~0755); umask(~0755);

View File

@ -3,6 +3,7 @@
#include <algorithm> #include <algorithm>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <vector>
namespace nytl { namespace nytl {
FUp::FUp(const std::string &err, const std::string &file, const std::string &func, int line){ FUp::FUp(const std::string &err, const std::string &file, const std::string &func, int line){
@ -45,7 +46,7 @@ namespace nytl {
return ch == ' ' || ch == '\r' || ch == '\t' || ch == '\r'; return ch == ' ' || ch == '\r' || ch == '\t' || ch == '\r';
} }
bool isUname(const std::string &str) noexcept { bool isUname(const std::string &str) {
if (str.empty() || str == "_") if (str.empty() || str == "_")
return false; return false;
if (isNUM(str[0])) if (isNUM(str[0]))
@ -55,4 +56,21 @@ namespace nytl {
return false; return false;
return true; return true;
} }
bool is_uname_dotted_sequence(const std::string& uinp) {
if (uinp.empty())
return false;
std::vector<std::string> r = {""};
for (char ch: uinp) {
if (ch == '.') {
r.emplace_back();
} else {
r.back() += ch;
}
}
for (const std::string& c: r)
if (!isUname(c))
return false;
return true;
}
} }

View File

@ -22,11 +22,9 @@ namespace nytl {
std::string prettyprint_errno(const std::string& pref); std::string prettyprint_errno(const std::string& pref);
#define THROW(err) throw FUp(err, __FILE__, __func__, __LINE__) #define THROW(err) throw FUp(err, __FILE__, __func__, __LINE__)
#define THROW_on_errno(err) THROW(prettyprint_errno(err)) #define THROW_on_errno(err) THROW(prettyprint_errno(err))
#define THROW_on_errno_pl() THROW(prettyprint_errno(""))
#define ASSERT(cond, err) do { if (!(cond)) { THROW(err); } } while (0); #define ASSERT(cond, err) do { if (!(cond)) { THROW(err); } } while (0);
#define ASSERT_pl(cond) ASSERT(cond, "Failed assertion `" #cond "`") #define ASSERT_pl(cond) ASSERT(cond, "Failed assertion `" #cond "`")
#define ASSERT_on_iret(iret, err) ASSERT((iret) >= 0, prettyprint_errno(err)); #define ASSERT_on_iret(iret, err) ASSERT((iret) >= 0, prettyprint_errno(err));
#define ASSERT_on_iret_pl(iret) ASSERT(iret >= 0, prettyprint_errno(""));
bool endsIn(const std::string& a, const std::string& b); bool endsIn(const std::string& a, const std::string& b);
@ -37,7 +35,8 @@ namespace nytl {
bool isUNCHAR(char ch); bool isUNCHAR(char ch);
bool isSPACE(char ch); bool isSPACE(char ch);
bool isUname(const std::string& str) noexcept; bool isUname(const std::string& str);
bool is_uname_dotted_sequence(const std::string& uinp);
} }
#endif #endif

View File

@ -18,11 +18,11 @@ namespace nytl {
/* No new JSON object will ever be created, I have one root json argument, /* No new JSON object will ever be created, I have one root json argument,
* all the other json variables are subtrees of it */ * all the other json variables are subtrees of it */
LocalVarValue rendering_core_execute_expression(global_elem_set_t& global_elems, LocalVarValue rendering_core_execute_expression(const global_elem_set_t& global_elems,
const std::vector<LocalVarValue>& local_vars, json::JSON& expr); const std::vector<LocalVarValue>& local_vars, const json::JSON& expr);
std::string rendering_core(const std::string& entry_func, const std::vector<json::JSON>& entry_arguments, std::string rendering_core(const std::string& entry_func, const std::vector<json::JSON>& entry_arguments,
std::map<std::string, Element>& elem_ns, const std::function<std::string(std::string)>& escape); const global_elem_set_t& elem_ns, const std::function<std::string(std::string)>& escape);
} }
#endif #endif

View File

@ -3,42 +3,88 @@
#include <assert.h> #include <assert.h>
namespace nytl { namespace nytl {
struct Frame { struct EEFrame {
json::JSON& expr; const json::JSON& expr;
LocalVarValue& result; LocalVarValue& result;
LocalVarValue temp_ret; LocalVarValue temp_ret;
size_t chain_el = 0; size_t chain_el = 0;
Frame(json::JSON &expr, LocalVarValue &result) EEFrame(const json::JSON &expr, LocalVarValue &result)
: expr(expr), : expr(expr),
result(result) { result(result) {
} }
uptr<Frame> toMe(bool returned_from_bottom, global_elem_set_t& global_elems, void descend(const json::JSON& what) {
if (result.is_json) {
const json::JSON& P = *result.JSON_subval;
if (P.isArray() && what.isInteger()) {
const std::vector<json::JSON> arr_p = P.asArray();
int64_t ind_w = what.asInteger().get_int();
ASSERT(ind_w > 0 && ind_w < arr_p.size(), "Expression \"array[integer]\" caused out-of-bound situation");
result = LocalVarValue{true, "", &arr_p[ind_w]};
} else if (P.isDictionary() && what.isString()) {
const std::map<std::string, json::JSON> dict_p = P.asDictionary();
const std::string& key_w = what.asString();
ASSERT(dict_p.count(key_w) == 1, "No such key exception");
result = LocalVarValue{true, "", &dict_p.at(key_w)};
} else
THROW("Incorrect type of \"json[json]\" expression. Unallowed signature of [] operator");
} else {
ASSERT(what.isString(), "Expression \"element[X]\" allowed only if X is string (json object)");
if (what.asString().empty())
return;
if (!is_uname_dotted_sequence(what.asString()))
THROW("Incorrect X in \"element[X]\"");
result.EL_name += ("." + what.asString());
}
}
uptr<EEFrame> toMe(bool returned, const global_elem_set_t& global_elems,
const std::vector<LocalVarValue>& local_vars) { const std::vector<LocalVarValue>& local_vars) {
if (returned_from_bottom) { if (returned) {
ASSERT(temp_ret.is_json, "Expression \"[ element ]\" is not allowed"); ASSERT(temp_ret.is_json, "Expression \"X[ element ]\" is not allowed");
assert(temp_ret.JSON_subval); assert(temp_ret.JSON_subval);
// json::JSON descend(*(temp_ret.JSON_subval));
// todo: make usable const JSON
} else { } else {
assert(expr.isDictionary()); assert(expr.isDictionary());
if ((*expr["V"]).isInteger()) { const json::JSON& val = expr["V"].g();
size_t lv_ind = (*expr["V"]).asInteger().get_int(); if (val.isInteger()) {
size_t lv_ind = val.asInteger().get_int();
assert(lv_ind < local_vars.size()); assert(lv_ind < local_vars.size());
result = local_vars[lv_ind]; result = local_vars[lv_ind];
} else if ((*expr["V"]).isString()) { } else if (val.isString()) {
std::string cur_el_name_str = (*expr["V"]).asString(); std::string cur_el_name_str = expr["V"].g().asString();
result = LocalVarValue{false, cur_el_name_str, NULL}; result = LocalVarValue{false, cur_el_name_str, NULL};
} else } else
assert(false); assert(false);
} }
if (chain_el == (*expr["C"]).) while (true) {
const std::vector<json::JSON>& chain = expr["C"].g().asArray();
if (chain_el >= chain.size())
return NULL;
const json::JSON& t = chain[chain_el++];
if (t.isDictionary())
return std::make_unique<EEFrame>(t, temp_ret);
descend(t);
}
} }
}; };
LocalVarValue rendering_core_execute_expression(global_elem_set_t& global_elems, LocalVarValue rendering_core_execute_expression(const global_elem_set_t& global_elems,
const std::vector<LocalVarValue>& local_vars, json::JSON& expr) { const std::vector<LocalVarValue>& local_vars, const json::JSON& expr) {
bool returned = false;
std::vector<uptr<EEFrame>> stack;
LocalVarValue result;
stack.push_back(std::make_unique<EEFrame>(expr, result));
while (!stack.empty()) {
EEFrame& cur = *stack.back();
uptr<EEFrame> todo = cur.toMe(returned, global_elems, local_vars);
returned = (bool)todo;
if (todo)
stack.push_back(todo);
else
stack.pop_back();
}
return result;
} }
} }

View File

@ -1,47 +1,15 @@
#include "core.h" #include "core.h"
#include "alotalot.h" #include "alotalot.h"
#include <string.h> #include <string.h>
#include <libjsonincpp/string_representation.h> #include <jsonincpp/string_representation.h>
#include <assert.h> #include <assert.h>
namespace nytl { namespace nytl {
std::string rendering_core(const std::string& entry_func, const std::vector<json::JSON>& entry_arguments, struct Ditch {
std::map<std::string, Element>& elem_ns, const std::function<std::string(std::string)>& escape)
{
size_t cur_line_width = 0;
std::string result; std::string result;
size_t cur_line_width = 0;
struct Frame { void append(const std::string& text) {
const Element* el = NULL;
/* Use by base elements to distinguish them */
std::string base_name;
size_t part_to_do = 0;
std::vector<LocalVarValue> passed_args;
/* This parameter incapsulates `cur_line_width` at some point for multiline `put-parts` */
size_t multiline_put_start = 0;
};
std::vector<uptr<Frame>> stack;
auto make_frame = [&](const std::string& name, std::vector<LocalVarValue> passed_args){
const Element* el = &elem_ns[name];
Frame* us = new Frame{el, el->base ? name : "", 0, std::move(passed_args), cur_line_width};
stack.push_back(uptr<Frame>(us));
};
ASSERT(elem_ns.count(entry_func) == 1, "No such element " + entry_func);
const Element& el = elem_ns[entry_func];
ASSERT(el.arguments.size() == entry_arguments.size(), "Signature mismatch " + entry_func);
for (const json::JSON& sigtbj: el.arguments) {
ASSERT(sigtbj.type == json::true_symbol, "Signature mismatch. Entry element can take only JSON arguments");
}
{
size_t AN = entry_arguments.size();
std::vector<LocalVarValue> entry_arguments_conv(AN);
for (size_t i = 0; i < AN; i++)
entry_arguments_conv[i] = {"", &entry_arguments[i]};
make_frame(entry_func, entry_arguments_conv);
}
auto append2res = [&](const std::string& text) {
size_t n = result.size(); size_t n = result.size();
result.resize(n + text.size()); result.resize(n + text.size());
memcpy((void*)&result.c_str()[n], text.c_str(), text.size()); memcpy((void*)&result.c_str()[n], text.c_str(), text.size());
@ -51,48 +19,116 @@ namespace nytl {
else else
cur_line_width++; cur_line_width++;
} }
}; }
auto linefeed2res = [&]() { };
result += "\n";
cur_line_width = 0; #define RFrame_passed const global_elem_set_t& elem_ns, Ditch& result, const std::function<std::string(std::string)>& escape
}; struct RFrame {
while (!stack.empty()) { virtual uptr<RFrame> toMe(bool returned, RFrame_passed) {assert(false);}
Frame& cur = *stack.back();
if (cur.el->base) { virtual ~RFrame() = default;
assert(cur.passed_args.size() == 1); };
const json::JSON* X = cur.passed_args[0].JSON_subval;
assert(X); struct RFrame_OverParts : public RFrame{
if (cur.base_name == "jesc") { std::string name;
append2res(escape(json::generate_str(*X, json::print_pretty))); std::vector<LocalVarValue> passed_args;
} else if (cur.base_name == "str2text") { /* This parameter incapsulates `cur_line_width` at some point for multiline `put-parts` */
ASSERT(X->isString(), "str2text takes json string"); size_t multiline_put_start = 0;
append2res(escape(X->asString())); /* main iterator of this frame. Persistent across control returns */
} else if (cur.base_name == "str2code") { size_t part_to_do = 0;
ASSERT(X->isString(), "str2code takes json string");
append2res(X->asString()); RFrame_OverParts(const std::string &name, const std::vector<LocalVarValue> &passed_args,
size_t multiline_put_start)
: name(name),
passed_args(passed_args),
multiline_put_start(multiline_put_start) {
}
uptr<RFrame> toMe(bool returned, RFrame_passed) override {
if (!returned)
ASSERT(elem_ns.count(name) == 1, "No such element");
const Element& el = elem_ns.at(name);
if (!returned) {
/* Continue to do checks */
size_t n = el.arguments.size();
ASSERT(n == passed_args.size(), "Argument count mismatch");
for (size_t i = 0; i < n; i++) {
if (el.arguments[i].type == json::true_symbol) {
ASSERT(passed_args[i].is_json, "Expected json element argument, got element");
} else {
// If not json is expected, element must be expected
assert(el.arguments[i].isArray());
ASSERT(!passed_args[i].is_json, "Expected element element arguemnt, got json");
ASSERT(elem_ns.count(passed_args[i].EL_name), "No such element, can't compare signatures of argument value");
const Element& arg_element = elem_ns.at(passed_args[i].EL_name);
// ASSERT(passed_args);
if(el.arguments[i].asArray() != arg_element.arguments)
THROW("Signature of argument " + std::to_string(i) + " does not match");
}
} }
stack.pop_back();
continue;
} }
if (cur.part_to_do == cur.el->parts.size()) { if (el.base) {
stack.pop_back(); assert(!returned);
continue; assert(passed_args.size() == 1);
const json::JSON* X = passed_args[0].JSON_subval;
assert(X);
if (name == "jesc") {
result.append(escape(json::generate_str(*X, json::print_pretty)));
} else if (name == "str2text") {
ASSERT(X->isString(), "str2text takes json string");
result.append(escape(X->asString()));
} else if (name == "str2code") {
ASSERT(X->isString(), "str2code takes json string");
result.append(X->asString());
}
return NULL;
} }
const ElementPart& cur_part = cur.el->parts[cur.part_to_do++]; while (true) {
if (cur_part.type == element_part_types::code) { if (part_to_do == el.parts.size())
const ElementPart::when_code_S& pt = cur_part.when_code; return NULL;
append2res(pt.lines); const ElementPart& cur_part = el.parts[part_to_do++];
} else if (cur_part.type == element_part_types::put) { if (cur_part.type == element_part_types::code) {
const ElementPart::when_put_S& pt = cur_part.when_put; const ElementPart::when_code_S& pt = cur_part.when_code;
// todo result.append(pt.lines);
} else if (cur_part.type == element_part_types::for_put) { } else if (cur_part.type == element_part_types::put) {
const ElementPart::when_for_put_S& pt = cur_part.when_for_put; const ElementPart::when_put_S& pt = cur_part.when_put;
// todo LocalVarValue called_element_expv = rendering_core_execute_expression(elem_ns, passed_args, pt.called_element);
} else if (cur_part.type == element_part_types::ref_put) { ASSERT(!called_element_expv.is_json, "Can't PUT json variable");
const ElementPart::when_ref_put_S& pt = cur_part.when_ref_put; size_t AN = pt.passed_arguments.size();
// todo std::vector<LocalVarValue> passed_arguments_expv(AN);
for (size_t i = 0; i < AN; i++)
passed_arguments_expv[i] = rendering_core_execute_expression(elem_ns, passed_args, pt.passed_arguments[i]);
return uptr<RFrame>(new RFrame_OverParts(called_element_expv.EL_name, passed_arguments_expv, result.cur_line_width));
} else if (cur_part.type == element_part_types::for_put) {
const ElementPart::when_for_put_S& pt = cur_part.when_for_put;
// todo
} else if (cur_part.type == element_part_types::ref_put) {
const ElementPart::when_ref_put_S& pt = cur_part.when_ref_put;
// todo
}
} }
} }
return result; };
std::string rendering_core(const std::string& entry_func, const std::vector<json::JSON>& entry_arguments,
const global_elem_set_t& elem_ns, const std::function<std::string(std::string)>& escape)
{
Ditch result;
std::vector<uptr<RFrame>> stack;
{
size_t AN = entry_arguments.size();
std::vector<LocalVarValue> entry_arguments_conv(AN);
for (size_t i = 0; i < AN; i++)
entry_arguments_conv[i] = {true, "", &entry_arguments[i]};
// stack.push_back(std::make_unique<>());
// make_frame(entry_func, entry_arguments_conv);
}
while (!stack.empty()) {
// Frame& cur = *stack.back();
}
return result.result;
} }
} }

View File

@ -126,24 +126,9 @@ namespace nytl {
} }
} }
void check_uinp_element(const std::string& uinp) {
if (uinp.empty())
THROW("empty???");
std::vector<std::string> r = {""};
for (char ch: uinp) {
if (ch == '.') {
r.emplace_back();
} else {
r.back() += ch;
}
}
for (const std::string& c: r)
ASSERT(isUname(c), "Incorrect name component");
}
/* Still can throw some stuff derived from std::exception (like bad alloc) */ /* Still can throw some stuff derived from std::exception (like bad alloc) */
std::string Templater::render(const std::string& element, const std::vector<json::JSON> &arguments) const { std::string Templater::render(const std::string& element, const std::vector<json::JSON> &arguments) const {
check_uinp_element(element); ASSERT(is_uname_dotted_sequence(element), "Incorrect entry element name");
return rendering_core(element, arguments, elements); return rendering_core(element, arguments, elements, settings.escape);
} }
} }

View File

@ -3,7 +3,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <libjsonincpp/jsonobj.h> #include <jsonincpp/jsonobj.h>
#include <functional> #include <functional>
#include "html_case.h" #include "html_case.h"

View File

@ -5,7 +5,7 @@
#include <engine_engine_number_9/connecting_assets/static_asset_manager.h> #include <engine_engine_number_9/connecting_assets/static_asset_manager.h>
#include <assert.h> #include <assert.h>
#include <sqlite3.h> #include <sqlite3.h>
#include <libjsonincpp/string_representation.h> #include <jsonincpp/string_representation.h>
#include <libregexis024vm/vm_opcodes.h> #include <libregexis024vm/vm_opcodes.h>
#include <engine_engine_number_9/form_data_structure/urlencoded_query.h> #include <engine_engine_number_9/form_data_structure/urlencoded_query.h>