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
diff --git a/src/asm2wsl.java b/src/asm2wsl.java
new file mode 100755 (executable)
index 0000000..125ac21
--- /dev/null
@@ -0,0 +1,746 @@
+\r
+/* \r
+Copyright 2012,2018 Doni Pracner\r
+\r
+This program is free software: you can redistribute it\r
+and/or modify it under the terms of the GNU General Public\r
+License as published by the Free Software Foundation, either\r
+version 3 of the License, or (at your option) any later\r
+version.\r
+\r
+This program is distributed in the hope that it will be\r
+useful, but WITHOUT ANY WARRANTY; without even the implied\r
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+PURPOSE. See the GNU General Public License for more\r
+details.\r
+\r
+You should have received a copy of the GNU General Public\r
+License along with this program. If not, see\r
+<http://www.gnu.org/licenses/>.\r
+\r
+*/\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+/**\r
+ * This program converts files from assembly x86 to WSL language which is a part\r
+ * of the FermaT Transformation system.<br />\r
+ * Currently it works only on a very limited subset of x86, and has a number of\r
+ * predefined macro names it uses for translation. It works with 16 bit\r
+ * registers (ax,bx, etc) and presumes that the rest of the variables are 8bit\r
+ * if not applied to a 16bit reg. Check the documentation for more details.\r
+ *\r
+ * @author Doni Pracner, http://perun.dmi.rs/pracner http://quemaster.com\r
+ */\r
+public class asm2wsl {\r
+\r
+       private static final String PROCEDURE_INTERNAL_SYS = "procedure_internal_sys";\r
+\r
+       /** translation processing switch */\r
+       public boolean originalInComments = false, translateComments = true,\r
+                       addMemoryDump = false, translateToPopPush = true;\r
+\r
+       int mode = MODE_0, nUnknownC = 0, nUnknownD = 0, nKnownC = 0;\r
+\r
+       boolean labelfound = false;\r
+\r
+       public static final String versionN = "0.81";\r
+\r
+       // regular comments from the original file\r
+       // OC when original code is inserted in the file, next to the translations\r
+       // SPEC special messages from the translator\r
+       // ERR error messages from the translator\r
+       public static final char C_REG = ' ', C_OC = '#', C_SPEC = '&', C_ERR = '!';\r
+\r
+       public static final int MODE_0 = 0, MODE_CODE = 1, MODE_DATA = 2,\r
+                       MODE_STACK = 3, N_MODES = 4;\r
+\r
+       public static final String CODE_SEG_START = "SKIP;\n ACTIONS A_S_start:\n A_S_start ==",\r
+                       CODE_SEG_END = "CALL Z;\nSKIP END\nENDACTIONS;\n",\r
+                       DATA_SEG_START = "VAR< ", DATA_SEG_END = " \tskipvar := 0 \n>:\n",\r
+                       fixl = "\n%x := (%x DIV 256) * 256 + t_e_m_p;",\r
+                       fixh = "\n%x := (%x MOD 256) + t_e_m_p * 256;";\r
+\r
+       public String getStandardStart() {\r
+               String ret = "C:\" This file automatically converted from assembler\";\n"\r
+                               + "C:\" with asm2wsl v " + versionN + "\";\n";\r
+               ret += "VAR < ax := 0, bx := 0, cx := 0, dx := 0,\n"\r
+                               + "     si := 0, di := 0, bp := 0, sp := 0, \n"\r
+                               + "     ss := 0, ds := 0, cs := 0, es := 0,\n"\r
+                               + "     flag_o := 0, flag_d := 0, flag_i := 0, flag_t := 0,\n"\r
+                               + "     flag_z := 0, flag_s := 0, flag_p := 0, flag_a := 0,\n"\r
+                               + "     flag_c := 0, overflow := 256, stack := < >, t_e_m_p := 0 > :\n";\r
+               if (addMemoryDump)\r
+                       ret += "BEGIN\n";\r
+               return ret;\r
+       }\r
+\r
+       public String getStandardEnd() {\r
+               String ret = "ENDVAR;\n";\r
+               if (addMemoryDump) {\r
+                       ret += "C:\" end original program. testing features following\";\n"\r
+                                       + "WHERE\n" + "PROC memdump(VAR) ==\n"\r
+                                       + "     PRINT(\"'memory' dump: \");\n"\r
+                                       + "     PRINT(\"ax \",ax,\" bx \",bx,\" cx \",cx,\" dx \",dx);\n"\r
+                                       + "     PRINT(\"flags:\");\n" + "       PRINT(\"ODITSZAPC\");\n"\r
+                                       + "     PRINT(flag_o,flag_d,flag_i,flag_t,flag_s,flag_z,flag_a,flag_p,flag_c)\n"\r
+                                       + "END\n" + "END\n";\r
+               }\r
+               ret += "\nENDVAR";\r
+               return ret;\r
+       }\r
+\r
+       /**\r
+        * When the param works with array addressing, this should reformat it so\r
+        * that it works as intended. An important thing to remember is that there\r
+        * is a[0] element in WSL, all arrays start with a[1].\r
+        */\r
+       public String arrayFix(String str) {\r
+               String param = str.substring(str.indexOf('[') + 1, str.indexOf(']'));\r
+               return str.replace(param + "]", formatParam(param) + "+1]");\r
+       }\r
+\r
+       /**\r
+        * Transforms an asembler source parameter as need so that it can be used in\r
+        * WSL. Among other things it converts Hex numbers to decimal, fixes array\r
+        * access indexes and the high/low parts of registers.\r
+        */\r
+       public String formatParam(String str) {\r
+               str = str.toLowerCase();\r
+               if (str.contains("["))\r
+                       str = arrayFix(str);\r
+               try {\r
+                       if (str.matches("[0-9][0-9a-f]*h"))\r
+                               return "" + Integer.parseInt(str.substring(0, str.length() - 1),\r
+                                               16);\r
+               } catch (Exception e) {\r
+                       System.err.println("error in hex param procesing");\r
+                       e.printStackTrace();\r
+               }\r
+               if (str.compareTo("al") == 0)\r
+                       return "(ax MOD 256)";\r
+               else if (str.compareTo("ah") == 0)\r
+                       return "(ax DIV 256)";\r
+               else if (str.compareTo("bl") == 0)\r
+                       return "(bx MOD 256)";\r
+               else if (str.compareTo("bh") == 0)\r
+                       return "(bx DIV 256)";\r
+               else if (str.compareTo("cl") == 0)\r
+                       return "(cx MOD 256)";\r
+               else if (str.compareTo("ch") == 0)\r
+                       return "(cx DIV 256)";\r
+               else if (str.compareTo("dl") == 0)\r
+                       return "(dx MOD 256)";\r
+               else if (str.compareTo("dh") == 0)\r
+                       return "(dx DIV 256)";\r
+               else\r
+               // for undefined variables\r
+               if (str.compareTo("(?)") == 0)\r
+                       return "\" \"";\r
+               else\r
+\r
+                       return str;\r
+       }\r
+\r
+       /**\r
+        * Transforms an asembler destination parameter as need so that it can be\r
+        * used in WSL. Among other things it fixes array access indexes and the\r
+        * high/low parts of registers.\r
+        */\r
+       public String formatDst(String str) {\r
+               if (str.contains("["))\r
+                       str = arrayFix(str);\r
+               str = str.toLowerCase();\r
+               if (str.length() == 2 && str.charAt(0) >= 'a' && str.charAt(0) <= 'd'\r
+                               && (str.charAt(1) == 'l' || str.charAt(1) == 'h'))\r
+                       return "t_e_m_p";\r
+               else\r
+                       return str;\r
+       }\r
+\r
+       /**\r
+        * Used for fixing low/high register access. The given param should be the\r
+        * dst operand of an assembler command.\r
+        */\r
+       public String getXRegisterFix(String str) {\r
+               str = str.toLowerCase();\r
+               if (str.length() == 2 && str.charAt(0) >= 'a' && str.charAt(0) <= 'd') {\r
+                       char c = str.charAt(0);\r
+                       if (str.charAt(1) == 'l')\r
+                               return fixl.replace('%', c);\r
+                       if (str.charAt(1) == 'h')\r
+                               return fixh.replace('%', c);\r
+               }\r
+               return "";\r
+       }\r
+\r
+       /**\r
+        * Creates a WSL comment with care to quote chars.\r
+        */\r
+       public static String createComment(String str) {\r
+               return createComment(str, C_REG);\r
+       }\r
+\r
+       /**\r
+        * Creates a WSL comment with care to quote chars, of the given type. Types\r
+        * are given as char constants. They can be default comments, comments that\r
+        * contain the original code in them, or additional comments regarding the\r
+        * translation process.\r
+        */\r
+       public static String createComment(String str, char type) {\r
+               return "C:\"" + type + str.replace("\"", "''") + "\";";\r
+       }\r
+\r
+       /**\r
+        * Creates a wsl statement that modifies the overflow limit based on the\r
+        * input string that should be the parameter of a command.\r
+        */\r
+       public String getOverflow(String str) {\r
+               int over = 256;\r
+               str = str.toLowerCase();\r
+               if (str.length() == 2) {\r
+                       if ((str.charAt(1) == 'x' && str.charAt(0) >= 'a'\r
+                                       && str.charAt(0) <= 'd')\r
+                                       || (str.compareTo("si") == 0 || str.compareTo("bp") == 0))\r
+                               over = 65536;\r
+               }\r
+               return "overflow := " + over + "; ";\r
+       }\r
+\r
+       private void debugPrint(ArrayList<String> com) {\r
+               System.out.println();\r
+               for (int i = 0; i < com.size(); i++) {\r
+                       System.out.print(com.get(i));\r
+                       System.out.print("||");\r
+               }\r
+       }\r
+\r
+       private boolean inMacro = false;\r
+\r
+       // internal state, if a procedure body is being translated currently\r
+       private boolean inProcedure = false;\r
+\r
+       // the name of the procedure currently translated, if there is one\r
+       private String currentProcName = "";\r
+\r
+       /**\r
+        * Takes a single assembler line and returns the translated WSL line(s). It\r
+        * also changes the translator modes (data, code etc).\r
+        */\r
+       public String processLine(String str) {\r
+               /* Most of the logic is here, some parts could be split off */\r
+               if (str.length() == 0)\r
+                       return "";\r
+               String[] split = str.split(";", 2);\r
+               String rez = split[0];\r
+               String comment = "";\r
+               // removes the comments\r
+               if (translateComments && split.length > 1)\r
+                       comment = createComment(split[1]);\r
+               if (rez.compareTo("") != 0) {\r
+                       // if there is a non-comment part\r
+                       String[] parts = rez.split("[\t ,]");\r
+                       // separators are whitespace: tab, space and comma\r
+                       ArrayList<String> com = new ArrayList<String>();\r
+                       for (String s : parts)\r
+                               if (s.compareTo("") != 0 && s != null)\r
+                                       com.add(s);\r
+                       rez = "";\r
+                       String a, b;\r
+                       // special case, we are processing lines in a macro definition\r
+                       if (inMacro) {\r
+                               Iterator<String> it = com.iterator();\r
+                               while (it.hasNext())\r
+                                       if (it.next().compareTo("endm") == 0)\r
+                                               inMacro = false;\r
+                               return createComment(str, C_SPEC) + "\n";\r
+                       }\r
+                       // by this time, all the real words should be in the com array\r
+                       int i = 0;\r
+                       boolean work = true;\r
+                       // debugPrint(com);\r
+                       while (i < com.size() && work) {\r
+                               String s = com.get(i).toLowerCase();\r
+                               if (s.endsWith(":")) { // should represent a label\r
+                                       s = s.substring(0, s.length() - 1);\r
+                                       rez += "CALL " + s + "\n END\n";\r
+                                       rez += s + " == ";\r
+                                       // labelfound = true;\r
+                               } else\r
+                               // ------------------------------------------------------------\r
+                               // procedures, calls and similar activities\r
+                               if (s.compareTo("proc") == 0) {\r
+                                       // if (labelfound)\r
+                                       rez += "CALL Z; SKIP END \n";\r
+                                       a = com.get(i - 1);\r
+                                       rez += a + " == ";\r
+                                       b = PROCEDURE_INTERNAL_SYS;\r
+                                       rez += "\nACTIONS " + b + ": \n";\r
+                                       rez += b + " == ";\r
+                                       inProcedure = true;\r
+                                       currentProcName = a;\r
+                               } else if (s.compareTo("endp") == 0) {\r
+                                       rez += " SKIP END\n ENDACTIONS\n END\n dummy" + nKnownC\r
+                                                       + " == ";\r
+                                       inProcedure = false;\r
+                               } else if (s.compareTo("ret") == 0) {\r
+                                       rez += " CALL Z;";\r
+                               } else if (s.compareTo("call") == 0) {\r
+                                       a = com.get(++i);\r
+                                       // check for recursive calls, don't do outside of current \r
+                                       // action system\r
+                                       if (inProcedure && currentProcName.equals(a))\r
+                                               a = PROCEDURE_INTERNAL_SYS;\r
+                                       rez += "CALL " + a + ";";\r
+                               } else\r
+                               // segments and other special assembler directives\r
+                               if (s.charAt(0) == '.') { //\r
+                                       if (s.compareTo(".code") == 0) {\r
+                                               rez = CODE_SEG_START;\r
+                                               mode = MODE_CODE;\r
+                                       } else if (s.compareTo(".data") == 0) {\r
+                                               rez = " ";\r
+                                               mode = MODE_DATA;\r
+                                       } else if (s.compareTo(".stack") == 0) {\r
+                                               rez = " ";\r
+                                               mode = MODE_STACK;\r
+                                       } else if (s.startsWith(".model")) {\r
+                                               if (!s.toLowerCase().endsWith("small")) {\r
+                                                       rez += createComment(\r
+                                                                       "other models than small not supported :: "\r
+                                                                                       + split[0],\r
+                                                                       C_SPEC);\r
+                                                       nUnknownD++;\r
+                                                       mode = MODE_0;\r
+                                               }\r
+                                       } else {\r
+                                               rez += createComment(\r
+                                                               "directive not supported :: " + split[0],\r
+                                                               C_SPEC);\r
+                                               nUnknownD++;\r
+                                               mode = MODE_0;\r
+                                       }\r
+                                       work = false;\r
+                               } else if (s.compareTo("assume") == 0) {\r
+                                       rez += createComment(\r
+                                                       "ASSUME commands not supported :: " + split[0],\r
+                                                       C_SPEC);\r
+                                       nUnknownD++;\r
+                                       work = false;\r
+                               } else if (s.compareTo("segment") == 0) {\r
+                                       String segn = com.get(i - 1).toLowerCase();\r
+                                       if (segn.compareTo("cseg") == 0\r
+                                                       || segn.compareTo("code") == 0\r
+                                                       || segn.compareTo("code_seg") == 0) {\r
+                                               rez += CODE_SEG_START;\r
+                                               mode = MODE_CODE;\r
+                                       } else if (segn.compareTo("dseg") == 0\r
+                                                       || segn.compareTo("data_seg") == 0\r
+                                                       || segn.compareTo("data") == 0) {\r
+                                               rez += " ";\r
+                                               mode = MODE_DATA;\r
+                                       } else if (segn.compareTo("sseg") == 0\r
+                                                       || segn.compareTo("stack_seg") == 0\r
+                                                       || segn.compareTo("stack") == 0) {\r
+                                               rez += " ";\r
+                                               mode = MODE_STACK;\r
+                                       } else {\r
+                                               rez += createComment(\r
+                                                               "unsuported segment type :: " + split[0],\r
+                                                               C_SPEC);\r
+                                               nUnknownD++;\r
+                                               mode = MODE_0;\r
+                                       }\r
+                                       work = false;\r
+                               } else if (s.compareTo("ends") == 0) { // segment end\r
+                                       if (i > 0) {\r
+                                               String segn = com.get(i - 1).toLowerCase();\r
+                                               if (segn.compareTo("cseg") == 0\r
+                                                               || segn.compareTo("code_seg") == 0\r
+                                                               || segn.compareTo("code") == 0\r
+                                                               || segn.compareTo("dseg") == 0\r
+                                                               || segn.compareTo("data") == 0\r
+                                                               || segn.compareTo("data_seg") == 0\r
+                                                               || segn.compareTo("sseg") == 0\r
+                                                               || segn.compareTo("stack") == 0\r
+                                                               || segn.compareTo("stack_seg") == 0) {\r
+                                                       rez += createComment("end of segment " + segn,\r
+                                                                       C_SPEC);\r
+                                                       mode = MODE_0;\r
+                                               } else {\r
+                                                       rez += createComment(\r
+                                                                       "unsuported segment type :: " + split[0],\r
+                                                                       C_SPEC);\r
+                                                       nUnknownD++;\r
+                                               }\r
+                                       } else {\r
+                                               rez += createComment("end of segment", C_SPEC);\r
+                                               mode = MODE_0;\r
+                                       }\r
+                                       work = false;\r
+                               } else\r
+                               // macro ideas ----\r
+                               if (s.compareTo("macro") == 0) {\r
+                                       rez += createComment(\r
+                                                       "found macro definition - macros unsuported",\r
+                                                       C_ERR);\r
+                                       nUnknownC++;\r
+                                       inMacro = true;\r
+                                       work = false;\r
+                               } else if (s.compareTo("endm") == 0) {\r
+                                       rez += createComment(\r
+                                                       "found macro definition end - macros unsuported",\r
+                                                       C_ERR);\r
+                                       nUnknownC++;\r
+                                       work = false;\r
+                               } else\r
+\r
+                               /*\r
+                                * ------------------------------\r
+                                *  \r
+                                * special macro names translated directly\r
+                                */\r
+                               if ((s.compareTo("print_str") == 0\r
+                                               || s.compareTo("print_num") == 0\r
+                                               || s.compareTo("print_char") == 0)\r
+                                               && com.get(i + 1).compareTo("macro") != 0) { \r
+                                       rez += "PRINFLUSH(" + com.get(i + 1) + ");";\r
+\r
+                                       work = false;\r
+                               } else if (s.compareTo("print_new_line") == 0\r
+                                               && (com.size() <= i + 1\r
+                                                               || com.get(i + 1).compareTo("macro") != 0)) { \r
+                                       rez += "PRINT(\"\");";\r
+\r
+                                       work = false;\r
+                               } else if (s.compareTo("read_str") == 0\r
+                                               && com.get(i + 1).compareTo("macro") != 0) { \r
+                                       rez += "@Read_Line_Proc(VAR " + com.get(i + 1)\r
+                                                       + ", Standard_Input_Port);";\r
+\r
+                                       work = false;\r
+                               } else if (s.compareTo("read_num") == 0\r
+                                               && com.get(i + 1).compareTo("macro") != 0) { \r
+                                       rez += "@Read_Line_Proc(VAR t_e_m_p, Standard_Input_Port);\n";\r
+                                       rez += com.get(i + 1) + " := @String_To_Num(t_e_m_p);";\r
+\r
+                                       work = false;\r
+                               } else if (s.compareTo("end_execution") == 0\r
+                                               && (com.size() <= i + 1\r
+                                                               || com.get(i + 1).compareTo("macro") != 0)) { \r
+                                       rez += "CALL Z;";\r
+\r
+                                       work = false;\r
+                               } else\r
+\r
+                               // ---------------------------------------\r
+                               // operators and similar commands\r
+                               if (s.compareTo("mov") == 0) {\r
+                                       a = com.get(i + 1);\r
+                                       b = com.get(i + 2).toLowerCase();\r
+                                       if ((b.compareTo("@data") == 0)\r
+                                                       || (b.compareTo("dseg") == 0)) {\r
+                                               rez += createComment("unneeded DATA segment fixes",\r
+                                                               C_SPEC);\r
+                                               work = false;\r
+                                       } else {// rez += getOverflow(a);\r
+                                               rez += formatDst(a) + " := " + formatParam(b) + ";";\r
+                                               rez += getXRegisterFix(a);\r
+                                               work = false;\r
+                                       }\r
+                               } else if (s.compareTo("add") == 0 || s.compareTo("adc") == 0) {\r
+                                       a = com.get(i + 1);\r
+                                       b = com.get(i + 2);\r
+                                       rez += getOverflow(a);\r
+                                       rez += formatDst(a) + " := " + formatParam(a) + " + "\r
+                                                       + formatParam(b) + ";\n";\r
+                                       if (s.compareTo("adc") == 0)\r
+                                               rez += formatDst(a) + " := " + formatParam(a) + " + "\r
+                                                               + " + flag_c;\n";\r
+                                       rez += "IF " + formatDst(a) + " >= overflow THEN "\r
+                                                       + formatDst(a) + " := " + formatDst(a)\r
+                                                       + " MOD overflow; flag_o :=1; flag_c := 1; ELSE flag_o :=0; flag_c := 0; FI;";\r
+                                       rez += getXRegisterFix(a);\r
+                                       work = false;\r
+                               } else if (s.compareTo("sub") == 0 || s.compareTo("cmp") == 0) {\r
+                                       a = com.get(i + 1);\r
+                                       b = com.get(i + 2);\r
+                                       // rez += getOverflow(a);\r
+                                       rez += "IF " + formatParam(a) + " = " + formatParam(b)\r
+                                                       + " THEN\n\t flag_z := 1\n ELSE\n\t flag_z := 0\n FI; ";\r
+                                       rez += "IF " + formatParam(a) + " < " + formatParam(b)\r
+                                                       + " THEN\n\t flag_c := 1\n ELSE\n\t flag_c := 0\n FI; ";\r
+                                       if (s.compareTo("sub") == 0)\r
+                                               rez += formatDst(a) + " := " + formatParam(a) + " - "\r
+                                                               + formatParam(b) + ";";\r
+                                       work = false;\r
+                               } else if (s.compareTo("inc") == 0) {\r
+                                       a = com.get(i + 1);\r
+                                       rez += getOverflow(a);\r
+                                       rez += formatDst(a) + " := " + formatParam(a) + " + 1;";\r
+                                       rez += getXRegisterFix(a);\r
+                                       work = false;\r
+                               } else if (s.compareTo("dec") == 0) {\r
+                                       a = com.get(i + 1);\r
+                                       rez += getOverflow(a);\r
+                                       rez += formatDst(a) + " := " + formatParam(a) + " - 1;";\r
+                                       rez += getXRegisterFix(a);\r
+                                       work = false;\r
+                               } else if (s.compareTo("shr") == 0) {\r
+                                       a = com.get(i + 1);\r
+                                       // rez += getOverflow(a);\r
+                                       rez += "IF " + formatParam(a) + " MOD 2 = 1 THEN "\r
+                                                       + " flag_c := 1; ELSE flag_c := 0; FI;";\r
+                                       rez += formatDst(a) + " := " + formatParam(a) + " DIV 2;";\r
+                                       rez += getXRegisterFix(a);\r
+                                       work = false;\r
+                               } else if (s.compareTo("shl") == 0) {\r
+                                       a = com.get(i + 1);\r
+                                       rez += getOverflow(a);\r
+                                       rez += formatDst(a) + " := " + formatParam(a) + " * 2;";\r
+                                       rez += "IF " + formatDst(a) + " >= overflow THEN "\r
+                                                       + formatDst(a) + " := " + formatDst(a)\r
+                                                       + " MOD overflow; flag_o :=1; flag_c := 1; ELSE flag_o :=0; flag_c := 0; FI;";\r
+                                       rez += getXRegisterFix(a);\r
+                                       work = false;\r
+                               } else if (s.compareTo("xchg") == 0) {\r
+                                       a = com.get(i + 1);\r
+                                       b = com.get(i + 2);\r
+                                       rez += "< " + formatDst(a) + " := " + formatParam(b) + ", "\r
+                                                       + formatDst(b) + " := " + formatParam(a) + " >;";\r
+                                       rez += getXRegisterFix(a);\r
+                                       work = false;\r
+                               } else\r
+                               // logical exp\r
+                               if (s.compareTo("and") == 0) {\r
+                                       // rez += com.get(i+1)+" := "+com.get(i+1)+" AND\r
+                                       // "+formatParam(com.get(i+2))+";";\r
+                                       rez += createComment(\r
+                                                       "and not implemented yet :: " + split[0], C_ERR);\r
+                                       nUnknownC++;\r
+                                       work = false;\r
+                               } else if (s.compareTo("xor") == 0) {\r
+                                       a = com.get(i + 1);\r
+                                       b = formatParam(com.get(i + 2));\r
+                                       if (a.compareTo(b) == 0)\r
+                                               rez += a + " := 0;";\r
+                                       else {\r
+                                               rez += createComment(\r
+                                                               "xor not implemnted yet :: " + split[0], C_ERR);\r
+                                               // a+" := ("+a+" AND NOT "+b+") OR (NOT "+a+" AND "+b+"\r
+                                               // );");\r
+                                               nUnknownC++;\r
+                                       }\r
+                                       work = false;\r
+                               } else if (s.compareTo("not") == 0) {\r
+                                       // rez += com.get(i+1)+" := NOT "+com.get(i+1)+";";\r
+                                       rez += createComment(\r
+                                                       "NOT not implemented yet :: " + split[0], C_ERR);\r
+                                       nUnknownC++;\r
+                                       work = false;\r
+                               } else\r
+                               // jumps\r
+                               if (s.compareTo("jmp") == 0) {\r
+                                       rez += "CALL " + com.get(i + 1) + ";";\r
+                                       work = false;\r
+                               } else if (s.compareTo("je") == 0 || s.compareTo("jz") == 0) {\r
+                                       rez += "IF flag_z = 1 THEN CALL " + com.get(i + 1) + " FI;";\r
+                                       work = false;\r
+                               } else if (s.compareTo("jne") == 0 || s.compareTo("jnz") == 0) {\r
+                                       rez += "IF flag_z = 0 THEN CALL " + com.get(i + 1) + " FI;";\r
+                                       work = false;\r
+                               } else if (s.compareTo("ja") == 0) {\r
+                                       rez += "IF flag_z = 0 AND flag_c = 0 THEN CALL "\r
+                                                       + com.get(i + 1) + " FI;";\r
+                                       work = false;\r
+                               } else if (s.compareTo("jae") == 0 || s.compareTo("jnc") == 0) {\r
+                                       rez += "IF flag_c = 0 THEN CALL " + com.get(i + 1) + " FI;";\r
+                                       work = false;\r
+                               } else if (s.compareTo("jb") == 0) {\r
+                                       rez += "IF flag_c = 1 THEN CALL " + com.get(i + 1) + " FI;";\r
+                                       work = false;\r
+                               } else if (s.compareTo("jcxz") == 0) {\r
+                                       rez += "IF cx = 0 THEN CALL " + com.get(i + 1) + " FI;";\r
+                                       work = false;\r
+                               } else if (s.compareTo("jo") == 0) {\r
+                                       rez += "IF flag_o = 1 THEN CALL " + com.get(i + 1) + " FI;";\r
+                                       work = false;\r
+                               } else if (s.compareTo("loop") == 0) {\r
+                                       rez += "cx := cx - 1;\n";\r
+                                       rez += "IF cx>0 THEN CALL " + com.get(i + 1)\r
+                                                       + " ELSE CALL dummy" + nKnownC + " FI\n";\r
+                                       rez += "END\ndummy" + nKnownC + " ==";\r
+                                       work = false;\r
+                               } else\r
+\r
+                               // end and other\r
+                               if (s.compareTo("end") == 0) {\r
+                                       // TODO parse the optional entry label that comes with end\r
+                                       rez += createComment("program end");\r
+                                       work = false;\r
+                               } else if (s.compareTo("nop") == 0) {\r
+                                       rez += "SKIP;";\r
+                                       work = false;\r
+                               } else\r
+\r
+                               // stack\r
+                               if (s.compareTo("pop") == 0) {\r
+                                       if (translateToPopPush) {\r
+                                               rez += "POP(" + formatDst(com.get(i + 1)) + ", stack);";\r
+                                       } else {\r
+                                               rez += formatDst(com.get(i + 1)) + " := HEAD(stack);\n";\r
+                                               rez += "stack := TAIL(stack);";\r
+                                       }\r
+                                       rez += getXRegisterFix(com.get(i + 1));\r
+                                       work = false;\r
+                               } else if (s.compareTo("push") == 0) {\r
+                                       if (translateToPopPush) {\r
+                                               rez += "PUSH(stack, " + formatParam(com.get(i + 1))\r
+                                                               + ");";\r
+                                       } else {\r
+                                               rez += "stack := < " + formatParam(com.get(i + 1))\r
+                                                               + " > ++ stack;";\r
+                                       }\r
+                                       work = false;\r
+                               } else\r
+                               // var definitions\r
+                               if (s.compareTo("db") == 0 || s.compareTo("dw") == 0) {\r
+                                       if (mode == MODE_DATA) {\r
+                                               if (com.size() == i + 2) {\r
+                                                       rez += "\t " + com.get(i - 1) + " := "\r
+                                                                       + formatParam(com.get(i + 1)) + ",";\r
+                                               } else {// array\r
+                                                       rez += "\t " + com.get(i - 1) + " := < "\r
+                                                                       + formatParam(com.get(i + 1));\r
+                                                       for (int j = i + 2; j < com.size(); j++)\r
+                                                               rez += "," + formatParam(com.get(j));\r
+                                                       rez += " >,";\r
+                                               }\r
+                                       } else {\r
+\r
+                                       }\r
+                               }\r
+                               i++;\r
+                       }\r
+                       if (rez.compareTo("") == 0 && com.size() > 0) {\r
+                               rez = createComment(" unkown command:" + split[0], C_ERR);\r
+                               nUnknownC++;\r
+                       } else\r
+                               nKnownC++; // this now counts the directives too...\r
+               }\r
+               return rez + " " + comment + "\n";\r
+\r
+       }\r
+\r
+       /**\r
+        * Converts an asm file to a wsl file. It also prints out the number of\r
+        * unsupported commands.\r
+        */\r
+       public void convertAFile(File f) {\r
+               try {\r
+                       BufferedReader in = new BufferedReader(\r
+                                       new InputStreamReader(new FileInputStream(f)));\r
+                       String str = in.readLine(), rez = f.getPath();\r
+                       if (rez.toLowerCase().endsWith(".asm"))\r
+                               rez = rez.substring(0, rez.length() - 4);\r
+                       PrintWriter out = new PrintWriter(\r
+                                       new OutputStreamWriter(new FileOutputStream(rez + ".wsl")));\r
+                       nUnknownD = 0;\r
+                       nUnknownC = 0;\r
+                       nKnownC = 0;\r
+                       StringBuilder[] sbs = new StringBuilder[N_MODES];\r
+                       for (int i = 0; i < N_MODES; i++)\r
+                               sbs[i] = new StringBuilder();\r
+                       while (str != null) {\r
+                               rez = processLine(str);\r
+                               if (originalInComments)\r
+                                       sbs[mode].append(createComment(str, C_OC) + "\n");\r
+                               sbs[mode].append(rez);\r
+                               str = in.readLine();\r
+                       }\r
+                       sbs[MODE_CODE].append(CODE_SEG_END);\r
+                       if (addMemoryDump)\r
+                               sbs[MODE_CODE].append("memdump();");\r
+                       sbs[MODE_DATA].append(DATA_SEG_END);\r
+                       // remove comments from dataseg\r
+                       String datastr = sbs[MODE_DATA].toString()\r
+                                       .replaceAll("C:\"(.*?)\";\n?", "");\r
+                       in.close();\r
+                       out.print(getStandardStart());\r
+                       out.print(sbs[MODE_0]);\r
+                       out.print(DATA_SEG_START);\r
+                       out.print(datastr); // out.print(sbs[MODE_DATA]);\r
+                       out.print(sbs[MODE_CODE]);\r
+                       out.print(getStandardEnd());\r
+                       out.close();\r
+                       if (nUnknownD > 0)\r
+                               System.out.println("warning: " + nUnknownD\r
+                                               + " unkown/unsuported directives were found");\r
+                       if (nUnknownC > 0)\r
+                               System.out.println("errors : " + nUnknownC\r
+                                               + " unkown/unsuported commands were found");\r
+                       System.out.println(nKnownC + " commands translated");\r
+               } catch (Exception e) {\r
+                       System.err.println("error in conversion:");\r
+                       e.printStackTrace();\r
+               }\r
+       }\r
+\r
+       public void run(String[] args) {\r
+               if (args.length == 0) {\r
+                       System.out.println("Assembler to WSL converter. v " + versionN\r
+                                       + ", by Doni Pracner");\r
+                       System.out.println("usage:\n\t asm2wsl {-option[ +-]} filename");\r
+                       System.out.println("options: (def value in parenthesis)");\r
+                       System.out.println("\t -oc : orignal code in comments ("\r
+                                       + (originalInComments ? "+" : "-") + ")");\r
+                       System.out.println("\t -c : translate comments ("\r
+                                       + (translateComments ? "+" : "-") + ")");\r
+                       System.out.println("\t -dump : add memory dump commands to end ("\r
+                                       + (addMemoryDump ? "+" : "-") + ")");\r
+               } else {\r
+                       if (args[0].compareTo("-h") == 0\r
+                                       || args[0].compareTo("--help") == 0) {\r
+                               run(new String[0]);\r
+                               return;\r
+                       }\r
+                       int i = 0;\r
+                       while (i < args.length && args[i].charAt(0) == '-') {\r
+                               if (args[i].startsWith("-oc")) {\r
+                                       if (args[i].length() == 4)\r
+                                               originalInComments = args[i].charAt(3) == '+';\r
+                                       else\r
+                                               originalInComments = true;\r
+                               } else if (args[i].startsWith("-c")) {\r
+                                       if (args[i].length() == 3)\r
+                                               translateComments = args[i].charAt(2) == '+';\r
+                                       else\r
+                                               translateComments = true;\r
+                               } else if (args[i].startsWith("-dump")) {\r
+                                       addMemoryDump = true;\r
+                                       if (args[i].length() == 6 && args[i].charAt(5) == '-')\r
+                                               addMemoryDump = false;\r
+                               }\r
+                               i++;\r
+                       }\r
+\r
+                       if (i >= args.length) {\r
+                               System.out.println("no filename supplied");\r
+                               System.exit(2);\r
+                       }\r
+                       File f = new File(args[i]);\r
+                       if (f.exists()) {\r
+                               Calendar now = Calendar.getInstance();\r
+                               convertAFile(f);\r
+                               long mili = Calendar.getInstance().getTimeInMillis()\r
+                                               - now.getTimeInMillis();\r
+                               System.out.println("conversion time:" + mili + " ms");\r
+                       } else\r
+                               System.out.println("file does not exist");\r
+               }\r
+       }\r
+\r
+       public static void main(String[] args) {\r
+               new asm2wsl().run(args);\r
+       }\r
+}\r
Svarog.pmf.uns.ac.rs/gitweb maintanance Doni Pracner