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