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