merge a2ee53b and resolved conflicts...
diff --git a/dexdump/DexDump.c b/dexdump/DexDump.c
index bd91236..6fed7aa 100644
--- a/dexdump/DexDump.c
+++ b/dexdump/DexDump.c
@@ -18,7 +18,16 @@
  * The "dexdump" tool is intended to mimic "objdump".  When possible, use
  * similar command-line arguments.
  *
- * TODO: rework the output format to be more regexp-friendly
+ * TODO: rework the "plain" output format to be more regexp-friendly
+ *
+ * Differences between XML output and the "current.xml" file:
+ * - classes in same package are not all grouped together; generally speaking
+ *   nothing is sorted
+ * - no "deprecated" on fields and methods
+ * - no "value" on fields
+ * - no parameter names
+ * - no generic signatures on parameters, e.g. type="java.lang.Class<?>"
+ * - class shows declared fields and methods; does not show inherited fields
  */
 #include "libdex/DexFile.h"
 #include "libdex/DexCatch.h"
@@ -44,6 +53,11 @@
 static InstructionWidth* gInstrWidth;
 static InstructionFormat* gInstrFormat;
 
+typedef enum OutputFormat {
+    OUTPUT_PLAIN = 0,               /* default */
+    OUTPUT_XML,                     /* fancy */
+} OutputFormat;
+
 /* command-line options */
 struct {
     bool checksumOnly;
@@ -52,7 +66,10 @@
     bool showSectionHeaders;
     bool ignoreBadChecksum;
     bool dumpRegisterMaps;
+    OutputFormat outputFormat;
     const char* tempFileName;
+    bool exportsOnly;
+    bool verbose;
 } gOptions;
 
 /* basic info about a field or method */
@@ -79,34 +96,134 @@
 }   
 
 /*
- * Return a newly-allocated string for the "dot version" of the class
- * name for the given type descriptor. That is, The initial "L" and
- * final ";" (if any) have been removed and all occurrences of '/'
- * have been changed to '.'.
+ * Converts a single-character primitive type into its human-readable
+ * equivalent.
+ */
+static const char* primitiveTypeLabel(char typeChar)
+{
+    switch (typeChar) {
+    case 'B':   return "byte";
+    case 'C':   return "char";
+    case 'D':   return "double";
+    case 'F':   return "float";
+    case 'I':   return "int";
+    case 'J':   return "long";
+    case 'S':   return "short";
+    case 'V':   return "void";
+    case 'Z':   return "boolean";
+    default:
+                return "UNKNOWN";
+    }
+}
+
+/*
+ * Converts a type descriptor to human-readable "dotted" form.  For
+ * example, "Ljava/lang/String;" becomes "java.lang.String", and
+ * "[I" becomes "int[]".  Also converts '$' to '.', which means this
+ * form can't be converted back to a descriptor.
  */
 static char* descriptorToDot(const char* str)
 {
-    size_t at = strlen(str);
+    int targetLen = strlen(str);
+    int offset = 0;
+    int arrayDepth = 0;
     char* newStr;
 
-    if (str[0] == 'L') {
-        assert(str[at - 1] == ';');
-        at -= 2; /* Two fewer chars to copy. */
-        str++; /* Skip the 'L'. */
+    /* strip leading [s; will be added to end */
+    while (targetLen > 1 && str[offset] == '[') {
+        offset++;
+        targetLen--;
+    }
+    arrayDepth = offset;
+
+    if (targetLen == 1) {
+        /* primitive type */
+        str = primitiveTypeLabel(str[offset]);
+        offset = 0;
+        targetLen = strlen(str);
+    } else {
+        /* account for leading 'L' and trailing ';' */
+        if (targetLen >= 2 && str[offset] == 'L' &&
+            str[offset+targetLen-1] == ';')
+        {
+            targetLen -= 2;
+            offset++;
+        }
     }
 
-    newStr = malloc(at + 1); /* Add one for the '\0'. */
-    newStr[at] = '\0';
+    newStr = malloc(targetLen + arrayDepth * 2 +1);
 
-    while (at > 0) {
-        at--;
-        newStr[at] = (str[at] == '/') ? '.' : str[at];
+    /* copy class name over */
+    int i;
+    for (i = 0; i < targetLen; i++) {
+        char ch = str[offset + i];
+        newStr[i] = (ch == '/' || ch == '$') ? '.' : ch;
+    }
+
+    /* add the appropriate number of brackets for arrays */
+    while (arrayDepth-- > 0) {
+        newStr[i++] = '[';
+        newStr[i++] = ']';
+    }
+    newStr[i] = '\0';
+    assert(i == targetLen + arrayDepth * 2);
+
+    return newStr;
+}
+
+/*
+ * Converts the class name portion of a type descriptor to human-readable
+ * "dotted" form.
+ *
+ * Returns a newly-allocated string.
+ */
+static char* descriptorClassToDot(const char* str)
+{
+    const char* lastSlash;
+    char* newStr;
+    char* cp;
+
+    /* reduce to just the class name, trimming trailing ';' */
+    lastSlash = strrchr(str, '/');
+    if (lastSlash == NULL)
+        lastSlash = str + 1;        /* start past 'L' */
+    else
+        lastSlash++;                /* start past '/' */
+
+    newStr = strdup(lastSlash);
+    newStr[strlen(lastSlash)-1] = '\0';
+    for (cp = newStr; *cp != '\0'; cp++) {
+        if (*cp == '$')
+            *cp = '.';
     }
 
     return newStr;
 }
 
 /*
+ * Returns a quoted string representing the boolean value.
+ */
+static const char* quotedBool(bool val)
+{
+    if (val)
+        return "\"true\"";
+    else
+        return "\"false\"";
+}
+
+static const char* quotedVisibility(u4 accessFlags)
+{
+    if ((accessFlags & ACC_PUBLIC) != 0)
+        return "\"public\"";
+    else if ((accessFlags & ACC_PROTECTED) != 0)
+        return "\"protected\"";
+    else if ((accessFlags & ACC_PRIVATE) != 0)
+        return "\"private\"";
+    else
+        return "\"package\"";
+}
+
+/*
  * Count the number of '1' bits in a word.
  *
  * Having completed this, I'm ready for an interview at Google.
@@ -126,7 +243,6 @@
     return count;
 }
 
-
 /*
  * Flag for use with createAccessFlagStr().
  */
@@ -322,7 +438,7 @@
 }
 
 /*
- * Dump an interface.
+ * Dump an interface that a class declares to implement.
  */
 void dumpInterface(const DexFile* pDexFile, const DexTypeItem* pTypeItem,
     int i)
@@ -330,7 +446,13 @@
     const char* interfaceName =
         dexStringByTypeIdx(pDexFile, pTypeItem->typeIdx);
 
-    printf("    #%d              : '%s'\n", i, interfaceName);
+    if (gOptions.outputFormat == OUTPUT_PLAIN) {
+        printf("    #%d              : '%s'\n", i, interfaceName);
+    } else {
+        char* dotted = descriptorToDot(interfaceName);
+        printf("<implements name=\"%s\">\n</implements>\n", dotted);
+        free(dotted);
+    }
 }
 
 /*
@@ -878,8 +1000,14 @@
     const DexMethodId* pMethodId;
     const char* backDescriptor;
     const char* name;
-    char* typeDescriptor;
-    char* accessStr;
+    char* typeDescriptor = NULL;
+    char* accessStr = NULL;
+
+    if (gOptions.exportsOnly &&
+        (pDexMethod->accessFlags & (ACC_PUBLIC | ACC_PROTECTED)) == 0)
+    {
+        return;
+    }
 
     pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
     name = dexStringById(pDexFile, pMethodId->nameIdx);
@@ -890,22 +1018,119 @@
     accessStr = createAccessFlagStr(pDexMethod->accessFlags,
                     kAccessForMethod);
 
-    printf("    #%d              : (in %s)\n", i, backDescriptor);
-    printf("      name          : '%s'\n", name);
-    printf("      type          : '%s'\n", typeDescriptor);
-    printf("      access        : 0x%04x (%s)\n",
-        pDexMethod->accessFlags, accessStr);
+    if (gOptions.outputFormat == OUTPUT_PLAIN) {
+        printf("    #%d              : (in %s)\n", i, backDescriptor);
+        printf("      name          : '%s'\n", name);
+        printf("      type          : '%s'\n", typeDescriptor);
+        printf("      access        : 0x%04x (%s)\n",
+            pDexMethod->accessFlags, accessStr);
 
-    if (pDexMethod->codeOff == 0) {
-        printf("      code          : (none)\n");
-    } else {
-        printf("      code          -\n");
-        dumpCode(pDexFile, pDexMethod);
+        if (pDexMethod->codeOff == 0) {
+            printf("      code          : (none)\n");
+        } else {
+            printf("      code          -\n");
+            dumpCode(pDexFile, pDexMethod);
+        }
+
+        if (gOptions.disassemble)
+            putchar('\n');
+    } else if (gOptions.outputFormat == OUTPUT_XML) {
+        bool constructor = (name[0] == '<');
+
+        if (constructor) {
+            char* tmp;
+
+            tmp = descriptorClassToDot(backDescriptor);
+            printf("<constructor name=\"%s\"\n", tmp);
+            free(tmp);
+
+            tmp = descriptorToDot(backDescriptor);
+            printf(" type=\"%s\"\n", tmp);
+            free(tmp);
+        } else {
+            printf("<method name=\"%s\"\n", name);
+
+            const char* returnType = strrchr(typeDescriptor, ')');
+            if (returnType == NULL) {
+                fprintf(stderr, "bad method type descriptor '%s'\n",
+                    typeDescriptor);
+                goto bail;
+            }
+
+            char* tmp = descriptorToDot(returnType+1);
+            printf(" return=\"%s\"\n", tmp);
+            free(tmp);
+
+            printf(" abstract=%s\n",
+                quotedBool((pDexMethod->accessFlags & ACC_ABSTRACT) != 0));
+            printf(" native=%s\n",
+                quotedBool((pDexMethod->accessFlags & ACC_NATIVE) != 0));
+
+            bool isSync =
+                (pDexMethod->accessFlags & ACC_SYNCHRONIZED) != 0 ||
+                (pDexMethod->accessFlags & ACC_DECLARED_SYNCHRONIZED) != 0;
+            printf(" synchronized=%s\n", quotedBool(isSync));
+        }
+
+        printf(" static=%s\n",
+            quotedBool((pDexMethod->accessFlags & ACC_STATIC) != 0));
+        printf(" final=%s\n",
+            quotedBool((pDexMethod->accessFlags & ACC_FINAL) != 0));
+        // "deprecated=" not knowable w/o parsing annotations
+        printf(" visibility=%s\n",
+            quotedVisibility(pDexMethod->accessFlags));
+
+        printf(">\n");
+
+        /*
+         * Parameters.
+         */
+        if (typeDescriptor[0] != '(') {
+            fprintf(stderr, "ERROR: bad descriptor '%s'\n", typeDescriptor);
+            goto bail;
+        }
+
+        char tmpBuf[strlen(typeDescriptor)+1];      /* more than big enough */
+        int argNum = 0;
+
+        const char* base = typeDescriptor+1;
+
+        while (*base != ')') {
+            char* cp = tmpBuf;
+
+            while (*base == '[')
+                *cp++ = *base++;
+
+            if (*base == 'L') {
+                /* copy through ';' */
+                do {
+                    *cp = *base++;
+                } while (*cp++ != ';');
+            } else {
+                /* primitive char, copy it */
+                if (strchr("ZBCSIFJD", *base) == NULL) {
+                    fprintf(stderr, "ERROR: bad method signature '%s'\n", base);
+                    goto bail;
+                }
+                *cp++ = *base++;
+            }
+
+            /* null terminate and display */
+            *cp++ = '\0';
+
+            char* tmp = descriptorToDot(tmpBuf);
+            printf("<parameter name=\"arg%d\" type=\"%s\">\n</parameter>\n",
+                argNum++, tmp);
+            free(tmp);
+        }
+
+        if (constructor)
+            printf("</constructor>\n");
+        else
+            printf("</method>\n");
     }
 
-    if (gOptions.disassemble)
-        putchar('\n');
-
+bail:
     free(typeDescriptor);
     free(accessStr);
 }
@@ -921,6 +1146,12 @@
     const char* typeDescriptor;
     char* accessStr;
 
+    if (gOptions.exportsOnly &&
+        (pSField->accessFlags & (ACC_PUBLIC | ACC_PROTECTED)) == 0)
+    {
+        return;
+    }
+
     pFieldId = dexGetFieldId(pDexFile, pSField->fieldIdx);
     name = dexStringById(pDexFile, pFieldId->nameIdx);
     typeDescriptor = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
@@ -928,11 +1159,35 @@
 
     accessStr = createAccessFlagStr(pSField->accessFlags, kAccessForField);
 
-    printf("    #%d              : (in %s)\n", i, backDescriptor);
-    printf("      name          : '%s'\n", name);
-    printf("      type          : '%s'\n", typeDescriptor);
-    printf("      access        : 0x%04x (%s)\n",
-        pSField->accessFlags, accessStr);
+    if (gOptions.outputFormat == OUTPUT_PLAIN) {
+        printf("    #%d              : (in %s)\n", i, backDescriptor);
+        printf("      name          : '%s'\n", name);
+        printf("      type          : '%s'\n", typeDescriptor);
+        printf("      access        : 0x%04x (%s)\n",
+            pSField->accessFlags, accessStr);
+    } else if (gOptions.outputFormat == OUTPUT_XML) {
+        char* tmp;
+
+        printf("<field name=\"%s\"\n", name);
+
+        tmp = descriptorToDot(typeDescriptor);
+        printf(" type=\"%s\"\n", tmp);
+        free(tmp);
+
+        printf(" transient=%s\n",
+            quotedBool((pSField->accessFlags & ACC_TRANSIENT) != 0));
+        printf(" volatile=%s\n",
+            quotedBool((pSField->accessFlags & ACC_VOLATILE) != 0));
+        // "value=" not knowable w/o parsing annotations
+        printf(" static=%s\n",
+            quotedBool((pSField->accessFlags & ACC_STATIC) != 0));
+        printf(" final=%s\n",
+            quotedBool((pSField->accessFlags & ACC_FINAL) != 0));
+        // "deprecated=" not knowable w/o parsing annotations
+        printf(" visibility=%s\n",
+            quotedVisibility(pSField->accessFlags));
+        printf(">\n</field>\n");
+    }
 
     free(accessStr);
 }
@@ -942,94 +1197,160 @@
  */
 void dumpIField(const DexFile* pDexFile, const DexField* pIField, int i)
 {
-    const DexFieldId* pFieldId;
-    const char* backDescriptor;
-    const char* name;
-    const char* typeDescriptor;
-    char* accessStr;
-
-    pFieldId = dexGetFieldId(pDexFile, pIField->fieldIdx);
-    name = dexStringById(pDexFile, pFieldId->nameIdx);
-    typeDescriptor = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
-    backDescriptor = dexStringByTypeIdx(pDexFile, pFieldId->classIdx);
-
-    accessStr = createAccessFlagStr(pIField->accessFlags, kAccessForField);
-
-    printf("    #%d              : (in %s)\n", i, backDescriptor);
-    printf("      name          : '%s'\n", name);
-    printf("      type          : '%s'\n", typeDescriptor);
-    printf("      access        : 0x%04x (%s)\n",
-        pIField->accessFlags, accessStr);
-
-    free(accessStr);
+    dumpSField(pDexFile, pIField, i);
 }
 
 /*
  * Dump the class.
  *
  * Note "idx" is a DexClassDef index, not a DexTypeId index.
+ *
+ * If "*pLastPackage" is NULL or does not match the current class' package,
+ * the value will be replaced with a newly-allocated string.
  */
-void dumpClass(DexFile* pDexFile, int idx)
+void dumpClass(DexFile* pDexFile, int idx, char** pLastPackage)
 {
     const DexTypeList* pInterfaces;
     const DexClassDef* pClassDef;
-    DexClassData* pClassData;
+    DexClassData* pClassData = NULL;
     const u1* pEncodedData;
     const char* fileName;
     const char* classDescriptor;
     const char* superclassDescriptor;
-    char* accessStr;
+    char* accessStr = NULL;
     int i;
 
     pClassDef = dexGetClassDef(pDexFile, idx);
-    printf("Class #%d            -\n", idx);
+
+    if (gOptions.exportsOnly && (pClassDef->accessFlags & ACC_PUBLIC) == 0) {
+        //printf("<!-- omitting non-public class %s -->\n",
+        //    classDescriptor);
+        goto bail;
+    }
 
     pEncodedData = dexGetClassData(pDexFile, pClassDef);
     pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);
 
     if (pClassData == NULL) {
-        printf("Trouble reading class data\n");
-        return;
+        printf("Trouble reading class data (#%d)\n", idx);
+        goto bail;
     }
     
     classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
-    printf("  Class descriptor  : '%s'\n", classDescriptor);
 
-    accessStr = createAccessFlagStr(pClassDef->accessFlags, kAccessForClass);
-    printf("  Access flags      : 0x%04x (%s)\n",
-        pClassDef->accessFlags, accessStr);
+    /*
+     * For the XML output, show the package name.  Ideally we'd gather
+     * up the classes, sort them, and dump them alphabetically so the
+     * package name wouldn't jump around, but that's not a great plan
+     * for something that needs to run on the device.
+     */
+    if (!(classDescriptor[0] == 'L' &&
+          classDescriptor[strlen(classDescriptor)-1] == ';'))
+    {
+        /* arrays and primitives should not be defined explicitly */
+        fprintf(stderr, "Malformed class name '%s'\n", classDescriptor);
+        /* keep going? */
+    } else if (gOptions.outputFormat == OUTPUT_XML) {
+        char* mangle;
+        char* lastSlash;
+        char* cp;
 
-    if (pClassDef->superclassIdx == kDexNoIndex)
-        superclassDescriptor = "(none)";
-    else {
-        superclassDescriptor =
-            dexStringByTypeIdx(pDexFile, pClassDef->superclassIdx);
-        printf("  Superclass        : '%s'\n", superclassDescriptor);
+        mangle = strdup(classDescriptor + 1);
+        mangle[strlen(mangle)-1] = '\0';
+
+        /* reduce to just the package name */
+        lastSlash = strrchr(mangle, '/');
+        if (lastSlash != NULL) {
+            *lastSlash = '\0';
+        } else {
+            *mangle = '\0';
+        }
+
+        for (cp = mangle; *cp != '\0'; cp++) {
+            if (*cp == '/')
+                *cp = '.';
+        }
+
+        if (*pLastPackage == NULL || strcmp(mangle, *pLastPackage) != 0) {
+            /* start of a new package */
+            if (*pLastPackage != NULL)
+                printf("</package>\n");
+            printf("<package name=\"%s\"\n>\n", mangle);
+            free(*pLastPackage);
+            *pLastPackage = mangle;
+        } else {
+            free(mangle);
+        }
     }
 
-    printf("  Interfaces        -\n");
+    accessStr = createAccessFlagStr(pClassDef->accessFlags, kAccessForClass);
+
+    if (pClassDef->superclassIdx == kDexNoIndex) {
+        superclassDescriptor = NULL;
+    } else {
+        superclassDescriptor =
+            dexStringByTypeIdx(pDexFile, pClassDef->superclassIdx);
+    }
+
+    if (gOptions.outputFormat == OUTPUT_PLAIN) {
+        printf("Class #%d            -\n", idx);
+        printf("  Class descriptor  : '%s'\n", classDescriptor);
+        printf("  Access flags      : 0x%04x (%s)\n",
+            pClassDef->accessFlags, accessStr);
+
+        if (superclassDescriptor != NULL)
+            printf("  Superclass        : '%s'\n", superclassDescriptor);
+
+        printf("  Interfaces        -\n");
+    } else {
+        char* tmp;
+
+        tmp = descriptorClassToDot(classDescriptor);
+        printf("<class name=\"%s\"\n", tmp);
+        free(tmp);
+
+        if (superclassDescriptor != NULL) {
+            tmp = descriptorToDot(superclassDescriptor);
+            printf(" extends=\"%s\"\n", tmp);
+            free(tmp);
+        }
+        printf(" abstract=%s\n",
+            quotedBool((pClassDef->accessFlags & ACC_ABSTRACT) != 0));
+        printf(" static=%s\n",
+            quotedBool((pClassDef->accessFlags & ACC_STATIC) != 0));
+        printf(" final=%s\n",
+            quotedBool((pClassDef->accessFlags & ACC_FINAL) != 0));
+        // "deprecated=" not knowable w/o parsing annotations
+        printf(" visibility=%s\n",
+            quotedVisibility(pClassDef->accessFlags));
+        printf(">\n");
+    }
     pInterfaces = dexGetInterfacesList(pDexFile, pClassDef);
     if (pInterfaces != NULL) {
         for (i = 0; i < (int) pInterfaces->size; i++)
             dumpInterface(pDexFile, dexGetTypeItem(pInterfaces, i), i);
     }
 
-    printf("  Static fields     -\n");
+    if (gOptions.outputFormat == OUTPUT_PLAIN)
+        printf("  Static fields     -\n");
     for (i = 0; i < (int) pClassData->header.staticFieldsSize; i++) {
         dumpSField(pDexFile, &pClassData->staticFields[i], i);
     }
 
-    printf("  Instance fields   -\n");
+    if (gOptions.outputFormat == OUTPUT_PLAIN)
+        printf("  Instance fields   -\n");
     for (i = 0; i < (int) pClassData->header.instanceFieldsSize; i++) {
         dumpIField(pDexFile, &pClassData->instanceFields[i], i);
     }
 
-    printf("  Direct methods    -\n");
+    if (gOptions.outputFormat == OUTPUT_PLAIN)
+        printf("  Direct methods    -\n");
     for (i = 0; i < (int) pClassData->header.directMethodsSize; i++) {
         dumpMethod(pDexFile, &pClassData->directMethods[i], i);
     }
 
-    printf("  Virtual methods   -\n");
+    if (gOptions.outputFormat == OUTPUT_PLAIN)
+        printf("  Virtual methods   -\n");
     for (i = 0; i < (int) pClassData->header.virtualMethodsSize; i++) {
         dumpMethod(pDexFile, &pClassData->virtualMethods[i], i);
     }
@@ -1040,11 +1361,18 @@
         fileName = dexStringById(pDexFile, pClassDef->sourceFileIdx);
     else
         fileName = "unknown";
-    printf("  source_file_idx   : %d (%s)\n",
-        pClassDef->sourceFileIdx, fileName);
 
-    printf("\n");
+    if (gOptions.outputFormat == OUTPUT_PLAIN) {
+        printf("  source_file_idx   : %d (%s)\n",
+            pClassDef->sourceFileIdx, fileName);
+        printf("\n");
+    }
 
+    if (gOptions.outputFormat == OUTPUT_XML) {
+        printf("</class>\n");
+    }
+
+bail:
     free(pClassData);
     free(accessStr);
 }
@@ -1256,10 +1584,13 @@
  */
 void processDexFile(const char* fileName, DexFile* pDexFile)
 {
+    char* package = NULL;
     int i;
 
-    printf("Opened '%s', DEX version '%.3s'\n", fileName,
-        pDexFile->pHeader->magic +4);
+    if (gOptions.verbose) {
+        printf("Opened '%s', DEX version '%.3s'\n", fileName,
+            pDexFile->pHeader->magic +4);
+    }
 
     if (gOptions.dumpRegisterMaps) {
         dumpRegisterMaps(pDexFile);
@@ -1269,12 +1600,24 @@
     if (gOptions.showFileHeaders)
         dumpFileHeader(pDexFile);
 
+    if (gOptions.outputFormat == OUTPUT_XML)
+        printf("<api>\n");
+
     for (i = 0; i < (int) pDexFile->pHeader->classDefsSize; i++) {
         if (gOptions.showSectionHeaders)
             dumpClassDef(pDexFile, i);
 
-        dumpClass(pDexFile, i);
+        dumpClass(pDexFile, i, &package);
     }
+
+    /* free the last one allocated */
+    if (package != NULL) {
+        printf("</package>\n");
+        free(package);
+    }
+
+    if (gOptions.outputFormat == OUTPUT_XML)
+        printf("</api>\n");
 }
 
 
@@ -1288,7 +1631,8 @@
     bool mapped = false;
     int result = -1;
 
-    printf("Processing '%s'...\n", fileName);
+    if (gOptions.verbose)
+        printf("Processing '%s'...\n", fileName);
 
     if (dexOpenAndMap(fileName, gOptions.tempFileName, &map, false) != 0)
         goto bail;
@@ -1328,7 +1672,7 @@
 {
     fprintf(stderr, "Copyright (C) 2007 The Android Open Source Project\n\n");
     fprintf(stderr,
-        "%s: [-c] [-d] [-f] [-h] [-m] [-i] [-t tempfile] dexfile...\n",
+        "%s: [-c] [-d] [-f] [-h] [-i] [-l layout] [-m] [-t tempfile] dexfile...\n",
         gProgName);
     fprintf(stderr, "\n");
     fprintf(stderr, " -c : verify checksum and exit\n");
@@ -1336,6 +1680,7 @@
     fprintf(stderr, " -f : display summary information from file header\n");
     fprintf(stderr, " -h : display file header details\n");
     fprintf(stderr, " -i : ignore checksum failures\n");
+    fprintf(stderr, " -l : output layout, either 'plain' or 'xml'\n");
     fprintf(stderr, " -m : dump register maps (and nothing else)\n");
     fprintf(stderr, " -t : temp file name (defaults to /sdcard/dex-temp-*)\n");
 }
@@ -1351,9 +1696,10 @@
     int ic;
 
     memset(&gOptions, 0, sizeof(gOptions));
+    gOptions.verbose = true;
 
     while (1) {
-        ic = getopt(argc, argv, "cdfhimt:");
+        ic = getopt(argc, argv, "cdfhil:mt:");
         if (ic < 0)
             break;
 
@@ -1373,11 +1719,22 @@
         case 'i':       // continue even if checksum is bad
             gOptions.ignoreBadChecksum = true;
             break;
+        case 'l':       // layout
+            if (strcmp(optarg, "plain") == 0) {
+                gOptions.outputFormat = OUTPUT_PLAIN;
+            } else if (strcmp(optarg, "xml") == 0) {
+                gOptions.outputFormat = OUTPUT_XML;
+                gOptions.verbose = false;
+                gOptions.exportsOnly = true;
+            } else {
+                wantUsage = true;
+            }
+            break;
         case 'm':       // dump register maps only
             gOptions.dumpRegisterMaps = true;
             break;
         case 't':       // temp file, used when opening compressed Jar
-            gOptions.tempFileName = argv[optind];
+            gOptions.tempFileName = optarg;
             break;
         default:
             wantUsage = true;
diff --git a/libdex/CmdUtils.c b/libdex/CmdUtils.c
index 35ced14..7dfee87 100644
--- a/libdex/CmdUtils.c
+++ b/libdex/CmdUtils.c
@@ -104,7 +104,7 @@
 {
     UnzipToFileResult result = kUTFRGenericFailure;
     int len = strlen(fileName);
-    char tempName[32];
+    char tempNameBuf[32];
     bool removeTemp = false;
     int fd = -1;
 
@@ -125,17 +125,17 @@
              * data to a temp file, the location of which varies.
              */
             if (access("/tmp", W_OK) == 0)
-                sprintf(tempName, "/tmp/dex-temp-%d", getpid());
+                sprintf(tempNameBuf, "/tmp/dex-temp-%d", getpid());
             else
-                sprintf(tempName, "/sdcard/dex-temp-%d", getpid());
+                sprintf(tempNameBuf, "/sdcard/dex-temp-%d", getpid());
 
-            tempFileName = tempName;
+            tempFileName = tempNameBuf;
         }
 
         result = dexUnzipToFile(fileName, tempFileName, quiet);
         
         if (result == kUTFRSuccess) {
-            //printf("+++ Good unzip to '%s'\n", tempName);
+            //printf("+++ Good unzip to '%s'\n", tempFileName);
             fileName = tempFileName;
             removeTemp = true;
         } else if (result == kUTFRNotZip) {
@@ -177,8 +177,10 @@
     if (fd >= 0)
         close(fd);
     if (removeTemp) {
-        if (unlink(tempName) != 0)
-            fprintf(stderr, "Warning: unable to remove temp '%s'\n", tempName);
+        if (unlink(tempFileName) != 0) {
+            fprintf(stderr, "Warning: unable to remove temp '%s'\n",
+                tempFileName);
+        }
     }
     return result;
 }