Main.cpp revision ce89f1531ed8b96b8b790b3f8b18dd4cf483f7f0
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Copyright 2006 The Android Open Source Project 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Android Asset Packaging Tool main entry point. 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt// 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#include "Main.h" 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "Bundle.h" 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <utils/Log.h> 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <utils/threads.h> 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <utils/List.h> 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <utils/Errors.h> 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <stdlib.h> 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <getopt.h> 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <assert.h> 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtusing namespace android; 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char* gProgName = "aapt"; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When running under Cygwin on Windows, this will convert slash-based 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * paths into back-slash-based ones. Otherwise the ApptAssets file comparisons 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * fail later as they use back-slash separators under Windows. 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This operates in-place on the path string. 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid convertPath(char *path) { 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (path != NULL && OS_PATH_SEPARATOR != '/') { 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (; *path; path++) { 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*path == '/') { 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *path = OS_PATH_SEPARATOR; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Print usage info. 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid usage(void) 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "Android Asset Packaging Tool\n\n"); 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "Usage:\n"); 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " %s l[ist] [-v] [-a] file.{zip,jar,apk}\n" 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " List contents of Zip-compatible archive.\n\n", gProgName); 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " %s d[ump] [--values] WHAT file.{apk} [asset [asset ...]]\n" 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " badging Print the label and icon for the app declared in APK.\n" 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " permissions Print the permissions from the APK.\n" 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " resources Print the resource table from the APK.\n" 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " configurations Print the configurations in the APK.\n" 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " xmltree Print the compiled xmls in the given assets.\n" 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " xmlstrings Print the strings of the given compiled xml assets.\n\n", gProgName); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " %s p[ackage] [-d][-f][-m][-u][-v][-x][-z][-M AndroidManifest.xml] \\\n" 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [-0 extension [-0 extension ...]] [-g tolerance] [-j jarfile] \\\n" 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [--debug-mode] [--min-sdk-version VAL] [--target-sdk-version VAL] \\\n" 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [--app-version VAL] [--app-version-name TEXT] [--custom-package VAL] \\\n" 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [--rename-manifest-package PACKAGE] \\\n" 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [--rename-instrumentation-target-package PACKAGE] \\\n" 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [--utf16] [--auto-add-overlay] \\\n" 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [--max-res-version VAL] \\\n" 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [-I base-package [-I base-package ...]] \\\n" 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [-A asset-source-dir] [-G class-list-file] [-P public-definitions-file] \\\n" 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [-S resource-sources [-S resource-sources ...]] " 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [-F apk-file] [-J R-file-dir] \\\n" 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [--product product1,product2,...] \\\n" 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [-o] \\\n" 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " [raw-files-dir [raw-files-dir] ...]\n" 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\n" 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Package the android resources. It will read assets and resources that are\n" 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " supplied with the -M -A -S or raw-files-dir arguments. The -J -P -F and -R\n" 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " options control which files are output.\n\n" 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt , gProgName); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " %s r[emove] [-v] file.{zip,jar,apk} file1 [file2 ...]\n" 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Delete specified files from Zip-compatible archive.\n\n", 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gProgName); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " %s a[dd] [-v] file.{zip,jar,apk} file1 [file2 ...]\n" 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Add specified files to Zip-compatible archive.\n\n", gProgName); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " %s v[ersion]\n" 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Print program version.\n\n", gProgName); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Modifiers:\n" 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -a print Android-specific data (resources, manifest) when listing\n" 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -c specify which configurations to include. The default is all\n" 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " configurations. The value of the parameter should be a comma\n" 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " separated list of configuration values. Locales should be specified\n" 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " as either a language or language-region pair. Some examples:\n" 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " en\n" 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " port,en\n" 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " port,land,en_US\n" 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " If you put the special locale, zz_ZZ on the list, it will perform\n" 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " pseudolocalization on the default locale, modifying all of the\n" 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " strings so you can look for strings that missed the\n" 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " internationalization process. For example:\n" 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " port,land,zz_ZZ\n" 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -d one or more device assets to include, separated by commas\n" 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -f force overwrite of existing files\n" 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -g specify a pixel tolerance to force images to grayscale, default 0\n" 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -j specify a jar or zip file containing classes to include\n" 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -k junk path of file(s) added\n" 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -m make package directories under location specified by -J\n" 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -o create overlay package (ie only resources; expects <overlay-package> in manifest)\n" 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -p pseudolocalize the default configuration\n" 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -u update existing packages (add new, replace older, remove deleted files)\n" 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -v verbose output\n" 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -x create extending (non-application) resource IDs\n" 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -z require localization of resource attributes marked with\n" 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " localization=\"suggested\"\n" 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -A additional directory in which to find raw asset files\n" 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -G A file to output proguard options into.\n" 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -F specify the apk file to output\n" 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -I add an existing package to base include set\n" 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -J specify where to output R.java resource constant definitions\n" 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -M specify full path to AndroidManifest.xml to include in zip\n" 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -P specify where to output public resource definitions\n" 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -S directory in which to find resources. Multiple directories will be scanned\n" 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " and the first match found (left to right) will take precedence.\n" 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -0 specifies an additional extension for which such files will not\n" 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " be stored compressed in the .apk. An empty string means to not\n" 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " compress any files at all.\n" 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --debug-mode\n" 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " inserts android:debuggable=\"true\" in to the application node of the\n" 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " manifest, making the application debuggable even on production devices.\n" 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --min-sdk-version\n" 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " inserts android:minSdkVersion in to manifest. If the version is 7 or\n" 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " higher, the default encoding for resources will be in UTF-8.\n" 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --target-sdk-version\n" 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " inserts android:targetSdkVersion in to manifest.\n" 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --max-res-version\n" 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " ignores versioned resource directories above the given value.\n" 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --values\n" 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " when used with \"dump resources\" also includes resource values.\n" 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --version-code\n" 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " inserts android:versionCode in to manifest.\n" 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --version-name\n" 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " inserts android:versionName in to manifest.\n" 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --custom-package\n" 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " generates R.java into a different package.\n" 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --extra-packages\n" 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " generate R.java for libraries. Separate libraries with ';'.\n" 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --auto-add-overlay\n" 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Automatically add resources that are only in overlays.\n" 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --rename-manifest-package\n" 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Rewrite the manifest so that its package name is the package name\n" 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " given here. Relative class names (for example .Foo) will be\n" 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " changed to absolute names with the old package so that the code\n" 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " does not need to change.\n" 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --rename-instrumentation-target-package\n" 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Rewrite the manifest so that all of its instrumentation\n" 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " components target the given package. Useful when used in\n" 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " conjunction with --rename-manifest-package to fix tests against\n" 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " a package that has been renamed.\n" 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --product\n" 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Specifies which variant to choose for strings that have\n" 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " product variants\n" 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --utf16\n" 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " changes default encoding for resources to UTF-16. Only useful when API\n" 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " level is set to 7 or higher where the default encoding is UTF-8.\n" 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " --non-constant-id\n" 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Make the resources ID non constant. This is required to make an R java class\n" 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " that does not contain the final value but is used to make reusable compiled\n" 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " libraries that need to access resources.\n"); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Dispatch the command. 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint handleCommand(Bundle* bundle) 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt //printf("--- command %d (verbose=%d force=%d):\n", 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // bundle->getCommand(), bundle->getVerbose(), bundle->getForce()); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt //for (int i = 0; i < bundle->getFileSpecCount(); i++) 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // printf(" %d: '%s'\n", i, bundle->getFileSpecEntry(i)); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (bundle->getCommand()) { 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case kCommandVersion: return doVersion(bundle); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case kCommandList: return doList(bundle); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case kCommandDump: return doDump(bundle); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case kCommandAdd: return doAdd(bundle); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case kCommandRemove: return doRemove(bundle); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case kCommandPackage: return doPackage(bundle); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "%s: requested command not yet supported\n", gProgName); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Parse args. 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint main(int argc, char* const argv[]) 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *prog = argv[0]; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Bundle bundle; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool wantUsage = false; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int result = 1; // pessimistically assume an error. 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tolerance = 0; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* default to compression */ 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setCompressionMethod(ZipEntry::kCompressDeflated); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (argc < 2) { 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (argv[1][0] == 'v') 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setCommand(kCommandVersion); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (argv[1][0] == 'd') 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setCommand(kCommandDump); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (argv[1][0] == 'l') 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setCommand(kCommandList); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (argv[1][0] == 'a') 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setCommand(kCommandAdd); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (argv[1][0] == 'r') 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setCommand(kCommandRemove); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (argv[1][0] == 'p') 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setCommand(kCommandPackage); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "ERROR: Unknown command '%s'\n", argv[1]); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argc -= 2; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argv += 2; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Pull out flags. We support "-fv" and "-f -v". 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (argc && argv[0][0] == '-') { 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* flag(s) found */ 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char* cp = argv[0] +1; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*cp != '\0') { 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (*cp) { 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'v': 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setVerbose(true); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'a': 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setAndroidList(true); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'c': 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argc--; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argv++; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!argc) { 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "ERROR: No argument supplied for '-c' option\n"); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.addConfigurations(argv[0]); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'f': 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setForce(true); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'g': 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argc--; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argv++; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!argc) { 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "ERROR: No argument supplied for '-g' option\n"); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tolerance = atoi(argv[0]); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setGrayscaleTolerance(tolerance); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("%s: Images with deviation <= %d will be forced to grayscale.\n", prog, tolerance); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'k': 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setJunkPath(true); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'm': 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setMakePackageDirs(true); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'o': 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setIsOverlayPackage(true); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'p': 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setPseudolocalize(true); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'u': 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setUpdate(true); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'x': 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setExtending(true); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'z': 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setRequireLocalization(true); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'j': 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argc--; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argv++; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!argc) { 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "ERROR: No argument supplied for '-j' option\n"); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt convertPath(argv[0]); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.addJarFile(argv[0]); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'A': 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argc--; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argv++; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!argc) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "ERROR: No argument supplied for '-A' option\n"); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt convertPath(argv[0]); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setAssetSourceDir(argv[0]); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'G': 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argc--; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argv++; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!argc) { 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "ERROR: No argument supplied for '-G' option\n"); 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt convertPath(argv[0]); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setProguardFile(argv[0]); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'I': 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argc--; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argv++; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!argc) { 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "ERROR: No argument supplied for '-I' option\n"); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt convertPath(argv[0]); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.addPackageInclude(argv[0]); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'F': 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argc--; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argv++; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!argc) { 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "ERROR: No argument supplied for '-F' option\n"); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt convertPath(argv[0]); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setOutputAPKFile(argv[0]); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'J': 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argc--; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argv++; 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!argc) { 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "ERROR: No argument supplied for '-J' option\n"); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt convertPath(argv[0]); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bundle.setRClassDir(argv[0]); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'M': 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argc--; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt argv++; 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!argc) { 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "ERROR: No argument supplied for '-M' option\n"); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wantUsage = true; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bail; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt convertPath(argv[0]); 374 bundle.setAndroidManifestFile(argv[0]); 375 break; 376 case 'P': 377 argc--; 378 argv++; 379 if (!argc) { 380 fprintf(stderr, "ERROR: No argument supplied for '-P' option\n"); 381 wantUsage = true; 382 goto bail; 383 } 384 convertPath(argv[0]); 385 bundle.setPublicOutputFile(argv[0]); 386 break; 387 case 'S': 388 argc--; 389 argv++; 390 if (!argc) { 391 fprintf(stderr, "ERROR: No argument supplied for '-S' option\n"); 392 wantUsage = true; 393 goto bail; 394 } 395 convertPath(argv[0]); 396 bundle.addResourceSourceDir(argv[0]); 397 break; 398 case '0': 399 argc--; 400 argv++; 401 if (!argc) { 402 fprintf(stderr, "ERROR: No argument supplied for '-e' option\n"); 403 wantUsage = true; 404 goto bail; 405 } 406 if (argv[0][0] != 0) { 407 bundle.addNoCompressExtension(argv[0]); 408 } else { 409 bundle.setCompressionMethod(ZipEntry::kCompressStored); 410 } 411 break; 412 case '-': 413 if (strcmp(cp, "-debug-mode") == 0) { 414 bundle.setDebugMode(true); 415 } else if (strcmp(cp, "-min-sdk-version") == 0) { 416 argc--; 417 argv++; 418 if (!argc) { 419 fprintf(stderr, "ERROR: No argument supplied for '--min-sdk-version' option\n"); 420 wantUsage = true; 421 goto bail; 422 } 423 bundle.setMinSdkVersion(argv[0]); 424 } else if (strcmp(cp, "-target-sdk-version") == 0) { 425 argc--; 426 argv++; 427 if (!argc) { 428 fprintf(stderr, "ERROR: No argument supplied for '--target-sdk-version' option\n"); 429 wantUsage = true; 430 goto bail; 431 } 432 bundle.setTargetSdkVersion(argv[0]); 433 } else if (strcmp(cp, "-max-sdk-version") == 0) { 434 argc--; 435 argv++; 436 if (!argc) { 437 fprintf(stderr, "ERROR: No argument supplied for '--max-sdk-version' option\n"); 438 wantUsage = true; 439 goto bail; 440 } 441 bundle.setMaxSdkVersion(argv[0]); 442 } else if (strcmp(cp, "-max-res-version") == 0) { 443 argc--; 444 argv++; 445 if (!argc) { 446 fprintf(stderr, "ERROR: No argument supplied for '--max-res-version' option\n"); 447 wantUsage = true; 448 goto bail; 449 } 450 bundle.setMaxResVersion(argv[0]); 451 } else if (strcmp(cp, "-version-code") == 0) { 452 argc--; 453 argv++; 454 if (!argc) { 455 fprintf(stderr, "ERROR: No argument supplied for '--version-code' option\n"); 456 wantUsage = true; 457 goto bail; 458 } 459 bundle.setVersionCode(argv[0]); 460 } else if (strcmp(cp, "-version-name") == 0) { 461 argc--; 462 argv++; 463 if (!argc) { 464 fprintf(stderr, "ERROR: No argument supplied for '--version-name' option\n"); 465 wantUsage = true; 466 goto bail; 467 } 468 bundle.setVersionName(argv[0]); 469 } else if (strcmp(cp, "-values") == 0) { 470 bundle.setValues(true); 471 } else if (strcmp(cp, "-custom-package") == 0) { 472 argc--; 473 argv++; 474 if (!argc) { 475 fprintf(stderr, "ERROR: No argument supplied for '--custom-package' option\n"); 476 wantUsage = true; 477 goto bail; 478 } 479 bundle.setCustomPackage(argv[0]); 480 } else if (strcmp(cp, "-extra-packages") == 0) { 481 argc--; 482 argv++; 483 if (!argc) { 484 fprintf(stderr, "ERROR: No argument supplied for '--extra-packages' option\n"); 485 wantUsage = true; 486 goto bail; 487 } 488 bundle.setExtraPackages(argv[0]); 489 } else if (strcmp(cp, "-utf16") == 0) { 490 bundle.setWantUTF16(true); 491 } else if (strcmp(cp, "-rename-manifest-package") == 0) { 492 argc--; 493 argv++; 494 if (!argc) { 495 fprintf(stderr, "ERROR: No argument supplied for '--rename-manifest-package' option\n"); 496 wantUsage = true; 497 goto bail; 498 } 499 bundle.setManifestPackageNameOverride(argv[0]); 500 } else if (strcmp(cp, "-rename-instrumentation-target-package") == 0) { 501 argc--; 502 argv++; 503 if (!argc) { 504 fprintf(stderr, "ERROR: No argument supplied for '--rename-instrumentation-target-package' option\n"); 505 wantUsage = true; 506 goto bail; 507 } 508 bundle.setInstrumentationPackageNameOverride(argv[0]); 509 } else if (strcmp(cp, "-auto-add-overlay") == 0) { 510 bundle.setAutoAddOverlay(true); 511 } else if (strcmp(cp, "-product") == 0) { 512 argc--; 513 argv++; 514 if (!argc) { 515 fprintf(stderr, "ERROR: No argument supplied for '--product' option\n"); 516 wantUsage = true; 517 goto bail; 518 } 519 bundle.setProduct(argv[0]); 520 } else if (strcmp(cp, "-non-constant-id") == 0) { 521 bundle.setNonConstantId(true); 522 } else { 523 fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp); 524 wantUsage = true; 525 goto bail; 526 } 527 cp += strlen(cp) - 1; 528 break; 529 default: 530 fprintf(stderr, "ERROR: Unknown flag '-%c'\n", *cp); 531 wantUsage = true; 532 goto bail; 533 } 534 535 cp++; 536 } 537 argc--; 538 argv++; 539 } 540 541 /* 542 * We're past the flags. The rest all goes straight in. 543 */ 544 bundle.setFileSpec(argv, argc); 545 546 result = handleCommand(&bundle); 547 548bail: 549 if (wantUsage) { 550 usage(); 551 result = 2; 552 } 553 554 //printf("--> returning %d\n", result); 555 return result; 556} 557