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 2013) 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; 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 = (version == 2006 ? "2006" : ""); 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(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"); } 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"+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.println(env.qualid + " = labcomm"+env.verStr+"_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"+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("&labcomm"+env.verStr+"_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, &labcomm"+env.verStr+"_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"+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, &labcomm"+env.verStr+"_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.println("result = labcomm"+env.verStr+"_write_" + getName() + "(w, " + env.qualid + ");"); 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) { } 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(); env.println("return labcomm"+env.verStr+"_internal_encoder_register("); env.indent(); env.println("e,"); env.println("&labcomm"+env.verStr+"_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, &labcomm"+env.verStr+"_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(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("};"); C_emitSizeofValue(env); env.println("struct labcomm"+env.verStr+"_signature labcomm"+env.verStr+"_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(" };"); } 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"+env.verStr+"_set_local_index(&labcomm"+env.verStr+"_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(" + "&labcomm" + env.verStr+"_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; } 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 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"+env.verStr+"_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, 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() ; } } }