summaryrefslogtreecommitdiff
path: root/cli/context.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-02-09 13:33:09 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-02-09 13:33:09 +0200
commita89ee85a4b94a57e996a233c9d21679d1e1217a9 (patch)
tree24b85140035a61c61849b4b4f359e9fdd83fd826 /cli/context.cxx
parentcf658f4475bb22dbfaa365d53b4a3fd7e6140ec4 (diff)
Add support for variable expansion (\$var$) in doc strings
Diffstat (limited to 'cli/context.cxx')
-rw-r--r--cli/context.cxx107
1 files changed, 97 insertions, 10 deletions
diff --git a/cli/context.cxx b/cli/context.cxx
index ea84f33..9ba20ab 100644
--- a/cli/context.cxx
+++ b/cli/context.cxx
@@ -618,24 +618,29 @@ format_line (output_type ot, string& r, const char* s, size_t n)
throw generation_failed ();
}
- // Extract the link target.
+ // Find the end of the link target.
//
- for (++i; i + 1 < n; ++i)
+ size_t b (++i + 1), e (b);
+ for (; i + 1 < n; ++i)
{
char c (s[i + 1]);
- if (c == ' ')
+ if (c == ' ' || c == '}')
{
- for (++i; i + 1 < n && s[i + 1] == ' '; ++i) ; // Skip spaces.
- break;
- }
+ e = i + 1;
- if (c == '}')
- break;
+ if (c == ' ') // Skip spaces.
+ for (++i; i + 1 < n && s[i + 1] == ' '; ++i) ;
- t += c;
+ break;
+ }
}
+ // Run the link target through format_line(ot_plain) to handle
+ // escaping (e.g., \\$).
+ //
+ format_line (ot_plain, t, s + b, e - b);
+
if (t.empty ())
{
cerr << "error: missing link target in documentation paragraph '"
@@ -1115,7 +1120,7 @@ html_margin (string& v)
string context::
-format (output_type ot, string const& s, bool para)
+format (semantics::scope& scope, output_type ot, string const& s, bool para)
{
stack<block> blocks;
blocks.push (block (block::text, para)); // Top-level.
@@ -1137,6 +1142,7 @@ format (output_type ot, string const& s, bool para)
const char* l;
size_t n;
+ string subst; // Variable-substituted.
if (pre)
{
@@ -1158,6 +1164,14 @@ format (output_type ot, string const& s, bool para)
l = s.c_str () + b;
n = (last ? s.size () : e) - b;
+
+ // Perform variable expansions (\$var$).
+ //
+ if (substitute (scope, l, n, subst))
+ {
+ l = subst.c_str ();
+ n = subst.size ();
+ }
}
const char* ol (l); // Original, full line for diagnostics.
@@ -1840,6 +1854,79 @@ substitute (const string& s, semantics::cli_unit& u, const path* d)
return r;
}
+bool context::
+substitute (semantics::scope& scope, const char* s, size_t n, string& result)
+{
+ bool sub (false);
+ result.clear ();
+
+ // Scan the string looking for variables (\$var$).
+ //
+ size_t b (0), e (b);
+ for (char p ('\0'); e != n; ++e)
+ {
+ char c (s[e]);
+
+ if (p == '\\')
+ {
+ if (c == '\\') // Escape sequence.
+ {
+ p = '\0';
+ continue;
+ }
+
+ if (c == '$')
+ {
+ // Variable expansion.
+ //
+ sub = true;
+
+ // Find the closing '$'.
+ //
+ size_t p (e + 1); // Position of the second '$'.
+ for (; p != n && s[p] != '$'; ++p) ;
+
+ if (p == n)
+ {
+ cerr << "error: missing closing '$' in '" << string (s, n) << "'"
+ << endl;
+ throw generation_failed ();
+ }
+
+ result.append (s, b, e - b - 1); // Save what came before.
+
+ // Var name.
+ //
+ ++e;
+ string v (s, e, p - e);
+
+ // Lookup and substiute.
+ //
+ using semantics::doc;
+
+ if (doc* d = unit.lookup<doc> (scope.fq_name (), "var: " + v))
+ result += d->front ();
+ else
+ {
+ cerr << "error: undefined variable '" << v << "' in '"
+ << string (s, n) << "'" << endl;
+ throw generation_failed ();
+ }
+
+ e = p;
+ b = e + 1;
+ }
+ }
+
+ p = s[e];
+ }
+
+ if (sub)
+ result.append (s, b, e - b); // Last chunk.
+
+ return sub;
+}
+
string context::
fq_name (semantics::nameable& n, bool cxx_name)
{