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