Merge branch 'master' into smalidea3

This commit is contained in:
Ben Gruver 2015-03-04 20:58:14 -08:00
commit 8c1d8ddef2
18 changed files with 136 additions and 244 deletions

3
.gitignore vendored
View File

@ -5,3 +5,6 @@
/dexlib2/accessorTestGenerator/build /dexlib2/accessorTestGenerator/build
/smali/build /smali/build
/util/build /util/build
*.iml
*.ipr
*.iws

50
NOTICE
View File

@ -85,56 +85,6 @@ limitations under the License.
******************************************************************************* *******************************************************************************
The smali mojo plugin is (very loosely) based on an unknown mojo plugin with
the following license:
*******************************************************************************
Copyright 2001-2005 The Apache Software Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*******************************************************************************
The RadixTree implementation in the "util" project is taken from
http://code.google.com/p/radixtree/ (version .3), and is used with minor
modifications in accordance with the following license:
*******************************************************************************
The MIT License
Copyright (c) 2008 Tahseen Ur Rehman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*******************************************************************************
Some parts of the smalidea plugin are based on code from the IDEA project, per the Some parts of the smalidea plugin are based on code from the IDEA project, per the
following license following license

View File

@ -29,8 +29,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
configurations { buildscript {
proguard repositories {
mavenCentral()
}
dependencies {
classpath depends.proguard_gradle
}
} }
dependencies { dependencies {
@ -41,8 +46,6 @@ dependencies {
testCompile depends.junit testCompile depends.junit
testCompile project(':smali') testCompile project(':smali')
proguard depends.proguard
} }
processResources.inputs.property('version', version) processResources.inputs.property('version', version)
@ -59,11 +62,11 @@ task fatJar(type: Jar) {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest { manifest {
attributes("Main-Class": "org.jf.baksmali.main") attributes('Main-Class': 'org.jf.baksmali.main')
} }
doLast { doLast {
if (!System.getProperty("os.name").toLowerCase().contains("windows")) { if (!System.getProperty('os.name').toLowerCase().contains('windows')) {
ant.symlink(link: file("${destinationDir}/baksmali.jar"), resource: archivePath, overwrite: true) ant.symlink(link: file("${destinationDir}/baksmali.jar"), resource: archivePath, overwrite: true)
} }
} }
@ -81,22 +84,22 @@ uploadArchives {
} }
} }
task proguard(type: JavaExec, dependsOn: fatJar) { task proguard(type: proguard.gradle.ProGuardTask, dependsOn: fatJar) {
def outFile = fatJar.destinationDir.getPath() + '/' + fatJar.baseName + '-' + fatJar.version + '-small' + '.' + fatJar.extension def outFile = fatJar.destinationDir.getPath() + '/' + fatJar.baseName + '-' + fatJar.version + '-small' + '.' + fatJar.extension
inputs.file fatJar.archivePath
outputs.file outFile
classpath = configurations.proguard injars fatJar.archivePath
main = 'proguard.ProGuard' outjars outFile
args '-injars ' + fatJar.archivePath
args '-outjars ' + outFile libraryjars "${System.properties['java.home']}/lib/rt.jar"
args '-libraryjars ' + System.properties['java.home'] + '/lib/rt.jar'
args '-dontobfuscate' dontobfuscate
args '-dontoptimize' dontoptimize
args '-keep public class org.jf.baksmali.main { public static void main(java.lang.String[]); }'
args '-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }' keep 'public class org.jf.baksmali.main { public static void main(java.lang.String[]); }'
args '-dontwarn com.google.common.**' keepclassmembers 'enum * { public static **[] values(); public static ** valueOf(java.lang.String); }'
args '-dontnote com.google.common.**'
dontwarn 'com.google.common.**'
dontnote 'com.google.common.**'
} }
tasks.getByPath(':release').dependsOn(proguard) tasks.getByPath(':release').dependsOn(proguard)

View File

@ -39,7 +39,7 @@ if (!('release' in gradle.startParameter.taskNames)) {
def versionSuffix def versionSuffix
try { try {
def git = org.eclipse.jgit.api.Git.open(file('.')) def git = org.eclipse.jgit.api.Git.open(file('.'))
def head = git.getRepository().getRef("HEAD") def head = git.getRepository().getRef('HEAD')
versionSuffix = head.getObjectId().abbreviate(8).name() versionSuffix = head.getObjectId().abbreviate(8).name()
if (!git.status().call().clean) { if (!git.status().call().clean) {
@ -90,7 +90,8 @@ subprojects {
stringtemplate: 'org.antlr:stringtemplate:3.2.1', stringtemplate: 'org.antlr:stringtemplate:3.2.1',
commons_cli: 'commons-cli:commons-cli:1.2', commons_cli: 'commons-cli:commons-cli:1.2',
jflex: 'de.jflex:jflex:1.4.3', jflex: 'de.jflex:jflex:1.4.3',
proguard: 'net.sf.proguard:proguard-base:4.8' jflex_plugin: 'co.tomlee.gradle.plugins:gradle-jflex-plugin:0.0.1',
proguard_gradle: 'net.sf.proguard:proguard-gradle:5.1'
] ]
} }
@ -124,7 +125,7 @@ subprojects {
} }
signing { signing {
required { gradle.taskGraph.hasTask("uploadArchives") } required { gradle.taskGraph.hasTask('uploadArchives') }
sign configurations.archives sign configurations.archives
} }
@ -135,7 +136,7 @@ subprojects {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
if (rootProject.hasProperty('sonatypeUsername') && rootProject.hasProperty('sonatypePassword')) { if (rootProject.hasProperty('sonatypeUsername') && rootProject.hasProperty('sonatypePassword')) {
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2/') {
authentication(userName: sonatypeUsername, password: sonatypePassword) authentication(userName: sonatypeUsername, password: sonatypePassword)
} }
} }
@ -182,5 +183,5 @@ buildscript {
} }
task wrapper(type: Wrapper) { task wrapper(type: Wrapper) {
gradleVersion = '1.10' gradleVersion = '2.3'
} }

View File

@ -39,4 +39,6 @@ LOCAL_SHARED_LIBRARIES := libdl
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE) LOCAL_LDFLAGS := -Wl,--hash-style=sysv
include $(BUILD_EXECUTABLE)

View File

@ -46,37 +46,6 @@ dependencies {
ext.testAccessorOutputDir = file("${buildDir}/generated-accessor-test-sources") ext.testAccessorOutputDir = file("${buildDir}/generated-accessor-test-sources")
ext.testAccessorOutputFile = file("${buildDir}/generated-accessor-test-sources/org/jf/dexlib2/AccessorTypes.java") ext.testAccessorOutputFile = file("${buildDir}/generated-accessor-test-sources/org/jf/dexlib2/AccessorTypes.java")
sourceSets {
// The sources for building the test dex file for the accessor test
accessorTestDex {
java {
srcDir testAccessorOutputDir
}
}
// The sources for the accessor test itself
accessorTest {
java {
compileClasspath += main.output
runtimeClasspath += main.output
}
}
}
configurations {
accessorTestDexCompile.extendsFrom compile
accessorTestDexRuntime.extendsFrom runtime
accessorTestCompile.extendsFrom testCompile
accessorTestRuntime.extendsFrom testRuntime
}
idea {
module {
testSourceDirs += sourceSets.accessorTest.java.srcDirs
}
}
// You must manually execute this task to regenerate SyntheticAccessorFSM.java, after modifying the ragel file // You must manually execute this task to regenerate SyntheticAccessorFSM.java, after modifying the ragel file
// e.g. ./gradlew ragel // e.g. ./gradlew ragel
task ragel(type:Exec) { task ragel(type:Exec) {
@ -87,36 +56,47 @@ task ragel(type:Exec) {
} }
task generateAccessorTestSource(type: JavaExec) { task generateAccessorTestSource(type: JavaExec) {
outputs.dir file(testAccessorOutputDir) doFirst {
file(testAccessorOutputFile.parent).mkdirs()
}
mkdir(file(testAccessorOutputFile).parent) outputs.dir file(testAccessorOutputDir)
sourceSets['test'].java.srcDir file(testAccessorOutputDir)
classpath = configurations.accessorTestGenerator classpath = configurations.accessorTestGenerator
main = 'org.jf.dexlib2.AccessorTestGenerator' main = 'org.jf.dexlib2.AccessorTestGenerator'
args testAccessorOutputFile args testAccessorOutputFile
} }
compileAccessorTestDexJava.dependsOn(generateAccessorTestSource) compileTestJava.dependsOn generateAccessorTestSource
task generateAccessorTestDex(type: Exec, dependsOn: compileAccessorTestDexJava) { task generateAccessorTestDex(type: Exec, dependsOn: compileTestJava) {
def outputDex = file("${sourceSets.accessorTest.output.resourcesDir}/accessorTest.dex") def outputDex = file(new File(sourceSets.test.output.resourcesDir, 'accessorTest.dex'))
mkdir(outputDex.parent)
inputs.dir project.sourceSets.accessorTestDex.output.classesDir doFirst {
file(outputDex.parent).mkdirs()
}
inputs.dir(project.sourceSets.test.output.classesDir)
outputs.file outputDex outputs.file outputDex
sourceSets.accessorTest.resources workingDir project.sourceSets.test.output.classesDir
workingDir project.sourceSets.accessorTestDex.output.classesDir
executable 'dx' executable 'dx'
args '--dex' args '--dex'
args '--no-strict'
args "--output=${outputDex}" args "--output=${outputDex}"
args '.'
}
task accessorTest(type: Test, dependsOn: generateAccessorTestDex) { doFirst {
testClassesDir = project.sourceSets.accessorTest.output.classesDir // this has to be done in doFirst, so that the generated classes will be available.
classpath = project.sourceSets.accessorTest.runtimeClasspath // otherwise, it the tree will be populated while the build is being configured,
// which is before the compileTestJava has run
fileTree(project.sourceSets.test.output.classesDir) {
include 'org/jf/dexlib2/AccessorTypes*.class'
}.each { File file ->
args file
}
}
} }
test.dependsOn generateAccessorTestDex
uploadArchives { uploadArchives {
repositories.mavenDeployer { repositories.mavenDeployer {

View File

@ -576,6 +576,9 @@ public abstract class DexWriter<
private void writeAnnotationSets(@Nonnull DexDataWriter writer) throws IOException { private void writeAnnotationSets(@Nonnull DexDataWriter writer) throws IOException {
writer.align(); writer.align();
annotationSetSectionOffset = writer.getPosition(); annotationSetSectionOffset = writer.getPosition();
if (shouldCreateEmptyAnnotationSet()) {
writer.writeInt(0);
}
for (Map.Entry<? extends AnnotationSetKey, Integer> entry: annotationSetSection.getItems()) { for (Map.Entry<? extends AnnotationSetKey, Integer> entry: annotationSetSection.getItems()) {
Collection<? extends AnnotationKey> annotations = Ordering.from(BaseAnnotation.BY_TYPE) Collection<? extends AnnotationKey> annotations = Ordering.from(BaseAnnotation.BY_TYPE)
.immutableSortedCopy(annotationSetSection.getAnnotations(entry.getKey())); .immutableSortedCopy(annotationSetSection.getAnnotations(entry.getKey()));
@ -613,6 +616,8 @@ public abstract class DexWriter<
for (AnnotationSetKey annotationSetKey: parameterAnnotations) { for (AnnotationSetKey annotationSetKey: parameterAnnotations) {
if (annotationSetSection.getAnnotations(annotationSetKey).size() > 0) { if (annotationSetSection.getAnnotations(annotationSetKey).size() > 0) {
writer.writeInt(annotationSetSection.getItemOffset(annotationSetKey)); writer.writeInt(annotationSetSection.getItemOffset(annotationSetKey));
} else if (shouldCreateEmptyAnnotationSet()) {
writer.writeInt(annotationSetSectionOffset);
} else { } else {
writer.writeInt(NO_OFFSET); writer.writeInt(NO_OFFSET);
} }
@ -1115,7 +1120,7 @@ public abstract class DexWriter<
if (annotationSection.getItems().size() > 0) { if (annotationSection.getItems().size() > 0) {
numItems++; numItems++;
} }
if (annotationSetSection.getItems().size() > 0) { if (annotationSetSection.getItems().size() > 0 || shouldCreateEmptyAnnotationSet()) {
numItems++; numItems++;
} }
if (numAnnotationSetRefItems > 0) { if (numAnnotationSetRefItems > 0) {
@ -1163,8 +1168,8 @@ public abstract class DexWriter<
writeMapItem(writer, ItemType.TYPE_LIST, typeListSection.getItems().size(), typeListSectionOffset); writeMapItem(writer, ItemType.TYPE_LIST, typeListSection.getItems().size(), typeListSectionOffset);
writeMapItem(writer, ItemType.ENCODED_ARRAY_ITEM, numEncodedArrayItems, encodedArraySectionOffset); writeMapItem(writer, ItemType.ENCODED_ARRAY_ITEM, numEncodedArrayItems, encodedArraySectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_ITEM, annotationSection.getItems().size(), annotationSectionOffset); writeMapItem(writer, ItemType.ANNOTATION_ITEM, annotationSection.getItems().size(), annotationSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_SET_ITEM, annotationSetSection.getItems().size(), writeMapItem(writer, ItemType.ANNOTATION_SET_ITEM,
annotationSetSectionOffset); annotationSetSection.getItems().size() + (shouldCreateEmptyAnnotationSet() ? 1 : 0), annotationSetSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_SET_REF_LIST, numAnnotationSetRefItems, annotationSetRefSectionOffset); writeMapItem(writer, ItemType.ANNOTATION_SET_REF_LIST, numAnnotationSetRefItems, annotationSetRefSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_DIRECTORY_ITEM, numAnnotationDirectoryItems, writeMapItem(writer, ItemType.ANNOTATION_DIRECTORY_ITEM, numAnnotationDirectoryItems,
annotationDirectorySectionOffset); annotationDirectorySectionOffset);
@ -1226,4 +1231,11 @@ public abstract class DexWriter<
writer.writeInt(0); writer.writeInt(0);
} }
} }
private boolean shouldCreateEmptyAnnotationSet() {
// Workaround for a crash in Dalvik VM before Jelly Bean MR1 (4.2)
// which is triggered by NO_OFFSET in parameter annotation list.
// (https://code.google.com/p/android/issues/detail?id=35304)
return (api < 17);
}
} }

View File

@ -1 +1,2 @@
org.gradle.daemon=true org.gradle.daemon=true
org.gradle.parallel=true

Binary file not shown.

View File

@ -1,6 +1,6 @@
#Sun Feb 02 12:47:14 PST 2014 #Sun Mar 01 19:20:47 PST 2015
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-all.zip

View File

@ -29,25 +29,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
configurations { apply plugin: 'antlr'
antlr3 apply plugin: 'jflex'
jflex
proguard buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath depends.jflex_plugin
classpath depends.proguard_gradle
}
} }
ext.antlrSource = 'src/main/antlr3' configurations {
ext.antlrOutput = file("${buildDir}/generated-sources/antlr3") // Remove the full antlr library that's added by the antlr plugin. We manually
// add the smaller antlr_runtime library instead
compile.exclude group: 'org.antlr', module: 'antlr'
ext.jflexSource = "src/main/jflex" // The jflex lexer doesn't have any runtime dependencies, so remove the dependency
ext.jflexOutput = file("${buildDir}/generated-sources/jflex") // that gets added by the jflex plugin
compile.exclude group: 'de.jflex', module: 'jflex'
ext.testAntlrSource = 'src/test/antlr3' }
ext.testAntlrOutput = file("${buildDir}/generated-test-sources/antlr3")
sourceSets.main.java.srcDir antlrOutput
sourceSets.main.java.srcDir jflexOutput
sourceSets.test.java.srcDir testAntlrOutput
idea { idea {
module { module {
@ -73,68 +76,10 @@ dependencies {
testCompile depends.junit testCompile depends.junit
antlr3 depends.antlr antlr depends.antlr
jflex depends.jflex jflex depends.jflex
proguard depends.proguard
} }
task generateParserAntlrSource(type: JavaExec) {
inputs.dir file(antlrSource)
outputs.dir file(antlrOutput)
mkdir(antlrOutput)
def grammars = fileTree(antlrSource).include('**/smaliParser.g')
classpath = configurations.antlr3
main = 'org.antlr.Tool'
args '-fo', relativePath("${antlrOutput}/org/jf/smali")
args grammars.files
}
task generateTreeWalkerAntlrSource(type: JavaExec) {
inputs.dir file(antlrSource)
outputs.dir file(antlrOutput)
mkdir(antlrOutput)
def grammars = fileTree(antlrSource).include('**/smaliTreeWalker.g')
classpath = configurations.antlr3
main = 'org.antlr.Tool'
args '-fo', relativePath("${antlrOutput}/org/jf/smali")
args grammars.files
}
task generateTestAntlrSource(type: JavaExec) {
inputs.dir file(testAntlrSource)
outputs.dir file(testAntlrOutput)
mkdir(testAntlrOutput)
def grammars = fileTree(testAntlrSource).include('**/*.g')
classpath = configurations.antlr3
main = 'org.antlr.Tool'
args '-fo', relativePath("${testAntlrOutput}/org/jf/smali")
args grammars.files.join(' ')
}
task generateJflexSource(type: JavaExec) {
inputs.dir file(jflexSource)
outputs.dir file(jflexOutput)
mkdir(jflexOutput)
def grammars = fileTree(jflexSource).include('**/*.flex')
classpath = configurations.jflex
main = 'JFlex.Main'
args '-q'
args '-d', relativePath("${jflexOutput}/org/jf/smali")
args grammars.files.join(' ')
environment LC_ALL: "en_US"
}
compileJava.dependsOn generateParserAntlrSource, generateTreeWalkerAntlrSource, generateJflexSource
compileTestJava.dependsOn generateTestAntlrSource
processResources.inputs.property('version', version) processResources.inputs.property('version', version)
processResources.expand('version': version) processResources.expand('version': version)
@ -149,17 +94,29 @@ task fatJar(type: Jar, dependsOn: jar) {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest { manifest {
attributes("Main-Class": "org.jf.smali.main") attributes('Main-Class': 'org.jf.smali.main')
} }
doLast { doLast {
if (!System.getProperty("os.name").toLowerCase().contains("windows")) { if (!System.getProperty('os.name').toLowerCase().contains('windows')) {
ant.symlink(link: file("${destinationDir}/smali.jar"), resource: archivePath, overwrite: true) ant.symlink(link: file("${destinationDir}/smali.jar"), resource: archivePath, overwrite: true)
} }
} }
} }
tasks.getByPath('build').dependsOn(fatJar) tasks.getByPath('build').dependsOn(fatJar)
generateTestGrammarSource {
outputDirectory = new File(outputDirectory, 'org/jf/smali')
}
generateGrammarSource {
outputDirectory = new File(outputDirectory, 'org/jf/smali')
}
generateJFlexSource {
outputDirectory = new File(outputDirectory, 'org/jf/smali')
}
uploadArchives { uploadArchives {
repositories.mavenDeployer { repositories.mavenDeployer {
pom.project { pom.project {
@ -171,22 +128,23 @@ uploadArchives {
} }
} }
task proguard(type: JavaExec, dependsOn: fatJar) { task proguard(type: proguard.gradle.ProGuardTask, dependsOn: fatJar) {
def outFile = fatJar.destinationDir.getPath() + '/' + fatJar.baseName + '-' + fatJar.version + '-small' + '.' + fatJar.extension def outFile = fatJar.destinationDir.getPath() + '/' + fatJar.baseName + '-' +
inputs.file fatJar.archivePath fatJar.version + '-small' + '.' + fatJar.extension
outputs.file outFile
classpath = configurations.proguard injars fatJar.archivePath
main = 'proguard.ProGuard' outjars outFile
args "-injars ${fatJar.archivePath}(!**/TestStringTemplate*.class)"
args "-outjars ${outFile}" libraryjars "${System.properties['java.home']}/lib/rt.jar"
args "-libraryjars ${System.properties['java.home']}/lib/rt.jar"
args '-dontobfuscate' dontobfuscate
args '-dontoptimize' dontoptimize
args '-keep public class org.jf.smali.main { public static void main(java.lang.String[]); }'
args '-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }' keep 'public class org.jf.smali.main { public static void main(java.lang.String[]); }'
args '-dontwarn com.google.common.**' keepclassmembers 'enum * { public static **[] values(); public static ** valueOf(java.lang.String); }'
args '-dontnote com.google.common.**'
dontwarn 'com.google.common.**'
dontnote 'com.google.common.**'
} }
tasks.getByPath(':release').dependsOn(proguard) tasks.getByPath(':release').dependsOn(proguard)

View File

@ -667,5 +667,5 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
"." { return invalidToken("Invalid directive"); } "." { return invalidToken("Invalid directive"); }
"." [a-zA-z\-_] { return invalidToken("Invalid directive"); } "." [a-zA-z\-_] { return invalidToken("Invalid directive"); }
"." [a-zA-z\-_] [a-zA-z0-9\-_]* { return invalidToken("Invalid directive"); } "." [a-zA-z\-_] [a-zA-z0-9\-_]* { return invalidToken("Invalid directive"); }
. { return invalidToken("Invalid text"); } [^] { return invalidToken("Invalid text"); }
} }

View File

@ -40,6 +40,7 @@ import org.junit.Test;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -158,7 +159,7 @@ public class LexerTest {
if (smaliStream == null) { if (smaliStream == null) {
Assert.fail("Could not load " + smaliFile); Assert.fail("Could not load " + smaliFile);
} }
smaliFlexLexer lexer = new smaliFlexLexer(smaliStream); smaliFlexLexer lexer = new smaliFlexLexer(new InputStreamReader(smaliStream));
lexer.setSourceFile(new File(test + ".smali")); lexer.setSourceFile(new File(test + ".smali"));
lexer.setSuppressErrors(true); lexer.setSuppressErrors(true);

View File

@ -68,7 +68,7 @@ public class ClassFileNameHandler {
public ClassFileNameHandler(File path, String fileExtension) { public ClassFileNameHandler(File path, String fileExtension) {
this.top = new DirectoryEntry(path); this.top = new DirectoryEntry(path);
this.fileExtension = fileExtension; this.fileExtension = fileExtension;
this.modifyWindowsReservedFilenames = testForWindowsReservedFileNames(path); this.modifyWindowsReservedFilenames = isWindows();
} }
// for testing // for testing
@ -229,27 +229,8 @@ public class ClassFileNameHandler {
return sb.toString(); return sb.toString();
} }
private static boolean testForWindowsReservedFileNames(File path) { private static boolean isWindows() {
String[] reservedNames = new String[]{"aux", "con", "com1", "com9", "lpt1", "com9"}; return System.getProperty("os.name").startsWith("Windows");
for (String reservedName: reservedNames) {
File f = new File(path, reservedName + ".smali");
if (f.exists()) {
continue;
}
try {
FileWriter writer = new FileWriter(f);
writer.write("test");
writer.flush();
writer.close();
f.delete(); //doesn't throw IOException
} catch (IOException ex) {
//if an exception occurred, it's likely that we're on a windows system.
return true;
}
}
return false;
} }
private static Pattern reservedFileNameRegex = Pattern.compile("^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\\..*)?$", private static Pattern reservedFileNameRegex = Pattern.compile("^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\\..*)?$",