FlatNode source_node = NodeEnumerator.getFlatNode(src);
s.append("
    public String downstreamDeclaration() {        StringBuffer s = new StringBuffer();                FlatNode source_node = NodeEnumerator.getFlatNode(src);        FlatNode my_node = NodeEnumerator.getFlatNode(dst);      if (my_node.contents instanceof SIRFilter) {          SIRFilter f = (SIRFilter)my_node.contents;          int peek_n = f.getPeekInt();          int pop_n = f.getPopInt();                  // String pop_expr = null;        int peek_buf_size = 1;        while (peek_buf_size < peek_n) {            peek_buf_size *= 2;        }        /* __pop_buf_DST, __head__DST, __tail__DST,  __init_pop_buf__DST         * seem to have to do with copying out any data items that are         * in the input buffer that are not popped in the current iteration */        String headName = "__head__" + dst;        String tailName = "__tail__" + dst;        String bufName = "__pop_buf__" + dst;                s.append(typeString); s.append(" ");        s.append(bufName); s.append("["); s.append(peek_buf_size); s.append("];\n");        s.append("int "); s.append(headName); s.append(";\n");        s.append("int "); s.append(tailName); s.append(";\n");        s.append("\n");	// problem between "extra" and init_pop_count        //int extra = FixedBufferTape.getRemaining(src,dst);	// going back to old method:	int extra = f.getPeekInt() - f.getPopInt();	// end :going back to old method:"        s.append("inline void __init_pop_buf__"); s.append(dst); s.append("() {\n");	int init_pop_count = extra;	{	    if (f instanceof SIRTwoStageFilter) {                SIRTwoStageFilter ff = (SIRTwoStageFilter)f;                int init_peek = ff.getInitPeekInt();                int init_pop = ff.getInitPopInt();                if (init_pop > init_peek) init_peek = init_pop;                init_pop_count = init_peek;                if (extra > (init_peek - init_pop))                    init_pop_count += extra - (init_peek - init_pop);            }	}        if (init_pop_count > 0) {            if (init_pop_count > 1) {                s.append("  for (int i=0; i<"); s.append(init_pop_count); s.append("; i++) {\n    ");                s.append(bufName); s.append("[i]=");                  s.append(popExpr()); s.append(";\n");                s.append("  }\n");            } else {                s.append("  "); s.append(bufName); s.append("[0]=");                s.append(popExpr()); s.append(";\n");            }        }        s.append("  "); s.append(tailName); s.append("=0;\n");        s.append("  "); s.append(headName); s.append("="); s.append(init_pop_count); s.append(";\n");        s.append("}\n");        s.append("\n");        // save_peek_buffer__DST and load_peek_buffer__DST        // presumably something to do with checkpointing...        // but using buffer called "__pop_buf__"DST above        // and using different size and modular arithmetic.        // XXX: presumably does not work any longer.        s.append(                "void save_peek_buffer__" + dst                  + "(object_write_buffer *buf) {\n"              + "  int i = 0, offs = " + tailName + ";\n"              + "  while (offs != " + headName + ") {\n"              + "    buf->write(&" + bufName + "[offs], sizeof("                  + typeString                  + "));\n    offs++;\n    offs&=" + (peek_buf_size - 1)                  + ";\n    i++;\n"              + "  }\n");        // p.print(" fprintf(stderr,\"buf size: %d\\n\", i);\n");        s.append("  assert(i == " + extra + ");\n");        s.append("}\n");        s.append("\n");        s.append("void load_peek_buffer__" + dst                + "(object_write_buffer *buf) {\n");        if (extra > 0) {            if (extra > 1) {                s.append("  for (int i = 0; i < " + extra + "; i++) {\n");                s.append("     buf->read(&" + bufName + "[i] , sizeof("                        + typeString + "));\n");                s.append("  }\n");            } else {                s.append("     buf->read(&" + bufName + "[0] , sizeof("                        + typeString + "));\n");            }        }        s.append("  " + tailName + "=0;\n");        s.append("  " + headName + "=" + extra + ";\n");        s.append("}\n\n");        s.append("inline void __update_pop_buf__" + dst + "() {\n");        if (peek_n <= pop_n) {            // no peek beyond pop            // TODO: candidate for partial unrolling?            // complete unrolls of buffer updates were removed            // as caused excessive file size to C++            if (pop_n > 0) {                if (pop_n > 1) {                    s.append("for (int i = 0; i < " + pop_n + "; i++) {\n");                    s.append("  " + bufName + "[i]=");                } else {                    s.append("  " + bufName + "[0]=");                }                s.append(popExpr()+";\n");                if (pop_n > 1) {                    s.append("}\n");                }            }            s.append("  " + tailName + " = 0;\n");            s.append("  " + headName + " = " + pop_n + ";\n");        } else {            // peek beyond pop => circular buffer            // TODO: candidate for partial unrolling?            if (pop_n > 0) {                if (pop_n > 1) {                    s.append("  for (int i = 0; i < " + pop_n + "; i++) {\n");                }                s.append("  " + bufName + "[" + headName                        + "]=");                s.append(popExpr()+";\n");                s.append("  " + headName + "++;");                s.append("  " + headName + "&=" + (peek_buf_size - 1)                        + ";\n");                if (pop_n > 1) {                    s.append("}\n");                }            }                    }        s.append("}\n\n");                // pop        s.append("\n");        s.append("inline " + typeString + " "                + ClusterUtils.popName(dst) + "() {\n");        //p.indent();        if (peek_n <= pop_n) {            s.append("return __pop_buf__" + dst + "[__tail__"                    + dst + "++];\n");        } else {            s.append(typeString                    + " res=__pop_buf__" + dst + "[__tail__"                    + dst + "];");            s.append("__tail__" + dst + "++;");            s.append("__tail__" + dst + "&=" + (peek_buf_size - 1)                    + ";\n");            s.append("return res;\n");        }        //p.outdent();        s.append("}\n");        s.append("\n");        // pop with argument (the source is not fused)        s.append("inline " + typeString + " "                + ClusterUtils.popName(dst) + "(int n) {\n");        //p.indent();        if (peek_n <= pop_n) {            s.append("" + typeString                    + " result = __pop_buf__" + dst + "[__tail__"                    + dst + "];\n");            s.append("__tail__" + dst + "+=n;\n");            s.append("return result;\n");        } else {            s.append(typeString                    + " res=__pop_buf__" + dst + "[__tail__"                    + dst + "];");            s.append("__tail__" + dst + "+=n;");            s.append("__tail__" + dst + "&=" + (peek_buf_size - 1)                    + ";\n");            s.append("return res;\n");        }        //p.outdent();        s.append("}\n");        s.append("\n");        s.append("inline " + typeString                + " " + ClusterUtils.peekName(dst)                + "(int offs) {\n");        //p.indent();        if (peek_n <= pop_n) {            s.append("return __pop_buf__" + dst + "[(__tail__"                    + dst + "+offs)];\n");        } else {            s.append("return __pop_buf__" + dst + "[(__tail__"                      + dst + "+offs)&" + (peek_buf_size - 1)                      + "];\n");        }        //p.outdent();        s.append("  }\n");        s.append("\n");        s.append("\n");      } else if (my_node.contents instanceof SIRSplitter) {                    // Splitter: push through from upstream to output tapes.          SIRSplitter splitter = (SIRSplitter)my_node.contents;          int sum_of_weights = splitter.getSumOfWeights();                    // List of tapes with upstream end == downstream end of this.          List<Tape> out = RegisterStreams.getNodeOutStreams(my_node.contents);          if (splitter.getType().equals(SIRSplitType.DUPLICATE)) {              // Duplicate splitter: push routine pushes "data"              // on every output tape.              s.append("void " + push_name +"("+ typeString +" data) {\n");              for (Tape to : out) {                if (s != null) {                        s.append("  " + to.pushPrefix() + "data" + to.pushSuffix() + ";\n");                }              }                     s.append("}\n");              s.append("\n");          } else {              // RoundRobin splitter: push routine puts data in push_buffer              // if push_buffer is full then copies correct portion to each output tapes.              s.append(typeString + " " + push_buffer + "[" + sum_of_weights + "];\n");              s.append("int " + push_index + " = 0;\n");              s.append("\n");              s.append("void " + push_name +"("+ typeString +" data) {\n");              s.append("  " + push_buffer + "[" + push_index + "++] = data;\n");              s.append("  if (" + push_index + " == " + sum_of_weights + ") {\n");              int offs = 0;                        for (int i = 0; i < out.size(); i++) {                int num = splitter.getWeight(i);                if (num != 0) {                  Tape to = out.get(i);                  s.append(to.pushManyItems(push_buffer,offs,num));                  s.append("\n");                  offs += num;                }              }              s.append("    " + push_index + " = 0;\n");              s.append("  }\n");              s.append("}\n");          }      }                    return s.toString();    }