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