gitweb on Svarog

projekti pod git sistemom za održavanje verzija -- projects under the git version control system
version 0.81
[asm2wsl.git] / src / asm2wsl.java
2 /*
3 Copyright 2012,2018 Doni Pracner
5 This program is free software: you can redistribute it
6 and/or modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation, either
8 version 3 of the License, or (at your option) any later
9 version.
11 This program is distributed in the hope that it will be
12 useful, but WITHOUT ANY WARRANTY; without even the implied
13 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the GNU General Public License for more
15 details.
17 You should have received a copy of the GNU General Public
18 License along with this program. If not, see
19 <http://www.gnu.org/licenses/>.
21 */
22 import java.io.*;
23 import java.util.*;
25 /**
26 * This program converts files from assembly x86 to WSL language which is a part
27 * of the FermaT Transformation system.<br />
28 * Currently it works only on a very limited subset of x86, and has a number of
29 * predefined macro names it uses for translation. It works with 16 bit
30 * registers (ax,bx, etc) and presumes that the rest of the variables are 8bit
31 * if not applied to a 16bit reg. Check the documentation for more details.
32 *
33 * @author Doni Pracner, http://perun.dmi.rs/pracner http://quemaster.com
34 */
35 public class asm2wsl {
37 private static final String PROCEDURE_INTERNAL_SYS = "procedure_internal_sys";
39 /** translation processing switch */
40 public boolean originalInComments = false, translateComments = true,
41 addMemoryDump = false, translateToPopPush = true;
43 int mode = MODE_0, nUnknownC = 0, nUnknownD = 0, nKnownC = 0;
45 boolean labelfound = false;
47 public static final String versionN = "0.81";
49 // regular comments from the original file
50 // OC when original code is inserted in the file, next to the translations
51 // SPEC special messages from the translator
52 // ERR error messages from the translator
53 public static final char C_REG = ' ', C_OC = '#', C_SPEC = '&', C_ERR = '!';
55 public static final int MODE_0 = 0, MODE_CODE = 1, MODE_DATA = 2,
56 MODE_STACK = 3, N_MODES = 4;
58 public static final String CODE_SEG_START = "SKIP;\n ACTIONS A_S_start:\n A_S_start ==",
59 CODE_SEG_END = "CALL Z;\nSKIP END\nENDACTIONS;\n",
60 DATA_SEG_START = "VAR< ", DATA_SEG_END = " \tskipvar := 0 \n>:\n",
61 fixl = "\n%x := (%x DIV 256) * 256 + t_e_m_p;",
62 fixh = "\n%x := (%x MOD 256) + t_e_m_p * 256;";
64 public String getStandardStart() {
65 String ret = "C:\" This file automatically converted from assembler\";\n"
66 + "C:\" with asm2wsl v " + versionN + "\";\n";
67 ret += "VAR < ax := 0, bx := 0, cx := 0, dx := 0,\n"
68 + " si := 0, di := 0, bp := 0, sp := 0, \n"
69 + " ss := 0, ds := 0, cs := 0, es := 0,\n"
70 + " flag_o := 0, flag_d := 0, flag_i := 0, flag_t := 0,\n"
71 + " flag_z := 0, flag_s := 0, flag_p := 0, flag_a := 0,\n"
72 + " flag_c := 0, overflow := 256, stack := < >, t_e_m_p := 0 > :\n";
73 if (addMemoryDump)
74 ret += "BEGIN\n";
75 return ret;
76 }
78 public String getStandardEnd() {
79 String ret = "ENDVAR;\n";
80 if (addMemoryDump) {
81 ret += "C:\" end original program. testing features following\";\n"
82 + "WHERE\n" + "PROC memdump(VAR) ==\n"
83 + " PRINT(\"'memory' dump: \");\n"
84 + " PRINT(\"ax \",ax,\" bx \",bx,\" cx \",cx,\" dx \",dx);\n"
85 + " PRINT(\"flags:\");\n" + " PRINT(\"ODITSZAPC\");\n"
86 + " PRINT(flag_o,flag_d,flag_i,flag_t,flag_s,flag_z,flag_a,flag_p,flag_c)\n"
87 + "END\n" + "END\n";
88 }
89 ret += "\nENDVAR";
90 return ret;
91 }
93 /**
94 * When the param works with array addressing, this should reformat it so
95 * that it works as intended. An important thing to remember is that there
96 * is a[0] element in WSL, all arrays start with a[1].
97 */
98 public String arrayFix(String str) {
99 String param = str.substring(str.indexOf('[') + 1, str.indexOf(']'));
100 return str.replace(param + "]", formatParam(param) + "+1]");
103 /**
104 * Transforms an asembler source parameter as need so that it can be used in
105 * WSL. Among other things it converts Hex numbers to decimal, fixes array
106 * access indexes and the high/low parts of registers.
107 */
108 public String formatParam(String str) {
109 str = str.toLowerCase();
110 if (str.contains("["))
111 str = arrayFix(str);
112 try {
113 if (str.matches("[0-9][0-9a-f]*h"))
114 return "" + Integer.parseInt(str.substring(0, str.length() - 1),
115 16);
116 } catch (Exception e) {
117 System.err.println("error in hex param procesing");
118 e.printStackTrace();
120 if (str.compareTo("al") == 0)
121 return "(ax MOD 256)";
122 else if (str.compareTo("ah") == 0)
123 return "(ax DIV 256)";
124 else if (str.compareTo("bl") == 0)
125 return "(bx MOD 256)";
126 else if (str.compareTo("bh") == 0)
127 return "(bx DIV 256)";
128 else if (str.compareTo("cl") == 0)
129 return "(cx MOD 256)";
130 else if (str.compareTo("ch") == 0)
131 return "(cx DIV 256)";
132 else if (str.compareTo("dl") == 0)
133 return "(dx MOD 256)";
134 else if (str.compareTo("dh") == 0)
135 return "(dx DIV 256)";
136 else
137 // for undefined variables
138 if (str.compareTo("(?)") == 0)
139 return "\" \"";
140 else
142 return str;
145 /**
146 * Transforms an asembler destination parameter as need so that it can be
147 * used in WSL. Among other things it fixes array access indexes and the
148 * high/low parts of registers.
149 */
150 public String formatDst(String str) {
151 if (str.contains("["))
152 str = arrayFix(str);
153 str = str.toLowerCase();
154 if (str.length() == 2 && str.charAt(0) >= 'a' && str.charAt(0) <= 'd'
155 && (str.charAt(1) == 'l' || str.charAt(1) == 'h'))
156 return "t_e_m_p";
157 else
158 return str;
161 /**
162 * Used for fixing low/high register access. The given param should be the
163 * dst operand of an assembler command.
164 */
165 public String getXRegisterFix(String str) {
166 str = str.toLowerCase();
167 if (str.length() == 2 && str.charAt(0) >= 'a' && str.charAt(0) <= 'd') {
168 char c = str.charAt(0);
169 if (str.charAt(1) == 'l')
170 return fixl.replace('%', c);
171 if (str.charAt(1) == 'h')
172 return fixh.replace('%', c);
174 return "";
177 /**
178 * Creates a WSL comment with care to quote chars.
179 */
180 public static String createComment(String str) {
181 return createComment(str, C_REG);
184 /**
185 * Creates a WSL comment with care to quote chars, of the given type. Types
186 * are given as char constants. They can be default comments, comments that
187 * contain the original code in them, or additional comments regarding the
188 * translation process.
189 */
190 public static String createComment(String str, char type) {
191 return "C:\"" + type + str.replace("\"", "''") + "\";";
194 /**
195 * Creates a wsl statement that modifies the overflow limit based on the
196 * input string that should be the parameter of a command.
197 */
198 public String getOverflow(String str) {
199 int over = 256;
200 str = str.toLowerCase();
201 if (str.length() == 2) {
202 if ((str.charAt(1) == 'x' && str.charAt(0) >= 'a'
203 && str.charAt(0) <= 'd')
204 || (str.compareTo("si") == 0 || str.compareTo("bp") == 0))
205 over = 65536;
207 return "overflow := " + over + "; ";
210 private void debugPrint(ArrayList<String> com) {
211 System.out.println();
212 for (int i = 0; i < com.size(); i++) {
213 System.out.print(com.get(i));
214 System.out.print("||");
218 private boolean inMacro = false;
220 // internal state, if a procedure body is being translated currently
221 private boolean inProcedure = false;
223 // the name of the procedure currently translated, if there is one
224 private String currentProcName = "";
226 /**
227 * Takes a single assembler line and returns the translated WSL line(s). It
228 * also changes the translator modes (data, code etc).
229 */
230 public String processLine(String str) {
231 /* Most of the logic is here, some parts could be split off */
232 if (str.length() == 0)
233 return "";
234 String[] split = str.split(";", 2);
235 String rez = split[0];
236 String comment = "";
237 // removes the comments
238 if (translateComments && split.length > 1)
239 comment = createComment(split[1]);
240 if (rez.compareTo("") != 0) {
241 // if there is a non-comment part
242 String[] parts = rez.split("[\t ,]");
243 // separators are whitespace: tab, space and comma
244 ArrayList<String> com = new ArrayList<String>();
245 for (String s : parts)
246 if (s.compareTo("") != 0 && s != null)
247 com.add(s);
248 rez = "";
249 String a, b;
250 // special case, we are processing lines in a macro definition
251 if (inMacro) {
252 Iterator<String> it = com.iterator();
253 while (it.hasNext())
254 if (it.next().compareTo("endm") == 0)
255 inMacro = false;
256 return createComment(str, C_SPEC) + "\n";
258 // by this time, all the real words should be in the com array
259 int i = 0;
260 boolean work = true;
261 // debugPrint(com);
262 while (i < com.size() && work) {
263 String s = com.get(i).toLowerCase();
264 if (s.endsWith(":")) { // should represent a label
265 s = s.substring(0, s.length() - 1);
266 rez += "CALL " + s + "\n END\n";
267 rez += s + " == ";
268 // labelfound = true;
269 } else
270 // ------------------------------------------------------------
271 // procedures, calls and similar activities
272 if (s.compareTo("proc") == 0) {
273 // if (labelfound)
274 rez += "CALL Z; SKIP END \n";
275 a = com.get(i - 1);
276 rez += a + " == ";
277 b = PROCEDURE_INTERNAL_SYS;
278 rez += "\nACTIONS " + b + ": \n";
279 rez += b + " == ";
280 inProcedure = true;
281 currentProcName = a;
282 } else if (s.compareTo("endp") == 0) {
283 rez += " SKIP END\n ENDACTIONS\n END\n dummy" + nKnownC
284 + " == ";
285 inProcedure = false;
286 } else if (s.compareTo("ret") == 0) {
287 rez += " CALL Z;";
288 } else if (s.compareTo("call") == 0) {
289 a = com.get(++i);
290 // check for recursive calls, don't do outside of current
291 // action system
292 if (inProcedure && currentProcName.equals(a))
293 a = PROCEDURE_INTERNAL_SYS;
294 rez += "CALL " + a + ";";
295 } else
296 // segments and other special assembler directives
297 if (s.charAt(0) == '.') { //
298 if (s.compareTo(".code") == 0) {
299 rez = CODE_SEG_START;
300 mode = MODE_CODE;
301 } else if (s.compareTo(".data") == 0) {
302 rez = " ";
303 mode = MODE_DATA;
304 } else if (s.compareTo(".stack") == 0) {
305 rez = " ";
306 mode = MODE_STACK;
307 } else if (s.startsWith(".model")) {
308 if (!s.toLowerCase().endsWith("small")) {
309 rez += createComment(
310 "other models than small not supported :: "
311 + split[0],
312 C_SPEC);
313 nUnknownD++;
314 mode = MODE_0;
316 } else {
317 rez += createComment(
318 "directive not supported :: " + split[0],
319 C_SPEC);
320 nUnknownD++;
321 mode = MODE_0;
323 work = false;
324 } else if (s.compareTo("assume") == 0) {
325 rez += createComment(
326 "ASSUME commands not supported :: " + split[0],
327 C_SPEC);
328 nUnknownD++;
329 work = false;
330 } else if (s.compareTo("segment") == 0) {
331 String segn = com.get(i - 1).toLowerCase();
332 if (segn.compareTo("cseg") == 0
333 || segn.compareTo("code") == 0
334 || segn.compareTo("code_seg") == 0) {
335 rez += CODE_SEG_START;
336 mode = MODE_CODE;
337 } else if (segn.compareTo("dseg") == 0
338 || segn.compareTo("data_seg") == 0
339 || segn.compareTo("data") == 0) {
340 rez += " ";
341 mode = MODE_DATA;
342 } else if (segn.compareTo("sseg") == 0
343 || segn.compareTo("stack_seg") == 0
344 || segn.compareTo("stack") == 0) {
345 rez += " ";
346 mode = MODE_STACK;
347 } else {
348 rez += createComment(
349 "unsuported segment type :: " + split[0],
350 C_SPEC);
351 nUnknownD++;
352 mode = MODE_0;
354 work = false;
355 } else if (s.compareTo("ends") == 0) { // segment end
356 if (i > 0) {
357 String segn = com.get(i - 1).toLowerCase();
358 if (segn.compareTo("cseg") == 0
359 || segn.compareTo("code_seg") == 0
360 || segn.compareTo("code") == 0
361 || segn.compareTo("dseg") == 0
362 || segn.compareTo("data") == 0
363 || segn.compareTo("data_seg") == 0
364 || segn.compareTo("sseg") == 0
365 || segn.compareTo("stack") == 0
366 || segn.compareTo("stack_seg") == 0) {
367 rez += createComment("end of segment " + segn,
368 C_SPEC);
369 mode = MODE_0;
370 } else {
371 rez += createComment(
372 "unsuported segment type :: " + split[0],
373 C_SPEC);
374 nUnknownD++;
376 } else {
377 rez += createComment("end of segment", C_SPEC);
378 mode = MODE_0;
380 work = false;
381 } else
382 // macro ideas ----
383 if (s.compareTo("macro") == 0) {
384 rez += createComment(
385 "found macro definition - macros unsuported",
386 C_ERR);
387 nUnknownC++;
388 inMacro = true;
389 work = false;
390 } else if (s.compareTo("endm") == 0) {
391 rez += createComment(
392 "found macro definition end - macros unsuported",
393 C_ERR);
394 nUnknownC++;
395 work = false;
396 } else
398 /*
399 * ------------------------------
400 *
401 * special macro names translated directly
402 */
403 if ((s.compareTo("print_str") == 0
404 || s.compareTo("print_num") == 0
405 || s.compareTo("print_char") == 0)
406 && com.get(i + 1).compareTo("macro") != 0) {
407 rez += "PRINFLUSH(" + com.get(i + 1) + ");";
409 work = false;
410 } else if (s.compareTo("print_new_line") == 0
411 && (com.size() <= i + 1
412 || com.get(i + 1).compareTo("macro") != 0)) {
413 rez += "PRINT(\"\");";
415 work = false;
416 } else if (s.compareTo("read_str") == 0
417 && com.get(i + 1).compareTo("macro") != 0) {
418 rez += "@Read_Line_Proc(VAR " + com.get(i + 1)
419 + ", Standard_Input_Port);";
421 work = false;
422 } else if (s.compareTo("read_num") == 0
423 && com.get(i + 1).compareTo("macro") != 0) {
424 rez += "@Read_Line_Proc(VAR t_e_m_p, Standard_Input_Port);\n";
425 rez += com.get(i + 1) + " := @String_To_Num(t_e_m_p);";
427 work = false;
428 } else if (s.compareTo("end_execution") == 0
429 && (com.size() <= i + 1
430 || com.get(i + 1).compareTo("macro") != 0)) {
431 rez += "CALL Z;";
433 work = false;
434 } else
436 // ---------------------------------------
437 // operators and similar commands
438 if (s.compareTo("mov") == 0) {
439 a = com.get(i + 1);
440 b = com.get(i + 2).toLowerCase();
441 if ((b.compareTo("@data") == 0)
442 || (b.compareTo("dseg") == 0)) {
443 rez += createComment("unneeded DATA segment fixes",
444 C_SPEC);
445 work = false;
446 } else {// rez += getOverflow(a);
447 rez += formatDst(a) + " := " + formatParam(b) + ";";
448 rez += getXRegisterFix(a);
449 work = false;
451 } else if (s.compareTo("add") == 0 || s.compareTo("adc") == 0) {
452 a = com.get(i + 1);
453 b = com.get(i + 2);
454 rez += getOverflow(a);
455 rez += formatDst(a) + " := " + formatParam(a) + " + "
456 + formatParam(b) + ";\n";
457 if (s.compareTo("adc") == 0)
458 rez += formatDst(a) + " := " + formatParam(a) + " + "
459 + " + flag_c;\n";
460 rez += "IF " + formatDst(a) + " >= overflow THEN "
461 + formatDst(a) + " := " + formatDst(a)
462 + " MOD overflow; flag_o :=1; flag_c := 1; ELSE flag_o :=0; flag_c := 0; FI;";
463 rez += getXRegisterFix(a);
464 work = false;
465 } else if (s.compareTo("sub") == 0 || s.compareTo("cmp") == 0) {
466 a = com.get(i + 1);
467 b = com.get(i + 2);
468 // rez += getOverflow(a);
469 rez += "IF " + formatParam(a) + " = " + formatParam(b)
470 + " THEN\n\t flag_z := 1\n ELSE\n\t flag_z := 0\n FI; ";
471 rez += "IF " + formatParam(a) + " < " + formatParam(b)
472 + " THEN\n\t flag_c := 1\n ELSE\n\t flag_c := 0\n FI; ";
473 if (s.compareTo("sub") == 0)
474 rez += formatDst(a) + " := " + formatParam(a) + " - "
475 + formatParam(b) + ";";
476 work = false;
477 } else if (s.compareTo("inc") == 0) {
478 a = com.get(i + 1);
479 rez += getOverflow(a);
480 rez += formatDst(a) + " := " + formatParam(a) + " + 1;";
481 rez += getXRegisterFix(a);
482 work = false;
483 } else if (s.compareTo("dec") == 0) {
484 a = com.get(i + 1);
485 rez += getOverflow(a);
486 rez += formatDst(a) + " := " + formatParam(a) + " - 1;";
487 rez += getXRegisterFix(a);
488 work = false;
489 } else if (s.compareTo("shr") == 0) {
490 a = com.get(i + 1);
491 // rez += getOverflow(a);
492 rez += "IF " + formatParam(a) + " MOD 2 = 1 THEN "
493 + " flag_c := 1; ELSE flag_c := 0; FI;";
494 rez += formatDst(a) + " := " + formatParam(a) + " DIV 2;";
495 rez += getXRegisterFix(a);
496 work = false;
497 } else if (s.compareTo("shl") == 0) {
498 a = com.get(i + 1);
499 rez += getOverflow(a);
500 rez += formatDst(a) + " := " + formatParam(a) + " * 2;";
501 rez += "IF " + formatDst(a) + " >= overflow THEN "
502 + formatDst(a) + " := " + formatDst(a)
503 + " MOD overflow; flag_o :=1; flag_c := 1; ELSE flag_o :=0; flag_c := 0; FI;";
504 rez += getXRegisterFix(a);
505 work = false;
506 } else if (s.compareTo("xchg") == 0) {
507 a = com.get(i + 1);
508 b = com.get(i + 2);
509 rez += "< " + formatDst(a) + " := " + formatParam(b) + ", "
510 + formatDst(b) + " := " + formatParam(a) + " >;";
511 rez += getXRegisterFix(a);
512 work = false;
513 } else
514 // logical exp
515 if (s.compareTo("and") == 0) {
516 // rez += com.get(i+1)+" := "+com.get(i+1)+" AND
517 // "+formatParam(com.get(i+2))+";";
518 rez += createComment(
519 "and not implemented yet :: " + split[0], C_ERR);
520 nUnknownC++;
521 work = false;
522 } else if (s.compareTo("xor") == 0) {
523 a = com.get(i + 1);
524 b = formatParam(com.get(i + 2));
525 if (a.compareTo(b) == 0)
526 rez += a + " := 0;";
527 else {
528 rez += createComment(
529 "xor not implemnted yet :: " + split[0], C_ERR);
530 // a+" := ("+a+" AND NOT "+b+") OR (NOT "+a+" AND "+b+"
531 // );");
532 nUnknownC++;
534 work = false;
535 } else if (s.compareTo("not") == 0) {
536 // rez += com.get(i+1)+" := NOT "+com.get(i+1)+";";
537 rez += createComment(
538 "NOT not implemented yet :: " + split[0], C_ERR);
539 nUnknownC++;
540 work = false;
541 } else
542 // jumps
543 if (s.compareTo("jmp") == 0) {
544 rez += "CALL " + com.get(i + 1) + ";";
545 work = false;
546 } else if (s.compareTo("je") == 0 || s.compareTo("jz") == 0) {
547 rez += "IF flag_z = 1 THEN CALL " + com.get(i + 1) + " FI;";
548 work = false;
549 } else if (s.compareTo("jne") == 0 || s.compareTo("jnz") == 0) {
550 rez += "IF flag_z = 0 THEN CALL " + com.get(i + 1) + " FI;";
551 work = false;
552 } else if (s.compareTo("ja") == 0) {
553 rez += "IF flag_z = 0 AND flag_c = 0 THEN CALL "
554 + com.get(i + 1) + " FI;";
555 work = false;
556 } else if (s.compareTo("jae") == 0 || s.compareTo("jnc") == 0) {
557 rez += "IF flag_c = 0 THEN CALL " + com.get(i + 1) + " FI;";
558 work = false;
559 } else if (s.compareTo("jb") == 0) {
560 rez += "IF flag_c = 1 THEN CALL " + com.get(i + 1) + " FI;";
561 work = false;
562 } else if (s.compareTo("jcxz") == 0) {
563 rez += "IF cx = 0 THEN CALL " + com.get(i + 1) + " FI;";
564 work = false;
565 } else if (s.compareTo("jo") == 0) {
566 rez += "IF flag_o = 1 THEN CALL " + com.get(i + 1) + " FI;";
567 work = false;
568 } else if (s.compareTo("loop") == 0) {
569 rez += "cx := cx - 1;\n";
570 rez += "IF cx>0 THEN CALL " + com.get(i + 1)
571 + " ELSE CALL dummy" + nKnownC + " FI\n";
572 rez += "END\ndummy" + nKnownC + " ==";
573 work = false;
574 } else
576 // end and other
577 if (s.compareTo("end") == 0) {
578 // TODO parse the optional entry label that comes with end
579 rez += createComment("program end");
580 work = false;
581 } else if (s.compareTo("nop") == 0) {
582 rez += "SKIP;";
583 work = false;
584 } else
586 // stack
587 if (s.compareTo("pop") == 0) {
588 if (translateToPopPush) {
589 rez += "POP(" + formatDst(com.get(i + 1)) + ", stack);";
590 } else {
591 rez += formatDst(com.get(i + 1)) + " := HEAD(stack);\n";
592 rez += "stack := TAIL(stack);";
594 rez += getXRegisterFix(com.get(i + 1));
595 work = false;
596 } else if (s.compareTo("push") == 0) {
597 if (translateToPopPush) {
598 rez += "PUSH(stack, " + formatParam(com.get(i + 1))
599 + ");";
600 } else {
601 rez += "stack := < " + formatParam(com.get(i + 1))
602 + " > ++ stack;";
604 work = false;
605 } else
606 // var definitions
607 if (s.compareTo("db") == 0 || s.compareTo("dw") == 0) {
608 if (mode == MODE_DATA) {
609 if (com.size() == i + 2) {
610 rez += "\t " + com.get(i - 1) + " := "
611 + formatParam(com.get(i + 1)) + ",";
612 } else {// array
613 rez += "\t " + com.get(i - 1) + " := < "
614 + formatParam(com.get(i + 1));
615 for (int j = i + 2; j < com.size(); j++)
616 rez += "," + formatParam(com.get(j));
617 rez += " >,";
619 } else {
623 i++;
625 if (rez.compareTo("") == 0 && com.size() > 0) {
626 rez = createComment(" unkown command:" + split[0], C_ERR);
627 nUnknownC++;
628 } else
629 nKnownC++; // this now counts the directives too...
631 return rez + " " + comment + "\n";
635 /**
636 * Converts an asm file to a wsl file. It also prints out the number of
637 * unsupported commands.
638 */
639 public void convertAFile(File f) {
640 try {
641 BufferedReader in = new BufferedReader(
642 new InputStreamReader(new FileInputStream(f)));
643 String str = in.readLine(), rez = f.getPath();
644 if (rez.toLowerCase().endsWith(".asm"))
645 rez = rez.substring(0, rez.length() - 4);
646 PrintWriter out = new PrintWriter(
647 new OutputStreamWriter(new FileOutputStream(rez + ".wsl")));
648 nUnknownD = 0;
649 nUnknownC = 0;
650 nKnownC = 0;
651 StringBuilder[] sbs = new StringBuilder[N_MODES];
652 for (int i = 0; i < N_MODES; i++)
653 sbs[i] = new StringBuilder();
654 while (str != null) {
655 rez = processLine(str);
656 if (originalInComments)
657 sbs[mode].append(createComment(str, C_OC) + "\n");
658 sbs[mode].append(rez);
659 str = in.readLine();
661 sbs[MODE_CODE].append(CODE_SEG_END);
662 if (addMemoryDump)
663 sbs[MODE_CODE].append("memdump();");
664 sbs[MODE_DATA].append(DATA_SEG_END);
665 // remove comments from dataseg
666 String datastr = sbs[MODE_DATA].toString()
667 .replaceAll("C:\"(.*?)\";\n?", "");
668 in.close();
669 out.print(getStandardStart());
670 out.print(sbs[MODE_0]);
671 out.print(DATA_SEG_START);
672 out.print(datastr); // out.print(sbs[MODE_DATA]);
673 out.print(sbs[MODE_CODE]);
674 out.print(getStandardEnd());
675 out.close();
676 if (nUnknownD > 0)
677 System.out.println("warning: " + nUnknownD
678 + " unkown/unsuported directives were found");
679 if (nUnknownC > 0)
680 System.out.println("errors : " + nUnknownC
681 + " unkown/unsuported commands were found");
682 System.out.println(nKnownC + " commands translated");
683 } catch (Exception e) {
684 System.err.println("error in conversion:");
685 e.printStackTrace();
689 public void run(String[] args) {
690 if (args.length == 0) {
691 System.out.println("Assembler to WSL converter. v " + versionN
692 + ", by Doni Pracner");
693 System.out.println("usage:\n\t asm2wsl {-option[ +-]} filename");
694 System.out.println("options: (def value in parenthesis)");
695 System.out.println("\t -oc : orignal code in comments ("
696 + (originalInComments ? "+" : "-") + ")");
697 System.out.println("\t -c : translate comments ("
698 + (translateComments ? "+" : "-") + ")");
699 System.out.println("\t -dump : add memory dump commands to end ("
700 + (addMemoryDump ? "+" : "-") + ")");
701 } else {
702 if (args[0].compareTo("-h") == 0
703 || args[0].compareTo("--help") == 0) {
704 run(new String[0]);
705 return;
707 int i = 0;
708 while (i < args.length && args[i].charAt(0) == '-') {
709 if (args[i].startsWith("-oc")) {
710 if (args[i].length() == 4)
711 originalInComments = args[i].charAt(3) == '+';
712 else
713 originalInComments = true;
714 } else if (args[i].startsWith("-c")) {
715 if (args[i].length() == 3)
716 translateComments = args[i].charAt(2) == '+';
717 else
718 translateComments = true;
719 } else if (args[i].startsWith("-dump")) {
720 addMemoryDump = true;
721 if (args[i].length() == 6 && args[i].charAt(5) == '-')
722 addMemoryDump = false;
724 i++;
727 if (i >= args.length) {
728 System.out.println("no filename supplied");
729 System.exit(2);
731 File f = new File(args[i]);
732 if (f.exists()) {
733 Calendar now = Calendar.getInstance();
734 convertAFile(f);
735 long mili = Calendar.getInstance().getTimeInMillis()
736 - now.getTimeInMillis();
737 System.out.println("conversion time:" + mili + " ms");
738 } else
739 System.out.println("file does not exist");
743 public static void main(String[] args) {
744 new asm2wsl().run(args);
Svarog.pmf.uns.ac.rs/gitweb maintanance Doni Pracner