soc.2012.android: e5c3faab: Added new ant rule that lets you extract...
michael at soc.pidgin.im
michael at soc.pidgin.im
Tue May 22 07:27:41 EDT 2012
----------------------------------------------------------------------
Revision: e5c3faab901ad36a96095fb8b006b5b839fe1f81
Parent: fc4081da0e84578be6b452a0bbc5d614d0106b65
Author: michael at soc.pidgin.im
Date: 05/22/12 07:14:31
Branch: im.pidgin.soc.2012.android
URL: http://d.pidgin.im/viewmtn/revision/info/e5c3faab901ad36a96095fb8b006b5b839fe1f81
Changelog:
Added new ant rule that lets you extract constants out of C files to be used by the java compiler.
Changes against parent fc4081da0e84578be6b452a0bbc5d614d0106b65
added android/workspace/im.pidgin.libpurple.build/src/im
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/ConstantExtractor.java
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/ConstantName.java
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/EnumItem.java
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/EnumName.java
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/EnumObject.java
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/ExtractConstants.java
added android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/ExtractorException.java
patched android/workspace/im.pidgin.libpurple.build/buildscripts/common.ant
-------------- next part --------------
============================================================
--- android/workspace/im.pidgin.libpurple.build/buildscripts/common.ant 3ae9a25edbffbbd20cad7cd6e17b10109cffa89e
+++ android/workspace/im.pidgin.libpurple.build/buildscripts/common.ant 3200e495859027e26387dd06be71633f981d9180
@@ -18,10 +18,9 @@
<property name="libpurple.downloads" location="${build.base}/downloads" />
<property name="libpurple.build" location="${build.base}/build" />
<property name="libpurple.prefix" location="${build.base}/build/prefix" />
- <property name="pidgin.base" value="${build.base}/../../../"/>
+ <property name="pidgin.base" location="${build.base}/../../../"/>
+ <property name="ndk.bin" location="${ndk.root}/bin"/>
-
-
<property name="libffi.version" value="3.0.11" />
<property name="gettext.version" value="0.18.1.1" />
<property name="libiconv.version" value="1.14" />
@@ -146,6 +145,14 @@
<taskdef resource="net/sf/antcontrib/antlib.xml">
</taskdef>
+
+ <path id="bin">
+ <pathelement path="${build.base}/bin"/>
+ </path>
+
+ <taskdef name="extractconstants" classpathref="bin" classname="im.pidgin.libpurple.build.constants.ExtractConstants"></taskdef>
+ <taskdef name="enum" classpathref="bin" classname="im.pidgin.libpurple.build.constants.EnumName"></taskdef>
+ <taskdef name="constant" classpathref="bin" classname="im.pidgin.libpurple.build.constants.ConstantName"></taskdef>
</target>
</project>
============================================================
--- /dev/null
+++ android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/ConstantExtractor.java b366175274d7fc88396a2ad956e380f47535c7de
@@ -0,0 +1,145 @@
+package im.pidgin.libpurple.build.constants;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.Hashtable;
+import java.util.Scanner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This is the main constant extractor class, that does all the work.
+ *
+ * @author michaelz
+ *
+ */
+public class ConstantExtractor {
+ private static final String DEFINE_LINE = "#define\\s+(\\w+)[ \\t]+([^\\n]*)";
+ private static final Pattern ENUM_OR_DEFINE = Pattern.compile("("
+ + DEFINE_LINE + ")|(" + EnumObject.ENUM_PATTERN_STRING + ")");
+ private static final Pattern DEFINE_PATTERN = Pattern.compile(DEFINE_LINE);
+
+ private final Hashtable<String, EnumObject> enums = new Hashtable<String, EnumObject>();
+ private final Hashtable<String, Integer> foundIntConstants = new Hashtable<String, Integer>();
+ private final Hashtable<String, String> foundStringConstants = new Hashtable<String, String>();
+
+ public ConstantExtractor() {
+ }
+
+ public void parseFile(File input) throws ExtractorException {
+ Scanner scanner;
+ try {
+ scanner = new Scanner(new FileInputStream(input));
+ } catch (FileNotFoundException e) {
+ throw new ExtractorException(e);
+ }
+ String found;
+ while (null != (found = scanner.findWithinHorizon(ENUM_OR_DEFINE, 0))) {
+ Matcher defineMatcher = DEFINE_PATTERN.matcher(found);
+ if (defineMatcher.matches()) {
+ foundDefine(defineMatcher.group(1), defineMatcher.group(2));
+ } else {
+ foundEnum(found);
+ }
+ }
+ }
+
+ private void foundEnum(String found) {
+ final EnumObject enumObj = new EnumObject(found);
+
+ enums.put(enumObj.getName(), enumObj);
+ }
+
+ /**
+ * Called when a definition was found
+ *
+ * @param name
+ * The name
+ * @param value
+ * The value as String (like in Source)
+ * @throws ExecuteException
+ */
+ private void foundDefine(String name, String value) {
+ try {
+ int intValue = Integer.parseInt(value);
+ foundIntConstants.put(name, intValue);
+ } catch (NumberFormatException e) {
+ String stringValue = getStringValue(value);
+ foundStringConstants.put(name, stringValue);
+ }
+
+ }
+
+ /**
+ * Converts a Source string to a real java string
+ *
+ * @param value
+ * The value in the source which has
+ * " on the start/end. e.g.: "xyz\u0032"
+ * @return A real java String.
+ * @throws StringFormatException
+ */
+ private String getStringValue(String withQuotes) {
+ if (!(withQuotes.startsWith("\"") && withQuotes.endsWith("\""))) {
+ throw new RuntimeException("String " + withQuotes
+ + " is not quoted.");
+ }
+ String value = withQuotes.substring(1, withQuotes.length() - 1);
+
+ Pattern p = Pattern
+ .compile("\\(?:([btnfr\"\'\\])|u([\\dA-Fa-f]{4})|([0-3]?[0-7]{1,2}))");
+ Matcher matcher = p.matcher(value);
+ while (matcher.find()) {
+ char replacement;
+ if (!matcher.group(1).isEmpty()) {
+ replacement = getUnescapedSequence(matcher.group(1));
+ } else if (!matcher.group(2).isEmpty()) {
+ int asInt = Integer.parseInt(matcher.group(2), 16);
+ if (asInt > Character.MAX_VALUE) {
+ throw new RuntimeException(withQuotes
+ + " contains illegal unicode definition");
+ }
+ replacement = (char) asInt;
+ } else if (!matcher.group(3).isEmpty()) {
+ replacement = (char) Integer.parseInt(matcher.group(3), 8);
+ } else {
+ replacement = ' ';
+ }
+ value = value.substring(0, matcher.start())
+ + Character.toString(replacement)
+ + value.substring(matcher.end());
+ }
+
+ return value;
+ }
+
+ private static char getUnescapedSequence(String group) {
+ if ("b".equals(group)) {
+ return '\b';
+ } else if ("t".equals(group)) {
+ return '\t';
+ } else if ("n".equals(group)) {
+ return '\n';
+ } else if ("f".equals(group)) {
+ return '\f';
+ } else if ("r".equals(group)) {
+ return '\r';
+ } else {
+ return group.charAt(0);
+ }
+ }
+
+ public EnumObject getEnum(String enumName) {
+ return enums.get(enumName);
+ }
+
+ public String getStringConstant(String enumName) {
+ return foundStringConstants.get(enumName);
+ }
+
+ public int getIntegerConstant(String enumName) {
+ return foundIntConstants.get(enumName);
+ }
+
+}
============================================================
--- /dev/null
+++ android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/ConstantName.java 0920055c401740013bdca767757fdeea3b3901d4
@@ -0,0 +1,22 @@
+package im.pidgin.libpurple.build.constants;
+
+/**
+ * This is a class for the ant <constant name=.../> tag.
+ *
+ * @author michaelz
+ *
+ */
+public class ConstantName {
+ private String name = "";
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void execute() {
+ }
+}
============================================================
--- /dev/null
+++ android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/EnumItem.java 387ef5a94d039c35a23450bf553875ecc6c1eefc
@@ -0,0 +1,31 @@
+package im.pidgin.libpurple.build.constants;
+
+/**
+ * This is a item of an enum.
+ * @author michaelz
+ *
+ */
+public class EnumItem {
+ private final String name;
+ private final int value;
+
+ public EnumItem(String name, int value) {
+ super();
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+}
============================================================
--- /dev/null
+++ android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/EnumName.java c8ead1fb94e9111a9e330592bf656849a917fd5a
@@ -0,0 +1,21 @@
+package im.pidgin.libpurple.build.constants;
+
+/**
+ * This is a class for the ant <enum name=.../> tag.
+ *
+ * @author michaelz
+ *
+ */
+public class EnumName {
+ private String name = "";
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void execute() {}
+}
============================================================
--- /dev/null
+++ android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/EnumObject.java 29fe374c35a22922025c3f25a19cd79d1e8353f6
@@ -0,0 +1,108 @@
+package im.pidgin.libpurple.build.constants;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This is a enum from a C file
+ * @author michaelz
+ *
+ */
+public class EnumObject {
+ private static final String ITEM_PATTERN_STRING = "\\s*(\\w+)\\s*(?:=\\s*(-?\\d+|0x[\\da-fA-F]+)\\s*)?";
+ private static final Pattern ITEM_PATTERN = Pattern.compile(
+ ITEM_PATTERN_STRING);
+ private static final String IGNORED_ENUM_PARTS = "/\\*[\\s\\S]*?\\*/|//[^\\n]*";
+ public static final String ENUM_PATTERN_STRING =
+ "\\s*typedef\\s+enum\\s+\\{\\s*([^\\}]*?)\\s*,?\\s*\\}\\s*(\\w+)\\s*;";
+ private static final Pattern ENUM_PATTERN = Pattern.compile(ENUM_PATTERN_STRING);
+ private String name;
+ private EnumItem[] items;
+ private String commonString;
+
+ public EnumObject(String enumSource) {
+ String uncommentedSource = enumSource.replaceAll(IGNORED_ENUM_PARTS, "");
+ Matcher m =
+ ENUM_PATTERN.matcher(
+ uncommentedSource);
+ if (!m.matches()) {
+ throw new IllegalArgumentException(
+ "Input does not match outer enum pattern (typedef enum {...} <name>)");
+ }
+ name = m.group(2);
+ String[] content = m.group(1).split(",");
+ items = new EnumItem[content.length];
+ int nextValue = 0;
+ for (int i = 0; i < content.length; i++) {
+ Matcher m2 =
+ ITEM_PATTERN
+ .matcher(content[i]);
+ if (!m2.matches()) {
+ throw new IllegalArgumentException("Enum constant " + i
+ + " does not match expected item regexp. Got: "
+ + content[i]);
+ }
+ String valueString = m2.group(2);
+ if (valueString != null && !valueString.isEmpty()) {
+ nextValue =
+ valueString.startsWith("0x") ? Integer.parseInt(
+ valueString.substring(2), 16) : Integer
+ .parseInt(valueString);
+ }
+ items[i] = new EnumItem(m2.group(1), nextValue);
+ nextValue++;
+ }
+
+ String commonString = computeCommonString(content);
+ this.commonString = commonString;
+ }
+
+ private String computeCommonString(String[] content) {
+ String commonString;
+ if (content.length > 0) {
+ commonString = items[0].getName();
+ for (int i = 1; i < items.length; i++) {
+ commonString = getCommonStart(items[i].getName(), commonString);
+ }
+ } else {
+ commonString = "";
+ }
+ return commonString;
+ }
+
+ private static String getCommonStart(String string, String string2) {
+ int end = Math.min(string.length(), string2.length());
+ for (int i = 0; i < end; i++) {
+ if (string.charAt(i) != string2.charAt(i)) {
+ return string.substring(0, i);
+ }
+ }
+ return string.substring(0, end);
+ }
+
+ /**
+ * Gets the name of the enum.
+ * @return The name as declared in the C file
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * gets the items of the enum as array.
+ * @return All items as array.
+ */
+ public EnumItem[] getItems() {
+ return items;
+ }
+
+ /**
+ * Gets a shorter version of the item name
+ * @param item The item index
+ * @return The name with the common part for this enum stripped.
+ */
+ public String getNiceItemName(int item) {
+ return items[item].getName().substring(commonString.length());
+ }
+
+}
============================================================
--- /dev/null
+++ android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/ExtractConstants.java 53d710d594d5f93298083c72aa5e335941797f77
@@ -0,0 +1,104 @@
+package im.pidgin.libpurple.build.constants;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.LinkedList;
+
+public class ExtractConstants {
+
+ private String input = "";
+ private String output = "";
+
+ private final LinkedList<ConstantName> constants = new LinkedList<ConstantName>();
+ private final LinkedList<EnumName> enums = new LinkedList<EnumName>();
+ private String packageString = "";
+
+
+ public void setInput(String input) {
+ this.input = input;
+
+ }
+
+ public void setOutput(String output) {
+ this.output = output;
+ }
+
+ public void setPackage(String packageString) {
+ this.packageString = packageString;
+ }
+
+ public ConstantName createConstant() {
+ ConstantName name = new ConstantName();
+ constants.add(name);
+ return name;
+ }
+
+ public EnumName createEnum() {
+ EnumName name = new EnumName();
+ enums.add(name);
+ return name;
+ }
+
+ /**
+ * This method is called by ant to execute this build item.
+ * @throws ExtractorException
+ */
+ public void execute() throws ExtractorException {
+ File in = new File(input);
+
+ File out = new File(output);
+
+ ConstantExtractor extractor = new ConstantExtractor();
+
+ extractor.parseFile(in);
+
+ PrintWriter writer;
+ try {
+ writer = new PrintWriter(out);
+ } catch (FileNotFoundException e) {
+ throw new ExtractorException(e.getMessage());
+ }
+
+ writeFileHeader(writer);
+
+ for (EnumName name : enums) {
+ EnumObject e = extractor.getEnum(name.getName());
+ if (e == null) {
+ throw new ExtractorException("Enum " + name.getName() + " not found.");
+ }
+
+ for (EnumItem item : e.getItems()) {
+ String itemName = item.getName();
+ int value = item.getValue();
+ writeIntConstant(writer, itemName, value);
+ }
+ }
+
+ for (ConstantName name : constants) {
+ int value = extractor.getIntegerConstant(name.getName());
+ writeIntConstant(writer, name.getName(), value);
+ }
+ writeFooter(writer);
+ writer.close();
+ }
+
+ private void writeFileHeader(PrintWriter writer) {
+ if (!packageString.isEmpty()) {
+ writer.println("package " + packageString + ";");
+ }
+ writer.println();
+ String className = new File(output).getName().replaceAll("\\.java$", "");
+ writer.println("public final class " + className + " {");
+ writer.println("\tprivate " + className + "() {}");
+ writer.println();
+ }
+
+ private void writeIntConstant(PrintWriter writer, String itemName, int value) {
+ writer.println("\tpublic static final int " + itemName + " = " + value + ";\n");
+ }
+
+ private void writeFooter(PrintWriter writer) {
+ writer.println("}");
+ }
+}
============================================================
--- /dev/null
+++ android/workspace/im.pidgin.libpurple.build/src/im/pidgin/libpurple/build/constants/ExtractorException.java 0b71f52fe428caf493a9b76897479e6d64c53265
@@ -0,0 +1,37 @@
+package im.pidgin.libpurple.build.constants;
+
+/**
+ * This exception is thrown if something during the neum extraction process goes
+ * wrong.
+ *
+ * @author michaelz
+ *
+ */
+public class ExtractorException extends Exception {
+
+ public ExtractorException() {
+ // TODO Auto-generated constructor stub
+ }
+
+ public ExtractorException(String message) {
+ super(message);
+ // TODO Auto-generated constructor stub
+ }
+
+ public ExtractorException(Throwable cause) {
+ super(cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ public ExtractorException(String message, Throwable cause) {
+ super(message, cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ public ExtractorException(String message, Throwable cause,
+ boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ // TODO Auto-generated constructor stub
+ }
+
+}
More information about the Commits
mailing list