Skip to content
Snippets Groups Projects
Select Git revision
1 result Searching

labcomm_decoder.c

Blame
  • Forked from Anders Blomdell / LabComm
    Source project has a limited visibility.
    C_CodeGen.jrag 31.17 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;
          if (rawPrefix.equals("")) {
            this.prefix = rawPrefix;
          } else {
            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;
          if (rawPrefix.equals("")) {
            this.prefix = rawPrefix;
          } else {
            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 <stdint.h>");
        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_emitDecoderDeclaration(env);
          getDecl(i).C_emitEncoderDeclaration(env);
          getDecl(i).C_emitSizeofDeclaration(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);
        }
        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");
      }
    
      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;
        }
        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_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("int labcomm_decoder_ioctl_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_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_encoder_register_" + 
    		env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_encoder *e);");
        env.unindent();
    
        env.println("int labcomm_encode_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_encoder *e,");
        env.println(env.prefix + getName() + " *v");
        env.unindent();
        env.println(");");
    
        env.println("int labcomm_encoder_ioctl_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_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 + ".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_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.println(env.qualid + " = labcomm_read_" + getName() + "(r);");
      }
    
      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_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_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_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_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_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("return labcomm_internal_decoder_register(");
        env.indent();
        env.println("d,");
        env.println("&labcomm_signature_" + env.prefix + getName() + ",");
        env.println("(labcomm_decoder_function)decode_" + env.prefix + getName() + ",");
        env.println("(labcomm_handler_function)handler,");
        env.println("context");
        env.unindent();
        env.println(");");
        env.unindent();
        env.println("}");
      }
    
    }
    
    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_decoder_ioctl_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_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_internal_decoder_ioctl(");
        env.indent();
        env.println("d, &labcomm_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) {
      }
    
      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_writer *w,");
        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_encode_" + env.prefix + getName() + "(");
        env.println("struct labcomm_encoder *e,");
        env.println(env.prefix + getName() + " *v");
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println("return labcomm_internal_encode(e, &labcomm_signature_" + 
    		env.prefix + getName() + 
    		", (labcomm_encoder_function)encode_" + 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) {
        env.println("result = 0;");
      }
    
      public void PrimType.C_emitEncoder(C_env env) {
        env.println("result = labcomm_write_" + getName() + 
                    "(w, " + env.qualid + ");");
        env.println("if (result != 0) { return result; }");
      }
    
      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_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) {
      }
    
      public void SampleDecl.C_emitEncoderRegisterHandler(C_env env) {
        env.println("int labcomm_encoder_register_" + 
    		env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_encoder *e");
        env.unindent();
        env.println(")");
        env.println("{");
        env.indent();
        env.println("return labcomm_internal_encoder_register(");
        env.indent();
        env.println("e,");
        env.println("&labcomm_signature_" + env.prefix + getName() + ",");
        env.println("(labcomm_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_encoder_ioctl_" + env.prefix + getName() + "(");
        env.indent();
        env.println("struct labcomm_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_internal_encoder_ioctl(");
        env.indent();
        env.println("e, &labcomm_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_Signature {
    
      public void ASTNode.C_emitSignature(C_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".C_emitSignature(C_env env)" + 
    		    " not declared");
      }
    
      public void Decl.C_emitSignature(C_env env) {
      }
    
      public void SampleDecl.C_emitSignature(C_env env) {
        env.println("static unsigned char signature_bytes_" + 
    		       env.prefix + getName() + "[] = {");
        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("struct labcomm_signature labcomm_signature_" + 
    		env.prefix + getName() + " = {");
        env.indent();
        env.println("LABCOMM_SAMPLE, \"" + getName() + "\",");
        env.println("(int (*)(struct labcomm_signature *, void *))labcomm_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(" };");
      }
    
      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) {
      }
    
      public void SampleDecl.C_emitConstructor(C_env env) {
        env.println("labcomm_set_local_index(&labcomm_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_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();
        env.println("int result = labcomm_size_packed32(labcomm_signature_" + 
                    env.prefix + getName() +".index);");
        if (C_isDynamic()) {
          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.println("result += 0 + 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 {
          for (int i = 0 ; i < getNumExp() ; i++) {
          	env.println("result += labcomm_size_packed32(" + 
    	            getExp(i).C_getLimit(env, i) + ");");
          }
          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," + env.prefix + getName() + "," + 
                     env.prefix + getName());
      }
    
      public void SampleDecl.C_info(C_env env) {
        env.println(",C,sample," + env.prefix + getName() + "," + 
                    env.prefix + getName());
      }
    
    }