diff options
Diffstat (limited to 'tools/aidl/generate_java.cpp')
-rw-r--r-- | tools/aidl/generate_java.cpp | 652 |
1 files changed, 0 insertions, 652 deletions
diff --git a/tools/aidl/generate_java.cpp b/tools/aidl/generate_java.cpp deleted file mode 100644 index e3c0af0..0000000 --- a/tools/aidl/generate_java.cpp +++ /dev/null @@ -1,652 +0,0 @@ -#include "generate_java.h" -#include "AST.h" -#include "Type.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -// ================================================= -class VariableFactory -{ -public: - VariableFactory(const string& base); // base must be short - Variable* Get(Type* type); - Variable* Get(int index); -private: - vector<Variable*> m_vars; - string m_base; - int m_index; -}; - -VariableFactory::VariableFactory(const string& base) - :m_base(base), - m_index(0) -{ -} - -Variable* -VariableFactory::Get(Type* type) -{ - char name[100]; - sprintf(name, "%s%d", m_base.c_str(), m_index); - m_index++; - Variable* v = new Variable(type, name); - m_vars.push_back(v); - return v; -} - -Variable* -VariableFactory::Get(int index) -{ - return m_vars[index]; -} - -// ================================================= -class StubClass : public Class -{ -public: - StubClass(Type* type, Type* interfaceType); - virtual ~StubClass(); - - Variable* transact_code; - Variable* transact_data; - Variable* transact_reply; - Variable* transact_flags; - SwitchStatement* transact_switch; -private: - void make_as_interface(Type* interfaceType); -}; - -StubClass::StubClass(Type* type, Type* interfaceType) - :Class() -{ - this->comment = "/** Local-side IPC implementation stub class. */"; - this->modifiers = PUBLIC | ABSTRACT | STATIC; - this->what = Class::CLASS; - this->type = type; - this->extends = BINDER_NATIVE_TYPE; - this->interfaces.push_back(interfaceType); - - // descriptor - Field* descriptor = new Field(STATIC | FINAL | PRIVATE, - new Variable(STRING_TYPE, "DESCRIPTOR")); - descriptor->value = "\"" + interfaceType->QualifiedName() + "\""; - this->elements.push_back(descriptor); - - // ctor - Method* ctor = new Method; - ctor->modifiers = PUBLIC; - ctor->comment = "/** Construct the stub at attach it to the " - "interface. */"; - ctor->name = "Stub"; - ctor->statements = new StatementBlock; - MethodCall* attach = new MethodCall(THIS_VALUE, "attachInterface", - 2, THIS_VALUE, new LiteralExpression("DESCRIPTOR")); - ctor->statements->Add(attach); - this->elements.push_back(ctor); - - // asInterface - make_as_interface(interfaceType); - - // asBinder - Method* asBinder = new Method; - asBinder->modifiers = PUBLIC; - asBinder->returnType = IBINDER_TYPE; - asBinder->name = "asBinder"; - asBinder->statements = new StatementBlock; - asBinder->statements->Add(new ReturnStatement(THIS_VALUE)); - this->elements.push_back(asBinder); - - // onTransact - this->transact_code = new Variable(INT_TYPE, "code"); - this->transact_data = new Variable(PARCEL_TYPE, "data"); - this->transact_reply = new Variable(PARCEL_TYPE, "reply"); - this->transact_flags = new Variable(INT_TYPE, "flags"); - Method* onTransact = new Method; - onTransact->modifiers = PUBLIC; - onTransact->returnType = BOOLEAN_TYPE; - onTransact->name = "onTransact"; - onTransact->parameters.push_back(this->transact_code); - onTransact->parameters.push_back(this->transact_data); - onTransact->parameters.push_back(this->transact_reply); - onTransact->parameters.push_back(this->transact_flags); - onTransact->statements = new StatementBlock; - onTransact->exceptions.push_back(REMOTE_EXCEPTION_TYPE); - this->elements.push_back(onTransact); - this->transact_switch = new SwitchStatement(this->transact_code); - - onTransact->statements->Add(this->transact_switch); - MethodCall* superCall = new MethodCall(SUPER_VALUE, "onTransact", 4, - this->transact_code, this->transact_data, - this->transact_reply, this->transact_flags); - onTransact->statements->Add(new ReturnStatement(superCall)); -} - -StubClass::~StubClass() -{ -} - -void -StubClass::make_as_interface(Type *interfaceType) -{ - Variable* obj = new Variable(IBINDER_TYPE, "obj"); - - Method* m = new Method; - m->comment = "/**\n * Cast an IBinder object into an "; - m->comment += interfaceType->Name(); - m->comment += " interface,\n"; - m->comment += " * generating a proxy if needed.\n */"; - m->modifiers = PUBLIC | STATIC; - m->returnType = interfaceType; - m->name = "asInterface"; - m->parameters.push_back(obj); - m->statements = new StatementBlock; - - IfStatement* ifstatement = new IfStatement(); - ifstatement->expression = new Comparison(obj, "==", NULL_VALUE); - ifstatement->statements = new StatementBlock; - ifstatement->statements->Add(new ReturnStatement(NULL_VALUE)); - m->statements->Add(ifstatement); - - // IInterface iin = obj.queryLocalInterface(DESCRIPTOR) - MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface"); - queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR")); - IInterfaceType* iinType = new IInterfaceType(); - Variable *iin = new Variable(iinType, "iin"); - VariableDeclaration* iinVd = new VariableDeclaration(iin, queryLocalInterface, iinType); - m->statements->Add(iinVd); - - // Ensure the instance type of the local object is as expected. - // One scenario where this is needed is if another package (with a - // different class loader) runs in the same process as the service. - - // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>) iin; - Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE); - Comparison* instOfCheck = new Comparison(iin, " instanceof ", - new LiteralExpression(interfaceType->QualifiedName())); - IfStatement* instOfStatement = new IfStatement(); - instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck); - instOfStatement->statements = new StatementBlock; - instOfStatement->statements->Add(new ReturnStatement(new Cast(interfaceType, iin))); - m->statements->Add(instOfStatement); - - string proxyType = interfaceType->QualifiedName(); - proxyType += ".Stub.Proxy"; - NewExpression* ne = new NewExpression(NAMES.Find(proxyType)); - ne->arguments.push_back(obj); - m->statements->Add(new ReturnStatement(ne)); - - this->elements.push_back(m); -} - - - -// ================================================= -class ProxyClass : public Class -{ -public: - ProxyClass(Type* type, InterfaceType* interfaceType); - virtual ~ProxyClass(); - - Variable* mRemote; - bool mOneWay; -}; - -ProxyClass::ProxyClass(Type* type, InterfaceType* interfaceType) - :Class() -{ - this->modifiers = PRIVATE | STATIC; - this->what = Class::CLASS; - this->type = type; - this->interfaces.push_back(interfaceType); - - mOneWay = interfaceType->OneWay(); - - // IBinder mRemote - mRemote = new Variable(IBINDER_TYPE, "mRemote"); - this->elements.push_back(new Field(PRIVATE, mRemote)); - - // Proxy() - Variable* remote = new Variable(IBINDER_TYPE, "remote"); - Method* ctor = new Method; - ctor->name = "Proxy"; - ctor->statements = new StatementBlock; - ctor->parameters.push_back(remote); - ctor->statements->Add(new Assignment(mRemote, remote)); - this->elements.push_back(ctor); - - // IBinder asBinder() - Method* asBinder = new Method; - asBinder->modifiers = PUBLIC; - asBinder->returnType = IBINDER_TYPE; - asBinder->name = "asBinder"; - asBinder->statements = new StatementBlock; - asBinder->statements->Add(new ReturnStatement(mRemote)); - this->elements.push_back(asBinder); -} - -ProxyClass::~ProxyClass() -{ -} - -// ================================================= -static string -gather_comments(extra_text_type* extra) -{ - string s; - while (extra) { - if (extra->which == SHORT_COMMENT) { - s += extra->data; - } - else if (extra->which == LONG_COMMENT) { - s += "/*"; - s += extra->data; - s += "*/"; - } - extra = extra->next; - } - return s; -} - -static string -append(const char* a, const char* b) -{ - string s = a; - s += b; - return s; -} - -static void -generate_new_array(Type* t, StatementBlock* addTo, Variable* v, - Variable* parcel) -{ - Variable* len = new Variable(INT_TYPE, v->name + "_length"); - addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt"))); - IfStatement* lencheck = new IfStatement(); - lencheck->expression = new Comparison(len, "<", new LiteralExpression("0")); - lencheck->statements->Add(new Assignment(v, NULL_VALUE)); - lencheck->elseif = new IfStatement(); - lencheck->elseif->statements->Add(new Assignment(v, - new NewArrayExpression(t, len))); - addTo->Add(lencheck); -} - -static void -generate_write_to_parcel(Type* t, StatementBlock* addTo, Variable* v, - Variable* parcel, int flags) -{ - if (v->dimension == 0) { - t->WriteToParcel(addTo, v, parcel, flags); - } - if (v->dimension == 1) { - t->WriteArrayToParcel(addTo, v, parcel, flags); - } -} - -static void -generate_create_from_parcel(Type* t, StatementBlock* addTo, Variable* v, - Variable* parcel) -{ - if (v->dimension == 0) { - t->CreateFromParcel(addTo, v, parcel); - } - if (v->dimension == 1) { - t->CreateArrayFromParcel(addTo, v, parcel); - } -} - -static void -generate_read_from_parcel(Type* t, StatementBlock* addTo, Variable* v, - Variable* parcel) -{ - if (v->dimension == 0) { - t->ReadFromParcel(addTo, v, parcel); - } - if (v->dimension == 1) { - t->ReadArrayFromParcel(addTo, v, parcel); - } -} - - -static void -generate_method(const method_type* method, Class* interface, - StubClass* stubClass, ProxyClass* proxyClass, int index) -{ - arg_type* arg; - int i; - bool hasOutParams = false; - - const bool oneway = proxyClass->mOneWay || method->oneway; - - // == the TRANSACT_ constant ============================================= - string transactCodeName = "TRANSACTION_"; - transactCodeName += method->name.data; - - char transactCodeValue[50]; - sprintf(transactCodeValue, "(IBinder.FIRST_CALL_TRANSACTION + %d)", index); - - Field* transactCode = new Field(STATIC | FINAL, - new Variable(INT_TYPE, transactCodeName)); - transactCode->value = transactCodeValue; - stubClass->elements.push_back(transactCode); - - // == the declaration in the interface =================================== - Method* decl = new Method; - decl->comment = gather_comments(method->comments_token->extra); - decl->modifiers = PUBLIC; - decl->returnType = NAMES.Search(method->type.type.data); - decl->returnTypeDimension = method->type.dimension; - decl->name = method->name.data; - - arg = method->args; - while (arg != NULL) { - decl->parameters.push_back(new Variable( - NAMES.Search(arg->type.type.data), arg->name.data, - arg->type.dimension)); - arg = arg->next; - } - - decl->exceptions.push_back(REMOTE_EXCEPTION_TYPE); - - interface->elements.push_back(decl); - - // == the stub method ==================================================== - - Case* c = new Case(transactCodeName); - - MethodCall* realCall = new MethodCall(THIS_VALUE, method->name.data); - - // interface token validation is the very first thing we do - c->statements->Add(new MethodCall(stubClass->transact_data, - "enforceInterface", 1, new LiteralExpression("DESCRIPTOR"))); - - // args - VariableFactory stubArgs("_arg"); - arg = method->args; - while (arg != NULL) { - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = stubArgs.Get(t); - v->dimension = arg->type.dimension; - - c->statements->Add(new VariableDeclaration(v)); - - if (convert_direction(arg->direction.data) & IN_PARAMETER) { - generate_create_from_parcel(t, c->statements, v, - stubClass->transact_data); - } else { - if (arg->type.dimension == 0) { - c->statements->Add(new Assignment( - v, new NewExpression(v->type))); - } - else if (arg->type.dimension == 1) { - generate_new_array(v->type, c->statements, v, - stubClass->transact_data); - } - else { - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, - __LINE__); - } - } - - realCall->arguments.push_back(v); - - arg = arg->next; - } - - // the real call - Variable* _result = NULL; - if (0 == strcmp(method->type.type.data, "void")) { - c->statements->Add(realCall); - - if (!oneway) { - // report that there were no exceptions - MethodCall* ex = new MethodCall(stubClass->transact_reply, - "writeNoException", 0); - c->statements->Add(ex); - } - } else { - _result = new Variable(decl->returnType, "_result", - decl->returnTypeDimension); - c->statements->Add(new VariableDeclaration(_result, realCall)); - - if (!oneway) { - // report that there were no exceptions - MethodCall* ex = new MethodCall(stubClass->transact_reply, - "writeNoException", 0); - c->statements->Add(ex); - } - - // marshall the return value - generate_write_to_parcel(decl->returnType, c->statements, _result, - stubClass->transact_reply, - Type::PARCELABLE_WRITE_RETURN_VALUE); - } - - // out parameters - i = 0; - arg = method->args; - while (arg != NULL) { - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = stubArgs.Get(i++); - - if (convert_direction(arg->direction.data) & OUT_PARAMETER) { - generate_write_to_parcel(t, c->statements, v, - stubClass->transact_reply, - Type::PARCELABLE_WRITE_RETURN_VALUE); - hasOutParams = true; - } - - arg = arg->next; - } - - // return true - c->statements->Add(new ReturnStatement(TRUE_VALUE)); - stubClass->transact_switch->cases.push_back(c); - - // == the proxy method =================================================== - Method* proxy = new Method; - proxy->comment = gather_comments(method->comments_token->extra); - proxy->modifiers = PUBLIC; - proxy->returnType = NAMES.Search(method->type.type.data); - proxy->returnTypeDimension = method->type.dimension; - proxy->name = method->name.data; - proxy->statements = new StatementBlock; - arg = method->args; - while (arg != NULL) { - proxy->parameters.push_back(new Variable( - NAMES.Search(arg->type.type.data), arg->name.data, - arg->type.dimension)); - arg = arg->next; - } - proxy->exceptions.push_back(REMOTE_EXCEPTION_TYPE); - proxyClass->elements.push_back(proxy); - - // the parcels - Variable* _data = new Variable(PARCEL_TYPE, "_data"); - proxy->statements->Add(new VariableDeclaration(_data, - new MethodCall(PARCEL_TYPE, "obtain"))); - Variable* _reply = NULL; - if (!oneway) { - _reply = new Variable(PARCEL_TYPE, "_reply"); - proxy->statements->Add(new VariableDeclaration(_reply, - new MethodCall(PARCEL_TYPE, "obtain"))); - } - - // the return value - _result = NULL; - if (0 != strcmp(method->type.type.data, "void")) { - _result = new Variable(proxy->returnType, "_result", - method->type.dimension); - proxy->statements->Add(new VariableDeclaration(_result)); - } - - // try and finally - TryStatement* tryStatement = new TryStatement(); - proxy->statements->Add(tryStatement); - FinallyStatement* finallyStatement = new FinallyStatement(); - proxy->statements->Add(finallyStatement); - - // the interface identifier token: the DESCRIPTOR constant, marshalled as a string - tryStatement->statements->Add(new MethodCall(_data, "writeInterfaceToken", - 1, new LiteralExpression("DESCRIPTOR"))); - - // the parameters - arg = method->args; - while (arg != NULL) { - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = new Variable(t, arg->name.data, arg->type.dimension); - int dir = convert_direction(arg->direction.data); - if (dir == OUT_PARAMETER && arg->type.dimension != 0) { - IfStatement* checklen = new IfStatement(); - checklen->expression = new Comparison(v, "==", NULL_VALUE); - checklen->statements->Add(new MethodCall(_data, "writeInt", 1, - new LiteralExpression("-1"))); - checklen->elseif = new IfStatement(); - checklen->elseif->statements->Add(new MethodCall(_data, "writeInt", - 1, new FieldVariable(v, "length"))); - tryStatement->statements->Add(checklen); - } - else if (dir & IN_PARAMETER) { - generate_write_to_parcel(t, tryStatement->statements, v, _data, 0); - } - arg = arg->next; - } - - // the transact call - MethodCall* call = new MethodCall(proxyClass->mRemote, "transact", 4, - new LiteralExpression("Stub." + transactCodeName), - _data, _reply ? _reply : NULL_VALUE, - new LiteralExpression( - oneway ? "IBinder.FLAG_ONEWAY" : "0")); - tryStatement->statements->Add(call); - - // throw back exceptions. - if (_reply) { - MethodCall* ex = new MethodCall(_reply, "readException", 0); - tryStatement->statements->Add(ex); - } - - // returning and cleanup - if (_reply != NULL) { - if (_result != NULL) { - generate_create_from_parcel(proxy->returnType, - tryStatement->statements, _result, _reply); - } - - // the out/inout parameters - arg = method->args; - while (arg != NULL) { - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = new Variable(t, arg->name.data, arg->type.dimension); - if (convert_direction(arg->direction.data) & OUT_PARAMETER) { - generate_read_from_parcel(t, tryStatement->statements, - v, _reply); - } - arg = arg->next; - } - - finallyStatement->statements->Add(new MethodCall(_reply, "recycle")); - } - finallyStatement->statements->Add(new MethodCall(_data, "recycle")); - - if (_result != NULL) { - proxy->statements->Add(new ReturnStatement(_result)); - } -} - -static void -generate_interface_descriptors(StubClass* stub, ProxyClass* proxy) -{ - // the interface descriptor transaction handler - Case* c = new Case("INTERFACE_TRANSACTION"); - c->statements->Add(new MethodCall(stub->transact_reply, "writeString", - 1, new LiteralExpression("DESCRIPTOR"))); - c->statements->Add(new ReturnStatement(TRUE_VALUE)); - stub->transact_switch->cases.push_back(c); - - // and the proxy-side method returning the descriptor directly - Method* getDesc = new Method; - getDesc->modifiers = PUBLIC; - getDesc->returnType = STRING_TYPE; - getDesc->returnTypeDimension = 0; - getDesc->name = "getInterfaceDescriptor"; - getDesc->statements = new StatementBlock; - getDesc->statements->Add(new ReturnStatement(new LiteralExpression("DESCRIPTOR"))); - proxy->elements.push_back(getDesc); -} - -static Class* -generate_interface_class(const interface_type* iface) -{ - InterfaceType* interfaceType = static_cast<InterfaceType*>( - NAMES.Find(iface->package, iface->name.data)); - - // the interface class - Class* interface = new Class; - interface->comment = gather_comments(iface->comments_token->extra); - interface->modifiers = PUBLIC; - interface->what = Class::INTERFACE; - interface->type = interfaceType; - interface->interfaces.push_back(IINTERFACE_TYPE); - - // the stub inner class - StubClass* stub = new StubClass( - NAMES.Find(iface->package, append(iface->name.data, ".Stub").c_str()), - interfaceType); - interface->elements.push_back(stub); - - // the proxy inner class - ProxyClass* proxy = new ProxyClass( - NAMES.Find(iface->package, - append(iface->name.data, ".Stub.Proxy").c_str()), - interfaceType); - stub->elements.push_back(proxy); - - // stub and proxy support for getInterfaceDescriptor() - generate_interface_descriptors(stub, proxy); - - // all the declared methods of the interface - int index = 0; - interface_item_type* item = iface->interface_items; - while (item != NULL) { - if (item->item_type == METHOD_TYPE) { - generate_method((method_type*)item, interface, stub, proxy, index); - } - item = item->next; - index++; - } - - return interface; -} - -int -generate_java(const string& filename, const string& originalSrc, - interface_type* iface) -{ - Document* document = new Document; - document->comment = ""; - if (iface->package) document->package = iface->package; - document->originalSrc = originalSrc; - document->classes.push_back(generate_interface_class(iface)); - -// printf("outputting... filename=%s\n", filename.c_str()); - FILE* to; - if (filename == "-") { - to = stdout; - } else { - /* open file in binary mode to ensure that the tool produces the - * same output on all platforms !! - */ - to = fopen(filename.c_str(), "wb"); - if (to == NULL) { - fprintf(stderr, "unable to open %s for write\n", filename.c_str()); - return 1; - } - } - - document->Write(to); - - fclose(to); - return 0; -} - |