From fe8cfbfb1aecb279e294fbaf3c8e3d26639942d1 Mon Sep 17 00:00:00 2001
From: Boris Kolpackov ";
+ break;
}
}
- format_line (ot, r, l, n);
+ // Output paragraph text.
+ //
+ if (n != 0)
+ format_line (ot, r, l, n);
- if (b == block::none) // Normal text.
+ // Output intermediate markup, if any.
+ //
+ if (ot == ot_html)
{
- if (para || !first) // End a paragraph?
+ switch (b)
{
- if (ot == ot_html)
+ case block::li:
+ if (blocks.top () == block::dl)
+ r += "";
-
- l += 3;
- n -= 3;
- blocks.push (b = block::h);
+ l += 4;
+ n -= 4;
+ }
+ else if (n >= 4 && strncmp (l, "\\li|", 4) == 0)
+ {
+ b = block::li;
+ l += 4;
+ n -= 4;
}
- // Figure out how many blocks we need to pop. Things get complicated
+ // Skip leading spaces after opening '|'.
+ //
+ while (n != 0 && (*l == 0x20 || *l == 0x0D || *l == 0x09)) {l++; n--;}
+
+ // Next figure out how many blocks we need to pop at the end of this
+ // paragraph (i.e., handle the "suffix"). Things get a bit complicated
// since '|' could be escaped.
//
size_t pc (0); // Pop count.
@@ -743,75 +758,203 @@ format (output_type ot, string const& s, bool para)
//
if (ec % 2 != 0)
--pc;
+
+ n -= pc; // Number of special '|' at the end.
+
+ // Skip trailing spaces before closing '|'.
+ //
+ while (n != 0 && (l[n - 1] == 0x20 ||
+ l[n - 1] == 0x0D ||
+ l[n - 1] == 0x09))
+ n--;
}
- if (pc > blocks.size ())
+ if (pc > blocks.size () + (b != block::text ? 1 : 0))
{
cerr << "error: extraneous '|' at the end of paragraph '"
<< string (ol, 0, on) << "'" << endl;
throw generation_failed ();
}
- n -= pc; // Number of special '|' at the end.
+ // Verify that this block type is valid in this context. Skip
+ // empty text blocks (can happen if we just have '|').
+ //
+ if (b != block::text || n != 0)
+ {
+ bool good (true);
+ block ob (blocks.empty () ? block (block::text) : blocks.top ());
+
+ switch (ob)
+ {
+ case block::h: good = false; break;
+ case block::ul:
+ case block::ol:
+ case block::dl: good = (b == block::li); break;
+ case block::li: good = (b == block::text); break;
+ case block::text: good = (b != block::li); break;
+ }
+
+ if (!good)
+ {
+ cerr << "error: " << b << " inside " << ob << " "
+ << "in documentation string '" << s << "'" << endl;
+ throw generation_failed ();
+ }
+ }
- // Some blocks, like \h, are single-paragraph and cannot be empty.
+ // Verify the block itself.
//
- if (b == block::h && n == 0)
+ switch (b)
{
- cerr << "error: empty paragraph '" << string (ol, 0, on) << "' "
- << "in documentation string '" << s << "'" << endl;
- throw generation_failed ();
+ case block::h:
+
+ // \h blocks are only valid if we are required to start a new
+ // paragraph (first_para is true).
+ //
+ if (!first_para)
+ {
+ cerr << "error: paragraph '" << string (ol, 0, on) << "' "
+ << "not allowed in '" << s << "'" << endl;
+ throw generation_failed ();
+ }
+
+ // \h must be single-paragraph.
+ //
+ if (pc == 0)
+ {
+ cerr << "error: '|' expected at the end of paragraph '"
+ << string (ol, 0, on) << "'" << endl;
+ throw generation_failed ();
+ }
+
+ // \h must not be empty.
+ //
+ if (n == 0)
+ {
+ cerr << "error: empty paragraph '" << string (ol, 0, on) << "' "
+ << "in documentation string '" << s << "'" << endl;
+ throw generation_failed ();
+ }
+
+ break;
+ case block::ul:
+ case block::ol:
+ case block::dl:
+
+ if (pc != 0)
+ {
+ cerr << "error: empty list '" << string (ol, 0, on) << "' "
+ << "in documentation string '" << s << "'" << endl;
+ throw generation_failed ();
+ }
+
+ if (n != 0)
+ {
+ cerr << "error: unexpected text after " << b << "| "
+ << "in paragraph '" << string (ol, 0, on) << "'" << endl;
+ throw generation_failed ();
+ }
+
+ break;
+ case block::li:
+
+ if (blocks.top () == block::dl)
+ {
+ if (n == 0)
+ {
+ cerr << "error: term text missing in paragraph '"
+ << string (ol, 0, on) << "'" << endl;
+ throw generation_failed ();
+ }
+ }
+
+ break;
+ case block::text:
+ break;
}
- if (b == block::none) // Normal text.
+ // Output opening markup.
+ //
+ if (ot == ot_html)
{
- if (para || !first) // Start a paragraph?
+ switch (b)
{
- if (ot == ot_html)
+ case block::h: r += "
"; break;
+ case block::ul: r += "
"; break;
+ case block::ol: r += "
"; break;
+ case block::dl: r += "
"; break;
+ case block::li:
+ r += (blocks.top () == block::dl ? "