1#include "Type.h"
2
3Namespace NAMES;
4
5Type* VOID_TYPE;
6Type* BOOLEAN_TYPE;
7Type* BYTE_TYPE;
8Type* CHAR_TYPE;
9Type* INT_TYPE;
10Type* LONG_TYPE;
11Type* FLOAT_TYPE;
12Type* DOUBLE_TYPE;
13Type* STRING_TYPE;
14Type* CHAR_SEQUENCE_TYPE;
15Type* TEXT_UTILS_TYPE;
16Type* REMOTE_EXCEPTION_TYPE;
17Type* RUNTIME_EXCEPTION_TYPE;
18Type* IBINDER_TYPE;
19Type* IINTERFACE_TYPE;
20Type* BINDER_NATIVE_TYPE;
21Type* BINDER_PROXY_TYPE;
22Type* PARCEL_TYPE;
23Type* PARCELABLE_INTERFACE_TYPE;
24Type* MAP_TYPE;
25Type* LIST_TYPE;
26Type* CLASSLOADER_TYPE;
27
28Expression* NULL_VALUE;
29Expression* THIS_VALUE;
30Expression* SUPER_VALUE;
31Expression* TRUE_VALUE;
32Expression* FALSE_VALUE;
33
34void
35register_base_types()
36{
37    VOID_TYPE = new BasicType("void", "XXX", "XXX", "XXX", "XXX", "XXX");
38    NAMES.Add(VOID_TYPE);
39
40    BOOLEAN_TYPE = new BooleanType();
41    NAMES.Add(BOOLEAN_TYPE);
42
43    BYTE_TYPE = new BasicType("byte", "writeByte", "readByte",
44                "writeByteArray", "createByteArray", "readByteArray");
45    NAMES.Add(BYTE_TYPE);
46
47    CHAR_TYPE = new CharType();
48    NAMES.Add(CHAR_TYPE);
49
50    INT_TYPE = new BasicType("int", "writeInt", "readInt",
51                "writeIntArray", "createIntArray", "readIntArray");
52    NAMES.Add(INT_TYPE);
53
54    LONG_TYPE = new BasicType("long", "writeLong", "readLong",
55                "writeLongArray", "createLongArray", "readLongArray");
56    NAMES.Add(LONG_TYPE);
57
58    FLOAT_TYPE = new BasicType("float", "writeFloat", "readFloat",
59                "writeFloatArray", "createFloatArray", "readFloatArray");
60    NAMES.Add(FLOAT_TYPE);
61
62    DOUBLE_TYPE = new BasicType("double", "writeDouble", "readDouble",
63                "writeDoubleArray", "createDoubleArray", "readDoubleArray");
64    NAMES.Add(DOUBLE_TYPE);
65
66    STRING_TYPE = new StringType();
67    NAMES.Add(STRING_TYPE);
68
69    CHAR_SEQUENCE_TYPE = new CharSequenceType();
70    NAMES.Add(CHAR_SEQUENCE_TYPE);
71
72    MAP_TYPE = new MapType();
73    NAMES.Add(MAP_TYPE);
74
75    LIST_TYPE = new ListType();
76    NAMES.Add(LIST_TYPE);
77
78    TEXT_UTILS_TYPE = new Type("android.text", "TextUtils",
79                                    Type::BUILT_IN, false, false);
80    NAMES.Add(TEXT_UTILS_TYPE);
81
82    REMOTE_EXCEPTION_TYPE = new RemoteExceptionType();
83    NAMES.Add(REMOTE_EXCEPTION_TYPE);
84
85    RUNTIME_EXCEPTION_TYPE = new RuntimeExceptionType();
86    NAMES.Add(RUNTIME_EXCEPTION_TYPE);
87
88    IBINDER_TYPE = new IBinderType();
89    NAMES.Add(IBINDER_TYPE);
90
91    IINTERFACE_TYPE = new IInterfaceType();
92    NAMES.Add(IINTERFACE_TYPE);
93
94    BINDER_NATIVE_TYPE = new BinderType();
95    NAMES.Add(BINDER_NATIVE_TYPE);
96
97    BINDER_PROXY_TYPE = new BinderProxyType();
98    NAMES.Add(BINDER_PROXY_TYPE);
99
100    PARCEL_TYPE = new ParcelType();
101    NAMES.Add(PARCEL_TYPE);
102
103    PARCELABLE_INTERFACE_TYPE = new ParcelableInterfaceType();
104    NAMES.Add(PARCELABLE_INTERFACE_TYPE);
105
106    CLASSLOADER_TYPE = new ClassLoaderType();
107    NAMES.Add(CLASSLOADER_TYPE);
108
109    NULL_VALUE = new LiteralExpression("null");
110    THIS_VALUE = new LiteralExpression("this");
111    SUPER_VALUE = new LiteralExpression("super");
112    TRUE_VALUE = new LiteralExpression("true");
113    FALSE_VALUE = new LiteralExpression("false");
114
115    NAMES.AddGenericType("java.util", "List", 1);
116    NAMES.AddGenericType("java.util", "Map", 2);
117}
118
119static Type*
120make_generic_type(const string& package, const string& name,
121                    const vector<Type*>& args)
122{
123    if (package == "java.util" && name == "List") {
124        return new GenericListType("java.util", "List", args);
125    }
126    return NULL;
127    //return new GenericType(package, name, args);
128}
129
130// ================================================================
131
132Type::Type(const string& name, int kind, bool canWriteToParcel, bool canBeOut)
133    :m_package(),
134     m_name(name),
135     m_declFile(""),
136     m_declLine(-1),
137     m_kind(kind),
138     m_canWriteToParcel(canWriteToParcel),
139     m_canBeOut(canBeOut)
140{
141    m_qualifiedName = name;
142}
143
144Type::Type(const string& package, const string& name,
145            int kind, bool canWriteToParcel, bool canBeOut,
146            const string& declFile, int declLine)
147    :m_package(package),
148     m_name(name),
149     m_declFile(declFile),
150     m_declLine(declLine),
151     m_kind(kind),
152     m_canWriteToParcel(canWriteToParcel),
153     m_canBeOut(canBeOut)
154{
155    if (package.length() > 0) {
156        m_qualifiedName = package;
157        m_qualifiedName += '.';
158    }
159    m_qualifiedName += name;
160}
161
162Type::~Type()
163{
164}
165
166bool
167Type::CanBeArray() const
168{
169    return false;
170}
171
172string
173Type::ImportType() const
174{
175    return m_qualifiedName;
176}
177
178string
179Type::CreatorName() const
180{
181    return "";
182}
183
184string
185Type::InstantiableName() const
186{
187    return QualifiedName();
188}
189
190
191void
192Type::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
193{
194    fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%sn",
195            __FILE__, __LINE__, m_qualifiedName.c_str());
196    addTo->Add(new LiteralExpression("/* WriteToParcel error "
197                + m_qualifiedName + " */"));
198}
199
200void
201Type::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
202{
203    fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
204            __FILE__, __LINE__, m_qualifiedName.c_str());
205    addTo->Add(new LiteralExpression("/* CreateFromParcel error "
206                + m_qualifiedName + " */"));
207}
208
209void
210Type::ReadFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
211{
212    fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
213            __FILE__, __LINE__, m_qualifiedName.c_str());
214    addTo->Add(new LiteralExpression("/* ReadFromParcel error "
215                + m_qualifiedName + " */"));
216}
217
218void
219Type::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
220{
221    fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
222            __FILE__, __LINE__, m_qualifiedName.c_str());
223    addTo->Add(new LiteralExpression("/* WriteArrayToParcel error "
224                + m_qualifiedName + " */"));
225}
226
227void
228Type::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
229                            Variable* parcel)
230{
231    fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
232            __FILE__, __LINE__, m_qualifiedName.c_str());
233    addTo->Add(new LiteralExpression("/* CreateArrayFromParcel error "
234                + m_qualifiedName + " */"));
235}
236
237void
238Type::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
239{
240    fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
241            __FILE__, __LINE__, m_qualifiedName.c_str());
242    addTo->Add(new LiteralExpression("/* ReadArrayFromParcel error "
243                + m_qualifiedName + " */"));
244}
245
246void
247Type::SetQualifiedName(const string& qualified)
248{
249    m_qualifiedName = qualified;
250}
251
252Expression*
253Type::BuildWriteToParcelFlags(int flags)
254{
255    if (flags == 0) {
256        return new LiteralExpression("0");
257    }
258    if ((flags&PARCELABLE_WRITE_RETURN_VALUE) != 0) {
259        return new FieldVariable(PARCELABLE_INTERFACE_TYPE,
260                "PARCELABLE_WRITE_RETURN_VALUE");
261    }
262    return new LiteralExpression("0");
263}
264
265// ================================================================
266
267BasicType::BasicType(const string& name, const string& marshallMethod,
268                     const string& unmarshallMethod,
269                     const string& writeArray, const string& createArray,
270                     const string& readArray)
271    :Type(name, BUILT_IN, true, false),
272     m_marshallMethod(marshallMethod),
273     m_unmarshallMethod(unmarshallMethod),
274     m_writeArrayMethod(writeArray),
275     m_createArrayMethod(createArray),
276     m_readArrayMethod(readArray)
277{
278}
279
280void
281BasicType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
282{
283    addTo->Add(new MethodCall(parcel, m_marshallMethod, 1, v));
284}
285
286void
287BasicType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
288{
289    addTo->Add(new Assignment(v, new MethodCall(parcel, m_unmarshallMethod)));
290}
291
292bool
293BasicType::CanBeArray() const
294{
295    return true;
296}
297
298void
299BasicType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
300{
301    addTo->Add(new MethodCall(parcel, m_writeArrayMethod, 1, v));
302}
303
304void
305BasicType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
306                            Variable* parcel)
307{
308    addTo->Add(new Assignment(v, new MethodCall(parcel, m_createArrayMethod)));
309}
310
311void
312BasicType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
313{
314    addTo->Add(new MethodCall(parcel, m_readArrayMethod, 1, v));
315}
316
317
318// ================================================================
319
320BooleanType::BooleanType()
321    :Type("boolean", BUILT_IN, true, false)
322{
323}
324
325void
326BooleanType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
327{
328    addTo->Add(new MethodCall(parcel, "writeInt", 1,
329                new Ternary(v, new LiteralExpression("1"),
330                    new LiteralExpression("0"))));
331}
332
333void
334BooleanType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
335{
336    addTo->Add(new Assignment(v, new Comparison(new LiteralExpression("0"),
337                    "!=", new MethodCall(parcel, "readInt"))));
338}
339
340bool
341BooleanType::CanBeArray() const
342{
343    return true;
344}
345
346void
347BooleanType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
348{
349    addTo->Add(new MethodCall(parcel, "writeBooleanArray", 1, v));
350}
351
352void
353BooleanType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
354                            Variable* parcel)
355{
356    addTo->Add(new Assignment(v, new MethodCall(parcel, "createBooleanArray")));
357}
358
359void
360BooleanType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
361{
362    addTo->Add(new MethodCall(parcel, "readBooleanArray", 1, v));
363}
364
365
366// ================================================================
367
368CharType::CharType()
369    :Type("char", BUILT_IN, true, false)
370{
371}
372
373void
374CharType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
375{
376    addTo->Add(new MethodCall(parcel, "writeInt", 1,
377                    new Cast(INT_TYPE, v)));
378}
379
380void
381CharType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
382{
383    addTo->Add(new Assignment(v, new MethodCall(parcel, "readInt"), this));
384}
385
386bool
387CharType::CanBeArray() const
388{
389    return true;
390}
391
392void
393CharType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
394{
395    addTo->Add(new MethodCall(parcel, "writeCharArray", 1, v));
396}
397
398void
399CharType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
400                            Variable* parcel)
401{
402    addTo->Add(new Assignment(v, new MethodCall(parcel, "createCharArray")));
403}
404
405void
406CharType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
407{
408    addTo->Add(new MethodCall(parcel, "readCharArray", 1, v));
409}
410
411// ================================================================
412
413StringType::StringType()
414    :Type("java.lang", "String", BUILT_IN, true, false)
415{
416}
417
418string
419StringType::CreatorName() const
420{
421    return "android.os.Parcel.STRING_CREATOR";
422}
423
424void
425StringType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
426{
427    addTo->Add(new MethodCall(parcel, "writeString", 1, v));
428}
429
430void
431StringType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
432{
433    addTo->Add(new Assignment(v, new MethodCall(parcel, "readString")));
434}
435
436bool
437StringType::CanBeArray() const
438{
439    return true;
440}
441
442void
443StringType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
444{
445    addTo->Add(new MethodCall(parcel, "writeStringArray", 1, v));
446}
447
448void
449StringType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
450                            Variable* parcel)
451{
452    addTo->Add(new Assignment(v, new MethodCall(parcel, "createStringArray")));
453}
454
455void
456StringType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
457{
458    addTo->Add(new MethodCall(parcel, "readStringArray", 1, v));
459}
460
461// ================================================================
462
463CharSequenceType::CharSequenceType()
464    :Type("java.lang", "CharSequence", BUILT_IN, true, false)
465{
466}
467
468string
469CharSequenceType::CreatorName() const
470{
471    return "android.os.Parcel.STRING_CREATOR";
472}
473
474void
475CharSequenceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
476{
477    // if (v != null) {
478    //     parcel.writeInt(1);
479    //     v.writeToParcel(parcel);
480    // } else {
481    //     parcel.writeInt(0);
482    // }
483    IfStatement* elsepart = new IfStatement();
484    elsepart->statements->Add(new MethodCall(parcel, "writeInt", 1,
485                                new LiteralExpression("0")));
486    IfStatement* ifpart = new IfStatement;
487    ifpart->expression = new Comparison(v, "!=", NULL_VALUE);
488    ifpart->elseif = elsepart;
489    ifpart->statements->Add(new MethodCall(parcel, "writeInt", 1,
490                                new LiteralExpression("1")));
491    ifpart->statements->Add(new MethodCall(TEXT_UTILS_TYPE, "writeToParcel",
492                                3, v, parcel, BuildWriteToParcelFlags(flags)));
493
494    addTo->Add(ifpart);
495}
496
497void
498CharSequenceType::CreateFromParcel(StatementBlock* addTo, Variable* v,
499                                Variable* parcel)
500{
501    // if (0 != parcel.readInt()) {
502    //     v = TextUtils.createFromParcel(parcel)
503    // } else {
504    //     v = null;
505    // }
506    IfStatement* elsepart = new IfStatement();
507    elsepart->statements->Add(new Assignment(v, NULL_VALUE));
508
509    IfStatement* ifpart = new IfStatement();
510    ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
511                new MethodCall(parcel, "readInt"));
512    ifpart->elseif = elsepart;
513    ifpart->statements->Add(new Assignment(v,
514                new MethodCall(TEXT_UTILS_TYPE,
515                                    "CHAR_SEQUENCE_CREATOR.createFromParcel", 1, parcel)));
516
517    addTo->Add(ifpart);
518}
519
520
521// ================================================================
522
523RemoteExceptionType::RemoteExceptionType()
524    :Type("android.os", "RemoteException", BUILT_IN, false, false)
525{
526}
527
528void
529RemoteExceptionType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
530{
531    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
532}
533
534void
535RemoteExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
536{
537    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
538}
539
540// ================================================================
541
542RuntimeExceptionType::RuntimeExceptionType()
543    :Type("java.lang", "RuntimeException", BUILT_IN, false, false)
544{
545}
546
547void
548RuntimeExceptionType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
549{
550    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
551}
552
553void
554RuntimeExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
555{
556    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
557}
558
559
560// ================================================================
561
562IBinderType::IBinderType()
563    :Type("android.os", "IBinder", BUILT_IN, true, false)
564{
565}
566
567void
568IBinderType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
569{
570    addTo->Add(new MethodCall(parcel, "writeStrongBinder", 1, v));
571}
572
573void
574IBinderType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
575{
576    addTo->Add(new Assignment(v, new MethodCall(parcel, "readStrongBinder")));
577}
578
579void
580IBinderType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
581{
582    addTo->Add(new MethodCall(parcel, "writeBinderArray", 1, v));
583}
584
585void
586IBinderType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
587                            Variable* parcel)
588{
589    addTo->Add(new Assignment(v, new MethodCall(parcel, "createBinderArray")));
590}
591
592void
593IBinderType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
594{
595    addTo->Add(new MethodCall(parcel, "readBinderArray", 1, v));
596}
597
598
599// ================================================================
600
601IInterfaceType::IInterfaceType()
602    :Type("android.os", "IInterface", BUILT_IN, false, false)
603{
604}
605
606void
607IInterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
608{
609    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
610}
611
612void
613IInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
614{
615    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
616}
617
618
619// ================================================================
620
621BinderType::BinderType()
622    :Type("android.os", "Binder", BUILT_IN, false, false)
623{
624}
625
626void
627BinderType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
628{
629    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
630}
631
632void
633BinderType::CreateFromParcel(StatementBlock* addTo, Variable* v,
634                                    Variable* parcel)
635{
636    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
637}
638
639
640// ================================================================
641
642BinderProxyType::BinderProxyType()
643    :Type("android.os", "BinderProxy", BUILT_IN, false, false)
644{
645}
646
647void
648BinderProxyType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
649{
650    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
651}
652
653void
654BinderProxyType::CreateFromParcel(StatementBlock* addTo, Variable* v,
655                                    Variable* parcel)
656{
657    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
658}
659
660
661// ================================================================
662
663ParcelType::ParcelType()
664    :Type("android.os", "Parcel", BUILT_IN, false, false)
665{
666}
667
668void
669ParcelType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
670{
671    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
672}
673
674void
675ParcelType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
676{
677    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
678}
679
680// ================================================================
681
682ParcelableInterfaceType::ParcelableInterfaceType()
683    :Type("android.os", "Parcelable", BUILT_IN, false, false)
684{
685}
686
687void
688ParcelableInterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
689{
690    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
691}
692
693void
694ParcelableInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
695{
696    fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
697}
698
699// ================================================================
700
701MapType::MapType()
702    :Type("java.util", "Map", BUILT_IN, true, true)
703{
704}
705
706void
707MapType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
708{
709    addTo->Add(new MethodCall(parcel, "writeMap", 1, v));
710}
711
712void
713MapType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
714{
715    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
716    addTo->Add(new VariableDeclaration(cl,
717        new LiteralExpression("this.getClass().getClassLoader()"),
718        CLASSLOADER_TYPE));
719    addTo->Add(new Assignment(v, new MethodCall(parcel, "readHashMap", 1, cl)));
720}
721
722void
723MapType::ReadFromParcel(StatementBlock* addTo, Variable* v,
724                    Variable* parcel)
725{
726    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
727    addTo->Add(new VariableDeclaration(cl,
728        new LiteralExpression("this.getClass().getClassLoader()"),
729        CLASSLOADER_TYPE));
730    addTo->Add(new MethodCall(parcel, "readMap", 2, v, cl));
731}
732
733
734// ================================================================
735
736ListType::ListType()
737    :Type("java.util", "List", BUILT_IN, true, true)
738{
739}
740
741string
742ListType::InstantiableName() const
743{
744    return "java.util.ArrayList";
745}
746
747void
748ListType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
749{
750    addTo->Add(new MethodCall(parcel, "writeList", 1, v));
751}
752
753void
754ListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
755{
756    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
757    addTo->Add(new VariableDeclaration(cl,
758        new LiteralExpression("this.getClass().getClassLoader()"),
759        CLASSLOADER_TYPE));
760    addTo->Add(new Assignment(v, new MethodCall(parcel, "readArrayList", 1, cl)));
761}
762
763void
764ListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
765                    Variable* parcel)
766{
767    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
768    addTo->Add(new VariableDeclaration(cl,
769        new LiteralExpression("this.getClass().getClassLoader()"),
770        CLASSLOADER_TYPE));
771    addTo->Add(new MethodCall(parcel, "readList", 2, v, cl));
772}
773
774
775// ================================================================
776
777ParcelableType::ParcelableType(const string& package, const string& name,
778                        bool builtIn, const string& declFile, int declLine)
779    :Type(package, name, builtIn ? BUILT_IN : PARCELABLE, true, true,
780            declFile, declLine)
781{
782}
783
784string
785ParcelableType::CreatorName() const
786{
787    return QualifiedName() + ".CREATOR";
788}
789
790void
791ParcelableType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
792{
793    // if (v != null) {
794    //     parcel.writeInt(1);
795    //     v.writeToParcel(parcel);
796    // } else {
797    //     parcel.writeInt(0);
798    // }
799    IfStatement* elsepart = new IfStatement();
800    elsepart->statements->Add(new MethodCall(parcel, "writeInt", 1,
801                                new LiteralExpression("0")));
802    IfStatement* ifpart = new IfStatement;
803    ifpart->expression = new Comparison(v, "!=", NULL_VALUE);
804    ifpart->elseif = elsepart;
805    ifpart->statements->Add(new MethodCall(parcel, "writeInt", 1,
806                                new LiteralExpression("1")));
807    ifpart->statements->Add(new MethodCall(v, "writeToParcel", 2,
808                                parcel, BuildWriteToParcelFlags(flags)));
809
810    addTo->Add(ifpart);
811}
812
813void
814ParcelableType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
815{
816    // if (0 != parcel.readInt()) {
817    //     v = CLASS.CREATOR.createFromParcel(parcel)
818    // } else {
819    //     v = null;
820    // }
821    IfStatement* elsepart = new IfStatement();
822    elsepart->statements->Add(new Assignment(v, NULL_VALUE));
823
824    IfStatement* ifpart = new IfStatement();
825    ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
826                new MethodCall(parcel, "readInt"));
827    ifpart->elseif = elsepart;
828    ifpart->statements->Add(new Assignment(v,
829                new MethodCall(v->type, "CREATOR.createFromParcel", 1, parcel)));
830
831    addTo->Add(ifpart);
832}
833
834void
835ParcelableType::ReadFromParcel(StatementBlock* addTo, Variable* v,
836                    Variable* parcel)
837{
838    // TODO: really, we don't need to have this extra check, but we
839    // don't have two separate marshalling code paths
840    // if (0 != parcel.readInt()) {
841    //     v.readFromParcel(parcel)
842    // }
843    IfStatement* ifpart = new IfStatement();
844    ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
845                new MethodCall(parcel, "readInt"));
846    ifpart->statements->Add(new MethodCall(v, "readFromParcel", 1, parcel));
847    addTo->Add(ifpart);
848}
849
850bool
851ParcelableType::CanBeArray() const
852{
853    return true;
854}
855
856void
857ParcelableType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
858{
859    addTo->Add(new MethodCall(parcel, "writeTypedArray", 2, v,
860                BuildWriteToParcelFlags(flags)));
861}
862
863void
864ParcelableType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
865                            Variable* parcel)
866{
867    string creator = v->type->QualifiedName() + ".CREATOR";
868    addTo->Add(new Assignment(v, new MethodCall(parcel,
869                "createTypedArray", 1, new LiteralExpression(creator))));
870}
871
872void
873ParcelableType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
874{
875    string creator = v->type->QualifiedName() + ".CREATOR";
876    addTo->Add(new MethodCall(parcel, "readTypedArray", 2,
877                    v, new LiteralExpression(creator)));
878}
879
880
881// ================================================================
882
883InterfaceType::InterfaceType(const string& package, const string& name,
884                        bool builtIn, bool oneway,
885                        const string& declFile, int declLine)
886    :Type(package, name, builtIn ? BUILT_IN : INTERFACE, true, false,
887                        declFile, declLine)
888    ,m_oneway(oneway)
889{
890}
891
892bool
893InterfaceType::OneWay() const
894{
895    return m_oneway;
896}
897
898void
899InterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
900{
901    // parcel.writeStrongBinder(v != null ? v.asBinder() : null);
902    addTo->Add(new MethodCall(parcel, "writeStrongBinder", 1,
903                new Ternary(
904                    new Comparison(v, "!=", NULL_VALUE),
905                    new MethodCall(v, "asBinder"),
906                    NULL_VALUE)));
907}
908
909void
910InterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
911{
912    // v = Interface.asInterface(parcel.readStrongBinder());
913    string type = v->type->QualifiedName();
914    type += ".Stub";
915    addTo->Add(new Assignment(v,
916                new MethodCall( NAMES.Find(type), "asInterface", 1,
917                    new MethodCall(parcel, "readStrongBinder"))));
918}
919
920
921// ================================================================
922
923GenericType::GenericType(const string& package, const string& name,
924                         const vector<Type*>& args)
925    :Type(package, name, BUILT_IN, true, true)
926{
927    m_args = args;
928
929    m_importName = package + '.' + name;
930
931    string gen = "<";
932    int N = args.size();
933    for (int i=0; i<N; i++) {
934        Type* t = args[i];
935        gen += t->QualifiedName();
936        if (i != N-1) {
937            gen += ',';
938        }
939    }
940    gen += '>';
941    m_genericArguments = gen;
942    SetQualifiedName(m_importName + gen);
943}
944
945string
946GenericType::GenericArguments() const
947{
948    return m_genericArguments;
949}
950
951string
952GenericType::ImportType() const
953{
954    return m_importName;
955}
956
957void
958GenericType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
959{
960    fprintf(stderr, "implement GenericType::WriteToParcel\n");
961}
962
963void
964GenericType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
965{
966    fprintf(stderr, "implement GenericType::CreateFromParcel\n");
967}
968
969void
970GenericType::ReadFromParcel(StatementBlock* addTo, Variable* v,
971                            Variable* parcel)
972{
973    fprintf(stderr, "implement GenericType::ReadFromParcel\n");
974}
975
976
977// ================================================================
978
979GenericListType::GenericListType(const string& package, const string& name,
980                         const vector<Type*>& args)
981    :GenericType(package, name, args),
982     m_creator(args[0]->CreatorName())
983{
984}
985
986string
987GenericListType::CreatorName() const
988{
989    return "android.os.Parcel.arrayListCreator";
990}
991
992string
993GenericListType::InstantiableName() const
994{
995    return "java.util.ArrayList" + GenericArguments();
996}
997
998void
999GenericListType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
1000{
1001    if (m_creator == STRING_TYPE->CreatorName()) {
1002        addTo->Add(new MethodCall(parcel, "writeStringList", 1, v));
1003    } else if (m_creator == IBINDER_TYPE->CreatorName()) {
1004        addTo->Add(new MethodCall(parcel, "writeBinderList", 1, v));
1005    } else {
1006        // parcel.writeTypedListXX(arg);
1007        addTo->Add(new MethodCall(parcel, "writeTypedList", 1, v));
1008    }
1009}
1010
1011void
1012GenericListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
1013{
1014    if (m_creator == STRING_TYPE->CreatorName()) {
1015        addTo->Add(new Assignment(v,
1016                   new MethodCall(parcel, "createStringArrayList", 0)));
1017    } else if (m_creator == IBINDER_TYPE->CreatorName()) {
1018        addTo->Add(new Assignment(v,
1019                   new MethodCall(parcel, "createBinderArrayList", 0)));
1020    } else {
1021        // v = _data.readTypedArrayList(XXX.creator);
1022        addTo->Add(new Assignment(v,
1023                   new MethodCall(parcel, "createTypedArrayList", 1,
1024                   new LiteralExpression(m_creator))));
1025    }
1026}
1027
1028void
1029GenericListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
1030                            Variable* parcel)
1031{
1032    if (m_creator == STRING_TYPE->CreatorName()) {
1033        addTo->Add(new MethodCall(parcel, "readStringList", 1, v));
1034    } else if (m_creator == IBINDER_TYPE->CreatorName()) {
1035        addTo->Add(new MethodCall(parcel, "readBinderList", 1, v));
1036    } else {
1037        // v = _data.readTypedList(v, XXX.creator);
1038        addTo->Add(new MethodCall(parcel, "readTypedList", 2,
1039                       v,
1040                       new LiteralExpression(m_creator)));
1041    }
1042}
1043
1044// ================================================================
1045
1046ClassLoaderType::ClassLoaderType()
1047    :Type("java.lang", "ClassLoader", BUILT_IN, false, false)
1048{
1049}
1050
1051
1052// ================================================================
1053
1054Namespace::Namespace()
1055{
1056}
1057
1058Namespace::~Namespace()
1059{
1060    int N = m_types.size();
1061    for (int i=0; i<N; i++) {
1062        delete m_types[i];
1063    }
1064}
1065
1066void
1067Namespace::Add(Type* type)
1068{
1069    Type* t = Find(type->QualifiedName());
1070    if (t == NULL) {
1071        m_types.push_back(type);
1072    }
1073}
1074
1075void
1076Namespace::AddGenericType(const string& package, const string& name, int args)
1077{
1078    Generic g;
1079        g.package = package;
1080        g.name = name;
1081        g.qualified = package + '.' + name;
1082        g.args = args;
1083    m_generics.push_back(g);
1084}
1085
1086Type*
1087Namespace::Find(const string& name) const
1088{
1089    int N = m_types.size();
1090    for (int i=0; i<N; i++) {
1091        if (m_types[i]->QualifiedName() == name) {
1092            return m_types[i];
1093        }
1094    }
1095    return NULL;
1096}
1097
1098Type*
1099Namespace::Find(const char* package, const char* name) const
1100{
1101    string s;
1102    if (package != NULL) {
1103        s += package;
1104        s += '.';
1105    }
1106    s += name;
1107    return Find(s);
1108}
1109
1110static string
1111normalize_generic(const string& s)
1112{
1113    string r;
1114    int N = s.size();
1115    for (int i=0; i<N; i++) {
1116        char c = s[i];
1117        if (!isspace(c)) {
1118            r += c;
1119        }
1120    }
1121    return r;
1122}
1123
1124Type*
1125Namespace::Search(const string& name)
1126{
1127    // an exact match wins
1128    Type* result = Find(name);
1129    if (result != NULL) {
1130        return result;
1131    }
1132
1133    // try the class names
1134    // our language doesn't allow you to not specify outer classes
1135    // when referencing an inner class.  that could be changed, and this
1136    // would be the place to do it, but I don't think the complexity in
1137    // scoping rules is worth it.
1138    int N = m_types.size();
1139    for (int i=0; i<N; i++) {
1140        if (m_types[i]->Name() == name) {
1141            return m_types[i];
1142        }
1143    }
1144
1145    // we got to here and it's not a generic, give up
1146    if (name.find('<') == name.npos) {
1147        return NULL;
1148    }
1149
1150    // remove any whitespace
1151    string normalized = normalize_generic(name);
1152
1153    // find the part before the '<', find a generic for it
1154    ssize_t baseIndex = normalized.find('<');
1155    string base(normalized.c_str(), baseIndex);
1156    const Generic* g = search_generic(base);
1157    if (g == NULL) {
1158        return NULL;
1159    }
1160
1161    // For each of the args, do a recursive search on it.  We don't allow
1162    // generics within generics like Java does, because we're really limiting
1163    // them to just built-in container classes, at least for now.  Our syntax
1164    // ensures this right now as well.
1165    vector<Type*> args;
1166    size_t start = baseIndex + 1;
1167    size_t end = start;
1168    while (normalized[start] != '\0') {
1169        end = normalized.find(',', start);
1170        if (end == normalized.npos) {
1171            end = normalized.find('>', start);
1172        }
1173        string s(normalized.c_str()+start, end-start);
1174        Type* t = this->Search(s);
1175        if (t == NULL) {
1176            // maybe we should print a warning here?
1177            return NULL;
1178        }
1179        args.push_back(t);
1180        start = end+1;
1181    }
1182
1183    // construct a GenericType, add it to our name set so they always get
1184    // the same object, and return it.
1185    result = make_generic_type(g->package, g->name, args);
1186    if (result == NULL) {
1187        return NULL;
1188    }
1189
1190    this->Add(result);
1191    return this->Find(result->QualifiedName());
1192}
1193
1194const Namespace::Generic*
1195Namespace::search_generic(const string& name) const
1196{
1197    int N = m_generics.size();
1198
1199    // first exact match
1200    for (int i=0; i<N; i++) {
1201        const Generic& g = m_generics[i];
1202        if (g.qualified == name) {
1203            return &g;
1204        }
1205    }
1206
1207    // then name match
1208    for (int i=0; i<N; i++) {
1209        const Generic& g = m_generics[i];
1210        if (g.name == name) {
1211            return &g;
1212        }
1213    }
1214
1215    return NULL;
1216}
1217
1218void
1219Namespace::Dump() const
1220{
1221    int n = m_types.size();
1222    for (int i=0; i<n; i++) {
1223        Type* t = m_types[i];
1224        printf("type: package=%s name=%s qualifiedName=%s\n",
1225                t->Package().c_str(), t->Name().c_str(),
1226                t->QualifiedName().c_str());
1227    }
1228}
1229