From: The Android Open Source Project Date: Tue, 29 Jun 2010 21:34:35 +0000 (-0700) Subject: set up fast-forward from froyo-release to gingerbread X-Git-Url: https://git.saurik.com/android/aapt.git/commitdiff_plain/edacf88c80e6d421cc3542268a263b9fa9e13a7f?hp=547f2c817fa6fdbf0fd9b53eae0fc84de60f577d set up fast-forward from froyo-release to gingerbread Change-Id: I22fc9465f5d8a0144b31803f431602fe3bda516a --- diff --git a/AaptAssets.cpp b/AaptAssets.cpp index efc9619..d6cfb12 100644 --- a/AaptAssets.cpp +++ b/AaptAssets.cpp @@ -766,6 +766,11 @@ bool AaptGroupEntry::getScreenLayoutSizeName(const char* name, (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) | ResTable_config::SCREENSIZE_LARGE; return true; + } else if (strcmp(name, "xlarge") == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) + | ResTable_config::SCREENSIZE_XLARGE; + return true; } return false; diff --git a/Android.mk b/Android.mk index 499a7ac..b339a2c 100644 --- a/Android.mk +++ b/Android.mk @@ -4,6 +4,9 @@ # Android Asset Packaging Tool # +# This tool is prebuilt if we're doing an app-only build. +ifeq ($(TARGET_BUILD_APPS),) + LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -53,3 +56,4 @@ LOCAL_MODULE := aapt include $(BUILD_HOST_EXECUTABLE) +endif # TARGET_BUILD_APPS diff --git a/ResourceTable.cpp b/ResourceTable.cpp index a2f085a..755b93b 100644 --- a/ResourceTable.cpp +++ b/ResourceTable.cpp @@ -573,6 +573,7 @@ status_t parseAndAddBag(Bundle* bundle, const String16& parentIdent, const String16& itemIdent, int32_t curFormat, + bool isFormatted, bool pseudolocalize, const bool overwrite, ResourceTable* outTable) @@ -583,7 +584,7 @@ status_t parseAndAddBag(Bundle* bundle, String16 str; Vector spans; err = parseStyledString(bundle, in->getPrintableSource().string(), - block, item16, &str, &spans, + block, item16, &str, &spans, isFormatted, pseudolocalize); if (err != NO_ERROR) { return err; @@ -616,6 +617,7 @@ status_t parseAndAddEntry(Bundle* bundle, const String16& curTag, bool curIsStyled, int32_t curFormat, + bool isFormatted, bool pseudolocalize, const bool overwrite, ResourceTable* outTable) @@ -626,7 +628,7 @@ status_t parseAndAddEntry(Bundle* bundle, Vector spans; err = parseStyledString(bundle, in->getPrintableSource().string(), block, curTag, &str, curIsStyled ? &spans : NULL, - pseudolocalize); + isFormatted, pseudolocalize); if (err < NO_ERROR) { return err; @@ -709,12 +711,18 @@ status_t compileResourceFile(Bundle* bundle, // useful attribute names and special values const String16 name16("name"); const String16 translatable16("translatable"); + const String16 formatted16("formatted"); const String16 false16("false"); const String16 myPackage(assets->getPackage()); bool hasErrors = false; - + + bool fileIsTranslatable = true; + if (strstr(in->getPrintableSource().string(), "donottranslate") != NULL) { + fileIsTranslatable = false; + } + DefaultKeyedVector nextPublicId(0); ResXMLTree::event_code_t code; @@ -751,6 +759,7 @@ status_t compileResourceFile(Bundle* bundle, bool curIsBagReplaceOnOverwrite = false; bool curIsStyled = false; bool curIsPseudolocalizable = false; + bool curIsFormatted = fileIsTranslatable; bool localHasErrors = false; if (strcmp16(block.getElementName(&len), skip16.string()) == 0) { @@ -1136,6 +1145,7 @@ status_t compileResourceFile(Bundle* bundle, String8 locale(rawLocale); String16 name; String16 translatable; + String16 formatted; size_t n = block.getAttributeCount(); for (size_t i = 0; i < n; i++) { @@ -1145,11 +1155,14 @@ status_t compileResourceFile(Bundle* bundle, name.setTo(block.getAttributeStringValue(i, &length)); } else if (strcmp16(attr, translatable16.string()) == 0) { translatable.setTo(block.getAttributeStringValue(i, &length)); + } else if (strcmp16(attr, formatted16.string()) == 0) { + formatted.setTo(block.getAttributeStringValue(i, &length)); } } if (name.size() > 0) { if (translatable == false16) { + curIsFormatted = false; // Untranslatable strings must only exist in the default [empty] locale if (locale.size() > 0) { fprintf(stderr, "aapt: warning: string '%s' in %s marked untranslatable but exists" @@ -1167,6 +1180,10 @@ status_t compileResourceFile(Bundle* bundle, } else { outTable->addLocalization(name, locale); } + + if (formatted == false16) { + curIsFormatted = false; + } } curTag = &string16; @@ -1356,7 +1373,7 @@ status_t compileResourceFile(Bundle* bundle, block.getPosition(&parserPosition); err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType, - ident, parentIdent, itemIdent, curFormat, + ident, parentIdent, itemIdent, curFormat, curIsFormatted, false, overwrite, outTable); if (err == NO_ERROR) { if (curIsPseudolocalizable && localeIsDefined(curParams) @@ -1365,8 +1382,8 @@ status_t compileResourceFile(Bundle* bundle, #if 1 block.setPosition(parserPosition); err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage, - curType, ident, parentIdent, itemIdent, curFormat, true, - overwrite, outTable); + curType, ident, parentIdent, itemIdent, curFormat, + curIsFormatted, true, overwrite, outTable); #endif } } @@ -1389,7 +1406,8 @@ status_t compileResourceFile(Bundle* bundle, block.getPosition(&parserPosition); err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident, - *curTag, curIsStyled, curFormat, false, overwrite, outTable); + *curTag, curIsStyled, curFormat, curIsFormatted, + false, overwrite, outTable); if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR? hasErrors = localHasErrors = true; @@ -1400,7 +1418,8 @@ status_t compileResourceFile(Bundle* bundle, // pseudolocalize here block.setPosition(parserPosition); err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType, - ident, *curTag, curIsStyled, curFormat, true, overwrite, outTable); + ident, *curTag, curIsStyled, curFormat, + curIsFormatted, true, overwrite, outTable); if (err != NO_ERROR) { hasErrors = localHasErrors = true; } diff --git a/XMLNode.cpp b/XMLNode.cpp index 4c59288..57ff47a 100644 --- a/XMLNode.cpp +++ b/XMLNode.cpp @@ -68,12 +68,118 @@ String16 getNamespaceResourcePackage(String16 namespaceUri, bool* outIsPublic) return String16(namespaceUri, namespaceUri.size()-prefixSize, prefixSize); } +status_t hasSubstitutionErrors(const char* fileName, + ResXMLTree* inXml, + String16 str16) +{ + const char16_t* str = str16.string(); + const char16_t* p = str; + const char16_t* end = str + str16.size(); + + bool nonpositional = false; + int argCount = 0; + + while (p < end) { + /* + * Look for the start of a Java-style substitution sequence. + */ + if (*p == '%' && p + 1 < end) { + p++; + + // A literal percent sign represented by %% + if (*p == '%') { + p++; + continue; + } + + argCount++; + + if (*p >= '0' && *p <= '9') { + do { + p++; + } while (*p >= '0' && *p <= '9'); + if (*p != '$') { + // This must be a size specification instead of position. + nonpositional = true; + } + } else if (*p == '<') { + // Reusing last argument; bad idea since it can be re-arranged. + nonpositional = true; + p++; + + // Optionally '$' can be specified at the end. + if (p < end && *p == '$') { + p++; + } + } else { + nonpositional = true; + } + + // Ignore flags and widths + while (p < end && (*p == '-' || + *p == '#' || + *p == '+' || + *p == ' ' || + *p == ',' || + *p == '(' || + (*p >= '0' && *p <= '9'))) { + p++; + } + + /* + * This is a shortcut to detect strings that are going to Time.format() + * instead of String.format() + * + * Comparison of String.format() and Time.format() args: + * + * String: ABC E GH ST X abcdefgh nost x + * Time: DEFGHKMS W Za d hkm s w yz + * + * Therefore we know it's definitely Time if we have: + * DFKMWZkmwyz + */ + if (p < end) { + switch (*p) { + case 'D': + case 'F': + case 'K': + case 'M': + case 'W': + case 'Z': + case 'k': + case 'm': + case 'w': + case 'y': + case 'z': + return NO_ERROR; + } + } + } + + p++; + } + + /* + * If we have more than one substitution in this string and any of them + * are not in positional form, give the user an error. + */ + if (argCount > 1 && nonpositional) { + SourcePos(String8(fileName), inXml->getLineNumber()).error( + "Multiple substitutions specified in non-positional format; " + "did you mean to add the formatted=\"true\" attribute?\n"); + return NOT_ENOUGH_DATA; + } + + return NO_ERROR; +} + status_t parseStyledString(Bundle* bundle, const char* fileName, ResXMLTree* inXml, const String16& endTag, String16* outString, Vector* outSpans, + bool isFormatted, bool pseudolocalize) { Vector spanStack; @@ -101,7 +207,11 @@ status_t parseStyledString(Bundle* bundle, std::string pseudo = pseudolocalize_string(orig); curString.append(String16(String8(pseudo.c_str()))); } else { - curString.append(text); + if (isFormatted && hasSubstitutionErrors(fileName, inXml, text) != NO_ERROR) { + return UNKNOWN_ERROR; + } else { + curString.append(text); + } } } else if (code == ResXMLTree::START_TAG) { const String16 element16(inXml->getElementName(&len)); diff --git a/XMLNode.h b/XMLNode.h index e9a263b..05624b7 100644 --- a/XMLNode.h +++ b/XMLNode.h @@ -25,6 +25,7 @@ status_t parseStyledString(Bundle* bundle, const String16& endTag, String16* outString, Vector* outSpans, + bool isFormatted, bool isPseudolocalizable); void printXMLBlock(ResXMLTree* block);