protected internal virtual int write(StringTemplate self, Object o, StringTemplateWriter outWriter, Object separator) { if (o == null) { return 0; } int n = 0; try { if (o is StringTemplate) { StringTemplate stToWrite = (StringTemplate) o; // failsafe: perhaps enclosing instance not set // Or, it could be set to another context! This occurs // when you store a template instance as an attribute of more // than one template (like both a header file and C file when // generating C code). It must execute within the context of // the enclosing template. stToWrite.setEnclosingInstance(self); // if self is found up the enclosing instance chain, then // infinite recursion if (StringTemplate.inLintMode() && StringTemplate.isRecursiveEnclosingInstance(stToWrite)) { // throw exception since sometimes eval keeps going // even after I ignore this write of o. throw new System.SystemException("infinite recursion to " + stToWrite.getTemplateDeclaratorString() + " referenced in " + stToWrite.getEnclosingInstance().getTemplateDeclaratorString() + "; stack trace:\n" + stToWrite.getEnclosingInstanceStackTrace()); } else { n = stToWrite.write(outWriter); } return n; } // normalize anything iteratable to iterator o = convertAnythingIteratableToIterator(o); if (o is IEnumerator) { IEnumerator iter = (IEnumerator) o; String separatorString = null; if (separator != null) { separatorString = computeSeparator(self, outWriter, separator); } int i = 0; int charWrittenForValue = 0; Object iterValue = null; while (iter.MoveNext()) { if (i > 0) { bool valueIsPureConditional = false; if (iterValue is StringTemplate) { StringTemplate iterValueST = (StringTemplate) iterValue; IList chunks = (IList) iterValueST.getChunks(); Expr firstChunk = (Expr) chunks[0]; valueIsPureConditional = firstChunk is ConditionalExpr && ((ConditionalExpr) firstChunk).getElseSubtemplate() == null; } bool emptyIteratedValue = valueIsPureConditional && charWrittenForValue == 0; if (!emptyIteratedValue && separator != null) { n += outWriter.write(separatorString); } } iterValue = iter.Current; charWrittenForValue = write(self, iterValue, outWriter, separator); n += charWrittenForValue; i++; } } else { AttributeRenderer renderer = self.getAttributeRenderer(o.GetType()); if ( renderer!=null ) { n = outWriter.write(renderer.ToString(o)); } else { n = outWriter.write(o.ToString()); } return n; } } catch (System.IO.IOException io) { self.error("problem writing object: " + o, io); } return n; }