Type.cpp revision 6c0236c53a30ea9fef28ee7c95a4dce2fa5ce2e1
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
906ParcelableType::ParcelableType(const string& package, const string& name,
907                            bool builtIn, bool canWriteToRpcData,
908                            const string& declFile, int declLine)
909    :Type(package, name, builtIn ? BUILT_IN : PARCELABLE, true, canWriteToRpcData, true,
910            declFile, declLine)
911{
912}
913
914string
915ParcelableType::CreatorName() const
916{
917    return QualifiedName() + ".CREATOR";
918}
919
920void
921ParcelableType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
922{
923    // if (v != null) {
924    //     parcel.writeInt(1);
925    //     v.writeToParcel(parcel);
926    // } else {
927    //     parcel.writeInt(0);
928    // }
929    IfStatement* elsepart = new IfStatement();
930    elsepart->statements->Add(new MethodCall(parcel, "writeInt", 1,
931                                new LiteralExpression("0")));
932    IfStatement* ifpart = new IfStatement;
933    ifpart->expression = new Comparison(v, "!=", NULL_VALUE);
934    ifpart->elseif = elsepart;
935    ifpart->statements->Add(new MethodCall(parcel, "writeInt", 1,
936                                new LiteralExpression("1")));
937    ifpart->statements->Add(new MethodCall(v, "writeToParcel", 2,
938                                parcel, BuildWriteToParcelFlags(flags)));
939
940    addTo->Add(ifpart);
941}
942
943void
944ParcelableType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
945{
946    // if (0 != parcel.readInt()) {
947    //     v = CLASS.CREATOR.createFromParcel(parcel)
948    // } else {
949    //     v = null;
950    // }
951    IfStatement* elsepart = new IfStatement();
952    elsepart->statements->Add(new Assignment(v, NULL_VALUE));
953
954    IfStatement* ifpart = new IfStatement();
955    ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
956                new MethodCall(parcel, "readInt"));
957    ifpart->elseif = elsepart;
958    ifpart->statements->Add(new Assignment(v,
959                new MethodCall(v->type, "CREATOR.createFromParcel", 1, parcel)));
960
961    addTo->Add(ifpart);
962}
963
964void
965ParcelableType::ReadFromParcel(StatementBlock* addTo, Variable* v,
966                    Variable* parcel, Variable**)
967{
968    // TODO: really, we don't need to have this extra check, but we
969    // don't have two separate marshalling code paths
970    // if (0 != parcel.readInt()) {
971    //     v.readFromParcel(parcel)
972    // }
973    IfStatement* ifpart = new IfStatement();
974    ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
975                new MethodCall(parcel, "readInt"));
976    ifpart->statements->Add(new MethodCall(v, "readFromParcel", 1, parcel));
977    addTo->Add(ifpart);
978}
979
980bool
981ParcelableType::CanBeArray() const
982{
983    return true;
984}
985
986void
987ParcelableType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
988{
989    addTo->Add(new MethodCall(parcel, "writeTypedArray", 2, v,
990                BuildWriteToParcelFlags(flags)));
991}
992
993void
994ParcelableType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
995                            Variable* parcel, Variable**)
996{
997    string creator = v->type->QualifiedName() + ".CREATOR";
998    addTo->Add(new Assignment(v, new MethodCall(parcel,
999                "createTypedArray", 1, new LiteralExpression(creator))));
1000}
1001
1002void
1003ParcelableType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
1004{
1005    string creator = v->type->QualifiedName() + ".CREATOR";
1006    addTo->Add(new MethodCall(parcel, "readTypedArray", 2,
1007                    v, new LiteralExpression(creator)));
1008}
1009
1010// ================================================================
1011
1012FlattenableType::FlattenableType(const string& package, const string& name,
1013                        bool builtIn, const string& declFile, int declLine)
1014    :Type(package, name, builtIn ? BUILT_IN : PARCELABLE, false, true, true,
1015            declFile, declLine)
1016{
1017}
1018
1019string
1020FlattenableType::CreatorName() const
1021{
1022    return QualifiedName() + ".CREATOR";
1023}
1024
1025void
1026FlattenableType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v,
1027                                    Variable* data, int flags)
1028{
1029    // if (v != null) {
1030    //     RpcData _obj = new RpcData();
1031    //     v.writeToRpcData(_obj);
1032    //     data.putRpcData(k, obj);
1033    // }
1034    IfStatement* ifpart = new IfStatement;
1035    ifpart->expression = new Comparison(v, "!=", NULL_VALUE);
1036    Variable* _obj = new Variable(RPC_DATA_TYPE, "_obj");
1037    ifpart->statements->Add(new VariableDeclaration(_obj, new NewExpression(RPC_DATA_TYPE)));
1038    ifpart->statements->Add(new MethodCall(v, "writeToRpcData", 1, _obj));
1039    ifpart->statements->Add(new MethodCall(data, "putRpcData", 2, k, _obj));
1040
1041    addTo->Add(ifpart);
1042}
1043
1044void
1045FlattenableType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v,
1046                                    Variable* data, Variable** cl)
1047{
1048    // RpcData _obj_XX = data.getRpcData(k);
1049    // if (_data_XX != null)
1050    //     v = CLASS.RPC_CREATOR.createFromParcel(parcel)
1051    // } else {
1052    //     v = null;
1053    // }
1054
1055    StatementBlock* block = new StatementBlock;
1056    addTo->Add(block);
1057
1058    Variable* _obj = new Variable(RPC_DATA_TYPE, "_obj");
1059    block->Add(new VariableDeclaration(_obj, new MethodCall(data, "getRpcData", 1, k)));
1060
1061    IfStatement* ifpart = new IfStatement();
1062    ifpart->expression = new Comparison(_obj, "!=", NULL_VALUE);
1063    ifpart->statements->Add(new Assignment(v,
1064                new MethodCall(v->type, "RPC_CREATOR.createFromRpcData", 1, data)));
1065
1066    IfStatement* elsepart = new IfStatement();
1067    ifpart->elseif = elsepart;
1068    elsepart->statements->Add(new Assignment(v, NULL_VALUE));
1069
1070    block->Add(ifpart);
1071}
1072
1073bool
1074FlattenableType::CanBeArray() const
1075{
1076    return true;
1077}
1078
1079// ================================================================
1080
1081InterfaceType::InterfaceType(const string& package, const string& name,
1082                        bool builtIn, bool oneway,
1083                        const string& declFile, int declLine)
1084    :Type(package, name, builtIn ? BUILT_IN : INTERFACE, true, false, false,
1085                        declFile, declLine)
1086    ,m_oneway(oneway)
1087{
1088}
1089
1090bool
1091InterfaceType::OneWay() const
1092{
1093    return m_oneway;
1094}
1095
1096void
1097InterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
1098{
1099    // parcel.writeStrongBinder(v != null ? v.asBinder() : null);
1100    addTo->Add(new MethodCall(parcel, "writeStrongBinder", 1,
1101                new Ternary(
1102                    new Comparison(v, "!=", NULL_VALUE),
1103                    new MethodCall(v, "asBinder"),
1104                    NULL_VALUE)));
1105}
1106
1107void
1108InterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
1109{
1110    // v = Interface.asInterface(parcel.readStrongBinder());
1111    string type = v->type->QualifiedName();
1112    type += ".Stub";
1113    addTo->Add(new Assignment(v,
1114                new MethodCall( NAMES.Find(type), "asInterface", 1,
1115                    new MethodCall(parcel, "readStrongBinder"))));
1116}
1117
1118
1119// ================================================================
1120
1121GenericType::GenericType(const string& package, const string& name,
1122                         const vector<Type*>& args)
1123    :Type(package, name, BUILT_IN, true, true, true)
1124{
1125    m_args = args;
1126
1127    m_importName = package + '.' + name;
1128
1129    string gen = "<";
1130    int N = args.size();
1131    for (int i=0; i<N; i++) {
1132        Type* t = args[i];
1133        gen += t->QualifiedName();
1134        if (i != N-1) {
1135            gen += ',';
1136        }
1137    }
1138    gen += '>';
1139    m_genericArguments = gen;
1140    SetQualifiedName(m_importName + gen);
1141}
1142
1143const vector<Type*>&
1144GenericType::GenericArgumentTypes() const
1145{
1146    return m_args;
1147}
1148
1149string
1150GenericType::GenericArguments() const
1151{
1152    return m_genericArguments;
1153}
1154
1155string
1156GenericType::ImportType() const
1157{
1158    return m_importName;
1159}
1160
1161void
1162GenericType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
1163{
1164    fprintf(stderr, "implement GenericType::WriteToParcel\n");
1165}
1166
1167void
1168GenericType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
1169{
1170    fprintf(stderr, "implement GenericType::CreateFromParcel\n");
1171}
1172
1173void
1174GenericType::ReadFromParcel(StatementBlock* addTo, Variable* v,
1175                            Variable* parcel, Variable**)
1176{
1177    fprintf(stderr, "implement GenericType::ReadFromParcel\n");
1178}
1179
1180
1181// ================================================================
1182
1183GenericListType::GenericListType(const string& package, const string& name,
1184                         const vector<Type*>& args)
1185    :GenericType(package, name, args),
1186     m_creator(args[0]->CreatorName())
1187{
1188}
1189
1190string
1191GenericListType::CreatorName() const
1192{
1193    return "android.os.Parcel.arrayListCreator";
1194}
1195
1196string
1197GenericListType::InstantiableName() const
1198{
1199    return "java.util.ArrayList" + GenericArguments();
1200}
1201
1202void
1203GenericListType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
1204{
1205    if (m_creator == STRING_TYPE->CreatorName()) {
1206        addTo->Add(new MethodCall(parcel, "writeStringList", 1, v));
1207    } else if (m_creator == IBINDER_TYPE->CreatorName()) {
1208        addTo->Add(new MethodCall(parcel, "writeBinderList", 1, v));
1209    } else {
1210        // parcel.writeTypedListXX(arg);
1211        addTo->Add(new MethodCall(parcel, "writeTypedList", 1, v));
1212    }
1213}
1214
1215void
1216GenericListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
1217{
1218    if (m_creator == STRING_TYPE->CreatorName()) {
1219        addTo->Add(new Assignment(v,
1220                   new MethodCall(parcel, "createStringArrayList", 0)));
1221    } else if (m_creator == IBINDER_TYPE->CreatorName()) {
1222        addTo->Add(new Assignment(v,
1223                   new MethodCall(parcel, "createBinderArrayList", 0)));
1224    } else {
1225        // v = _data.readTypedArrayList(XXX.creator);
1226        addTo->Add(new Assignment(v,
1227                   new MethodCall(parcel, "createTypedArrayList", 1,
1228                   new LiteralExpression(m_creator))));
1229    }
1230}
1231
1232void
1233GenericListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
1234                            Variable* parcel, Variable**)
1235{
1236    if (m_creator == STRING_TYPE->CreatorName()) {
1237        addTo->Add(new MethodCall(parcel, "readStringList", 1, v));
1238    } else if (m_creator == IBINDER_TYPE->CreatorName()) {
1239        addTo->Add(new MethodCall(parcel, "readBinderList", 1, v));
1240    } else {
1241        // v = _data.readTypedList(v, XXX.creator);
1242        addTo->Add(new MethodCall(parcel, "readTypedList", 2,
1243                       v,
1244                       new LiteralExpression(m_creator)));
1245    }
1246}
1247
1248void
1249GenericListType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v,
1250        Variable* data, int flags)
1251{
1252    addTo->Add(new MethodCall(data, "putList", 2, k, v));
1253}
1254
1255void
1256GenericListType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v,
1257        Variable* data, Variable** cl)
1258{
1259    string classArg = GenericArgumentTypes()[0]->QualifiedName();
1260    classArg += ".class";
1261    addTo->Add(new Assignment(v, new MethodCall(data, "getList", 2, k,
1262                    new LiteralExpression(classArg))));
1263}
1264
1265
1266// ================================================================
1267
1268RpcDataType::RpcDataType()
1269    :ParcelableType("com.android.athome.rpc", "RpcData", true, true)
1270{
1271}
1272
1273void
1274RpcDataType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v,
1275        Variable* data, int flags)
1276{
1277    addTo->Add(new MethodCall(data, "putRpcData", 2, k, v));
1278}
1279
1280void
1281RpcDataType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, Variable* data,
1282        Variable** cl)
1283{
1284    addTo->Add(new Assignment(v, new MethodCall(data, "getRpcData", 1, k)));
1285}
1286
1287
1288// ================================================================
1289
1290ClassLoaderType::ClassLoaderType()
1291    :Type("java.lang", "ClassLoader", BUILT_IN, false, false, false)
1292{
1293}
1294
1295
1296// ================================================================
1297
1298Namespace::Namespace()
1299{
1300}
1301
1302Namespace::~Namespace()
1303{
1304    int N = m_types.size();
1305    for (int i=0; i<N; i++) {
1306        delete m_types[i];
1307    }
1308}
1309
1310void
1311Namespace::Add(Type* type)
1312{
1313    Type* t = Find(type->QualifiedName());
1314    if (t == NULL) {
1315        m_types.push_back(type);
1316    }
1317}
1318
1319void
1320Namespace::AddGenericType(const string& package, const string& name, int args)
1321{
1322    Generic g;
1323        g.package = package;
1324        g.name = name;
1325        g.qualified = package + '.' + name;
1326        g.args = args;
1327    m_generics.push_back(g);
1328}
1329
1330Type*
1331Namespace::Find(const string& name) const
1332{
1333    int N = m_types.size();
1334    for (int i=0; i<N; i++) {
1335        if (m_types[i]->QualifiedName() == name) {
1336            return m_types[i];
1337        }
1338    }
1339    return NULL;
1340}
1341
1342Type*
1343Namespace::Find(const char* package, const char* name) const
1344{
1345    string s;
1346    if (package != NULL) {
1347        s += package;
1348        s += '.';
1349    }
1350    s += name;
1351    return Find(s);
1352}
1353
1354static string
1355normalize_generic(const string& s)
1356{
1357    string r;
1358    int N = s.size();
1359    for (int i=0; i<N; i++) {
1360        char c = s[i];
1361        if (!isspace(c)) {
1362            r += c;
1363        }
1364    }
1365    return r;
1366}
1367
1368Type*
1369Namespace::Search(const string& name)
1370{
1371    // an exact match wins
1372    Type* result = Find(name);
1373    if (result != NULL) {
1374        return result;
1375    }
1376
1377    // try the class names
1378    // our language doesn't allow you to not specify outer classes
1379    // when referencing an inner class.  that could be changed, and this
1380    // would be the place to do it, but I don't think the complexity in
1381    // scoping rules is worth it.
1382    int N = m_types.size();
1383    for (int i=0; i<N; i++) {
1384        if (m_types[i]->Name() == name) {
1385            return m_types[i];
1386        }
1387    }
1388
1389    // we got to here and it's not a generic, give up
1390    if (name.find('<') == name.npos) {
1391        return NULL;
1392    }
1393
1394    // remove any whitespace
1395    string normalized = normalize_generic(name);
1396
1397    // find the part before the '<', find a generic for it
1398    ssize_t baseIndex = normalized.find('<');
1399    string base(normalized.c_str(), baseIndex);
1400    const Generic* g = search_generic(base);
1401    if (g == NULL) {
1402        return NULL;
1403    }
1404
1405    // For each of the args, do a recursive search on it.  We don't allow
1406    // generics within generics like Java does, because we're really limiting
1407    // them to just built-in container classes, at least for now.  Our syntax
1408    // ensures this right now as well.
1409    vector<Type*> args;
1410    size_t start = baseIndex + 1;
1411    size_t end = start;
1412    while (normalized[start] != '\0') {
1413        end = normalized.find(',', start);
1414        if (end == normalized.npos) {
1415            end = normalized.find('>', start);
1416        }
1417        string s(normalized.c_str()+start, end-start);
1418        Type* t = this->Search(s);
1419        if (t == NULL) {
1420            // maybe we should print a warning here?
1421            return NULL;
1422        }
1423        args.push_back(t);
1424        start = end+1;
1425    }
1426
1427    // construct a GenericType, add it to our name set so they always get
1428    // the same object, and return it.
1429    result = make_generic_type(g->package, g->name, args);
1430    if (result == NULL) {
1431        return NULL;
1432    }
1433
1434    this->Add(result);
1435    return this->Find(result->QualifiedName());
1436}
1437
1438const Namespace::Generic*
1439Namespace::search_generic(const string& name) const
1440{
1441    int N = m_generics.size();
1442
1443    // first exact match
1444    for (int i=0; i<N; i++) {
1445        const Generic& g = m_generics[i];
1446        if (g.qualified == name) {
1447            return &g;
1448        }
1449    }
1450
1451    // then name match
1452    for (int i=0; i<N; i++) {
1453        const Generic& g = m_generics[i];
1454        if (g.name == name) {
1455            return &g;
1456        }
1457    }
1458
1459    return NULL;
1460}
1461
1462void
1463Namespace::Dump() const
1464{
1465    int n = m_types.size();
1466    for (int i=0; i<n; i++) {
1467        Type* t = m_types[i];
1468        printf("type: package=%s name=%s qualifiedName=%s\n",
1469                t->Package().c_str(), t->Name().c_str(),
1470                t->QualifiedName().c_str());
1471    }
1472}
1473