diff --git a/src/runtime/c/pgf/linearizer.cxx b/src/runtime/c/pgf/linearizer.cxx index 9fdc583be..a1090fb0e 100644 --- a/src/runtime/c/pgf/linearizer.cxx +++ b/src/runtime/c/pgf/linearizer.cxx @@ -56,7 +56,7 @@ PgfLinearizer::TreeNode::TreeNode(PgfLinearizer *linearizer) linearizer->prev = this; } -void PgfLinearizer::TreeNode::linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r) +bool PgfLinearizer::TreeNode::linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r) { TreeNode *arg = args; while (d > 0) { @@ -67,7 +67,7 @@ void PgfLinearizer::TreeNode::linearize_arg(PgfLinearizationOutputIface *out, Pg } if (arg == NULL) throw pgf_error("Missing argument"); - arg->linearize(out, linearizer, r); + return arg->linearize(out, linearizer, r); } void PgfLinearizer::TreeNode::linearize_var(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r) @@ -87,7 +87,7 @@ void PgfLinearizer::TreeNode::linearize_var(PgfLinearizationOutputIface *out, Pg out->symbol_token(linearizer->printer.get_text()); } -void PgfLinearizer::TreeNode::linearize_item(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, Item *item, vector syms) +bool PgfLinearizer::TreeNode::linearize_item(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, Item *item, vector syms) { for (size_t i = 0; i < syms.size(); i++) { PgfSymbol sym = syms[i]; @@ -96,13 +96,15 @@ void PgfLinearizer::TreeNode::linearize_item(PgfLinearizationOutputIface *out, P case PgfSymbolCat::tag: { auto sym_cat = ref::untagged(sym); size_t r = item->eval(ref::from_ptr(&sym_cat->r)); - linearize_arg(out, linearizer, sym_cat->d, r); + if (!linearize_arg(out, linearizer, sym_cat->d, r)) + return false; break; } case PgfSymbolLit::tag: { auto sym_lit = ref::untagged(sym); size_t r = item->eval(ref::from_ptr(&sym_lit->r)); - linearize_arg(out, linearizer, sym_lit->d, r); + if (!linearize_arg(out, linearizer, sym_lit->d, r)) + return false; break; } case PgfSymbolVar::tag: { @@ -205,6 +207,8 @@ void PgfLinearizer::TreeNode::linearize_item(PgfLinearizationOutputIface *out, P break; } } + + return true; } PgfLinearizer::TreeLinNode::TreeLinNode(PgfLinearizer *linearizer, ref lin) @@ -261,13 +265,6 @@ bool PgfLinearizer::TreeLinNode::resolve(PgfLinearizer *linearizer) rule_index++; } - for (size_t i = 0; i < lin->lincat->fields.size(); i++) { - if (items[i] == NULL) { - rule_index = 0; - return false; - } - } - return true; } @@ -276,8 +273,11 @@ bool PgfLinearizer::TreeLinNode::check_category(PgfLinearizer *linearizer, PgfTe return (textcmp(&lin->absfun->type->name, cat) == 0); } -void PgfLinearizer::TreeLinNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex) +bool PgfLinearizer::TreeLinNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex) { + if (items[lindex] == NULL) + return false; + PgfText *cat = &lin->absfun->type->name; PgfText *field = &*lin->lincat->fields[lindex]; @@ -294,8 +294,9 @@ void PgfLinearizer::TreeLinNode::linearize(PgfLinearizationOutputIface *out, Pgf linearizer->pre_stack->bracket_stack = bracket; } - linearize_item(out, linearizer, - items[lindex],items[lindex]->rule->syms.as_vector()); + if (!linearize_item(out, linearizer, + items[lindex],items[lindex]->rule->syms.as_vector())) + return false; if (linearizer->pre_stack == NULL) out->end_phrase(cat, fid, field, &lin->name); @@ -309,6 +310,8 @@ void PgfLinearizer::TreeLinNode::linearize(PgfLinearizationOutputIface *out, Pgf bracket->fun = &lin->name; linearizer->pre_stack->bracket_stack = bracket; } + + return true; } ref PgfLinearizer::TreeLinNode::get_lincat(PgfLinearizer *linearizer) @@ -410,23 +413,24 @@ bool PgfLinearizer::TreeLindefNode::check_category(PgfLinearizer *linearizer, Pg return true; } -void PgfLinearizer::TreeLindefNode::linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r) +bool PgfLinearizer::TreeLindefNode::linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r) { linearizer->flush_pre_stack(out, literal); out->symbol_token(literal); TreeNode *arg = args; while (arg != NULL) { - arg->linearize(out,linearizer,0); + if (!arg->linearize(out,linearizer,0)) + return false; arg = arg->next_arg; } + return true; } -void PgfLinearizer::TreeLindefNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex) +bool PgfLinearizer::TreeLindefNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex) { if (lincat==0) { - linearize_arg(out, linearizer, 0, 0); - return; + return linearize_arg(out, linearizer, 0, 0); } PgfText *cat = &lincat->name; @@ -445,8 +449,9 @@ void PgfLinearizer::TreeLindefNode::linearize(PgfLinearizationOutputIface *out, linearizer->pre_stack->bracket_stack = bracket; } - linearize_item(out, linearizer, - items[lindex],items[lindex]->rule->syms.as_vector()); + if (!linearize_item(out, linearizer, + items[lindex],items[lindex]->rule->syms.as_vector())) + return false; if (linearizer->pre_stack == NULL) out->end_phrase(cat, fid, field, linearizer->wild); @@ -460,6 +465,7 @@ void PgfLinearizer::TreeLindefNode::linearize(PgfLinearizationOutputIface *out, bracket->fun = linearizer->wild; linearizer->pre_stack->bracket_stack = bracket; } + return true; } ref PgfLinearizer::TreeLindefNode::get_lincat(PgfLinearizer *linearizer) @@ -537,13 +543,13 @@ bool PgfLinearizer::TreeLinrefNode::resolve(PgfLinearizer *linearizer) return true; } -void PgfLinearizer::TreeLinrefNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex) +bool PgfLinearizer::TreeLinrefNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex) { ref lincat = args->get_lincat(linearizer); if (lincat != 0) { - linearize_item(out, linearizer, item, item->rule->syms.as_vector()); + return linearize_item(out, linearizer, item, item->rule->syms.as_vector()); } else { - args->linearize(out, linearizer, lindex); + return args->linearize(out, linearizer, lindex); } } @@ -569,7 +575,7 @@ bool PgfLinearizer::TreeLitNode::check_category(PgfLinearizer *linearizer, PgfTe return (textcmp(&lincat->name, cat) == 0); } -void PgfLinearizer::TreeLitNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex) +bool PgfLinearizer::TreeLitNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex) { PgfText *field = NULL; if (lincat != 0) { @@ -583,6 +589,8 @@ void PgfLinearizer::TreeLitNode::linearize(PgfLinearizationOutputIface *out, Pgf out->symbol_token(literal); if (lincat != 0) out->end_phrase(&lincat->name, fid, field, linearizer->wild); + + return true; } ref PgfLinearizer::TreeLitNode::get_lincat(PgfLinearizer *linearizer) diff --git a/src/runtime/c/pgf/linearizer.h b/src/runtime/c/pgf/linearizer.h index 0976de2fa..7fb99a5ab 100644 --- a/src/runtime/c/pgf/linearizer.h +++ b/src/runtime/c/pgf/linearizer.h @@ -83,10 +83,10 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { TreeNode(PgfLinearizer *linearizer); virtual bool resolve(PgfLinearizer *linearizer) { return true; }; virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat)=0; - virtual void linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r); + virtual bool linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r); virtual void linearize_var(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r); - virtual void linearize_item(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, Item *item, vector syms); - virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)=0; + virtual bool linearize_item(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, Item *item, vector syms); + virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)=0; virtual ref get_lincat(PgfLinearizer *linearizer)=0; virtual ~TreeNode() { free(hoas_vars); }; }; @@ -99,7 +99,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { TreeLinNode(PgfLinearizer *linearizer, ref lin); virtual bool resolve(PgfLinearizer *linearizer); virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat); - virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); + virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); virtual ref get_lincat(PgfLinearizer *linearizer); virtual ~TreeLinNode(); }; @@ -114,8 +114,8 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { TreeLindefNode(PgfLinearizer *linearizer, PgfText *fun, PgfText *lit); virtual bool resolve(PgfLinearizer *linearizer); virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat); - virtual void linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r); - virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); + virtual bool linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r); + virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); virtual ref get_lincat(PgfLinearizer *linearizer); ~TreeLindefNode(); }; @@ -127,7 +127,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { TreeLinrefNode(PgfLinearizer *linearizer, TreeNode *root); virtual bool resolve(PgfLinearizer *linearizer); virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat) { return true; }; - virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); + virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); virtual ref get_lincat(PgfLinearizer *linearizer); ~TreeLinrefNode(); }; @@ -138,7 +138,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { TreeLitNode(PgfLinearizer *linearizer, ref lincat, PgfText *lit); virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat); - virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); + virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); virtual ref get_lincat(PgfLinearizer *linearizer); ~TreeLitNode() { free(literal); }; }; @@ -147,7 +147,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { TreeChunksNode(PgfLinearizer *linearizer); virtual bool resolve(PgfLinearizer *linearizer); virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat); - virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); + virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); virtual ref get_lincat(PgfLinearizer *linearizer); }; @@ -191,9 +191,11 @@ public: bool resolve(); void reverse_and_label(bool add_linref); - void linearize(PgfLinearizationOutputIface *out, size_t lindex) { - prev->linearize(out, this, lindex); + bool linearize(PgfLinearizationOutputIface *out, size_t lindex) { + if (!prev->linearize(out, this, lindex)) + return false; flush_pre_stack(out, NULL); + return true; } ref get_lincat() { return prev->get_lincat(this); diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index e71c913eb..2db16e1ef 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -2530,7 +2530,10 @@ PgfText *pgf_linearize(PgfDB *db, PgfConcrRevision revision, m->match_expr(&linearizer, expr); linearizer.reverse_and_label(true); if (linearizer.resolve()) { - linearizer.linearize(&out, 0); + if (!linearizer.linearize(&out, 0)) { + free(out.get_text()); + return NULL; + } return out.get_text(); } } PGF_API_END @@ -2594,12 +2597,13 @@ PgfText **pgf_tabular_linearize(PgfDB *db, PgfConcrRevision revision, throw pgf_systemerror(ENOMEM); size_t pos = 0; for (size_t i = 0; i < lincat->fields.size(); i++) { - linearizer.linearize(&out, i); - + bool ok = linearizer.linearize(&out, i); PgfText *text = out.get_text(); - if (text != NULL) { + if (ok) { res[pos++] = textdup(&*lincat->fields[i]); res[pos++] = text; + } else { + free(text); } } res[pos++] = NULL;