gitweb on Svarog

projekti pod git sistemom za održavanje verzija -- projects under the git version control system
b807bc8d7be03f539ead619073a336d996f9af3d
[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 sub: {
277 prl(getTopTwo());
278 prl("tempres := tempb - tempa;");
279 prl(cmdToEStack("tempres"));
280 break;
282 case mul: {
283 prl(getTopTwo());
284 prl("tempres := tempb * tempa;");
285 prl(cmdToEStack("tempres"));
286 break;
288 case div: {
289 prl(getTopTwo());
290 prl("IF tempa = 0 THEN ERROR(\"division by zero\") FI;");
291 prl("tempres := tempb DIV tempa;");
292 prl(cmdToEStack("tempres"));
293 break;
295 case rem: {
296 prl(getTopTwo());
297 prl("IF tempa = 0 THEN ERROR(\"division by zero\") FI;");
298 prl("tempres := tempb MOD tempa;");
299 prl(cmdToEStack("tempres"));
300 break;
303 case enter: {
304 prl(createComment("enter not fully procesed yet"));
305 get();
306 get();
307 break;
309 case return_: {
310 prl(createComment("return not fully procesed yet"));
311 break;
313 case exit: {
314 prl(createComment("exit not fully procesed yet"));
315 break;
318 // the prints
319 case bprint: {
320 prl(getTopTwo());
321 prl("PRINT(tempb);");
322 break;
324 case print: {
325 // TODO need to make it a char
326 prl(getTopTwo());
327 prl("PRINT(tempb);");
328 break;
330 default:
331 prl(createComment("unknown op error: " + op, C_ERR));
332 break;
335 op = get();
336 if (op >= 0)
337 prl("CALL a" + counter + " END");
339 prl("CALL Z;\nSKIP END\nENDACTIONS;\n");
340 prl(getStandardEnd());
344 public void convertFile(File f) {
345 try {
346 convertStream(new FileInputStream(f));
347 } catch (Exception ex) {
348 ex.printStackTrace();
352 public void printHelp() {
353 System.out.println("MicroJava bytecode to WSL converter. v " + versionN
354 + ", by Doni Pracner");
355 System.out.println("usage:\n\t {options} mjc2wsl filename [outfile]");
356 System.out.println("options:\n\t--screen print output to screen");
357 System.out.println("\t-o --oc include original code in comments");
360 public String makeDefaultOutName(String inname){
361 String rez = inname;
362 if (inname.endsWith(".obj"))
363 rez = rez.substring(0, rez.length() - 4);
364 return rez + ".wsl";
367 public void run(String[] args) {
368 if (args.length == 0) {
369 printHelp();
370 } else {
371 int i = 0;
372 while (i < args.length && args[i].charAt(0) == '-') {
373 if (args[i].compareTo("-h") == 0) {
374 printHelp();
375 return;
376 } else if (args[i].compareTo("-o") == 0
377 || args[i].startsWith("--oc")) {
378 if (args[i].length() == 2)
379 originalInComments = true;
380 else if (args[i].length() == 5)
381 originalInComments = args[i].charAt(4) == '+';
382 else
383 originalInComments = true;
384 } else if (args[i].startsWith("--screen")) {
385 out = new PrintWriter(System.out);
387 i++;
390 if (i >= args.length) {
391 System.out.println("no filename supplied");
392 System.exit(2);
394 File f = new File(args[i]);
396 if (i + 1 < args.length) {
397 try {
398 out = new PrintWriter(args[i + 1]);
399 } catch (Exception e) {
400 System.err.println("error in opening out file:");
401 e.printStackTrace();
404 if (out == null) {
405 // if not set to screen, or a file, make a default filename
406 try {
407 out = new PrintWriter(makeDefaultOutName(args[i]));
408 } catch (Exception e) {
409 System.err.println("error in opening out file:");
410 e.printStackTrace();
413 if (f.exists()) {
414 Calendar now = Calendar.getInstance();
415 convertFile(f);
416 long mili = Calendar.getInstance().getTimeInMillis()
417 - now.getTimeInMillis();
418 System.out.println("conversion time:" + mili + " ms");
419 out.close();
420 } else
421 System.out.println("file does not exist");
425 public static void main(String[] args) {
426 new mjc2wsl().run(args);
Svarog.pmf.uns.ac.rs/gitweb maintanance Doni Pracner