gitweb on Svarog

projekti pod git sistemom za održavanje verzija -- projects under the git version control system
mjc2wsl - proper processing of the cond jumps
[mjc2wsl.git] / src / mjc2wsl.java
1 import java.io.*;
2 import java.util.*;
4 /**
5 * This program converts file from compiled MicroJava bytecode to WSL language
6 * which is a part of the FermaT Transformation system. MicroJava is a subset
7 * used in Compiler Construction courses by Hanspeter Moessenboeck, not
8 * "Java ME".
9 *
10 * @author Doni Pracner, http://perun.dmi.rs/pracner http://quemaster.com
11 */
12 public class mjc2wsl{
13 public static String versionN = "0.1.2";
15 /** Constant used for marking a regular comment from the original file */
16 public static final char C_REG = ' ';
17 /**
18 * Constant used for marking when original code is inserted in the file,
19 * next to the translations
20 */
21 public static final char C_OC = '#';
22 /** Constant used for marking special messages from the translator */
23 public static final char C_SPEC = '&';
24 /** Constant used for marking error messages from the translator */
25 public static final char C_ERR = '!';
27 /** instruction code in MicroJava bytecode. */
28 public static final int
29 load = 1,
30 load_0 = 2,
31 load_1 = 3,
32 load_2 = 4,
33 load_3 = 5,
34 store = 6,
35 store_0 = 7,
36 store_1 = 8,
37 store_2 = 9,
38 store_3 = 10,
39 getstatic = 11,
40 putstatic = 12,
41 getfield = 13,
42 putfield = 14,
43 const_0 = 15,
44 const_1 = 16,
45 const_2 = 17,
46 const_3 = 18,
47 const_4 = 19,
48 const_5 = 20,
49 const_m1 = 21,
50 const_ = 22,
51 add = 23,
52 sub = 24,
53 mul = 25,
54 div = 26,
55 rem = 27,
56 neg = 28,
57 shl = 29,
58 shr = 30,
59 inc = 31,
60 new_ = 32,
61 newarray = 33,
62 aload = 34,
63 astore = 35,
64 baload = 36,
65 bastore = 37,
66 arraylength = 38,
67 pop = 39,
68 dup = 40,
69 dup2 = 41,
70 jmp = 42,
71 jeq = 43,
72 jne = 44,
73 jlt = 45,
74 jle = 46,
75 jgt = 47,
76 jge = 48,
77 call = 49,
78 return_ = 50,
79 enter = 51,
80 exit = 52,
81 read = 53,
82 print = 54,
83 bread = 55,
84 bprint = 56,
85 trap = 57;
87 public String getStandardStart(){
88 StringBuilder ret = new StringBuilder(
89 "C:\" This file automatically converted from microjava bytecode\";\n"
90 +"C:\" with mjc2wsl v "+versionN+"\";\n");
92 ret.append("VAR < tempa := 0, tempb := 0, tempres :=0,\n");
93 for (int i = 0; i <= 3; i++)
94 ret.append("loc" + i + " := 0, ");
95 ret.append("\n estack := < >, t_e_m_p := 0 > :");
97 return ret.toString();
98 }
100 public String getStandardEnd(){
101 return "SKIP\nENDVAR";
104 private boolean originalInComments = false;
106 private InputStream mainIn;
107 private PrintWriter out = null;
108 private int counter = -1;
110 private void pr(int i){
111 out.print(i);
114 private void pr(char i){
115 out.print(i);
118 private void pr(String i){
119 out.print(i);
122 private void prl(String i){
123 out.println(i);
126 private int get() {
127 int res = -1;
128 try {
129 res = mainIn.read();
130 if (res >= 0)
131 res = res << 24 >>> 24;
132 } catch (IOException ex) {
133 ex.printStackTrace();
135 counter++;
136 return res;
139 private int get2() {
140 return (get() * 256 + get()) << 16 >> 16;
143 private int get4() {
144 return (get2() << 16) + (get2() << 16 >>> 16);
147 private String loc(int i){
148 return "loc" + i;
151 /**
152 * Creates a WSL comment with care to quote chars.
153 */
154 public static String createComment(String str){
155 return createComment(str, C_REG);
158 /**
159 * Creates a WSL comment with care to quote chars, of the
160 * given type. Types are given as char constants. They can be
161 * default comments, comments that contain the original code
162 * in them, or additional comments regarding the translation
163 * process.
164 */
165 public static String createComment(String str, char type) {
166 return "C:\"" + type + str.replace("\"", "''") + "\";";
169 private String cmdToEStack(int i) {
170 return "estack := <" + i + " > ++ estack;";
173 private String cmdToEStack(String i) {
174 return "estack := <" + i + " > ++ estack;";
177 private String cmdFromEStack(String st) {
178 return st + " := HEAD(estack); estack := TAIL(estack);";
181 private String getTopTwo(){
182 return cmdFromEStack("tempa") + "\n" + cmdFromEStack("tempb");
185 private String getTop() {
186 return cmdFromEStack("tempa");
189 private String getRelationFor(int opcode) throws Exception {
190 switch (opcode) {
191 case jeq: return "=";
192 case jne: return "#";
193 case jlt: return "<";
194 case jle: return "<=";
195 case jgt: return ">";
196 case jge: return ">=";
198 throw new Exception("Wrong opcode for a relation");
201 public void convertStream(InputStream ins) throws Exception{
202 mainIn = ins;
203 //skip start TODO make better
204 for (int i = 0; i < 14; i++)
205 get();
207 prl(getStandardStart());
208 prl("SKIP;\n ACTIONS A_S_start:\n A_S_start == CALL a14 END");
209 int op = get();
210 while (op >= 0) {
211 if (originalInComments)
212 prl(createComment("" + op, C_OC));
213 prl("a" + counter + " == ");
214 switch (op) {
215 case load: {
216 prl(cmdToEStack(loc(get())));
217 break;
219 case load_0:
220 case load_1:
221 case load_2:
222 case load_3: {
223 prl(cmdToEStack(loc(op - load_0)));
224 break;
226 case store: {
227 prl(cmdFromEStack(loc(get())));
228 break;
230 case store_0:
231 case store_1:
232 case store_2:
233 case store_3: {
234 prl(cmdFromEStack(loc(op - store_0)));
235 break;
237 case const_: {
238 prl(cmdToEStack(get4()));
239 break;
242 case const_0:
243 case const_1:
244 case const_2:
245 case const_3:
246 case const_4:
247 case const_5: {
248 prl(cmdToEStack(op - const_0));
249 break;
252 case jmp: {
253 prl("CALL a" + (counter + get2()) + ";");
254 break;
257 case jeq:
258 case jne:
259 case jlt:
260 case jle:
261 case jgt:
262 case jge: {
263 prl(getTopTwo());
264 prl("IF tempb "+ getRelationFor(op)
265 +" tempa THEN CALL a" + (counter + get2())
266 + " FI;");
267 break;
270 case add: {
271 prl(getTopTwo());
272 prl("tempres := tempb + tempa;");
273 prl(cmdToEStack("tempres"));
274 break;
276 case div: {
277 prl(getTopTwo());
278 prl("tempres := tempb / tempa;");
279 prl(cmdToEStack("tempres"));
280 break;
283 case enter: {
284 prl(createComment("enter not fully procesed yet"));
285 get();
286 get();
287 break;
289 case return_: {
290 prl(createComment("return not fully procesed yet"));
291 break;
293 case exit: {
294 prl(createComment("exit not fully procesed yet"));
295 break;
298 // the prints
299 case bprint: {
300 prl(getTopTwo());
301 prl("PRINT(tempb);");
302 break;
304 case print: {
305 // TODO need to make it a char
306 prl(getTopTwo());
307 prl("PRINT(tempb);");
308 break;
310 default:
311 prl(createComment("unknown op error: " + op, C_ERR));
312 break;
315 op = get();
316 if (op >= 0)
317 prl("CALL a" + counter + " END");
319 prl("CALL Z;\nSKIP END\nENDACTIONS;\n");
320 prl(getStandardEnd());
324 public void convertFile(File f) {
325 try {
326 convertStream(new FileInputStream(f));
327 } catch (Exception ex) {
328 ex.printStackTrace();
332 public void printHelp() {
333 System.out.println("MicroJava bytecode to WSL converter. v " + versionN
334 + ", by Doni Pracner");
335 System.out.println("usage:\n\t {options} mjc2wsl filename [outfile]");
336 System.out.println("options:\n\t--screen print output to screen");
337 System.out.println("\t-o --oc include original code in comments");
340 public String makeDefaultOutName(String inname){
341 String rez = inname;
342 if (inname.endsWith(".obj"))
343 rez = rez.substring(0, rez.length() - 4);
344 return rez + ".wsl";
347 public void run(String[] args) {
348 if (args.length == 0) {
349 printHelp();
350 } else {
351 int i = 0;
352 while (i < args.length && args[i].charAt(0) == '-') {
353 if (args[i].compareTo("-h") == 0) {
354 printHelp();
355 return;
356 } else if (args[i].compareTo("-o") == 0
357 || args[i].startsWith("--oc")) {
358 if (args[i].length() == 2)
359 originalInComments = true;
360 else if (args[i].length() == 5)
361 originalInComments = args[i].charAt(4) == '+';
362 else
363 originalInComments = true;
364 } else if (args[i].startsWith("--screen")) {
365 out = new PrintWriter(System.out);
367 i++;
370 if (i >= args.length) {
371 System.out.println("no filename supplied");
372 System.exit(2);
374 File f = new File(args[i]);
376 if (i + 1 < args.length) {
377 try {
378 out = new PrintWriter(args[i + 1]);
379 } catch (Exception e) {
380 System.err.println("error in opening out file:");
381 e.printStackTrace();
384 if (out == null) {
385 // if not set to screen, or a file, make a default filename
386 try {
387 out = new PrintWriter(makeDefaultOutName(args[i]));
388 } catch (Exception e) {
389 System.err.println("error in opening out file:");
390 e.printStackTrace();
393 if (f.exists()) {
394 Calendar now = Calendar.getInstance();
395 convertFile(f);
396 long mili = Calendar.getInstance().getTimeInMillis()
397 - now.getTimeInMillis();
398 System.out.println("conversion time:" + mili + " ms");
399 out.close();
400 } else
401 System.out.println("file does not exist");
405 public static void main(String[] args) {
406 new mjc2wsl().run(args);
Svarog.pmf.uns.ac.rs/gitweb maintanance Doni Pracner