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

C_CodeGen.jrag

Blame
  • Forked from Anders Blomdell / LabComm
    544 commits behind the upstream repository.
    C_CodeGen.jrag 29.02 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 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 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;
    
        private C_env(String qualid, String lcName, String rawPrefix, 
    		  int indent, int depth, C_printer printer) {
          this.qualid = qualid;
          this.lcName = lcName;
          this.rawPrefix = rawPrefix;
          this.prefix = rawPrefix + "_";
          this.indent = indent;
          this.depth = depth;
          this.printer = printer;
        }
    
        public C_env(String qualid, String lcName, String rawPrefix, 
    		 PrintStream out) {
          this.qualid = qualid;
          this.lcName = lcName;
          this.rawPrefix = rawPrefix;
          this.prefix = rawPrefix + "_";
          this.depth = 0;
          this.indent = 0;
          this.printer = new C_printer(out);
        }
    
        public C_env nestArray(String suffix) {
          return new C_env(qualid + suffix, lcName, rawPrefix, 
    		       indent, depth + 1, printer);
        }
    
        public C_env nestStruct(String suffix) {
          return new C_env(qualid + suffix, lcName, rawPrefix, 
    		       indent, depth, printer);
        }
    
        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(String s) {
          printer.println(this, s);
        }
    
      }
    
      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 = ".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(".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) {
        C_env env = new C_env("", lcName, prefix, out);
    
        // 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.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) {
        C_env env = new C_env("", lcName, prefix, out);
    
        // Include
        env.println("#include \"labcomm.h\"");
        env.println("#include \"labcomm_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_emitSignatureDeclaration(env);
          getDecl(i).C_emitDecoderRegisterDeclaration(env);
          getDecl(i).C_emitEncoderDeclaration(env);
          getDecl(i).C_emitSizeofDeclaration(env);
          env.println("");
        }
        C_emitForAll(env);
      }
    
      public void Program.C_emitC(C_env env) {
        C_emitSignature(env);
        for (int i = 0; i < getNumDecl(); i++) {
          getDecl(i).C_emitDecoder(env);
          getDecl(i).C_emitDecoderRegisterHandler(env);
          getDecl(i).C_emitEncoder(env);
          getDecl(i).C_emitEncoderRegisterHandler(env);
          getDecl(i).C_emitSizeof(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");
      }
    
      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("unsigned char"); } break;
          case LABCOMM_BYTE: { env.print("unsigned char"); } break;
          case LABCOMM_STRING: { env.print("char*"); } break;
          case LABCOMM_LONG: { env.print("long long"); } break;
          default: { env.print(getName()); } 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_emitDecoderRegisterDeclaration(C_env env) {
      }
    
      public void SampleDecl.C_emitDecoderRegisterDeclaration(C_env env) {
        env.println("void labcomm_decoder_register_" + 
    		env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_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(");");
      }
      
      public void Decl.C_emitEncoderDeclaration(C_env env) {
      }
    
      public void SampleDecl.C_emitEncoderDeclaration(C_env env) {
        env.println("void labcomm_encoder_register_" + 
    		env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_encoder *e);");
        env.unindent();
    
        env.println("void labcomm_encode_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_encoder *e,");
        env.println(env.prefix + getName() + " *v");
        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 + ".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_" + getName() + "(");
        env.indent();
        env.println("labcomm_decoder_t *d,");
        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.println(env.qualid + " = labcomm_decode_" + getName() + "(d);");
      }
    
      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_decode_int(d);");
        env.println(env.qualid + ".n_" + i + " = labcomm_decode_packed32(d);");
      }
    
      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 = malloc(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("free(" + 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("free(" + 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("void labcomm_decoder_register_" + 
    		env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_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("labcomm_internal_decoder_register(");
        env.indent();
        env.println("d,");
        env.println("&labcomm_signature_" + env.prefix + getName() + ",");
        env.println("(labcomm_decoder_typecast_t)decode_" + getName() + ",");
        env.println("(labcomm_handler_typecast_t)handler,");
        env.println("context");
        env.unindent();
        env.println(");");
        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) {
      }
    
      public void SampleDecl.C_emitEncoder(C_env env) {
        env = env.nestStruct("(*v)");
        env.println("static void encode_" + getName() + "(");
        env.indent();
        env.println("labcomm_encoder_t *e,");
        env.println(env.prefix + getName() + " *v");
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println("e->writer.write(&e->writer, labcomm_writer_start);");
        env.println("labcomm_encode_type_index(e, &labcomm_signature_" + 
    		env.prefix + getName() + ");");
        env.println("{");
        env.indent();
        getType().C_emitEncoder(env);
        env.unindent();
        env.println("}");
        env.println("e->writer.write(&e->writer, labcomm_writer_end);");
        env.unindent();
        env.println("}");
    
        // Typesafe encode wrapper
        env.println("void labcomm_encode_" + env.prefix + getName() + "(");
        env.println("labcomm_encoder_t *e,");
        env.println(env.prefix + getName() + " *v");
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println("labcomm_internal_encode(e, &labcomm_signature_" + 
    		env.prefix + getName() + ", v);");
        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) {
      }
    
      public void PrimType.C_emitEncoder(C_env env) {
        env.println("labcomm_encode_" + getName() + "(e, " + env.qualid + ");");
      }
    
      public void UserType.C_emitEncoder(C_env env) {
        lookupType(getName()).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_encode_int(e, " + env.qualid + ".n_" + i + ");");
        env.println("labcomm_encode_packed32(e, " + 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) {
      }
    
      public void SampleDecl.C_emitEncoderRegisterHandler(C_env env) {
        env.println("void labcomm_encoder_register_" + 
    		env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_encoder *e");
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println("labcomm_internal_encoder_register(");
        env.indent();
        env.println("e,");
        env.println("&labcomm_signature_" + env.prefix + getName() + ",");
        env.println("(labcomm_encode_typecast_t)encode_" + getName());
        env.unindent();
        env.println(");");
        env.unindent();
        env.println("}");
      }
     
    
    }
    
    aspect C_Signature {
    
      public void ASTNode.C_emitSignature(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitSignature(C_env env)" + 
    		    " not declared");
      }
    
      public void Program.C_emitSignature(C_env env) {
        for (int i = 0; i < getNumDecl(); i++) {
          getDecl(i).C_emitSignature(env);
        }
      }
    
      public void Decl.C_emitSignature(C_env env) {
      }
    
      public void SampleDecl.C_emitSignature(C_env env) {
        env.println("static unsigned char signature_bytes_" + 
    		       getName() + "[] = {");
    //    C_genFlatSignature(env);
        SignatureList signature = signature();
        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("labcomm_signature_t labcomm_signature_" + 
    		env.prefix + getName() + " = {");
        env.indent();
        env.println("LABCOMM_SAMPLE, \"" + getName() + "\",");
        env.println("(int (*)(void *))labcomm_sizeof_" + 
    		env.prefix + getName() + ",");
        env.println("sizeof(signature_bytes_" + getName() + "),");
        env.println("signature_bytes_"+ getName());
        env.unindent();
        env.println(" };");
      }
    
      public void ASTNode.C_genFlatSignature(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_genFlatSignature(C_env env)" + 
    		    " not declared");
      }
    
      public void TypeDecl.C_genFlatSignature(C_env env) {
        getType().C_genFlatSignature(env);
      }
    
      public void SampleDecl.C_genFlatSignature(C_env env) {
        getType().C_genFlatSignature(env);
      }
    
      public void PrimType.C_genFlatSignature(C_env env) {
        C_genFlatSignature(env, getToken());
        env.println("// " + getName());
      }
    
      public void UserType.C_genFlatSignature(C_env env) {
        lookupType(getName()).C_genFlatSignature(env);
      }
    
      public void ArrayType.C_genFlatSignature(C_env env) {
        C_genFlatSignature(env, LABCOMM_ARRAY);
        env.println("// LABCOMM_ARRAY");
        C_genFlatSignature(env, getNumExp());
        env.println("// # of dimensions");
        for (int i = 0 ; i < getNumExp() ; i++) {
          getExp(i).C_genFlatSignature(env);
          env.println("");
        }
        getType().C_genFlatSignature(env);
      }
    
      public void StructType.C_genFlatSignature(C_env env) {
        C_genFlatSignature(env, LABCOMM_STRUCT);
        env.println("// LABCOMM_STRUCT");
        C_genFlatSignature(env, getNumField());
        env.println("// # of fields");
        for (int i = 0 ; i < getNumField() ; i++) {
          getField(i).C_genFlatSignature(env);
        }
      }
    
      public void Field.C_genFlatSignature(C_env env) {
        C_genFlatSignature(env, getName());
        env.println("");
        getType().C_genFlatSignature(env);
      }
    
      public void IntegerLiteral.C_genFlatSignature(C_env env) {
        C_genFlatSignature(env, Integer.parseInt(getValue()));
        env.print("// " + getValue());
      }
    
      public void VariableSize.C_genFlatSignature(C_env env) {
        C_genFlatSignature(env, 0);
        env.print("// _");
      }
    
      public void ASTNode.C_genFlatSignature(C_env env, int value) {
        env.print("  ");
        for (int i = 24 ; i >= 0 ; i -= 8) {
          env.print("0x");
          String hex = Integer.toHexString((value >> i) & 0xff);
          if (hex.length() == 1) { env.print("0"); }
          env.print(hex);
          env.print(", ");
        }
      }
    
      public void ASTNode.C_genFlatSignature(C_env env, String value) {
        C_genFlatSignature(env, value.length());
        env.println("");
        env.print("  ");
        for (int i = 0 ; i < value.length() ; i++) {
          env.print("'" + value.charAt(i) +"', ");
        }
      }
    
    }
    
    aspect C_Sizeof {
    
      public void Decl.C_emitSizeofDeclaration(C_env env) {
      }
    
      public void SampleDecl.C_emitSizeofDeclaration(C_env env) {
        env.println("extern int labcomm_sizeof_" + env.prefix + getName() +
    		"(" + env.prefix + getName() + " *v);");
      }
    
      public int Decl.C_fixedSizeof() {
        return getType().C_fixedSizeof();
      }
    
      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; }
          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_emitSizeof(C_env env) {
      }
    
      public void SampleDecl.C_emitSizeof(C_env env) {
        env = env.nestStruct("(*v)");
        env.println("int labcomm_sizeof_" + env.prefix + getName() +
    		"(" + env.prefix + getName() + " *v)");
        env.println("{");
        env.indent();
        if (C_isDynamic()) {
          env.println("int result = 4;");
          getType().C_emitSizeof(env);
          env.println("return result;");
        } else {
          env.println("return " + (4 + C_fixedSizeof()) + ";");
        }    
        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.println("result += 4 + strlen(" + env.qualid + ");"); 
          } 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 ArrayType.C_emitSizeof(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_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) {
        C_env env = new C_env("", "", prefix, out);
        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," + getName() + "," + getName());
      }
    
      public void SampleDecl.C_info(C_env env) {
        env.println("C,sample," + getName() + "," + getName());
      }
    
    }