auto import from //depot/cupcake/@135843
diff --git a/tools/aidl/Type.cpp b/tools/aidl/Type.cpp
new file mode 100755
index 0000000..a44072d
--- /dev/null
+++ b/tools/aidl/Type.cpp
@@ -0,0 +1,1228 @@
+#include "Type.h"
+
+Namespace NAMES;
+
+Type* VOID_TYPE;
+Type* BOOLEAN_TYPE;
+Type* BYTE_TYPE;
+Type* CHAR_TYPE;
+Type* INT_TYPE;
+Type* LONG_TYPE;
+Type* FLOAT_TYPE;
+Type* DOUBLE_TYPE;
+Type* STRING_TYPE;
+Type* CHAR_SEQUENCE_TYPE;
+Type* TEXT_UTILS_TYPE;
+Type* REMOTE_EXCEPTION_TYPE;
+Type* RUNTIME_EXCEPTION_TYPE;
+Type* IBINDER_TYPE;
+Type* IINTERFACE_TYPE;
+Type* BINDER_NATIVE_TYPE;
+Type* BINDER_PROXY_TYPE;
+Type* PARCEL_TYPE;
+Type* PARCELABLE_INTERFACE_TYPE;
+Type* MAP_TYPE;
+Type* LIST_TYPE;
+Type* CLASSLOADER_TYPE;
+
+Expression* NULL_VALUE;
+Expression* THIS_VALUE;
+Expression* SUPER_VALUE;
+Expression* TRUE_VALUE;
+Expression* FALSE_VALUE;
+
+void
+register_base_types()
+{
+ VOID_TYPE = new BasicType("void", "XXX", "XXX", "XXX", "XXX", "XXX");
+ NAMES.Add(VOID_TYPE);
+
+ BOOLEAN_TYPE = new BooleanType();
+ NAMES.Add(BOOLEAN_TYPE);
+
+ BYTE_TYPE = new BasicType("byte", "writeByte", "readByte",
+ "writeByteArray", "createByteArray", "readByteArray");
+ NAMES.Add(BYTE_TYPE);
+
+ CHAR_TYPE = new CharType();
+ NAMES.Add(CHAR_TYPE);
+
+ INT_TYPE = new BasicType("int", "writeInt", "readInt",
+ "writeIntArray", "createIntArray", "readIntArray");
+ NAMES.Add(INT_TYPE);
+
+ LONG_TYPE = new BasicType("long", "writeLong", "readLong",
+ "writeLongArray", "createLongArray", "readLongArray");
+ NAMES.Add(LONG_TYPE);
+
+ FLOAT_TYPE = new BasicType("float", "writeFloat", "readFloat",
+ "writeFloatArray", "createFloatArray", "readFloatArray");
+ NAMES.Add(FLOAT_TYPE);
+
+ DOUBLE_TYPE = new BasicType("double", "writeDouble", "readDouble",
+ "writeDoubleArray", "createDoubleArray", "readDoubleArray");
+ NAMES.Add(DOUBLE_TYPE);
+
+ STRING_TYPE = new StringType();
+ NAMES.Add(STRING_TYPE);
+
+ CHAR_SEQUENCE_TYPE = new CharSequenceType();
+ NAMES.Add(CHAR_SEQUENCE_TYPE);
+
+ MAP_TYPE = new MapType();
+ NAMES.Add(MAP_TYPE);
+
+ LIST_TYPE = new ListType();
+ NAMES.Add(LIST_TYPE);
+
+ TEXT_UTILS_TYPE = new Type("android.text", "TextUtils",
+ Type::BUILT_IN, false, false);
+ NAMES.Add(TEXT_UTILS_TYPE);
+
+ REMOTE_EXCEPTION_TYPE = new RemoteExceptionType();
+ NAMES.Add(REMOTE_EXCEPTION_TYPE);
+
+ RUNTIME_EXCEPTION_TYPE = new RuntimeExceptionType();
+ NAMES.Add(RUNTIME_EXCEPTION_TYPE);
+
+ IBINDER_TYPE = new IBinderType();
+ NAMES.Add(IBINDER_TYPE);
+
+ IINTERFACE_TYPE = new IInterfaceType();
+ NAMES.Add(IINTERFACE_TYPE);
+
+ BINDER_NATIVE_TYPE = new BinderType();
+ NAMES.Add(BINDER_NATIVE_TYPE);
+
+ BINDER_PROXY_TYPE = new BinderProxyType();
+ NAMES.Add(BINDER_PROXY_TYPE);
+
+ PARCEL_TYPE = new ParcelType();
+ NAMES.Add(PARCEL_TYPE);
+
+ PARCELABLE_INTERFACE_TYPE = new ParcelableInterfaceType();
+ NAMES.Add(PARCELABLE_INTERFACE_TYPE);
+
+ CLASSLOADER_TYPE = new ClassLoaderType();
+ NAMES.Add(CLASSLOADER_TYPE);
+
+ NULL_VALUE = new LiteralExpression("null");
+ THIS_VALUE = new LiteralExpression("this");
+ SUPER_VALUE = new LiteralExpression("super");
+ TRUE_VALUE = new LiteralExpression("true");
+ FALSE_VALUE = new LiteralExpression("false");
+
+ NAMES.AddGenericType("java.util", "List", 1);
+ NAMES.AddGenericType("java.util", "Map", 2);
+}
+
+static Type*
+make_generic_type(const string& package, const string& name,
+ const vector<Type*>& args)
+{
+ if (package == "java.util" && name == "List") {
+ return new GenericListType("java.util", "List", args);
+ }
+ return NULL;
+ //return new GenericType(package, name, args);
+}
+
+// ================================================================
+
+Type::Type(const string& name, int kind, bool canWriteToParcel, bool canBeOut)
+ :m_package(),
+ m_name(name),
+ m_declFile(""),
+ m_declLine(-1),
+ m_kind(kind),
+ m_canWriteToParcel(canWriteToParcel),
+ m_canBeOut(canBeOut)
+{
+ m_qualifiedName = name;
+}
+
+Type::Type(const string& package, const string& name,
+ int kind, bool canWriteToParcel, bool canBeOut,
+ const string& declFile, int declLine)
+ :m_package(package),
+ m_name(name),
+ m_declFile(declFile),
+ m_declLine(declLine),
+ m_kind(kind),
+ m_canWriteToParcel(canWriteToParcel),
+ m_canBeOut(canBeOut)
+{
+ if (package.length() > 0) {
+ m_qualifiedName = package;
+ m_qualifiedName += '.';
+ }
+ m_qualifiedName += name;
+}
+
+Type::~Type()
+{
+}
+
+bool
+Type::CanBeArray() const
+{
+ return false;
+}
+
+string
+Type::ImportType() const
+{
+ return m_qualifiedName;
+}
+
+string
+Type::CreatorName() const
+{
+ return "";
+}
+
+string
+Type::InstantiableName() const
+{
+ return QualifiedName();
+}
+
+
+void
+Type::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%sn",
+ __FILE__, __LINE__, m_qualifiedName.c_str());
+ addTo->Add(new LiteralExpression("/* WriteToParcel error "
+ + m_qualifiedName + " */"));
+}
+
+void
+Type::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
+ __FILE__, __LINE__, m_qualifiedName.c_str());
+ addTo->Add(new LiteralExpression("/* CreateFromParcel error "
+ + m_qualifiedName + " */"));
+}
+
+void
+Type::ReadFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
+ __FILE__, __LINE__, m_qualifiedName.c_str());
+ addTo->Add(new LiteralExpression("/* ReadFromParcel error "
+ + m_qualifiedName + " */"));
+}
+
+void
+Type::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
+ __FILE__, __LINE__, m_qualifiedName.c_str());
+ addTo->Add(new LiteralExpression("/* WriteArrayToParcel error "
+ + m_qualifiedName + " */"));
+}
+
+void
+Type::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
+ __FILE__, __LINE__, m_qualifiedName.c_str());
+ addTo->Add(new LiteralExpression("/* CreateArrayFromParcel error "
+ + m_qualifiedName + " */"));
+}
+
+void
+Type::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
+ __FILE__, __LINE__, m_qualifiedName.c_str());
+ addTo->Add(new LiteralExpression("/* ReadArrayFromParcel error "
+ + m_qualifiedName + " */"));
+}
+
+void
+Type::SetQualifiedName(const string& qualified)
+{
+ m_qualifiedName = qualified;
+}
+
+Expression*
+Type::BuildWriteToParcelFlags(int flags)
+{
+ if (flags == 0) {
+ return new LiteralExpression("0");
+ }
+ if ((flags&PARCELABLE_WRITE_RETURN_VALUE) != 0) {
+ return new FieldVariable(PARCELABLE_INTERFACE_TYPE,
+ "PARCELABLE_WRITE_RETURN_VALUE");
+ }
+ return new LiteralExpression("0");
+}
+
+// ================================================================
+
+BasicType::BasicType(const string& name, const string& marshallMethod,
+ const string& unmarshallMethod,
+ const string& writeArray, const string& createArray,
+ const string& readArray)
+ :Type(name, BUILT_IN, true, false),
+ m_marshallMethod(marshallMethod),
+ m_unmarshallMethod(unmarshallMethod),
+ m_writeArrayMethod(writeArray),
+ m_createArrayMethod(createArray),
+ m_readArrayMethod(readArray)
+{
+}
+
+void
+BasicType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, m_marshallMethod, 1, v));
+}
+
+void
+BasicType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ addTo->Add(new Assignment(v, new MethodCall(parcel, m_unmarshallMethod)));
+}
+
+bool
+BasicType::CanBeArray() const
+{
+ return true;
+}
+
+void
+BasicType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, m_writeArrayMethod, 1, v));
+}
+
+void
+BasicType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ addTo->Add(new Assignment(v, new MethodCall(parcel, m_createArrayMethod)));
+}
+
+void
+BasicType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ addTo->Add(new MethodCall(parcel, m_readArrayMethod, 1, v));
+}
+
+
+// ================================================================
+
+BooleanType::BooleanType()
+ :Type("boolean", BUILT_IN, true, false)
+{
+}
+
+void
+BooleanType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeInt", 1,
+ new Ternary(v, new LiteralExpression("1"),
+ new LiteralExpression("0"))));
+}
+
+void
+BooleanType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ addTo->Add(new Assignment(v, new Comparison(new LiteralExpression("0"),
+ "!=", new MethodCall(parcel, "readInt"))));
+}
+
+bool
+BooleanType::CanBeArray() const
+{
+ return true;
+}
+
+void
+BooleanType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeBooleanArray", 1, v));
+}
+
+void
+BooleanType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ addTo->Add(new Assignment(v, new MethodCall(parcel, "createBooleanArray")));
+}
+
+void
+BooleanType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ addTo->Add(new MethodCall(parcel, "readBooleanArray", 1, v));
+}
+
+
+// ================================================================
+
+CharType::CharType()
+ :Type("char", BUILT_IN, true, false)
+{
+}
+
+void
+CharType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeInt", 1,
+ new Cast(INT_TYPE, v)));
+}
+
+void
+CharType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ addTo->Add(new Assignment(v, new MethodCall(parcel, "readInt"), this));
+}
+
+bool
+CharType::CanBeArray() const
+{
+ return true;
+}
+
+void
+CharType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeCharArray", 1, v));
+}
+
+void
+CharType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ addTo->Add(new Assignment(v, new MethodCall(parcel, "createCharArray")));
+}
+
+void
+CharType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ addTo->Add(new MethodCall(parcel, "readCharArray", 1, v));
+}
+
+// ================================================================
+
+StringType::StringType()
+ :Type("java.lang", "String", BUILT_IN, true, false)
+{
+}
+
+string
+StringType::CreatorName() const
+{
+ return "android.os.Parcel.STRING_CREATOR";
+}
+
+void
+StringType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeString", 1, v));
+}
+
+void
+StringType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ addTo->Add(new Assignment(v, new MethodCall(parcel, "readString")));
+}
+
+bool
+StringType::CanBeArray() const
+{
+ return true;
+}
+
+void
+StringType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeStringArray", 1, v));
+}
+
+void
+StringType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ addTo->Add(new Assignment(v, new MethodCall(parcel, "createStringArray")));
+}
+
+void
+StringType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ addTo->Add(new MethodCall(parcel, "readStringArray", 1, v));
+}
+
+// ================================================================
+
+CharSequenceType::CharSequenceType()
+ :Type("java.lang", "CharSequence", BUILT_IN, true, false)
+{
+}
+
+string
+CharSequenceType::CreatorName() const
+{
+ return "android.os.Parcel.STRING_CREATOR";
+}
+
+void
+CharSequenceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ // if (v != null) {
+ // parcel.writeInt(1);
+ // v.writeToParcel(parcel);
+ // } else {
+ // parcel.writeInt(0);
+ // }
+ IfStatement* elsepart = new IfStatement();
+ elsepart->statements->Add(new MethodCall(parcel, "writeInt", 1,
+ new LiteralExpression("0")));
+ IfStatement* ifpart = new IfStatement;
+ ifpart->expression = new Comparison(v, "!=", NULL_VALUE);
+ ifpart->elseif = elsepart;
+ ifpart->statements->Add(new MethodCall(parcel, "writeInt", 1,
+ new LiteralExpression("1")));
+ ifpart->statements->Add(new MethodCall(TEXT_UTILS_TYPE, "writeToParcel",
+ 3, v, parcel, BuildWriteToParcelFlags(flags)));
+
+ addTo->Add(ifpart);
+}
+
+void
+CharSequenceType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ // if (0 != parcel.readInt()) {
+ // v = TextUtils.createFromParcel(parcel)
+ // } else {
+ // v = null;
+ // }
+ IfStatement* elsepart = new IfStatement();
+ elsepart->statements->Add(new Assignment(v, NULL_VALUE));
+
+ IfStatement* ifpart = new IfStatement();
+ ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
+ new MethodCall(parcel, "readInt"));
+ ifpart->elseif = elsepart;
+ ifpart->statements->Add(new Assignment(v,
+ new MethodCall(TEXT_UTILS_TYPE,
+ "CHAR_SEQUENCE_CREATOR.createFromParcel", 1, parcel)));
+
+ addTo->Add(ifpart);
+}
+
+
+// ================================================================
+
+RemoteExceptionType::RemoteExceptionType()
+ :Type("android.os", "RemoteException", BUILT_IN, false, false)
+{
+}
+
+void
+RemoteExceptionType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void
+RemoteExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+// ================================================================
+
+RuntimeExceptionType::RuntimeExceptionType()
+ :Type("java.lang", "RuntimeException", BUILT_IN, false, false)
+{
+}
+
+void
+RuntimeExceptionType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void
+RuntimeExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+
+// ================================================================
+
+IBinderType::IBinderType()
+ :Type("android.os", "IBinder", BUILT_IN, true, false)
+{
+}
+
+void
+IBinderType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeStrongBinder", 1, v));
+}
+
+void
+IBinderType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ addTo->Add(new Assignment(v, new MethodCall(parcel, "readStrongBinder")));
+}
+
+void
+IBinderType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeBinderArray", 1, v));
+}
+
+void
+IBinderType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ addTo->Add(new Assignment(v, new MethodCall(parcel, "createBinderArray")));
+}
+
+void
+IBinderType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ addTo->Add(new MethodCall(parcel, "readBinderArray", 1, v));
+}
+
+
+// ================================================================
+
+IInterfaceType::IInterfaceType()
+ :Type("android.os", "IInterface", BUILT_IN, false, false)
+{
+}
+
+void
+IInterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void
+IInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+
+// ================================================================
+
+BinderType::BinderType()
+ :Type("android.os", "Binder", BUILT_IN, false, false)
+{
+}
+
+void
+BinderType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void
+BinderType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+
+// ================================================================
+
+BinderProxyType::BinderProxyType()
+ :Type("android.os", "BinderProxy", BUILT_IN, false, false)
+{
+}
+
+void
+BinderProxyType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void
+BinderProxyType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+
+// ================================================================
+
+ParcelType::ParcelType()
+ :Type("android.os", "Parcel", BUILT_IN, false, false)
+{
+}
+
+void
+ParcelType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void
+ParcelType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+// ================================================================
+
+ParcelableInterfaceType::ParcelableInterfaceType()
+ :Type("android.os", "Parcelable", BUILT_IN, false, false)
+{
+}
+
+void
+ParcelableInterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void
+ParcelableInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+// ================================================================
+
+MapType::MapType()
+ :Type("java.util", "Map", BUILT_IN, true, true)
+{
+}
+
+void
+MapType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeMap", 1, v));
+}
+
+void
+MapType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
+ addTo->Add(new VariableDeclaration(cl,
+ new LiteralExpression("this.getClass().getClassLoader()"),
+ CLASSLOADER_TYPE));
+ addTo->Add(new Assignment(v, new MethodCall(parcel, "readHashMap", 1, cl)));
+}
+
+void
+MapType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
+ addTo->Add(new VariableDeclaration(cl,
+ new LiteralExpression("this.getClass().getClassLoader()"),
+ CLASSLOADER_TYPE));
+ addTo->Add(new MethodCall(parcel, "readMap", 2, v, cl));
+}
+
+
+// ================================================================
+
+ListType::ListType()
+ :Type("java.util", "List", BUILT_IN, true, true)
+{
+}
+
+string
+ListType::InstantiableName() const
+{
+ return "java.util.ArrayList";
+}
+
+void
+ListType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeList", 1, v));
+}
+
+void
+ListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
+ addTo->Add(new VariableDeclaration(cl,
+ new LiteralExpression("this.getClass().getClassLoader()"),
+ CLASSLOADER_TYPE));
+ addTo->Add(new Assignment(v, new MethodCall(parcel, "readArrayList", 1, cl)));
+}
+
+void
+ListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
+ addTo->Add(new VariableDeclaration(cl,
+ new LiteralExpression("this.getClass().getClassLoader()"),
+ CLASSLOADER_TYPE));
+ addTo->Add(new MethodCall(parcel, "readList", 2, v, cl));
+}
+
+
+// ================================================================
+
+ParcelableType::ParcelableType(const string& package, const string& name,
+ bool builtIn, const string& declFile, int declLine)
+ :Type(package, name, builtIn ? BUILT_IN : PARCELABLE, true, true,
+ declFile, declLine)
+{
+}
+
+string
+ParcelableType::CreatorName() const
+{
+ return QualifiedName() + ".CREATOR";
+}
+
+void
+ParcelableType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ // if (v != null) {
+ // parcel.writeInt(1);
+ // v.writeToParcel(parcel);
+ // } else {
+ // parcel.writeInt(0);
+ // }
+ IfStatement* elsepart = new IfStatement();
+ elsepart->statements->Add(new MethodCall(parcel, "writeInt", 1,
+ new LiteralExpression("0")));
+ IfStatement* ifpart = new IfStatement;
+ ifpart->expression = new Comparison(v, "!=", NULL_VALUE);
+ ifpart->elseif = elsepart;
+ ifpart->statements->Add(new MethodCall(parcel, "writeInt", 1,
+ new LiteralExpression("1")));
+ ifpart->statements->Add(new MethodCall(v, "writeToParcel", 2,
+ parcel, BuildWriteToParcelFlags(flags)));
+
+ addTo->Add(ifpart);
+}
+
+void
+ParcelableType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ // if (0 != parcel.readInt()) {
+ // v = CLASS.CREATOR.createFromParcel(parcel)
+ // } else {
+ // v = null;
+ // }
+ IfStatement* elsepart = new IfStatement();
+ elsepart->statements->Add(new Assignment(v, NULL_VALUE));
+
+ IfStatement* ifpart = new IfStatement();
+ ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
+ new MethodCall(parcel, "readInt"));
+ ifpart->elseif = elsepart;
+ ifpart->statements->Add(new Assignment(v,
+ new MethodCall(v->type, "CREATOR.createFromParcel", 1, parcel)));
+
+ addTo->Add(ifpart);
+}
+
+void
+ParcelableType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ // TODO: really, we don't need to have this extra check, but we
+ // don't have two separate marshalling code paths
+ // if (0 != parcel.readInt()) {
+ // v.readFromParcel(parcel)
+ // }
+ IfStatement* ifpart = new IfStatement();
+ ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
+ new MethodCall(parcel, "readInt"));
+ ifpart->statements->Add(new MethodCall(v, "readFromParcel", 1, parcel));
+ addTo->Add(ifpart);
+}
+
+bool
+ParcelableType::CanBeArray() const
+{
+ return true;
+}
+
+void
+ParcelableType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ addTo->Add(new MethodCall(parcel, "writeTypedArray", 2, v,
+ BuildWriteToParcelFlags(flags)));
+}
+
+void
+ParcelableType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ string creator = v->type->QualifiedName() + ".CREATOR";
+ addTo->Add(new Assignment(v, new MethodCall(parcel,
+ "createTypedArray", 1, new LiteralExpression(creator))));
+}
+
+void
+ParcelableType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ string creator = v->type->QualifiedName() + ".CREATOR";
+ addTo->Add(new MethodCall(parcel, "readTypedArray", 2,
+ v, new LiteralExpression(creator)));
+}
+
+
+// ================================================================
+
+InterfaceType::InterfaceType(const string& package, const string& name,
+ bool builtIn, bool oneway,
+ const string& declFile, int declLine)
+ :Type(package, name, builtIn ? BUILT_IN : INTERFACE, true, false,
+ declFile, declLine)
+ ,m_oneway(oneway)
+{
+}
+
+bool
+InterfaceType::OneWay() const
+{
+ return m_oneway;
+}
+
+void
+InterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ // parcel.writeStrongBinder(v != null ? v.asBinder() : null);
+ addTo->Add(new MethodCall(parcel, "writeStrongBinder", 1,
+ new Ternary(
+ new Comparison(v, "!=", NULL_VALUE),
+ new MethodCall(v, "asBinder"),
+ NULL_VALUE)));
+}
+
+void
+InterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ // v = Interface.asInterface(parcel.readStrongBinder());
+ string type = v->type->QualifiedName();
+ type += ".Stub";
+ addTo->Add(new Assignment(v,
+ new MethodCall( NAMES.Find(type), "asInterface", 1,
+ new MethodCall(parcel, "readStrongBinder"))));
+}
+
+
+// ================================================================
+
+GenericType::GenericType(const string& package, const string& name,
+ const vector<Type*>& args)
+ :Type(package, name, BUILT_IN, true, true)
+{
+ m_args = args;
+
+ m_importName = package + '.' + name;
+
+ string gen = "<";
+ int N = args.size();
+ for (int i=0; i<N; i++) {
+ Type* t = args[i];
+ gen += t->QualifiedName();
+ if (i != N-1) {
+ gen += ',';
+ }
+ }
+ gen += '>';
+ m_genericArguments = gen;
+ SetQualifiedName(m_importName + gen);
+}
+
+string
+GenericType::GenericArguments() const
+{
+ return m_genericArguments;
+}
+
+string
+GenericType::ImportType() const
+{
+ return m_importName;
+}
+
+void
+GenericType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ fprintf(stderr, "implement GenericType::WriteToParcel\n");
+}
+
+void
+GenericType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ fprintf(stderr, "implement GenericType::CreateFromParcel\n");
+}
+
+void
+GenericType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ fprintf(stderr, "implement GenericType::ReadFromParcel\n");
+}
+
+
+// ================================================================
+
+GenericListType::GenericListType(const string& package, const string& name,
+ const vector<Type*>& args)
+ :GenericType(package, name, args),
+ m_creator(args[0]->CreatorName())
+{
+}
+
+string
+GenericListType::CreatorName() const
+{
+ return "android.os.Parcel.arrayListCreator";
+}
+
+string
+GenericListType::InstantiableName() const
+{
+ return "java.util.ArrayList" + GenericArguments();
+}
+
+void
+GenericListType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+{
+ if (m_creator == STRING_TYPE->CreatorName()) {
+ addTo->Add(new MethodCall(parcel, "writeStringList", 1, v));
+ } else if (m_creator == IBINDER_TYPE->CreatorName()) {
+ addTo->Add(new MethodCall(parcel, "writeBinderList", 1, v));
+ } else {
+ // parcel.writeTypedListXX(arg);
+ addTo->Add(new MethodCall(parcel, "writeTypedList", 1, v));
+ }
+}
+
+void
+GenericListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+{
+ if (m_creator == STRING_TYPE->CreatorName()) {
+ addTo->Add(new Assignment(v,
+ new MethodCall(parcel, "createStringArrayList", 0)));
+ } else if (m_creator == IBINDER_TYPE->CreatorName()) {
+ addTo->Add(new Assignment(v,
+ new MethodCall(parcel, "createBinderArrayList", 0)));
+ } else {
+ // v = _data.readTypedArrayList(XXX.creator);
+ addTo->Add(new Assignment(v,
+ new MethodCall(parcel, "createTypedArrayList", 1,
+ new LiteralExpression(m_creator))));
+ }
+}
+
+void
+GenericListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+ Variable* parcel)
+{
+ if (m_creator == STRING_TYPE->CreatorName()) {
+ addTo->Add(new MethodCall(parcel, "readStringList", 1, v));
+ } else if (m_creator == IBINDER_TYPE->CreatorName()) {
+ addTo->Add(new MethodCall(parcel, "readBinderList", 1, v));
+ } else {
+ // v = _data.readTypedList(v, XXX.creator);
+ addTo->Add(new MethodCall(parcel, "readTypedList", 2,
+ v,
+ new LiteralExpression(m_creator)));
+ }
+}
+
+// ================================================================
+
+ClassLoaderType::ClassLoaderType()
+ :Type("java.lang", "ClassLoader", BUILT_IN, false, false)
+{
+}
+
+
+// ================================================================
+
+Namespace::Namespace()
+{
+}
+
+Namespace::~Namespace()
+{
+ int N = m_types.size();
+ for (int i=0; i<N; i++) {
+ delete m_types[i];
+ }
+}
+
+void
+Namespace::Add(Type* type)
+{
+ Type* t = Find(type->QualifiedName());
+ if (t == NULL) {
+ m_types.push_back(type);
+ }
+}
+
+void
+Namespace::AddGenericType(const string& package, const string& name, int args)
+{
+ Generic g;
+ g.package = package;
+ g.name = name;
+ g.qualified = package + '.' + name;
+ g.args = args;
+ m_generics.push_back(g);
+}
+
+Type*
+Namespace::Find(const string& name) const
+{
+ int N = m_types.size();
+ for (int i=0; i<N; i++) {
+ if (m_types[i]->QualifiedName() == name) {
+ return m_types[i];
+ }
+ }
+ return NULL;
+}
+
+Type*
+Namespace::Find(const char* package, const char* name) const
+{
+ string s;
+ if (package != NULL) {
+ s += package;
+ s += '.';
+ }
+ s += name;
+ return Find(s);
+}
+
+static string
+normalize_generic(const string& s)
+{
+ string r;
+ int N = s.size();
+ for (int i=0; i<N; i++) {
+ char c = s[i];
+ if (!isspace(c)) {
+ r += c;
+ }
+ }
+ return r;
+}
+
+Type*
+Namespace::Search(const string& name)
+{
+ // an exact match wins
+ Type* result = Find(name);
+ if (result != NULL) {
+ return result;
+ }
+
+ // try the class names
+ // our language doesn't allow you to not specify outer classes
+ // when referencing an inner class. that could be changed, and this
+ // would be the place to do it, but I don't think the complexity in
+ // scoping rules is worth it.
+ int N = m_types.size();
+ for (int i=0; i<N; i++) {
+ if (m_types[i]->Name() == name) {
+ return m_types[i];
+ }
+ }
+
+ // we got to here and it's not a generic, give up
+ if (name.find('<') == name.npos) {
+ return NULL;
+ }
+
+ // remove any whitespace
+ string normalized = normalize_generic(name);
+
+ // find the part before the '<', find a generic for it
+ ssize_t baseIndex = normalized.find('<');
+ string base(normalized.c_str(), baseIndex);
+ const Generic* g = search_generic(base);
+ if (g == NULL) {
+ return NULL;
+ }
+
+ // For each of the args, do a recursive search on it. We don't allow
+ // generics within generics like Java does, because we're really limiting
+ // them to just built-in container classes, at least for now. Our syntax
+ // ensures this right now as well.
+ vector<Type*> args;
+ size_t start = baseIndex + 1;
+ size_t end = start;
+ while (normalized[start] != '\0') {
+ end = normalized.find(',', start);
+ if (end == normalized.npos) {
+ end = normalized.find('>', start);
+ }
+ string s(normalized.c_str()+start, end-start);
+ Type* t = this->Search(s);
+ if (t == NULL) {
+ // maybe we should print a warning here?
+ return NULL;
+ }
+ args.push_back(t);
+ start = end+1;
+ }
+
+ // construct a GenericType, add it to our name set so they always get
+ // the same object, and return it.
+ result = make_generic_type(g->package, g->name, args);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ this->Add(result);
+ return this->Find(result->QualifiedName());
+}
+
+const Namespace::Generic*
+Namespace::search_generic(const string& name) const
+{
+ int N = m_generics.size();
+
+ // first exact match
+ for (int i=0; i<N; i++) {
+ const Generic& g = m_generics[i];
+ if (g.qualified == name) {
+ return &g;
+ }
+ }
+
+ // then name match
+ for (int i=0; i<N; i++) {
+ const Generic& g = m_generics[i];
+ if (g.name == name) {
+ return &g;
+ }
+ }
+
+ return NULL;
+}
+
+void
+Namespace::Dump() const
+{
+ int n = m_types.size();
+ for (int i=0; i<n; i++) {
+ Type* t = m_types[i];
+ printf("type: package=%s name=%s qualifiedName=%s\n",
+ t->Package().c_str(), t->Name().c_str(),
+ t->QualifiedName().c_str());
+ }
+}