You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Compiler.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later.
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. */
  15. package sample.preproc;
  16. import java.io.IOException;
  17. import java.io.BufferedReader;
  18. import java.io.FileReader;
  19. import java.io.BufferedWriter;
  20. import java.io.FileWriter;
  21. import java.util.Vector;
  22. import javassist.CannotCompileException;
  23. import javassist.CtClass;
  24. import javassist.ClassPool;
  25. /**
  26. * This is a preprocessor for Java source programs using annotated
  27. * import declarations.
  28. *
  29. * <ul><pre>
  30. * import <i>class-name</i> by <i>assistant-name</i> [(<i>arg1, arg2, ...</i>)]
  31. * </pre></ul>
  32. *
  33. * <p>To process this annotation, run this class as follows:
  34. *
  35. * <ul><pre>
  36. * java sample.preproc.Compiler sample.j
  37. * </pre></ul>
  38. *
  39. * <p>This command produces <code>sample.java</code>, which only includes
  40. * regular import declarations. Also, the Javassist program
  41. * specified by <i>assistant-name</i> is executed so that it produces
  42. * class files under the <code>./tmpjvst</code> directory. The class
  43. * specified by <i>assistant-name</i> must implement
  44. * <code>sample.preproc.Assistant</code>.
  45. *
  46. * @see sample.preproc.Assistant
  47. */
  48. public class Compiler {
  49. protected BufferedReader input;
  50. protected BufferedWriter output;
  51. protected ClassPool classPool;
  52. /**
  53. * Constructs a <code>Compiler</code> with a source file.
  54. *
  55. * @param inputname the name of the source file.
  56. */
  57. public Compiler(String inputname) throws CannotCompileException {
  58. try {
  59. input = new BufferedReader(new FileReader(inputname));
  60. }
  61. catch (IOException e) {
  62. throw new CannotCompileException("cannot open: " + inputname);
  63. }
  64. String outputname = getOutputFilename(inputname);
  65. if (outputname.equals(inputname))
  66. throw new CannotCompileException("invalid source name: "
  67. + inputname);
  68. try {
  69. output = new BufferedWriter(new FileWriter(outputname));
  70. }
  71. catch (IOException e) {
  72. throw new CannotCompileException("cannot open: " + outputname);
  73. }
  74. classPool = ClassPool.getDefault();
  75. }
  76. /**
  77. * Starts preprocessing.
  78. */
  79. public void process() throws IOException, CannotCompileException {
  80. int c;
  81. CommentSkipper reader = new CommentSkipper(input, output);
  82. while ((c = reader.read()) != -1) {
  83. output.write(c);
  84. if (c == 'p') {
  85. if (skipPackage(reader))
  86. break;
  87. }
  88. else if (c == 'i')
  89. readImport(reader);
  90. else if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
  91. break;
  92. }
  93. while ((c = input.read()) != -1)
  94. output.write(c);
  95. input.close();
  96. output.close();
  97. }
  98. private boolean skipPackage(CommentSkipper reader) throws IOException {
  99. int c;
  100. c = reader.read();
  101. output.write(c);
  102. if (c != 'a')
  103. return true;
  104. while ((c = reader.read()) != -1) {
  105. output.write(c);
  106. if (c == ';')
  107. break;
  108. }
  109. return false;
  110. }
  111. private void readImport(CommentSkipper reader)
  112. throws IOException, CannotCompileException
  113. {
  114. int word[] = new int[5];
  115. int c;
  116. for (int i = 0; i < 5; ++i) {
  117. word[i] = reader.read();
  118. output.write(word[i]);
  119. }
  120. if (word[0] != 'm' || word[1] != 'p' || word[2] != 'o'
  121. || word[3] != 'r' || word[4] != 't')
  122. return; // syntax error?
  123. c = skipSpaces(reader, ' ');
  124. StringBuffer classbuf = new StringBuffer();
  125. while (c != ' ' && c != '\t' && c != '\n' && c != '\r'
  126. && c != ';' && c != -1) {
  127. classbuf.append((char)c);
  128. c = reader.read();
  129. }
  130. String importclass = classbuf.toString();
  131. c = skipSpaces(reader, c);
  132. if (c == ';') {
  133. output.write(importclass);
  134. output.write(';');
  135. return;
  136. }
  137. if (c != 'b')
  138. syntaxError(importclass);
  139. reader.read(); // skip 'y'
  140. StringBuffer assistant = new StringBuffer();
  141. Vector args = new Vector();
  142. c = readAssistant(reader, importclass, assistant, args);
  143. c = skipSpaces(reader, c);
  144. if (c != ';')
  145. syntaxError(importclass);
  146. runAssistant(importclass, assistant.toString(), args);
  147. }
  148. void syntaxError(String importclass) throws CannotCompileException {
  149. throw new CannotCompileException("Syntax error. Cannot import "
  150. + importclass);
  151. }
  152. int readAssistant(CommentSkipper reader, String importclass,
  153. StringBuffer assistant, Vector args)
  154. throws IOException, CannotCompileException
  155. {
  156. int c = readArgument(reader, assistant);
  157. c = skipSpaces(reader, c);
  158. if (c == '(') {
  159. do {
  160. StringBuffer arg = new StringBuffer();
  161. c = readArgument(reader, arg);
  162. args.addElement(arg.toString());
  163. c = skipSpaces(reader, c);
  164. } while (c == ',');
  165. if (c != ')')
  166. syntaxError(importclass);
  167. return reader.read();
  168. }
  169. return c;
  170. }
  171. int readArgument(CommentSkipper reader, StringBuffer buf)
  172. throws IOException
  173. {
  174. int c = skipSpaces(reader, ' ');
  175. while ('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
  176. || '0' <= c && c <= '9' || c == '.' || c == '_') {
  177. buf.append((char)c);
  178. c = reader.read();
  179. }
  180. return c;
  181. }
  182. int skipSpaces(CommentSkipper reader, int c) throws IOException {
  183. while (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
  184. if (c == '\n' || c == '\r')
  185. output.write(c);
  186. c = reader.read();
  187. }
  188. return c;
  189. }
  190. /**
  191. * Is invoked if this compiler encoutenrs:
  192. *
  193. * <ul><pre>
  194. * import <i>class name</i> by <i>assistant</i> (<i>args1</i>, <i>args2</i>, ...);
  195. * </pre></ul>
  196. *
  197. * @param classname class name
  198. * @param assistantname assistant
  199. * @param argv args1, args2, ...
  200. */
  201. private void runAssistant(String importname, String assistantname,
  202. Vector argv)
  203. throws IOException, CannotCompileException
  204. {
  205. Class assistant;
  206. Assistant a;
  207. int s = argv.size();
  208. String[] args = new String[s];
  209. for (int i = 0; i < s; ++i)
  210. args[i] = (String)argv.elementAt(i);
  211. try {
  212. assistant = Class.forName(assistantname);
  213. }
  214. catch (ClassNotFoundException e) {
  215. throw new CannotCompileException("Cannot find " + assistantname);
  216. }
  217. try {
  218. a = (Assistant)assistant.newInstance();
  219. }
  220. catch (Exception e) {
  221. throw new CannotCompileException(e);
  222. }
  223. CtClass[] imports = a.assist(classPool, importname, args);
  224. s = imports.length;
  225. if (s < 1)
  226. output.write(" java.lang.Object;");
  227. else {
  228. output.write(' ');
  229. output.write(imports[0].getName());
  230. output.write(';');
  231. for (int i = 1; i < s; ++i) {
  232. output.write(" import ");
  233. output.write(imports[1].getName());
  234. output.write(';');
  235. }
  236. }
  237. }
  238. private String getOutputFilename(String input) {
  239. int i = input.lastIndexOf('.');
  240. if (i < 0)
  241. i = input.length();
  242. return input.substring(0, i) + ".java";
  243. }
  244. public static void main(String[] args) {
  245. if (args.length > 0)
  246. try {
  247. Compiler c = new Compiler(args[0]);
  248. c.process();
  249. }
  250. catch (IOException e) {
  251. System.err.println(e);
  252. }
  253. catch (CannotCompileException e) {
  254. System.err.println(e);
  255. }
  256. else {
  257. System.err.println("Javassist version " + CtClass.version);
  258. System.err.println("No source file is specified.");
  259. }
  260. }
  261. }
  262. class CommentSkipper {
  263. private BufferedReader input;
  264. private BufferedWriter output;
  265. public CommentSkipper(BufferedReader reader, BufferedWriter writer) {
  266. input = reader;
  267. output = writer;
  268. }
  269. public int read() throws IOException {
  270. int c;
  271. while ((c = input.read()) != -1)
  272. if (c != '/')
  273. return c;
  274. else {
  275. c = input.read();
  276. if (c == '/')
  277. skipCxxComments();
  278. else if (c == '*')
  279. skipCComments();
  280. else
  281. output.write('/');
  282. }
  283. return c;
  284. }
  285. private void skipCxxComments() throws IOException {
  286. int c;
  287. output.write("//");
  288. while ((c = input.read()) != -1) {
  289. output.write(c);
  290. if (c == '\n' || c == '\r')
  291. break;
  292. }
  293. }
  294. private void skipCComments() throws IOException {
  295. int c;
  296. boolean star = false;
  297. output.write("/*");
  298. while ((c = input.read()) != -1) {
  299. output.write(c);
  300. if (c == '*')
  301. star = true;
  302. else if(star && c == '/')
  303. break;
  304. else
  305. star = false;
  306. }
  307. }
  308. }