diff --git a/src/runtime/c/pgf/linearizer.cxx b/src/runtime/c/pgf/linearizer.cxx index b2152e3e1..c91bcb953 100644 --- a/src/runtime/c/pgf/linearizer.cxx +++ b/src/runtime/c/pgf/linearizer.cxx @@ -522,9 +522,10 @@ bool PgfLinearizer::resolve() return true; } -void PgfLinearizer::reverse_and_label() +void PgfLinearizer::reverse_and_label(bool add_linref) { - new TreeLinrefNode(this, root); + if (add_linref) + new TreeLinrefNode(this, root); // Reverse the list of nodes and label them with fid; int fid = 0; @@ -710,6 +711,7 @@ PgfText *PgfLinearizationOutput::get_text() free(printer.get_text()); return NULL; } + bind = true; return printer.get_text(); } diff --git a/src/runtime/c/pgf/linearizer.h b/src/runtime/c/pgf/linearizer.h index 78ead3802..816a83fb9 100644 --- a/src/runtime/c/pgf/linearizer.h +++ b/src/runtime/c/pgf/linearizer.h @@ -134,11 +134,14 @@ public: PgfLinearizer(PgfPrintContext *ctxt, ref concr, PgfMarshaller *m); bool resolve(); - void reverse_and_label(); - void linearize(PgfLinearizationOutputIface *out) { - root->linearize(out, this, 0); + void reverse_and_label(bool add_linref); + void linearize(PgfLinearizationOutputIface *out, size_t lindex) { + root->linearize(out, this, lindex); flush_pre_stack(out, NULL); } + ref get_lincat() { + return root->get_lincat(this); + } ~PgfLinearizer(); diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index b976ef492..2321cf025 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -2005,9 +2005,9 @@ PgfText *pgf_linearize(PgfDB *db, PgfConcrRevision revision, PgfLinearizationOutput out; PgfLinearizer linearizer(ctxt, concr, m); m->match_expr(&linearizer, expr); - linearizer.reverse_and_label(); + linearizer.reverse_and_label(true); if (linearizer.resolve()) { - linearizer.linearize(&out); + linearizer.linearize(&out, 0); return out.get_text(); } } PGF_API_END @@ -2015,6 +2015,43 @@ PgfText *pgf_linearize(PgfDB *db, PgfConcrRevision revision, return NULL; } +PGF_API +PgfText **pgf_tabular_linearize(PgfDB *db, PgfConcrRevision revision, + PgfExpr expr, PgfPrintContext *ctxt, + PgfMarshaller *m, size_t *n_fields, + PgfExn* err) +{ + PGF_API_BEGIN { + DB_scope scope(db, READER_SCOPE); + + ref concr = PgfDB::revision2concr(revision); + PgfLinearizationOutput out; + PgfLinearizer linearizer(ctxt, concr, m); + m->match_expr(&linearizer, expr); + linearizer.reverse_and_label(false); + if (linearizer.resolve()) { + ref lincat = linearizer.get_lincat(); + PgfText **res = (PgfText **) + malloc(lincat->fields->len*2*sizeof(PgfText*)); + size_t pos = 0; + for (size_t i = 0; i < lincat->fields->len; i++) { + linearizer.linearize(&out, i); + + PgfText *text = out.get_text(); + if (text != NULL) { + res[pos] = textdup(&(*lincat->fields->data[i])); + res[pos+1] = text; + pos += 2; + } + } + *n_fields = pos/2; + return res; + } + } PGF_API_END + + return NULL; +} + PGF_API_DECL void pgf_bracketed_linearize(PgfDB *db, PgfConcrRevision revision, PgfExpr expr, PgfPrintContext *ctxt, @@ -2028,9 +2065,9 @@ void pgf_bracketed_linearize(PgfDB *db, PgfConcrRevision revision, ref concr = PgfDB::revision2concr(revision); PgfLinearizer linearizer(ctxt, concr, m); m->match_expr(&linearizer, expr); - linearizer.reverse_and_label(); + linearizer.reverse_and_label(true); if (linearizer.resolve()) { - linearizer.linearize(out); + linearizer.linearize(out, 0); } } PGF_API_END } @@ -2245,9 +2282,9 @@ pgf_graphviz_parse_tree(PgfDB *db, PgfConcrRevision revision, PgfLinearizationGraphvizOutput out; PgfLinearizer linearizer(ctxt, concr, m); m->match_expr(&linearizer, expr); - linearizer.reverse_and_label(); + linearizer.reverse_and_label(true); if (linearizer.resolve()) { - linearizer.linearize(&out); + linearizer.linearize(&out, 0); return out.generate_graphviz(opts); } } PGF_API_END diff --git a/src/runtime/c/pgf/pgf.h b/src/runtime/c/pgf/pgf.h index e1078338c..278c8a0ef 100644 --- a/src/runtime/c/pgf/pgf.h +++ b/src/runtime/c/pgf/pgf.h @@ -632,6 +632,12 @@ PgfText *pgf_linearize(PgfDB *db, PgfConcrRevision revision, PgfMarshaller *m, PgfExn* err); +PGF_API +PgfText **pgf_tabular_linearize(PgfDB *db, PgfConcrRevision revision, + PgfExpr expr, PgfPrintContext *ctxt, + PgfMarshaller *m, size_t *n_fields, + PgfExn* err); + PGF_API_DECL void pgf_bracketed_linearize(PgfDB *db, PgfConcrRevision revision, PgfExpr expr, PgfPrintContext *ctxt, diff --git a/src/runtime/haskell/PGF2.hsc b/src/runtime/haskell/PGF2.hsc index be0f9eab0..63c6c5a83 100644 --- a/src/runtime/haskell/PGF2.hsc +++ b/src/runtime/haskell/PGF2.hsc @@ -626,10 +626,26 @@ linearizeAll lang e = error "TODO: linearizeAll" -- | Generates a table of linearizations for an expression tabularLinearize :: Concr -> Expr -> [(String, String)] -tabularLinearize lang e = - case tabularLinearizeAll lang e of - (lins:_) -> lins - _ -> [] +tabularLinearize c e = + unsafePerformIO $ + withForeignPtr (c_revision c) $ \c_revision -> + bracket (newStablePtr e) freeStablePtr $ \c_e -> + withForeignPtr marshaller $ \m -> + alloca $ \p_n_fields -> + bracket (withPgfExn "tabularLinearize" (pgf_tabular_linearize (c_db c) c_revision c_e nullPtr m p_n_fields)) free $ \c_texts -> do + n_fields <- peek p_n_fields + peekTable n_fields c_texts + where + peekTable 0 c_texts = return [] + peekTable n c_texts = do + c_field <- peek c_texts + field <- peekText c_field + free c_field + c_lin <- peek (c_texts `plusPtr` (#size PgfText*)) + lin <- peekText c_lin + free c_lin + table <- peekTable (n-1) (c_texts `plusPtr` (2*(#size PgfText*))) + return ((field,lin):table) -- | Generates a table of linearizations for an expression tabularLinearizeAll :: Concr -> Expr -> [[(String, String)]] diff --git a/src/runtime/haskell/PGF2/FFI.hsc b/src/runtime/haskell/PGF2/FFI.hsc index 79a30ca49..7d91dcac7 100644 --- a/src/runtime/haskell/PGF2/FFI.hsc +++ b/src/runtime/haskell/PGF2/FFI.hsc @@ -209,6 +209,8 @@ foreign import ccall pgf_has_linearization :: Ptr PgfDB -> Ptr Concr -> Ptr PgfT foreign import ccall pgf_linearize :: Ptr PgfDB -> Ptr Concr -> StablePtr Expr -> Ptr PgfPrintContext -> Ptr PgfMarshaller -> Ptr PgfExn -> IO (Ptr PgfText) +foreign import ccall pgf_tabular_linearize :: Ptr PgfDB -> Ptr Concr -> StablePtr Expr -> Ptr PgfPrintContext -> Ptr PgfMarshaller -> Ptr CSize -> Ptr PgfExn -> IO (Ptr (Ptr PgfText)) + foreign import ccall pgf_bracketed_linearize :: Ptr PgfDB -> Ptr Concr -> StablePtr Expr -> Ptr PgfPrintContext -> Ptr PgfMarshaller -> Ptr PgfLinearizationOutputIface -> Ptr PgfExn -> IO () foreign import ccall "wrapper" wrapSymbol0 :: Wrapper (Ptr PgfLinearizationOutputIface -> IO ())