Fix crash due to recursive function call when a counter references itself.

e.g.:

Counter
    Name                 Version
    LabelString          "\theVersion.0"
End


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23166 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Bernhard Roider 2008-02-23 20:38:57 +00:00
parent 21a3cd14d2
commit 52ccb98354
2 changed files with 43 additions and 11 deletions

View File

@ -339,23 +339,48 @@ docstring Counters::labelItem(docstring const & ctr,
docstring Counters::theCounter(docstring const & counter) docstring Counters::theCounter(docstring const & counter)
{
std::set<docstring> callers;
return theCounter(counter, callers);
}
docstring Counters::theCounter(docstring const & counter,
std::set<docstring> & callers)
{ {
if (!hasCounter(counter)) if (!hasCounter(counter))
return from_ascii("??"); return from_ascii("??");
Counter const & c = counterList[counter]; docstring label;
docstring ls = appendix() ? c.labelStringAppendix() : c.labelString();
if (ls.empty()) { if (callers.find(counter) == callers.end()) {
if (!c.master().empty())
ls = from_ascii("\\the") + c.master() + from_ascii("."); pair<std::set<docstring>::iterator, bool> result = callers.insert(counter);
ls += from_ascii("\\arabic{") + counter + "}";
Counter const & c = counterList[counter];
docstring ls = appendix() ? c.labelStringAppendix() : c.labelString();
if (ls.empty()) {
if (!c.master().empty())
ls = from_ascii("\\the") + c.master() + from_ascii(".");
ls += from_ascii("\\arabic{") + counter + "}";
}
label = counterLabel(ls, &callers);
callers.erase(result.first);
} else {
// recursion detected
lyxerr << "Warning: Recursion in label for counter `"
<< counter << "' detected"
<< endl;
} }
return counterLabel(ls);
return label;
} }
docstring Counters::counterLabel(docstring const & format) docstring Counters::counterLabel(docstring const & format,
std::set<docstring> * callers)
{ {
docstring label = format; docstring label = format;
@ -373,10 +398,11 @@ docstring Counters::counterLabel(docstring const & format)
&& lowercase(label[k]) <= 'z') && lowercase(label[k]) <= 'z')
++k; ++k;
docstring counter = label.substr(j, k - j); docstring counter = label.substr(j, k - j);
docstring repl = theCounter(counter); docstring repl = callers? theCounter(counter, *callers):
theCounter(counter);
label.replace(i, k - j + 4, repl); label.replace(i, k - j + 4, repl);
} }
while (true) { while (true) {
//lyxerr << "label=" << to_utf8(label) << endl; //lyxerr << "label=" << to_utf8(label) << endl;

View File

@ -18,6 +18,7 @@
#include "support/docstring.h" #include "support/docstring.h"
#include <map> #include <map>
#include <set>
namespace lyx { namespace lyx {
@ -105,7 +106,8 @@ public:
docstring theCounter(docstring const & c); docstring theCounter(docstring const & c);
/// Replace om format all the LaTeX-like macros that depend on /// Replace om format all the LaTeX-like macros that depend on
/// counters. /// counters.
docstring counterLabel(docstring const & format); docstring counterLabel(docstring const & format,
std::set<docstring> * callers = 0);
/// Are we in apendix? /// Are we in apendix?
bool appendix() const { return appendix_; }; bool appendix() const { return appendix_; };
/// Set the state variable indicating whether we are in appendix. /// Set the state variable indicating whether we are in appendix.
@ -115,6 +117,10 @@ public:
/// Sets the current enclosing float. /// Sets the current enclosing float.
void current_float(std::string const & f) { current_float_ = f; } void current_float(std::string const & f) { current_float_ = f; }
private: private:
/// returns the expanded string representation of the counter
/// with recursion protection through callers.
docstring theCounter(docstring const & c,
std::set<docstring> & callers);
/// Returns the value of the counter according to the /// Returns the value of the counter according to the
/// numbering scheme numbertype. /// numbering scheme numbertype.
/* Available numbering schemes are arabic (1, 2,...), roman /* Available numbering schemes are arabic (1, 2,...), roman