Skip to content
Snippets Groups Projects
Select Git revision
  • labcomm2014
  • labcomm2006
  • master default
  • python_sig_hash
  • typedefs
  • anders.blomdell
  • typeref
  • pragma
  • compiler-refactoring
  • labcomm2013
  • v2014.6
  • v2015.0
  • v2014.5
  • v2014.4
  • v2006.0
  • v2014.3
  • v2014.2
  • v2014.1
  • v2014.0
  • v2013.0
20 results

C_CodeGen.jrag

Blame
  • C_CodeGen.jrag 49.62 KiB
    import java.util.Vector;
    
    aspect C_CodeGenEnv {
    
      // Environment wrapper for C-code generation
      // handles qualid nesting, indentation, file writing and
      // prefix propagation
    
      public class C_env {
    
        final private static class C_printer {
          
          private boolean newline = true;
          private PrintStream out;
    
          public C_printer(PrintStream out) {
    	this.out = out;
          }
    
          public void print(C_env env, String s) {
    	if (newline) {
    	  newline = false;
    	  for (int i = 0 ; i < env.indent ; i++) {
    	    out.print("  ");
    	  }
    	}
    	out.print(s);
          }
          public void println(C_env env, String s) {
    	print(env, s);
    	out.println();
    	newline = true;
          }
        }
    
        public final int version; //labcomm version (2006 or 2014)
        public final String verStr; // version suffix to append (currently _2006 and empty string)
    
        public final String qualid;
        public final String lcName;
        public final String rawPrefix;
        public final String prefix;
        private int indent;
        public final int depth;
        private C_printer printer;
        public final int nestedLevel;
        private boolean rootIsPointer;
        private int rootLevel;
    
        public boolean versionHasMetaData() {
          return version != 2006;
        }
    
        private C_env(String qualid, String lcName, String rawPrefix, 
    		  int indent, int depth, C_printer printer,
                      int nestedLevel, int version)
        {
          this.version = version;
          this.verStr = LabCommVersion.versionString(version);
          this.qualid = qualid;
          this.lcName = lcName;
          this.rawPrefix = rawPrefix;
          if (rawPrefix == null) {
            System.err.println("WARNING: prefix==null");
            this.prefix = ""; 
          } else if (rawPrefix.equals("")) {
            this.prefix = rawPrefix;
          } else {
            this.prefix = rawPrefix + "_";
          }
          this.indent = indent;
          this.depth = depth;
          this.printer = printer;
          this.nestedLevel = nestedLevel;
        }
    
        public C_env(String qualid, String lcName, String rawPrefix,
    		 PrintStream out, int version)
        {
          this(qualid, lcName, rawPrefix, 0, 0, new C_printer(out), 0, version);
        }
    
        public C_env(String qualid, String lcName, String rawPrefix,
    		 int indent, int depth, C_printer printer, int version) {
                this(qualid, lcName, rawPrefix, indent, depth, printer, 0, version);
        }
    
        public C_env nestArray(String suffix) {
          return new C_env(qualid + suffix, lcName, rawPrefix,
    		       indent, depth + 1, printer, nestedLevel + 1, version);
        }
    
        public C_env nestStruct(String suffix) {
          return new C_env(qualid + suffix, lcName, rawPrefix, 
    		       indent, depth, printer, nestedLevel + 1, version);
        }
    
        public void indent() {
          indent++;
        }
    
        public void unindent() {
          indent--;
        }
    
        public String prefix() {
          return rawPrefix;
        }
    
        public void print(String s) {
          printer.print(this, s);
        }
    
        public void println() {
          printer.println(this, "");
        }
    
        public void println(String s) {
          printer.println(this, s);
        }
    
        public C_env setPointer() {
          rootIsPointer = true;
          rootLevel = nestedLevel;
          return this;
        }
    
        public String memberAccessor() {
          return (rootIsPointer && (nestedLevel == rootLevel)) ? "->" : ".";
        }
    
        public String accessor() {
          return (rootIsPointer && (nestedLevel == rootLevel)) ? "*" : "";
        }
      }
    
      public C_env ArrayType.C_Nest(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_Nest(C_env env)" + 
    		    " not declared");
      }
    
      public C_env FixedArrayType.C_Nest(C_env env) {
        String index = env.memberAccessor() + "a";
        for (int i = 0 ; i < getNumExp() ; i++) {
          index += "[i_" + env.depth + "_" + i + "]";
        }
        return env.nestArray(index);
      }
    
      public C_env VariableArrayType.C_Nest(C_env env) {
        return env.nestArray(env.memberAccessor() + "a[i_" + env.depth + "]");
      }
    
    
    }
    
    aspect C_IsDynamic {
      
      // Determine if a type has dynamically allocated data
      syn boolean Decl.C_isDynamic() = getType().C_isDynamic();
      syn boolean Type.C_isDynamic() = false;
      syn boolean PrimType.C_isDynamic() = getToken() == LABCOMM_STRING;
      syn boolean UserType.C_isDynamic() = 
        lookupType(getName()).getType().C_isDynamic();
      syn boolean StructType.C_isDynamic() {
        for (int i = 0 ; i < getNumField() ; i++) {
          if (getField(i).getType().C_isDynamic()) {
    	return true;
          }
        }
        return false;
      }
      syn boolean FixedArrayType.C_isDynamic() = getType().C_isDynamic();
      syn boolean VariableArrayType.C_isDynamic() = true;
    }
    
    aspect C_CodeGen {
    
      public void Program.C_genH(PrintStream out, Vector includes, 
    			     String lcName, String prefix, int version) {
        C_env env = new C_env("", lcName, prefix, out, version);
    
        // Hackish prettyprint preamble
        out.println("/* LabComm declarations:");
        pp(out);
        out.println("*/");
        env.println("");
        env.println("");
        env.println("#ifndef __LABCOMM_" + env.lcName + "_H__"); 
        env.println("#define __LABCOMM_" + env.lcName + "_H__");
        env.println("");
    
        // Include
        env.println("#include \"labcomm"+env.verStr+".h\"");
        for (int i = 0 ; i < includes.size() ; i++) {
          env.println("#include \"" + includes.get(i) + "\"");
        }
        env.println("");
    
        C_emitH(env);
    
        env.println("#endif");
      }
    
      public void Program.C_genC(PrintStream out, Vector includes, 
    			     String lcName, String prefix, int version) {
        C_env env = new C_env("", lcName, prefix, out, version);
    
        // Include
        env.println("#include \"labcomm"+env.verStr+".h\"");
        env.println("#include \"labcomm"+env.verStr+"_private.h\"");
        for (int i = 0 ; i < includes.size() ; i++) {
          env.println("#include \"" + includes.get(i) + "\"");
        }
        env.println("");
        
        // Method Implementations
        C_emitC(env);
      }
    
      public void Program.C_emitH(C_env env) {
        for (int i = 0; i < getNumDecl(); i++) {
          getDecl(i).C_emitType(env);
          getDecl(i).C_emitDecoderDeclaration(env);
          getDecl(i).C_emitEncoderDeclaration(env);
          getDecl(i).C_emitSizeofDeclaration(env);
          getDecl(i).C_emitCopyDeclaration(env);
          getDecl(i).C_emitCopyDeallocationDeclaration(env);
          env.println("");
        }
        C_emitConstructorDeclaration(env);
        C_emitForAll(env);
      }
    
      public void Program.C_emitC(C_env env) {
        for (int i = 0; i < getNumDecl(); i++) {
          getDecl(i).C_emitSignature(env);
          getDecl(i).C_emitDecoder(env);
          getDecl(i).C_emitDecoderRegisterHandler(env);
          getDecl(i).C_emitDecoderIoctl(env);
          getDecl(i).C_emitEncoder(env);
          getDecl(i).C_emitEncoderRegisterHandler(env);
          getDecl(i).C_emitEncoderIoctl(env);
          getDecl(i).C_emitSizeof(env);
          getDecl(i).C_emitCopy(env);
          getDecl(i).C_emitCopyDeallocation(env);
        }
        C_emitConstructor(env);
      }
     
    }
    
    aspect C_Common {
    
      public void ArrayType.C_emitLoopVariables(C_env env) {
        for (int i = 0 ; i < getNumExp() ; i++) {
          env.println("int i_" + env.depth + "_" + i + ";");
        }
      }
    
    }
    
    aspect C_Type {
    
      public void Decl.C_emitType(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitType(C_env env)" + 
    		    " not declared");
      }
    
      public void TypeDecl.C_emitType(C_env env) {
        env.println("#ifndef PREDEFINED_" + env.prefix + getName());
        env.print("typedef ");
        getType().C_emitType(env, env.prefix + getName());
        env.println(";");
        env.println("#endif");
      }
    
      public void SampleDecl.C_emitType(C_env env) {
        env.println("#ifndef PREDEFINED_" + env.prefix + getName());
        env.print("typedef ");
        getType().C_emitType(env, env.prefix + getName());
        env.println(";");
        env.println("#endif");
        env.println("extern const struct labcomm"+env.verStr+"_signature " +
                    "*labcomm"+env.verStr+"_signature_" + env.prefix + getName() + 
                    ";");
      }
    
      public void Type.C_emitType(C_env env, String name) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitType(C_env env, String name)" + 
    		    " not declared");
      }
    
      public void VoidType.C_emitType(C_env env, String name) {
        env.print("char " + name);
      }
    
      public void PrimType.C_emitType(C_env env, String name) {
        switch (getToken()) {
          case LABCOMM_BOOLEAN: { env.print("uint8_t"); } break;
          case LABCOMM_BYTE: { env.print("uint8_t"); } break;
          case LABCOMM_SHORT: { env.print("int16_t"); } break;
          case LABCOMM_INT: { env.print("int32_t"); } break;
          case LABCOMM_LONG: { env.print("int64_t"); } break;
          case LABCOMM_FLOAT: { env.print("float"); } break;
          case LABCOMM_DOUBLE: { env.print("double"); } break;
          case LABCOMM_STRING: { env.print("char*"); } break;
          case LABCOMM_SAMPLE: { 
            env.print("const struct labcomm_signature *"); 
          } break;
        }
        env.print(" " + name);
      }
    
      public void UserType.C_emitType(C_env env, String name) {
        env.print(env.prefix + getName() + " " + name);
      }
    
      public void StructType.C_emitType(C_env env, String name) {
        env.println("struct {");
        env.indent();
        for (int i = 0 ; i < getNumField() ; i++) {
          getField(i).C_emitType(env);
          env.println(";");
        }
        env.unindent();
        env.print("} " + name);
      }
    
      public void Field.C_emitType(C_env env) {
        getType().C_emitType(env, getName());
      }
    
      public void FixedArrayType.C_emitType(C_env env, String name) {
        env.println("struct {");
        env.indent();
        StringBuffer index = new StringBuffer("a");
        for (int i = 0 ; i < getNumExp() ; i++) {
          index.append("[" + getExp(i).C_getValue() + "]");
        }
        getType().C_emitType(env, index.toString());
        env.println(";");
        env.unindent();
        env.print("} " + name);
      }
    
      public void VariableArrayType.C_emitType(C_env env, String name) {
        env.println("struct {");
        env.indent();
        for (int i = 0 ; i < getNumExp() ; i++) {
          if (getExp(i) instanceof VariableSize) {
    	env.println("int n_" + i + ";");
          } else {
    	env.println("// n_" + i + "=" + getExp(i).C_getValue());
          }
        }
        getType().C_emitType(env, "*a");
        env.println(";");
        env.unindent();
        env.print("} " + name);
      }
    
      public String Exp.C_getValue() {
       throw new Error(this.getClass().getName() + 
    		    ".C_getValue()" + 
    		    " not declared");
      }
    
      public String IntegerLiteral.C_getValue() {
        return getValue();
      }
    
    }
    
    aspect C_Declarations {
    
      public void Decl.C_emitDecoderDeclaration(C_env env) {
      }
    
      public void SampleDecl.C_emitDecoderDeclaration(C_env env) {
        env.println("int labcomm"+env.verStr+"_decoder_register_" + 
    		env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_decoder *d,");
        env.println("void (*handler)(");
        env.indent();
        env.println(env.prefix + getName() + " *v,");
        env.println("void *context");
        env.unindent();
        env.println("),");
        env.println("void *context");
        env.unindent();
        env.println(");");
    
        env.println("int labcomm"+env.verStr+"_decoder_ioctl_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_decoder *d,");
        env.println("int ioctl_action,");
        env.println("...");
        env.unindent();
        env.println(");");
      }
      
      public void Decl.C_emitEncoderDeclaration(C_env env) {
      }
    //
      public void SampleDecl.C_emitEncoderDeclaration(C_env env) {
        env.println("int labcomm"+env.verStr+"_encoder_register_" + 
    		env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_encoder *e);");
        env.unindent();
    
        env.println("int labcomm"+env.verStr+"_encode_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_encoder *e");
        if(!isVoid() ) {
            env.println(", "+env.prefix + getName() + " *v");
        }
        env.unindent();
        env.println(");");
    
        env.println("int labcomm"+env.verStr+"_encoder_ioctl_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_encoder *e,");
        env.println("int ioctl_action,");
        env.println("...");
        env.unindent();
        env.println(");");
      }
    
    }
    
    aspect C_Limit {
    
      public String Exp.C_getLimit(C_env env, int i) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitDecoderLimit(C_env env, int i)" + 
    		    " not declared");
      }
    
      public String IntegerLiteral.C_getLimit(C_env env, int i) {
        return getValue();
      }
    
      public String VariableSize.C_getLimit(C_env env, int i) {
        return env.qualid + env.memberAccessor() + "n_" + i;
      }
      
    }
    
    aspect C_Index {
    
      public void ArrayType.C_emitCalcIndex(C_env env) {
      }
    
      public void VariableArrayType.C_emitCalcIndex(C_env env) {
        env.print("int i_" + env.depth + " = ");
    
        String i_prefix = "i_" + env.depth + "_";
        String expr = i_prefix + "0";
        for (int i = 1 ; i < getNumExp() ; i++) {
          expr = "(" + expr + ") * " +
    	getExp(i).C_getLimit(env, i) + " + " + 
    	i_prefix + i;
        }
        env.println(expr + ";");
      }
    
    }
    
    aspect C_Decoder {
    
      public void Decl.C_emitDecoder(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitDecoder(C_env env)" + 
    		    " not declared");
      }
    
      public void TypeDecl.C_emitDecoder(C_env env) {
      }
    
      public void SampleDecl.C_emitDecoder(C_env env) {
        env = env.nestStruct("v");
        env.println("static void decode_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_reader *r,");
        env.println("void (*handle)(");
        env.indent();
        env.println(env.prefix + getName() + " *v,");
        env.println("void *context");
        env.unindent();
        env.println("),");
        env.println("void *context");
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println(env.prefix + getName() + " v;");
        getType().C_emitDecoder(env);
        env.println("handle(&v, context);");
        if (C_isDynamic()) {
          env.println("{");
          env.indent();
          getType().C_emitDecoderDeallocation(env);
          env.unindent();
          env.println("}");
        }
        env.unindent();
        env.println("}");
      }
    
      public void Type.C_emitDecoder(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitDecoder(C_env env)" + 
    		    " not declared");
      }
    
      public void VoidType.C_emitDecoder(C_env env) {
      }
    
      public void PrimType.C_emitDecoder(C_env env) {
        env.print(env.qualid + " = ");
        switch (getToken()) {
          case LABCOMM_SAMPLE: { 
            env.println("labcomm_internal_decoder_index_to_signature(" +
                        "r->decoder, labcomm"+env.verStr+"_read_int(r));");
          } break;
          default: {
            env.println("labcomm"+env.verStr+"_read_" + getName() + "(r);");
          }; break;
        }
      }
    
      public void UserType.C_emitDecoder(C_env env) {
        lookupType(getName()).getType().C_emitDecoder(env);
      }
    
      public void StructType.C_emitDecoder(C_env env) {
        for (int i = 0 ; i < getNumField() ; i++) {
          getField(i).C_emitDecoder(env);
        }
      }
    
      public void ArrayType.C_emitDecoder(C_env env) {
        C_emitDecoderDecodeLimit(env);
        C_emitDecoderArrayAllocate(env);
        env.println("{");
        env.indent();
        C_emitLoopVariables(env);
        for (int i = 0 ; i < getNumExp() ; i++) {
          String iterator = "i_" + env.depth + "_" + i;
          env.println("for (" + iterator + " = 0" +
    		  " ; " +
    		  iterator + " < " + getExp(i).C_getLimit(env, i) +
    		  " ; " +
    		  iterator + "++) {");
          env.indent();
        }
        C_emitCalcIndex(env);
        getType().C_emitDecoder(C_Nest(env));
        for (int i = getNumExp() - 1 ; i >= 0 ; i--) {
          env.unindent();
          env.println("}");
        }
        env.unindent();
        env.println("}");
      }
    
      public void Field.C_emitDecoder(C_env env) {
        getType().C_emitDecoder(env.nestStruct("." + getName()));
      }
    
      public void Exp.C_emitDecoderDecodeLimit(C_env env, int i) {
      }
    
      public void VariableSize.C_emitDecoderDecodeLimit(C_env env, int i) {
        env.println(env.qualid + ".n_" + i + " = labcomm"+env.verStr+"_read_packed32(r);");
      }
    
      public void ArrayType.C_emitDecoderDecodeLimit(C_env env) {
        for (int i = 0 ; i < getNumExp() ; i++) {
          getExp(i).C_emitDecoderDecodeLimit(env, i);
        }
      }
    
      public void ArrayType.C_emitDecoderArrayAllocate(C_env env) {
      }
    
      public void VariableArrayType.C_emitDecoderArrayAllocate(C_env env) {
        env.print(env.qualid + 
                  ".a = labcomm"+env.verStr+"_memory_alloc(r->memory, 1, sizeof(" + 
    	      env.qualid + ".a[0])");
        for (int i = 0 ; i < getNumExp() ; i++) {
          env.print(" * " + getExp(i).C_getLimit(env, i));
        }
        env.println(");");
      }
    
      // Code for deallocation of dynamically allocated data 
    
      public void Type.C_emitDecoderDeallocation(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitDecoderDeallocation(C_env env)" + 
    		    " not declared");
      }
    
      public void PrimType.C_emitDecoderDeallocation(C_env env) {
        if (C_isDynamic()) {
          env.println("labcomm"+env.verStr+"_memory_free(r->memory, 1, " + 
                      env.qualid + ");");
        }
      }
    
      public void UserType.C_emitDecoderDeallocation(C_env env) {
        if (C_isDynamic()) {
          lookupType(getName()).getType().C_emitDecoderDeallocation(env);
        }
      }
    
      public void StructType.C_emitDecoderDeallocation(C_env env) {
        if (C_isDynamic()) {
          for (int i = 0 ; i < getNumField() ; i++) {
    	getField(i).C_emitDecoderDeallocation(env);
          }
        }
      }
    
      public void ArrayType.C_emitDecoderDeallocation(C_env env) {
        if (getType().C_isDynamic()) {
          env.println("{");
          env.indent();
          C_emitLoopVariables(env);
          for (int i = 0 ; i < getNumExp() ; i++) {
    	String iterator = "i_" + env.depth + "_" + i;
    	env.println("for (" + iterator + " = 0" +
    		    " ; " +
    		    iterator + " < " + getExp(i).C_getLimit(env, i) +
    		    " ; " +
    		    iterator + "++) {");
    	env.indent();
          }
          C_emitCalcIndex(env);
          getType().C_emitDecoderDeallocation(C_Nest(env));
          for (int i = 0 ; i < getNumExp() ; i++) {
    	env.unindent();
    	env.println("}");
          }
          env.unindent();
          env.println("}");
        }
      }
    
      public void VariableArrayType.C_emitDecoderDeallocation(C_env env) {
        super.C_emitDecoderDeallocation(env);
        env.println("labcomm"+env.verStr+"_memory_free(r->memory, 1, " + 
                    env.qualid + ".a);");
      }
    
      public void Field.C_emitDecoderDeallocation(C_env env) {
        getType().C_emitDecoderDeallocation(env.nestStruct("." + getName()));
      }
    
      public void Decl.C_emitDecoderRegisterHandler(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitDecoderRegisterHandler(C_env env)" + 
    		    " not declared");
      }
    
      public void TypeDecl.C_emitDecoderRegisterHandler(C_env env) {
      }
    
      public void SampleDecl.C_emitDecoderRegisterHandler(C_env env) {
        env.println("int labcomm"+env.verStr+"_decoder_register_" + 
    		env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_decoder *d,");
        env.println("void (*handler)(");
        env.indent();
        env.println(env.prefix + getName() + " *v,");
        env.println("void *context");
        env.unindent();
        env.println("),");
        env.println("void *context");
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println("return labcomm"+env.verStr+"_internal_decoder_register(");
        env.indent();
        env.println("d,");
        env.println("&signature_" + env.prefix + getName() + ",");
        env.println("(labcomm"+env.verStr+"_decoder_function)decode_" + env.prefix + getName() + ",");
        env.println("(labcomm"+env.verStr+"_handler_function)handler,");
        env.println("context");
        env.unindent();
        env.println(");");
        env.unindent();
        env.println("}");
      }
    
    }
    
    aspect C_copy {
    
      private void SampleDecl.C_emitCopyFunctionParam(C_env env, String src,
    						  String dst)
      {
        env.println("void labcomm" + env.verStr + "_copy_" +
                    env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm" + env.verStr + "_memory *mem,");
        env.println(env.prefix + getName() + " *" + dst + ",");
        env.println(env.prefix + getName() + " *" + src);
        env.unindent();
        env.print(")");
      }
    
      public void Decl.C_emitCopyDeclaration(C_env env) {
      }
    
      public void SampleDecl.C_emitCopyDeclaration(C_env env) {
        C_emitCopyFunctionParam(env, "src", "dst");
        env.println(";");
      }
    
      public void Decl.C_emitCopy(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitCopy(C_env env)" + 
    		    " not declared");
      }
    
      public void TypeDecl.C_emitCopy(C_env env) {
      }
    
      public void SampleDecl.C_emitCopy(C_env env) {
        final String dst = "dst";
        final String src = "src";
        C_env env_src = env.nestStruct(src).setPointer();
        C_env env_dst = env.nestStruct(dst).setPointer();
    
        C_emitCopyFunctionParam(env_src, src, dst);
        env_src.println("");
        env_src.println("{");
        env_src.indent();
        getType().C_emitCopy(env_src, env_dst);
        env_src.unindent();
        env_src.println("}");
      }
    
      public void Type.C_emitCopy(C_env env_src, C_env env_dst) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitCopy(C_env env)" + 
    		    " not declared");
      }
    
      public void VoidType.C_emitCopy(C_env env_src, C_env env_dst) {
      }
    
      public void PrimType.C_emitCopy(C_env env_src, C_env env_dst) {
        if (C_isDynamic()) {
          env_src.println(String.format(
    	  "%s%s = labcomm%s_memory_alloc(mem, 1, strlen(%s%s)+1);",
    	  env_dst.accessor(), env_dst.qualid,
              env_src.verStr,
    	  env_src.accessor(), env_src.qualid));
          env_src.println(String.format(
    	  "memcpy(%s%s, %s%s, strlen(%s%s)+1);",
    	  env_dst.accessor(), env_dst.qualid,
    	  env_src.accessor(), env_src.qualid,
    	  env_src.accessor(), env_src.qualid));
        } else {
          env_src.println(env_dst.accessor() + env_dst.qualid + " = " +
    		      env_src.accessor() + env_src.qualid + ";");
        }
      }
    
      public void UserType.C_emitCopy(C_env env_src, C_env env_dst) {
        lookupType(getName()).getType().C_emitCopy(env_src, env_dst);
      }
    
      public void StructType.C_emitCopy(C_env env_src, C_env env_dst) {
        for (int i = 0 ; i < getNumField() ; i++) {
          getField(i).C_emitCopy(env_src, env_dst);
        }
      }
    
      public void ArrayType.C_emitCopy(C_env env_src, C_env env_dst) {
        C_emitCopyDecodeLimit(env_src, env_dst);
        C_emitCopyArrayAllocate(env_src, env_dst);
        env_src.println("{");
        env_src.indent();
        C_emitLoopVariables(env_src);
        for (int i = 0 ; i < getNumExp() ; i++) {
          String iterator = "i_" + env_src.depth + "_" + i;
          env_src.println("for (" + iterator + " = 0" +
    		  " ; " +
    		  iterator + " < " + getExp(i).C_getLimit(env_src, i) +
    		  " ; " +
    		  iterator + "++) {");
          env_src.indent();
        }
        C_emitCalcIndex(env_src);
        getType().C_emitCopy(C_Nest(env_src), C_Nest(env_dst));
        for (int i = getNumExp() - 1 ; i >= 0 ; i--) {
          env_src.unindent();
          env_src.println("}");
        }
        env_src.unindent();
        env_src.println("}");
      }
    
      public void Field.C_emitCopy(C_env env_src, C_env env_dst) {
        String fnam = env_src.memberAccessor() + getName();
        getType().C_emitCopy(env_src.nestStruct(fnam), env_dst.nestStruct(fnam));
      }
    
      public void Exp.C_emitCopyDecodeLimit(C_env env_src, C_env env_dst, int i) {
        // Ordinary array has no length-member.
      }
    
      public void VariableSize.C_emitCopyDecodeLimit(C_env env_src, C_env env_dst, int i) {
        String src = env_src.qualid + env_src.memberAccessor() + "n_" + i;
        String dst = env_dst.qualid + env_dst.memberAccessor() + "n_" + i;
        env_src.println(dst + " = " + src + ";");
      }
    
      public void ArrayType.C_emitCopyDecodeLimit(C_env env_src, C_env env_dst) {
        for (int i = 0 ; i < getNumExp() ; i++) {
          getExp(i).C_emitCopyDecodeLimit(env_src, env_dst, i);
        }
      }
    
      public void ArrayType.C_emitCopyArrayAllocate(C_env env_src, C_env env_dst) {
      }
    
      public void VariableArrayType.C_emitCopyArrayAllocate(C_env env_src,
    							C_env env_dst)
      {
        env_src.print(env_dst.qualid + env_dst.memberAccessor() +
                      "a = labcomm" + env_src.verStr +
                      "_memory_alloc(mem, 1, sizeof(" +
    		  env_src.qualid + env_src.memberAccessor() + "a[0])");
        for (int i = 0 ; i < getNumExp() ; i++) {
          env_src.print(" * " + getExp(i).C_getLimit(env_src, i));
        }
        env_dst.println(");");
      }
    
      // Code for deallocation of dynamically allocated data in a copy.
    
      private void SampleDecl.C_emitCopyDeallocationFunctionParam(C_env env,
    							      String par)
      {
        env.println("void labcomm" + env.verStr + "_copy_free_" +
                    env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm" + env.verStr + "_memory *mem,");
        env.println(env.prefix + getName() + " *" + par);
        env.unindent();
        env.print(")");
      }
    
      public void Decl.C_emitCopyDeallocationDeclaration(C_env env) {
      }
    
      public void SampleDecl.C_emitCopyDeallocationDeclaration(C_env env) {
        C_emitCopyDeallocationFunctionParam(env, "c");
        env.println(";");
      }
    
      public void Decl.C_emitCopyDeallocation(C_env env) {
        throw new Error(this.getClass().getName() +
    		    ".C_emitCopy(C_env env)" +
    		    " not declared");
      }
    
      public void TypeDecl.C_emitCopyDeallocation(C_env env) {
      }
    
      public void SampleDecl.C_emitCopyDeallocation(C_env env) {
        String par = "par";
        env = env.nestStruct(par).setPointer();
    
        C_emitCopyDeallocationFunctionParam(env, par);
        env.println("");
        env.println("{");
        env.indent();
        getType().C_emitCopyDeallocation(env);
        env.unindent();
        env.println("}");
      }
    
      public void Type.C_emitCopyDeallocation(C_env env) {
        throw new Error(this.getClass().getName() +
      		    ".C_emitCopyDeallocation(C_env env)" +
      		    " not declared");
      }
    
      public void VoidType.C_emitCopyDeallocation(C_env env) {
      }
    
      public void PrimType.C_emitCopyDeallocation(C_env env) {
        if (C_isDynamic()) {
          env.println("labcomm" + env.verStr + "_memory_free(mem, 1, " +
                      env.accessor() + env.qualid + ");");
        }
      }
    
      public void UserType.C_emitCopyDeallocation(C_env env) {
        if (C_isDynamic()) {
          lookupType(getName()).getType().C_emitCopyDeallocation(env);
        }
      }
    
      public void StructType.C_emitCopyDeallocation(C_env env) {
        if (C_isDynamic()) {
          for (int i = 0 ; i < getNumField() ; i++) {
      	getField(i).C_emitCopyDeallocation(env);
          }
        }
      }
    
      public void ArrayType.C_emitCopyDeallocation(C_env env) {
        if (getType().C_isDynamic()) {
          env.println("{");
          env.indent();
          C_emitLoopVariables(env);
          for (int i = 0 ; i < getNumExp() ; i++) {
      	String iterator = "i_" + env.depth + "_" + i;
      	env.println("for (" + iterator + " = 0" +
      		    " ; " +
      		    iterator + " < " + getExp(i).C_getLimit(env, i) +
      		    " ; " +
      		    iterator + "++) {");
      	env.indent();
          }
          C_emitCalcIndex(env);
          getType().C_emitCopyDeallocation(C_Nest(env));
          for (int i = 0 ; i < getNumExp() ; i++) {
      	env.unindent();
      	env.println("}");
          }
          env.unindent();
          env.println("}");
        }
      }
    
      public void VariableArrayType.C_emitCopyDeallocation(C_env env) {
        super.C_emitCopyDeallocation(env);
        env.println("labcomm" + env.verStr + "_memory_free(mem, 1, " +
                    env.qualid + env.memberAccessor() + "a);");
      }
    
      public void Field.C_emitCopyDeallocation(C_env env) {
        getType().C_emitCopyDeallocation(env.nestStruct(env.memberAccessor()
    						    + getName()));
      }
    }
    
    aspect C_DecoderIoctl {
    
      public void Decl.C_emitDecoderIoctl(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitDecoderIoctl(C_env env)" + 
    		    " not declared");
      }
    
      public void TypeDecl.C_emitDecoderIoctl(C_env env) {
      }
    
      public void SampleDecl.C_emitDecoderIoctl(C_env env) {
        env.println("int labcomm"+env.verStr+"_decoder_ioctl_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_decoder *d,");
        env.println("int ioctl_action,");
        env.println("...");
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println("int result;");
        env.println("va_list va;");
        env.println("va_start(va, ioctl_action);");
        env.println("result = labcomm"+env.verStr+"_internal_decoder_ioctl(");
        env.indent();
        env.println("d, &signature_" + env.prefix + getName() + ", ");
        env.println("ioctl_action, va);");
        env.unindent();
        env.println("va_end(va);");
        env.println("return result;");
        env.unindent();
        env.println("}");
      }
    }
    
    
    aspect C_Encoder {
    
      public void Decl.C_emitEncoder(C_env env) {
        throw new Error(this.getClass().getName() + 
            ".C_emitEncoder()" + 
            " not declared");
      }
    
      public void TypeDecl.C_emitEncoder(C_env env) {
        // do nothing for type decls
      }
    
      public void SampleDecl.C_emitEncoder(C_env env) {
        env = env.nestStruct("(*v)");
        env.println("static int encode_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_writer *w");
        if(!isVoid() ) {
            env.println(", "+env.prefix + getName() + " *v");
        }
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println("int result = 0;");
        getType().C_emitEncoder(env);
        env.println("return result;");
        env.unindent();
        env.println("}");
    
        // Typesafe encode wrapper
        env.println("int labcomm"+env.verStr+"_encode_" + env.prefix + getName() + "(");
        env.println("struct labcomm"+env.verStr+"_encoder *e");
        if(!isVoid() ) {
            env.println(", "+env.prefix + getName() + " *v");
        }
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println("return labcomm"+env.verStr+"_internal_encode(e, &signature_" + 
    		env.prefix + getName() + 
    		", (labcomm"+env.verStr+"_encoder_function)encode_" + 
                    env.prefix + getName() +
    		(!isVoid()?", v":", NULL")+");");
        env.unindent();
        env.println("}");
      }
    
      public void Type.C_emitEncoder(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitEncoder(C_env env)" + 
    		    " not declared");
      }
    
      public void VoidType.C_emitEncoder(C_env env) {
        env.println("result = 0;");
      }
    
      public void PrimType.C_emitEncoder(C_env env) {
        env.print("result = ");
        switch (getToken()) {
          case LABCOMM_SAMPLE: { 
            env.println("labcomm"+env.verStr+"_write_int(w, " + 
                        "labcomm_internal_encoder_signature_to_index(w->encoder, " +
                        env.qualid + "));");
          } break;
          default: {
            env.println("labcomm"+env.verStr+"_write_" + getName() + 
                        "(w, " + env.qualid + ");");
          } break;
        }
        env.println("if (result != 0) { return result; }");
      }
    
      public void UserType.C_emitEncoder(C_env env) {
        decl().getType().C_emitEncoder(env);
      }
    
      public void StructType.C_emitEncoder(C_env env) {
        for (int i = 0 ; i < getNumField() ; i++) {
          getField(i).C_emitEncoder(env);
        }
      }
    
      public void ArrayType.C_emitEncoder(C_env env) {
        C_emitEncoderEncodeLimit(env);
        env.println("{");
        env.indent();
        C_emitLoopVariables(env);
        for (int i = 0 ; i < getNumExp() ; i++) {
          String iterator = "i_" + env.depth + "_" + i;
          env.println("for (" + iterator + " = 0" +
    		  " ; " +
    		  iterator + " < " + getExp(i).C_getLimit(env, i) +
    		  " ; " +
    		  iterator + "++) {");
          env.indent();
        }
        C_emitCalcIndex(env);
        getType().C_emitEncoder(C_Nest(env));
        for (int i = getNumExp() - 1 ; i >= 0 ; i--) {
          env.unindent();
          env.println("}");
        }
        env.unindent();
        env.println("}");
      }
    
      public void Field.C_emitEncoder(C_env env) {
        getType().C_emitEncoder(env.nestStruct("." + getName()));
      }
    
      public void Exp.C_emitEncoderEncodeLimit(C_env env, int i) {
      }
    
      public void VariableSize.C_emitEncoderEncodeLimit(C_env env, int i) {
        env.println("labcomm"+env.verStr+"_write_packed32(w, " + env.qualid + ".n_" + i + ");");
      }
    
      public void ArrayType.C_emitEncoderEncodeLimit(C_env env) {
        for (int i = 0 ; i < getNumExp() ; i++) {
          getExp(i).C_emitEncoderEncodeLimit(env, i);
        }
      }
    
      public void Decl.C_emitEncoderRegisterHandler(C_env env) {
        throw new Error(this.getClass().getName() + 
      		    ".C_emitEncoderRegisterHandler(C_env env)" + 
      		    " not declared");
      }
      
      public void TypeDecl.C_emitEncoderRegisterHandler(C_env env) {
        // do nothing for type decls
      }
      
      public void SampleDecl.C_emitEncoderRegisterHandler(C_env env) {
        env.println("int labcomm"+env.verStr+"_encoder_register_" + 
    		env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_encoder *e");
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        C_emitUserTypeDeps(env, null, false); //XXX HERE BE DRAGONS
                                              //currently set to false to turn off
                                              //outputting of code
        env.println("return labcomm"+env.verStr+"_internal_encoder_register(");
        env.indent();
        env.println("e,");
        env.println("&signature_" + env.prefix + getName() + ",");
        env.println("(labcomm"+env.verStr+"_encoder_function)encode_" + env.prefix + getName());
        env.unindent();
        env.println(");");
        env.unindent();
        env.println("}");
      }
    
    }
    
    aspect C_EncoderIoctl {
    
      public void Decl.C_emitEncoderIoctl(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitEncoderIoctl()" + 
    		    " not declared");
      }
    
      public void TypeDecl.C_emitEncoderIoctl(C_env env) {
      }
    
      public void SampleDecl.C_emitEncoderIoctl(C_env env) {
        env.println("int labcomm"+env.verStr+"_encoder_ioctl_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm"+env.verStr+"_encoder *e,");
        env.println("int ioctl_action,");
        env.println("...");
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println("int result;");
        env.println("va_list va;");
        env.println("va_start(va, ioctl_action);");
        env.println("result = labcomm"+env.verStr+"_internal_encoder_ioctl(");
        env.indent();
        env.println("e, &signature_" + env.prefix + getName() + ", ");
        env.println("ioctl_action, va);");
        env.unindent();
        env.println("va_end(va);");
        env.println("return result;");
        env.unindent();
        env.println("}");
      }
    
    }
    
    aspect C_TypeDependencies {
      public void Decl.C_emitUserTypeDeps(C_env env, String via, boolean outputCode) {
        if( hasDependencies() ) {
            Iterator<Decl> it = type_dependencies().iterator();
            while(it.hasNext()) {
                Decl t = it.next();
    
                t.C_emitUserTypeDeps(env, t.getName(), outputCode);
                if(outputCode) {
                   System.out.println("Decl.C_emitUserTypeDeps registering "+t.getName());
                   env.println("labcomm"+env.verStr+"_encoder_register_"+env.prefix + t.getName()+"(e);");
                } else {  // Just output a comment
    	        String refpath = (via == null) ? "directly" : "indirectly via "+via;
    	       env.println(" //Depends ("+refpath+") on "+t.getName() );
                }
            }
        } 
      }
      public void Decl.C_emitUserTypeRefs(C_env env, String via, boolean outputCode) {
        if( isReferenced() ) {
            Iterator<Decl> it = type_references().iterator();
            while(it.hasNext()) {
                Decl t = it.next();
    
                t.C_emitUserTypeRefs(env, t.getName(), outputCode);
                if(outputCode) {
                   env.println("labcomm"+env.verStr+"_encoder_register_"+env.prefix + t.getName()+"(e);");
                } else {  // Just output a comment
    	        String refpath = (via == null) ? "directly" : "indirectly via "+via;
    	       env.println(" //Is referenced ("+refpath+")  by "+t.getName() );
                }
            }
        } 
      }
    }
    
    aspect C_Signature {
    
      public void ASTNode.C_emitSignature(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitSignature(C_env env)" + 
    		    " not declared");
      }
    
      syn String Decl.C_DeclTypeString();
      eq SampleDecl.C_DeclTypeString() = "LABCOMM_SAMPLE";
      eq TypeDecl.C_DeclTypeString() = "LABCOMM_TYPEDEF";
    
      public void Decl.C_emitSignature(C_env env) {
        C_emitFlatSignature(env);
    //
    //  if( false && (isReferenced() || isSampleDecl())){ 
    //    Signature signature = getSignature();
    //    signature.C_emitSignature(env, !isSampleDecl());
    //  } else {
    //    env.println("// not emitting signature for "+getName()+isReferenced()+isSampleDecl());  
    //  }
    //  if(env.versionHasMetaData()) { 
    //    if(isReferenced() || isSampleDecl()){
    //        env.println("(int (*)(void *))labcomm"+env.verStr+"_signature_" + 
    //	 	env.prefix + getName() + "_emit_signature");
    //    } else {
    //        env.println("NULL");  // HERE BE DRAGONS! Is it worth the size saving to skip emitting the emit_signature function for unused types?
    //                              //                  The code won't likely end up in a target system anyway?
    //    }
    //  }
    //  env.unindent();
    //  env.println(" };");
    //
      }
    
      public void ASTNode.C_emitFlatSignature(C_env env) {
        throw new Error(this.getClass().getName() + 
                        ".C_emitFlatSignature(C_env env)" + 
                        " not declared");
      }
    
      public void Decl.C_emitFlatSignature(C_env env) {
      }
    
      public void SampleDecl.C_emitFlatSignature(C_env env){
        env.println("static unsigned char signature_bytes_" + 
      	        env.prefix + getName() + "[] = {");
        SignatureList signature = flatSignature(env.version);
        for (int i = 0 ; i < signature.size() ; i++) {
          String comment = signature.getComment(i);
          if (comment != null) {
            env.println(signature.getIndent(i) + "// " + comment);
          }
          byte[] data = signature.getData(i, env.version);
          if (data != null) {
            env.print(signature.getIndent(i));
            for (int j = 0 ; j < data.length ; j++) {
              env.print(data[j] + ", ");
            }
            env.println("");
          }
        }
        env.println("};");
    
        C_emitSizeofValue(env);
        env.println("static struct labcomm"+env.verStr+"_signature " +
                    "signature_" + env.prefix + getName() + " = {");
        env.indent();
        env.println("\"" + getName() + "\",");
        env.println("sizeof_" + env.prefix + getName() + ",");
        env.println("sizeof(signature_bytes_" + env.prefix + getName() + "),");
        env.println("signature_bytes_" + env.prefix + getName() + ",");
        env.println("0");
        env.unindent();
        env.println(" };");
        env.println("const struct labcomm"+env.verStr+"_signature " +
                    "*labcomm"+env.verStr+"_signature_" + env.prefix + getName() + 
                    " = &signature_" + env.prefix + getName() + ";");
      }
    
        public void Signature.C_emitSignature(C_env env, boolean decl){
          getSignatureList().C_emitSignature(env, decl);
        }
    
        public abstract void SignatureLine.C_emitSignature(C_env env, boolean decl);
    
        public void TypeRefSignatureLine.C_emitSignature(C_env env, boolean isDecl){ 
          //env.print(getIndentString());
          //env.println("LABCOMM_SIGDEF_SIGNATURE(labcomm"+env.verStr+"_signature_" + env.prefix + decl.getName() +"),");
        }
    
        public void DataSignatureLine.C_emitSignature(C_env env, boolean decl){ 
           //   String comment = getComment();
           //   if (comment != null && comment.length() > 0) {
           //     env.println(getIndentString() + "// " + comment);
           //   }
           //   byte[] data = getData(env.version);
           //   if (data != null && data.length > 0) {
           //     env.print(getIndentString());
           //     env.print("LABCOMM_SIGDEF_BYTES("+data.length+", \"");
           //     for (int j = 0 ; j < data.length ; j++) {
           //       byte d = data[j];
           //       //if(d>='a'&&d<='z' || d>='A'&&d<='Z'|| d>='0'&&d<='9'  )
           //       //  env.print(""+(char)d);
           //       //else
           //       env.print("\\x"+Integer.toHexString(d));
           //     }
           //     env.println("\"),");
           // }
        }
    //
    //
    //      byte[] data = getData(env.version);
    //        if (data != null) {
    //            for (int j = 0 ; j < data.length ; j++) {
    //                env.print(getIndentString());
    //                //env.print("printf(\"labcomm"+env.verStr+"_write_byte( w, (unsigned char)"+ String.format("0x%02X ", data[j]) +")\\n\"); ");
    //                env.print("labcomm"+env.verStr+"_write_byte( w, (unsigned char)"+ String.format("0x%02X ", data[j]) +"); ");
    //                env.println("if (result != 0) { return result; }");
    //            }
    //            env.println();
    //        }
    //
    //}
      public void SignatureList.C_emitSignature(C_env env, boolean decl) { 
    //  env.println("static struct labcomm_signature_data signature_tree_" + 
    //  	 env.prefix + parentDecl().getName() + "[] = {");
    //  env.indent();
    //  for (int i = 0 ; i < size() ; i++) {
    //    SignatureLine l = getSignatureLine(i);
    //    l.C_emitSignature(env, decl);
    //  }
    //  
    //  env.println("LABCOMM_SIGDEF_END");
    //  env.println("};");
    //  env.unindent();
    //  env.println();
      }
    
    
    
    //  public void SampleDecl.C_emitSignature(C_env env) {
    //    env.println("static unsigned char signature_bytes_" + 
    //		       env.prefix + getName() + "[] = {");
    //    SignatureList signature = signature(env.version);
    //    for (int i = 0 ; i < signature.size() ; i++) {
    //      String comment = signature.getComment(i);
    //      if (comment != null) {
    //        env.println(signature.getIndent(i) + "// " + comment);
    //      }
    //      byte[] data = signature.getData(i);
    //      if (data != null) {
    //        env.print(signature.getIndent(i));
    //        for (int j = 0 ; j < data.length ; j++) {
    //          env.print(data[j] + ", ");
    //        }
    //        env.println("");
    //      }
    //    }
    //    env.println("};");
    //    env.println("struct labcomm"+env.verStr+"_signature labcomm"+env.verStr+"_signature_" + 
    //		env.prefix + getName() + " = {");
    //    env.indent();
    //    env.println("LABCOMM_SAMPLE, \"" + getName() + "\",");
    //    env.println("(int (*)(struct labcomm"+env.verStr+"_signature *, void *))labcomm"+env.verStr+"_sizeof_" + 
    //		env.prefix + getName() + ",");
    //    env.println("sizeof(signature_bytes_" + env.prefix + getName() + "),");
    //    env.println("signature_bytes_" + env.prefix + getName() + ",");
    //    env.println("0");
    //    env.unindent();
    //    env.println(" };");
    //  }
    
    }
    aspect C_Constructor {
      public void ASTNode.C_emitConstructor(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitConstructor(C_env env)" + 
    		    " not declared");
      }
    
      public void Program.C_emitConstructor(C_env env) {
        env.println("LABCOMM_CONSTRUCTOR void init_" +
    		env.prefix + "_signatures(void)");
        env.println("{");
        env.indent();
        env.println("static int initialized = 0;");
        env.println("if (initialized == 0) {");
        env.indent();
        env.println("initialized = 1;");
        for (int i = 0; i < getNumDecl(); i++) {
          getDecl(i).C_emitConstructor(env);
        }
        env.unindent();
        env.println("}"); 
        env.unindent();
        env.println("}"); 
      }
    
      public void Decl.C_emitConstructor(C_env env) {
      }
    //XXX
      public void SampleDecl.C_emitConstructor(C_env env) {
        env.println("labcomm"+env.verStr+"_set_local_index(&signature_" + 
    		env.prefix + getName() + ");");
      }
    
    
      public void ASTNode.C_emitConstructorDeclaration(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitConstructorDeclaration(C_env env)" + 
    		    " not declared");
      }
    
      public void Program.C_emitConstructorDeclaration(C_env env) {
        env.println("void init_" + env.prefix + "_signatures(void);");
      }
    
    }
    
    aspect C_Sizeof {
     public void Decl.C_emitSizeofDeclaration(C_env env) {
      }
    
      public void SampleDecl.C_emitSizeofDeclaration(C_env env) {
        env.println("extern int labcomm"+env.verStr+"_sizeof_" + env.prefix + getName() +
            "(" + env.prefix + getName() + " *v);");
      }
    
      public int Decl.C_fixedSizeof() {
        return getType().C_fixedSizeof();
      }
    
      public void Decl.C_emitSizeof(C_env env) {
      }
    
      public void SampleDecl.C_emitSizeof(C_env env) {
        env = env.nestStruct("(*v)");
        env.println("int labcomm"+env.verStr+"_sizeof_" + env.prefix + getName() +
            "(" + env.prefix + getName() + " *v)");
        env.println("{");
        env.indent();
        env.println("return labcomm"+env.verStr+"_internal_sizeof(" +
                    "&signature_" + env.prefix + getName() +
                    ", v);");
        env.unindent();
        env.println("}");
      }
    
      public int Type.C_fixedSizeof() {
        throw new Error(this.getClass().getName() + 
                ".C_fixedSizeof()" + 
                " not declared");
      }
    
      public int VoidType.C_fixedSizeof() {
        return 0;
      }
    
      public int PrimType.C_fixedSizeof() {
        switch (getToken()) {
          case LABCOMM_BOOLEAN: { return 1; } 
          case LABCOMM_BYTE: { return 1; } 
          case LABCOMM_SHORT: { return 2; } 
          case LABCOMM_INT: { return 4; } 
          case LABCOMM_LONG: { return 8; }
          case LABCOMM_FLOAT: { return 4; }
          case LABCOMM_DOUBLE: { return 8; }
          case LABCOMM_SAMPLE: { return 4; }
          default: { 
        throw new Error(this.getClass().getName() + 
                ".C_fixedSizeof()" + 
                " unknown size (" + getName() + ")"); 
          } 
        }
      }
    
      public int UserType.C_fixedSizeof() {
        return lookupType(getName()).getType().C_fixedSizeof();
      }
    
      public int StructType.C_fixedSizeof() {
        int result = 0;
        for (int i = 0 ; i < getNumField() ; i++) {
          result += getField(i).getType().C_fixedSizeof();
        }
        return result;
      }
    
      public int ArrayType.C_fixedSizeof() {
        int elements = 1;
        for (int i = 0 ; i < getNumExp() ; i++) {
          int n = Integer.parseInt(((IntegerLiteral)getExp(i)).getValue());
          elements = elements * n;
        }
        return getType().C_fixedSizeof() * elements;
      }
    
      public void Decl.C_emitSizeofValue(C_env env) {
      }
    
      public void SampleDecl.C_emitSizeofValue(C_env env) {
        env = env.nestStruct("(*v)");
        env.println("static int sizeof_" + env.prefix + getName() + "(void *vv)");
        env.println("{");
        env.indent();
        env.println("int result = 0;");
        if (C_isDynamic()) {
          env.println(env.prefix + getName() + " *v = vv;");
          getType().C_emitSizeof(env);
        } else {
          env.println("result += " + C_fixedSizeof() + ";");
        }    
        env.println("return result;");
        env.unindent();
        env.println("}");
      }
    
      public void Type.C_emitSizeof(C_env env) {
        throw new Error(this.getClass().getName() + 
                ".C_emitSizeof(C_env env)" + 
                " not declared");
      }
    
      public void PrimType.C_emitSizeof(C_env env) {
        switch (getToken()) {
          case LABCOMM_STRING: { 
            env.print("{ int l = strlen(" + env.qualid + "); ");
        env.println("result += labcomm"+env.verStr+"_size_packed32(l) + l; }"); 
          } break;
          default: { 
        throw new Error(this.getClass().getName() + 
                ".C_emitSizeof(C_env env)" + 
                " known size (" + getName() + ")"); 
          } 
        }
      }
    
      public void UserType.C_emitSizeof(C_env env) {
        lookupType(getName()).getType().C_emitSizeof(env);
      }
    
      public void StructType.C_emitSizeof(C_env env) {
        int fixed = 0;
        for (int i = 0 ; i < getNumField() ; i++) {
          if (getField(i).getType().C_isDynamic()) {
        getField(i).getType().C_emitSizeof(
          env.nestStruct("." + getField(i).getName()));
          } else {
        fixed += getField(i).getType().C_fixedSizeof();
          }
        }
        if (fixed > 0) {
          env.println("result += " + fixed + ";");
        }
      }
    
      public void Exp.C_emitSizeof(C_env env, int i) {
      }
    
      public void VariableSize.C_emitSizeof(C_env env, int i) {
        env.println("result += labcomm"+env.verStr+"_size_packed32(" + 
                    env.qualid + env.memberAccessor() + "n_" + i + ");");
      }
    
      public void ArrayType.C_emitSizeof(C_env env) {
        for (int i = 0 ; i < getNumExp() ; i++) {
          getExp(i).C_emitSizeof(env, i);
        }
        if (getType().C_isDynamic()) {
          env.println("{");
          env.indent();
          C_emitLoopVariables(env);
          for (int i = 0 ; i < getNumExp() ; i++) {
            String iterator = "i_" + env.depth + "_" + i;
            env.println("for (" + iterator + " = 0" +
                        " ; " +
                        iterator + " < " + getExp(i).C_getLimit(env, i) +
                        " ; " +
                        iterator + "++) {");
            env.indent();
          }
          C_emitCalcIndex(env);
          getType().C_emitSizeof(C_Nest(env));
          for (int i = 0 ; i < getNumExp() ; i++) {
            env.unindent();
            env.println("}");
          }
          env.unindent();
          env.println("}");
        } else {
          env.print("result += " + getType().C_fixedSizeof());
          for (int i = 0 ; i < getNumExp() ; i++) {
            env.print(" * " + getExp(i).C_getLimit(env, i));
          }
          env.println(";");      
        }
      }
    }
    
    aspect C_forAll {
    
      public void Program.C_emitForAll(C_env env) {
        env.print("#define LABCOMM_FORALL_SAMPLES_" + env.lcName + 
    		"(func, sep)");
        env.indent();
        boolean needSeparator = false;
        for (int i = 0; i < getNumDecl(); i++) {
          String s = getDecl(i).C_forAll(env);
          if (s != null) {
    	if (needSeparator) { env.print(" sep"); }
    	env.println(" \\");
    	env.print(s);
    	needSeparator = true;
          }
        }
        env.println("");
        env.unindent();
      }
      
      public String Decl.C_forAll(C_env env) {
        return null;
      }
    
      public String SampleDecl.C_forAll(C_env env) {
        return "func(" + getName() + ", " + env.prefix + getName() + ")";
      }
    
    }
    
    aspect C_Info {
    
      public void Program.C_info(PrintStream out, String prefix, int version) {
        C_env env = new C_env("", "", prefix, out, version);
        for (int i = 0; i < getNumDecl(); i++) {
          getDecl(i).C_info(env);
        }
      }
    
      public void Decl.C_info(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_info((C_env env)" + 
    		    " not declared");
      }
    
      public void TypeDecl.C_info(C_env env) {
        env.println(",C,typedef," + env.prefix + getName() + "," + 
                     env.prefix + getName() + "," +
                     C_info_type_or_void(env.prefix));
      }
    
      public void SampleDecl.C_info(C_env env) {
        env.println(",C,sample," + env.prefix + getName() + "," + 
                     env.prefix + getName() + "," +
                     C_info_type_or_void(env.prefix));
      }
    
      // make void types explicitly as they require special treatment
      // in encoder/decoder calls
      protected String Decl.C_info_type_or_void(String prefix) {
        if(isVoid() ) {
          return "void";
        } else {
          return prefix + getName() ;
        }
      }
    }