From: crawshaw Date: Tue, 23 Nov 2004 15:10:33 +0000 (+0000) Subject: fix multiple bugs and add package support. compiler can now compile itself X-Git-Url: http://git.megacz.com/?p=org.ibex.tool.git;a=commitdiff_plain;h=f421ead1069fcf2dbb959db93202d458dc3ee70f fix multiple bugs and add package support. compiler can now compile itself darcs-hash:20041123151033-2eb37-25eec6ed371db0c75157813d9da49e13af0b4927.gz --- diff --git a/src/java/org/ibex/tool/Compiler.java b/src/java/org/ibex/tool/Compiler.java index 4ab50be..08a399a 100644 --- a/src/java/org/ibex/tool/Compiler.java +++ b/src/java/org/ibex/tool/Compiler.java @@ -21,47 +21,134 @@ import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; public class Compiler { + // Static Entry Point ///////////////////////////////////////////////////// + + public static void main(String[] args) { + String source = null, target = null; + String srcdir = null, blddir = null; + + for (int i=0; i < args.length; i++) { + if (args[i].charAt(0) == '-') { + if (args[i].length() == 1) { + System.out.println("Illegal switch: -"); return; } + switch (args[i].charAt(1)) { + case '-': + if (args[i].equals("--help")) printHelp(); + else System.out.println("Unknown switch: -"); + return; + case 'd': + if (i == args.length - 1) { + System.out.println("Missing parameter: "+args[i]); return; } + blddir = args[++i]; + break; + case 's': + if (i == args.length - 1) { + System.out.println("Missing parameter: "+args[i]); return; } + source = args[++i]; + break; + case 't': + if (i == args.length - 1) { + System.out.println("Missing parameter: "+args[i]); return; } + target = args[++i]; + break; + case 'h': + printHelp(); return; + + } + } else srcdir = args[i]; + } + + Compiler c = new Compiler(); + if (blddir != null) c.setBuildDir(blddir); + if (srcdir != null) c.setSourceDir(srcdir); + if (source != null) c.setSource(source); + if (target != null) c.setTarget(target); + c.compile(); + } + private static void printHelp() { + System.out.println("Usage java -cp ... org.ibex.tool.Compiler "); + System.out.println("Options:"); + System.out.println(" -d Location for generated class files."); + System.out.println(" -s Compile with specified source compatibility."); + System.out.println(" -t Compile with specified class file compatibility."); + System.out.println(" -h or --help Print this message."); + System.out.println(""); + } + + + // Compiler Interface ///////////////////////////////////////////////////// + private ClassLoader loader = ClassLoader.getSystemClassLoader(); private Map loaded = new HashMap(); - private Writer out = new PrintWriter(System.out); + private PrintWriter out = new PrintWriter(System.out); private Preprocessor preprocessor = new Preprocessor(null, null, Collections.EMPTY_LIST); private Source[] sources; - private ICompilationUnit[] units; + private File builddir = new File("."); + private File sourcedir = new File("."); - public static void main(String[] args) { - new Compiler(args); - } + public Compiler() { } - public Compiler(String[] files) { - sources = new Source[files.length]; - units = new ICompilationUnit[files.length]; + public void setBuildDir(String dir) { builddir = new File(dir == null ? "." : dir); } + public void setSourceDir(String dir) { sourcedir = new File(dir == null ? "." : dir); } - for (int i=0; i < files.length; i++) { - char[][] n = classname(files[i]); - sources[i] = new Source(new File(files[i]), name(n), pack(n)); - units[i] = sources[i].unit; - } + /** Pass CompilerOptions.VERSION_1_*. A String of form "1.1", ".2", etc. */ + public void setSource(String v) { settings.put(CompilerOptions.OPTION_Source, v); } + + /** Pass CompilerOptions.VERSION_1_*. A String of form "1.1", ".2", etc. */ + public void setTarget(String v) { settings.put(CompilerOptions.OPTION_TargetPlatform, v); } + + public void setBuilddir(File f) { builddir = f; } + public void compile() { + List s = new ArrayList(); + filterSources(s, sourcedir, new char[0][]); + System.out.println("working with "+s.size() +" sources"); + sources = new Source[s.size()]; s.toArray(sources); + ICompilationUnit[] units = new ICompilationUnit[s.size()]; + for (int i=0; i < sources.length; i++) units[i] = sources[i].unit; + + System.out.println("compiling"); org.eclipse.jdt.internal.compiler.Compiler jdt = new org.eclipse.jdt.internal.compiler.Compiler( env, policy, settings, results, problems); jdt.compile(units); } + private final FilenameFilter filterSrcs = new FilenameFilter() { + public boolean accept(File dir, String name) { return name.endsWith(".java"); } + }; + private final FileFilter filterDirs = new FileFilter() { + public boolean accept(File path) { return path.isDirectory(); } + }; + private void filterSources(List s, File dir, char[][] pack) { + File[] ja = dir.listFiles(filterSrcs); + for (int i=0; i < ja.length; i++) + s.add(new Source(ja[i], name(classname(ja[i].getName())), pack)); + + File[] d = dir.listFiles(filterDirs); + for (int i=0; i < d.length; i++) { + char[][] newpack = new char[pack.length + 1][]; + for (int j=0; j < pack.length; j++) newpack[j] = pack[j]; + newpack[pack.length] = d[i].getName().toCharArray(); + filterSources(s, d[i], newpack); + } + } + /** Represents a file to be compiled. */ final class Source { + char[] fileName; char[] n; char[][] p; File orig; char[] processed = null; byte[] compiled = null; - ICompilationUnit unit = new ICompilationUnit() { + final ICompilationUnit unit = new ICompilationUnit() { public char[] getMainTypeName() { return n; } public char[][] getPackageName() { return p; } - public char[] getFileName() { return orig.getName().toCharArray(); } + public char[] getFileName() { return fileName; } public char[] getContents() { if (processed != null) return processed; @@ -93,7 +180,10 @@ public class Compiler { }; private Source(File o, char[] n, char[][] p) { - orig = o; this.n = n; this.p = p; } + orig = o; this.n = n; this.p = p; + try { fileName = orig.getCanonicalPath().toCharArray(); } // FIXME: dont use full path + catch (IOException e) { fileName = orig.getName().toCharArray(); } + } } // ClassLoader Wrappers /////////////////////////////////////////////////// @@ -118,21 +208,21 @@ public class Compiler { if (Modifier.isFinal(m) && Modifier.isStatic(m)) { try { Class type = f.getType(); - if (type == Boolean.class) { + if (type == Boolean.TYPE) { c = new BooleanConstant(f.getBoolean(null)); - } else if (type == Byte.class) { + } else if (type == Byte.TYPE) { c = new ByteConstant(f.getByte(null)); - } else if (type == Character.class) { + } else if (type == Character.TYPE) { c = new CharConstant(f.getChar(null)); - } else if (type == Double.class) { + } else if (type == Double.TYPE) { c = new DoubleConstant(f.getDouble(null)); - } else if (type == Float.class) { + } else if (type == Float.TYPE) { c = new FloatConstant(f.getFloat(null)); - } else if (type == Integer.class) { + } else if (type == Integer.TYPE) { c = new IntConstant(f.getInt(null)); - } else if (type == Long.class) { + } else if (type == Long.TYPE) { c = new LongConstant(f.getLong(null)); - } else if (type == Short.class) { + } else if (type == Short.TYPE) { c = new ShortConstant(f.getShort(null)); } else if (type == String.class) { c = new StringConstant((String)f.get(null)); @@ -182,6 +272,8 @@ public class Compiler { for (int i=0; i < ex.length; i++) ex[i] = name(exs[i]); desc = descriptor(m.getParameterTypes(), m.getReturnType()); + /*if (new String(desc).indexOf("[") > -1) + System.out.println("method: "+m+", desc="+new String(desc));*/ // DEBUG } public int getModifiers() { return m.getModifiers(); } public char[] getSelector() { return m.getName().toCharArray(); } @@ -245,6 +337,12 @@ public class Compiler { public boolean isMember() { return false; } // FIXME public char[] sourceFileName() { return null; } public char[] getFileName() { return null; } + + public boolean equals(Object o) { + return o == this || super.equals(o) || + (o != null && o instanceof LoadedClass && + c.equals(((LoadedClass)o).c)); + } } @@ -254,13 +352,21 @@ public class Compiler { final INameEnvironment env = new INameEnvironment() { public NameEnvironmentAnswer findType(char[][] c) { return findType(name(c), pack(c)); } public NameEnvironmentAnswer findType(char[] n, char[][] p) { + boolean DEBUG = false; + if (DEBUG) System.out.println("requesting: "+ str(p, '.') + "."+new String(n)); + try { Class c = Class.forName(str(p, '.') + '.' + new String(n)); + if (DEBUG) System.out.println("found class: "+ c); IBinaryType b = (IBinaryType)loaded.get(c); if (b == null) loaded.put(c, b = new LoadedClass(c)); + if (DEBUG) System.out.println("returning "+b+", name="+new String(b.getName())); return new NameEnvironmentAnswer(b); } catch (ClassNotFoundException e) {} + // cut out searches for java.* packages in sources list + if (p.length > 0 && eq(p[0], "java".toCharArray())) return null; + try { for (int i=0; i < sources.length; i++) if (eq(n, sources[i].n) && eq(p, sources[i].p)) @@ -280,7 +386,7 @@ public class Compiler { if (eq(name, sources[i].n) && eq(parent, sources[i].p)) return false; return loader.getResource(parentName + ".class") == null && - loader.getResource(parentName + '/' + name + ".class") == null; + loader.getResource(parentName + '/' + new String(name) + ".class") == null; } public void cleanup() {} }; @@ -301,31 +407,37 @@ public class Compiler { /** Used by compiler for processing compiled classes and their errors. */ private final ICompilerRequestor results = new ICompilerRequestor() { public void acceptResult(CompilationResult result) { + System.out.println("got result: "+result); if (result.hasProblems()) { boolean hasErrors = false; IProblem[] p = result.getProblems(); - try { - for (int i=0; i < p.length; i++) { - if (p[i].isError()) hasErrors = true; - out.write(p[i].getOriginatingFileName()); - out.write(':'); - out.write(p[i].getSourceLineNumber()); - out.write(':'); - out.write(p[i].getMessage()); - } - } catch (IOException e) { - System.out.println("severe: IOException on out"); // FIXME - e.printStackTrace(); + for (int i=0; i < p.length; i++) { + if (p[i].isError()) hasErrors = true; + out.print(p[i].getOriginatingFileName()); + out.print(':'); + out.print(p[i].getSourceLineNumber()); + out.print(':'); + out.println(p[i].getMessage()); } + out.flush(); if (hasErrors) return; } ClassFile[] c = result.getClassFiles(); for (int i=0; i < c.length; i++) { try { - String name = str(c[i].getCompoundName(), '/') + ".class"; + // build package path to new class file + File path = builddir; + char[][] name = c[i].getCompoundName(); + path = new File(builddir, str(pack(name), '/')); + System.out.println("DEBUG: creating path "+path+", out of builddir="+builddir); + if (!path.exists()) path.mkdirs(); + + // write new class file + path = new File(path, new String(name(name)) + ".class"); + System.out.println("DEBUG: writing file "+path); OutputStream o = new BufferedOutputStream( - new FileOutputStream(new File(name))); + new FileOutputStream(path)); o.write(c[i].getBytes()); o.close(); } catch (IOException e) { @@ -359,9 +471,11 @@ public class Compiler { /** Convert class name into a String. */ private static String str(char[][] name, char delim) { StringBuffer b = new StringBuffer(); - if (name != null) for (int i=0; i < name.length; i++) - if (name[i] != null) { b.append(delim); b.append(name[i]); } - if (b.length() > 0) b.deleteCharAt(0); + for (int i=0; name != null && i < name.length; i++) { + if (name[i] == null || name[i].length == 0) continue; + if (i > 0) b.append(delim); + b.append(name[i]); + } return b.toString(); } @@ -410,7 +524,7 @@ public class Compiler { switch (name.charAt(0)) { case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z': case 'V': case '[': - sb.append(name); break; + sb.append(name(p)); break; case 'b': if (name.equals("boolean")) { sb.append('Z'); break; } if (name.equals("byte")) { sb.append('B'); break; }