hello,

yesterday i played around with layout files and created the following counter definition (ok, i didn't read the docs carefully enough)

Counter
        Name                 MajorVersion
        LabelString          "\theMajorVersion.0"
End

Using this counter causes lyx to crash because of the recursion in the label string. The attached patch catches the recursion and prints a warning message to the console.

ok to commit?

bernhard
Index: src/Counters.cpp
===================================================================
--- src/Counters.cpp    (revision 23138)
+++ src/Counters.cpp    (working copy)
@@ -338,24 +338,51 @@
 }
 
 
-docstring Counters::theCounter(docstring const & counter)
+docstring Counters::theCounter(docstring const & counter,
+                                                          std::set<docstring> 
* callers)
 {
        if (!hasCounter(counter))
                return from_ascii("??");
 
-       Counter const & c = counterList[counter];
-       docstring ls = appendix() ? c.labelStringAppendix() : c.labelString();
+       bool owner = false;
+       if (!callers) {
+               callers = new std::set<docstring>;
+               owner = true;
+       }
 
-       if (ls.empty()) {
-               if (!c.master().empty())
-                       ls = from_ascii("\\the") + c.master() + from_ascii(".");
-               ls += from_ascii("\\arabic{") + counter + "}";
+       docstring label;
+
+       if (callers->find(counter) == callers->end()) {
+               
+               pair<std::set<docstring>::iterator, bool> result = 
callers->insert(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);
+
+       if (owner) {
+               delete callers;
+       }
+
+       return label;
 }
 
 
-docstring Counters::counterLabel(docstring const & format)
+docstring Counters::counterLabel(docstring const & format,
+                                                            
std::set<docstring> * callers)
 {
        docstring label = format;
 
@@ -373,10 +400,10 @@
                       && lowercase(label[k]) <= 'z')
                        ++k;
                docstring counter = label.substr(j, k - j);
-               docstring repl = theCounter(counter);
+               docstring repl = theCounter(counter, callers);
                label.replace(i, k - j + 4, repl);
        }
-       
+
        while (true) {
                //lyxerr << "label=" << to_utf8(label) << endl;
 
Index: src/Counters.h
===================================================================
--- src/Counters.h      (revision 23138)
+++ src/Counters.h      (working copy)
@@ -18,6 +18,7 @@
 #include "support/docstring.h"
 
 #include <map>
+#include <set>
 
 
 namespace lyx {
@@ -102,10 +103,12 @@
        void copy(Counters & from, Counters & to,
                  docstring const & match = docstring());
        /// returns the expanded string representation of the counter.
-       docstring theCounter(docstring const & c);
+       docstring theCounter(docstring const & c, 
+                 std::set<docstring> * callers = 0);
        /// Replace om format all the LaTeX-like macros that depend on
        /// counters.
-       docstring counterLabel(docstring const & format);
+       docstring counterLabel(docstring const & format, 
+                 std::set<docstring> * callers = 0);
        /// Are we in apendix?
        bool appendix() const { return appendix_; };
        /// Set the state variable indicating whether we are in appendix.

Reply via email to