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