Ver Fonte

Auto stash before merge of "develop" and "origin/develop"

Wilfried Klaas há 6 anos atrás
pai
commit
3175cc423f

+ 6 - 0
.gitignore

@@ -3,3 +3,9 @@
 SimpleServo\.hex
 
 SimpleServo\.txt
+
+*.hex
+
+dependency-reduced-pom\.xml
+
+\.settings/

+ 0 - 6
.settings/org.eclipse.core.resources.prefs

@@ -1,6 +0,0 @@
-eclipse.preferences.version=1
-encoding//src/main/java=UTF-8
-encoding//src/main/resources=UTF-8
-encoding//src/test/java=UTF-8
-encoding//src/test/resources=UTF-8
-encoding/<project>=UTF-8

+ 0 - 9
.settings/org.eclipse.jdt.core.prefs

@@ -1,9 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
-org.eclipse.jdt.core.compiler.compliance=1.8
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=1.8

+ 0 - 4
.settings/org.eclipse.m2e.core.prefs

@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1

+ 0 - 153
dependency-reduced-pom.xml

@@ -1,153 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>de.mcs.tools.sps</groupId>
-  <artifactId>SPSEmulator</artifactId>
-  <name>${project.groupId}:${project.artifactId}</name>
-  <version>0.0.1-SNAPSHOT</version>
-  <description>SPS Emulator wirtten in java.</description>
-  <url>http://www.wk-music.de</url>
-  <developers>
-    <developer>
-      <name>Wilfried Klaas</name>
-      <email>w.klaas@gmx.de</email>
-      <organization>MCS</organization>
-      <organizationUrl>http://www.wk-music.de</organizationUrl>
-    </developer>
-  </developers>
-  <licenses>
-    <license>
-      <name>The Apache License, Version 2.0</name>
-      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
-    </license>
-  </licenses>
-  <build>
-    <plugins>
-      <plugin>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.3</version>
-        <configuration>
-          <source>1.8</source>
-          <target>1.8</target>
-        </configuration>
-      </plugin>
-      <plugin>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <version>2.19.1</version>
-        <dependencies>
-          <dependency>
-            <groupId>org.junit.platform</groupId>
-            <artifactId>junit-platform-surefire-provider</artifactId>
-            <version>1.1.0</version>
-          </dependency>
-          <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter-engine</artifactId>
-            <version>5.1.0</version>
-          </dependency>
-        </dependencies>
-      </plugin>
-      <plugin>
-        <artifactId>maven-jar-plugin</artifactId>
-        <version>2.6</version>
-        <configuration>
-          <archive>
-            <manifest>
-              <mainClass>de.mcs.tools.sps.SPSAssembler</mainClass>
-              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
-              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
-            </manifest>
-            <manifestEntries>
-              <Build-Time>${maven.build.timestamp}</Build-Time>
-              <Application-Name>SPSTools</Application-Name>
-              <Application-Update-Id>72</Application-Update-Id>
-              <Application-Update-Url>http\://wkla.no-ip.biz/downloader/version.php?ID\=73</Application-Update-Url>
-              <Application-Url>http\://wkla.no-ip.biz/</Application-Url>
-              <Implementation-Vendor>MCS, Media Computer Software</Implementation-Vendor>
-            </manifestEntries>
-          </archive>
-        </configuration>
-      </plugin>
-      <plugin>
-        <artifactId>maven-shade-plugin</artifactId>
-        <version>2.4.1</version>
-        <executions>
-          <execution>
-            <phase>package</phase>
-            <goals>
-              <goal>shade</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>com.akathist.maven.plugins.launch4j</groupId>
-        <artifactId>launch4j-maven-plugin</artifactId>
-        <version>1.7.24</version>
-        <executions>
-          <execution>
-            <id>l4j-clui</id>
-            <phase>package</phase>
-            <goals>
-              <goal>launch4j</goal>
-            </goals>
-            <configuration>
-              <dontWrapJar>false</dontWrapJar>
-              <headerType>console</headerType>
-              <jar>${project.build.directory}/${project.artifactId}-${project.version}.jar</jar>
-              <outfile>${project.build.directory}/MCSSPSTools.exe</outfile>
-              <downloadUrl>http://java.com/download</downloadUrl>
-              <icon>src\main\resources\MSA.ico</icon>
-              <jre>
-                <path>/jre</path>
-                <minVersion>1.8.0</minVersion>
-                <jdkPreference>jreOnly</jdkPreference>
-              </jre>
-              <versionInfo>
-                <fileVersion>1.0.0.0</fileVersion>
-                <txtFileVersion>${project.version}</txtFileVersion>
-                <fileDescription>${project.name}</fileDescription>
-                <copyright>2018 MCS</copyright>
-                <productVersion>1.0.0.0</productVersion>
-                <txtProductVersion>1.0.0.0</txtProductVersion>
-                <productName>${project.name}</productName>
-                <companyName>MCS</companyName>
-                <internalName>MCSSPSTools</internalName>
-                <originalFilename>MCSSPSTools.exe</originalFilename>
-              </versionInfo>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-  <dependencies>
-    <dependency>
-      <groupId>org.junit.jupiter</groupId>
-      <artifactId>junit-jupiter-api</artifactId>
-      <version>5.1.0</version>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <artifactId>apiguardian-api</artifactId>
-          <groupId>org.apiguardian</groupId>
-        </exclusion>
-        <exclusion>
-          <artifactId>opentest4j</artifactId>
-          <groupId>org.opentest4j</groupId>
-        </exclusion>
-        <exclusion>
-          <artifactId>junit-platform-commons</artifactId>
-          <groupId>org.junit.platform</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-  </dependencies>
-  <properties>
-    <maven.build.timestamp.format>dd.mm.yyyy HH:mm</maven.build.timestamp.format>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <jackson.version>2.8.5</jackson.version>
-    <timestamp>${maven.build.timestamp}</timestamp>
-  </properties>
-</project>
-

+ 11 - 7
examples/Blink.tps

@@ -1,19 +1,23 @@
 /* 
 Kommentar über mehrere Zeilen
 */
+
+.macro macro1 output time
+PORT output
+WAIT time
+PORT #0x00
+WAIT time
+.endmacro
+
 .include macro_blink
 :loop
 .macro1 #0x0f 200ms
+
 PORT #0x0F ;Zeilenkommentar
 WAIT 200ms
 PORT #0x00
 WAIT 200ms
 RJMP :loop
 
-
-.macro macro1 output time
-PORT output
-WAIT time
-PORT #0x00
-WAIT time
-.endmacro
+.macro empty
+.endmacro

+ 52 - 0
src/main/java/de/mcs/tools/sps/HEXTextOutputter.java

@@ -0,0 +1,52 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.List;
+
+import de.mcs.tools.sps.mnemonic.Mnemonic;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class HEXTextOutputter implements Outputter {
+
+  public final String FORMAT = "TPSTXT";
+
+  /**
+   * 
+   */
+  public HEXTextOutputter() {
+    // TODO Auto-generated constructor stub
+  }
+
+  /* (non-Javadoc)
+   * @see de.mcs.tools.sps.Outputter#output(java.util.List, java.io.OutputStream)
+   */
+  @Override
+  public void output(List<Mnemonic> mnemonics, OutputStream output) {
+    try (Writer writer = new BufferedWriter(new OutputStreamWriter(output))) {
+      int address = 0;
+      for (Mnemonic mnemonic : mnemonics) {
+        writer.write(String.format("%02x", mnemonic.getByte()));
+        address++;
+        if ((address % 8) == 0) {
+          writer.write("\r\n");
+        } else {
+          writer.write(" ");
+        }
+      }
+    } catch (IOException e) {
+      e.printStackTrace();
+    } finally {
+    }
+  }
+
+}

+ 42 - 0
src/main/java/de/mcs/tools/sps/IntelHEXOutputter.java

@@ -0,0 +1,42 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps;
+
+import java.io.OutputStream;
+import java.util.List;
+
+import de.mcs.tools.IntelHex;
+import de.mcs.tools.sps.mnemonic.Mnemonic;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class IntelHEXOutputter implements Outputter {
+
+  public final String FORMAT = "HEX";
+
+  /**
+   * 
+   */
+  public IntelHEXOutputter() {
+    // TODO Auto-generated constructor stub
+  }
+
+  /* (non-Javadoc)
+   * @see de.mcs.tools.sps.Outputter#output(java.util.List, java.io.OutputStream)
+   */
+  @Override
+  public void output(List<Mnemonic> mnemonics, OutputStream output) {
+    IntelHex intelHex = new IntelHex();
+    byte[] data = new byte[mnemonics.size()];
+    int i = 0;
+    for (Mnemonic mnemonic : mnemonics) {
+      data[i] = (byte) mnemonic.getByte();
+      i++;
+    }
+    intelHex.writeHexStream(output, data);
+  }
+
+}

+ 21 - 0
src/main/java/de/mcs/tools/sps/Macro.java

@@ -24,6 +24,8 @@ package de.mcs.tools.sps;
 import java.util.ArrayList;
 import java.util.List;
 
+import de.mcs.tools.sps.exceptions.SyntaxError;
+
 /**
  * @author wklaa_000
  *
@@ -68,4 +70,23 @@ public class Macro {
   public void addLine(String line) {
     lines.add(line);
   }
+
+  public List<String> processMacro(String[] values, int lineNumber) throws SyntaxError {
+    if (values.length != args.length) {
+      throw new SyntaxError(lineNumber,
+          String.format("count of macro arguments (%d) are not the same as in macro definition (%d) of macro \"%s\".",
+              values.length, args.length, name));
+    }
+    List<String> mnemonics = new ArrayList<>();
+    lines.forEach(l -> {
+      String line = l;
+      for (int i = 0; i < args.length; i++) {
+        String key = args[i];
+        String value = values[i];
+        line = line.replace(key, value);
+      }
+      mnemonics.add(line);
+    });
+    return mnemonics;
+  }
 }

+ 19 - 0
src/main/java/de/mcs/tools/sps/Outputter.java

@@ -0,0 +1,19 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps;
+
+import java.io.OutputStream;
+import java.util.List;
+
+import de.mcs.tools.sps.mnemonic.Mnemonic;
+
+/**
+ * @author w.klaas
+ *
+ */
+public interface Outputter {
+
+  void output(List<Mnemonic> mnemonics, OutputStream output);
+
+}

+ 236 - 157
src/main/java/de/mcs/tools/sps/SPSAssembler.java

@@ -21,13 +21,10 @@
  */
 package de.mcs.tools.sps;
 
-import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
-import java.io.FileWriter;
 import java.io.IOException;
-import java.io.Writer;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.util.ArrayList;
@@ -40,7 +37,7 @@ import java.util.Map.Entry;
 
 import org.apache.commons.lang3.StringUtils;
 
-import de.mcs.tools.IntelHex;
+import de.mcs.tools.sps.exceptions.IllegalArgument;
 import de.mcs.tools.sps.exceptions.SyntaxError;
 import de.mcs.tools.sps.mnemonic.CALL;
 import de.mcs.tools.sps.mnemonic.HARDWARE;
@@ -69,24 +66,18 @@ public class SPSAssembler {
   private static final String START_MACRO_DEFINITION = ".macro";
   private static File source;
   private static HARDWARE destination;
-  private static int lineNumber;
-  private static int srcLineNumber;
-  private static Map<String, Integer> labels = new HashMap<>();
-  private static boolean inBlockComment;
-  private static List<Mnemonic> mnemonics = new ArrayList<>();
   private static File destinationFile;
   private static FORMAT outputFormat;
-  private static File include;
-  private static boolean inMacro;
-  private static Macro actualMacro;
-  private static Map<String, Macro> macros = new HashMap<>();
+  private static File includes;
 
-  /**
-   * 
-   */
-  public SPSAssembler() {
-    // TODO Auto-generated constructor stub
-  }
+  private int lineNumber;
+  // private int srcLineNumber;
+  private Map<String, Integer> labels;
+  private boolean inBlockComment;
+  private List<Mnemonic> mnemonics;
+  private boolean inMacro;
+  private Macro actualMacro;
+  private Map<String, Macro> macros;
 
   @SwitchOption(shortKey = 'h', longKey = "help", name = "help", help = "show this help page", required = false, defaultValue = false)
   public static void doHelp(boolean value) {
@@ -106,10 +97,10 @@ public class SPSAssembler {
     destination = HARDWARE.valueOf((value.toUpperCase()));
   }
 
-  @FileOption(shortKey = 'i', longKey = "include", name = "include", defaultValue = "", help = "where to find the include files.", required = false)
+  @FileOption(shortKey = 'i', longKey = "includes", name = "includes", defaultValue = "", help = "where to find the includes files.", required = false)
   public static void setDestinationSystem(File file) {
     if ((file != null) && !file.getName().equals("")) {
-      include = file;
+      includes = file;
     }
   }
 
@@ -152,137 +143,162 @@ public class SPSAssembler {
         destinationFile = new File(source.getParentFile(), name + ext);
       }
       System.out.printf("destination file: %s \r\n", destinationFile.getName());
+      System.out.printf("output format: %s \r\n", outputFormat.name());
       System.out.println();
 
       try {
-        List<String> sourceFile = Files.readAllLines(source.toPath(), Charset.forName("UTF-8"));
-        for (String line : sourceFile) {
-          srcLineNumber++;
-          parseLine(srcLineNumber, line);
-        }
+        SPSAssembler spsAssembler = new SPSAssembler();
+        spsAssembler.doWork(source);
+
+        List<Mnemonic> mnemonics = spsAssembler.getMnemonics();
+
+        outputMnemonics(mnemonics);
+
+        outputLabels(spsAssembler);
+
+        outputMacros(spsAssembler);
+
+        outputFile(mnemonics);
 
       } catch (SyntaxError e) {
         e.printStackTrace();
         System.err.println(e.getMessage());
         System.exit(-1);
       }
-      // Checking destination
-      for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
-        Mnemonic mnemonic = iterator.next();
-        if (!mnemonic.allowedHardware().contains(destination)) {
-          throw new SyntaxError(mnemonic.getLineNumber(), String.format(
-              "the mnemonic \"%s\" with the argument \"%s\" is not availble on the choosen hardware \"%s\"",
-              mnemonic.getName(), mnemonic.getArgument() == null ? "" : mnemonic.getArgument(), destination.name()));
-        }
-      }
-
-      System.out.println("parsing line numbers");
-      int address = 0;
-      Mnemonic predecessor = null;
-      for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
-        Mnemonic mnemonic = iterator.next();
-        if ((mnemonic instanceof JMP) || (mnemonic instanceof LOOPC) || (mnemonic instanceof LOOPD)
-            || (mnemonic instanceof CALL)) {
-          if (mnemonic.isLabel()) {
-            processJMP(mnemonic, predecessor);
-          }
-        }
-        if (mnemonic instanceof RJMP) {
-          if (mnemonic.isLabel()) {
-            processRJMP(address, mnemonic);
-          }
-        }
-        address++;
-        predecessor = mnemonic;
-      }
-
-      System.out.println("Mnemonics");
-      int pos = 0;
-      for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
-        Mnemonic mnemonic = iterator.next();
-        System.out.printf("0x%03x: %s\r\n", pos, mnemonic.toString());
-        pos++;
-      }
-
-      if ((labels != null) && (labels.size() > 0)) {
-        System.out.println();
-        System.out.println("labels");
-        for (Entry<String, Integer> entry : labels.entrySet()) {
-          System.out.printf("%s: 0x%03x\r\n", entry.getKey(), entry.getValue());
-        }
-      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
 
+  /**
+   * @param mnemonics
+   * @throws IOException
+   * @throws FileNotFoundException
+   */
+  private static void outputFile(List<Mnemonic> mnemonics) throws IOException, FileNotFoundException {
+    try (FileOutputStream output = new FileOutputStream(destinationFile)) {
       if (outputFormat.equals(FORMAT.HEX)) {
-        outputHEX();
+        new IntelHEXOutputter().output(mnemonics, output);
       } else if (outputFormat.equals(FORMAT.TPSTXT)) {
-        outputTPSTXT();
+        new TPSTextOutputter().output(mnemonics, output);
       } else if (outputFormat.equals(FORMAT.HEXTXT)) {
-        outputHEXTXT();
+        new HEXTextOutputter().output(mnemonics, output);
       }
-    } catch (Exception e) {
-      e.printStackTrace();
+    } finally {
     }
   }
 
-  private static void outputHEXTXT() {
-    try (Writer writer = new BufferedWriter(new FileWriter(destinationFile))) {
-      int address = 0;
-      for (Mnemonic mnemonic : mnemonics) {
-        writer.write(String.format("%02x", mnemonic.getByte()));
-        address++;
-        if ((address % 8) == 0) {
-          writer.write("\r\n");
-        } else {
-          writer.write(" ");
-        }
+  /**
+   * @param spsAssembler
+   */
+  private static void outputMacros(SPSAssembler spsAssembler) {
+    Map<String, Macro> macros = spsAssembler.getMacros();
+    if ((macros != null) && (macros.size() > 0)) {
+      System.out.println();
+      System.out.println("macros");
+      for (Macro macro : macros.values()) {
+        System.out.printf("%s: %s\r\n", macro.getName(), macro.toString());
       }
-    } catch (IOException e) {
-      e.printStackTrace();
-    } finally {
     }
   }
 
-  private static void outputTPSTXT() {
-    try (Writer writer = new BufferedWriter(new FileWriter(destinationFile))) {
-      writer.write("Addr   BD   Befehl   Daten     Kommentar\r\n");
-      int address = 0;
-      for (Mnemonic mnemonic : mnemonics) {
-        byte lowNibble = (byte) (mnemonic.getByte() & 0x0f);
-        byte highNibble = (byte) ((mnemonic.getByte() >> 4) & 0x0f);
-        writer.write(String.format("0x%03x  %02x   %4s     %4s      %s %s\r\n", address, mnemonic.getByte(),
-            nibbleToString(highNibble), nibbleToString(lowNibble), mnemonic.getName(),
-            StringUtils.isEmpty(mnemonic.getArgument()) ? "" : mnemonic.getArgument()));
-        address++;
+  /**
+   * @param spsAssembler
+   */
+  private static void outputLabels(SPSAssembler spsAssembler) {
+    Map<String, Integer> labels = spsAssembler.getLabels();
+    if ((labels != null) && (labels.size() > 0)) {
+      System.out.println();
+      System.out.println("labels");
+      for (Entry<String, Integer> entry : labels.entrySet()) {
+        System.out.printf("%s: 0x%03x\r\n", entry.getKey(), entry.getValue());
       }
-    } catch (IOException e) {
-      e.printStackTrace();
-    } finally {
     }
   }
 
-  private static String nibbleToString(byte lowNibble) {
-    StringBuilder b = new StringBuilder();
-    b.append((lowNibble & 0x08) > 0 ? "X" : "0");
-    b.append((lowNibble & 0x04) > 0 ? "X" : "0");
-    b.append((lowNibble & 0x02) > 0 ? "X" : "0");
-    b.append((lowNibble & 0x01) > 0 ? "X" : "0");
-    return b.toString();
+  /**
+   * @param mnemonics
+   */
+  private static void outputMnemonics(List<Mnemonic> mnemonics) {
+    System.out.println("Mnemonics");
+    int pos = 0;
+    for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
+      Mnemonic mnemonic = iterator.next();
+      System.out.printf("0x%03x: %s\r\n", pos, mnemonic.toString());
+      pos++;
+    }
+  }
+
+  /**
+   * 
+   */
+  public SPSAssembler() {
+    lineNumber = 0;
+    // srcLineNumber = 0;
+    labels = new HashMap<>();
+    inBlockComment = false;
+    mnemonics = new ArrayList<>();
+    inMacro = false;
+    actualMacro = null;
+    macros = new HashMap<>();
   }
 
-  private static void outputHEX() throws FileNotFoundException, IOException {
-    IntelHex intelHex = new IntelHex();
-    byte[] data = new byte[mnemonics.size()];
-    int i = 0;
-    for (Mnemonic mnemonic : mnemonics) {
-      data[i] = (byte) mnemonic.getByte();
-      i++;
+  private void doWork(File source) throws IOException, SyntaxError {
+    List<String> sourceFile = Files.readAllLines(source.toPath(), Charset.forName("UTF-8"));
+    for (int i = 0; i < sourceFile.size(); i++) {
+      String line = sourceFile.get(i);
+
+      List<String> linesToAdd;
+      do {
+        linesToAdd = parseLine(i, line);
+        if (linesToAdd != null) {
+          sourceFile.remove(i);
+          sourceFile.addAll(i, linesToAdd);
+          line = sourceFile.get(i);
+          linesToAdd = parseLine(i, line);
+        }
+      } while (linesToAdd != null);
+    }
+
+    // Checking destination
+    checkingHardware();
+
+    System.out.printf("start parsing file: %s\r\n", source.getName());
+    int address = 0;
+    Mnemonic predecessor = null;
+    for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
+      Mnemonic mnemonic = iterator.next();
+      if ((mnemonic instanceof JMP) || (mnemonic instanceof LOOPC) || (mnemonic instanceof LOOPD)
+          || (mnemonic instanceof CALL)) {
+        if (mnemonic.isLabel()) {
+          processJMP(mnemonic, predecessor);
+        }
+      }
+      if (mnemonic instanceof RJMP) {
+        if (mnemonic.isLabel()) {
+          processRJMP(address, mnemonic);
+        }
+      }
+      address++;
+      predecessor = mnemonic;
     }
-    FileOutputStream output = new FileOutputStream(destinationFile);
-    intelHex.writeHexStream(output, data);
-    output.close();
   }
 
-  private static void processJMP(Mnemonic mnemonic, Mnemonic predecessor) throws SyntaxError {
+  /**
+   * @throws SyntaxError
+   */
+  private void checkingHardware() throws SyntaxError {
+    for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
+      Mnemonic mnemonic = iterator.next();
+      if (!mnemonic.allowedHardware().contains(destination)) {
+        throw new SyntaxError(mnemonic.getLineNumber(),
+            String.format("the mnemonic \"%s\" with the argument \"%s\" is not availble on the choosen hardware \"%s\"",
+                mnemonic.getName(), mnemonic.getArgument() == null ? "" : mnemonic.getArgument(), destination.name()));
+      }
+    }
+  }
+
+  private void processJMP(Mnemonic mnemonic, Mnemonic predecessor) throws SyntaxError {
     String label = mnemonic.getArgument();
     if (!labels.containsKey(label)) {
       throw new SyntaxError(mnemonic.getLineNumber(),
@@ -302,7 +318,7 @@ public class SPSAssembler {
     }
   }
 
-  private static void processRJMP(int address, Mnemonic mnemonic) throws SyntaxError {
+  private void processRJMP(int address, Mnemonic mnemonic) throws SyntaxError {
     String label = mnemonic.getArgument();
     if (!labels.containsKey(label)) {
       throw new SyntaxError(mnemonic.getLineNumber(),
@@ -318,49 +334,45 @@ public class SPSAssembler {
     mnemonic.checkArgument();
   }
 
-  private static void parseLine(int srcLineNumber, String srcLine) throws SyntaxError {
+  private List<String> parseLine(int srcLineNumber, String srcLine) throws SyntaxError, IOException {
     String line = srcLine.trim();
-    if (inMacro) {
-      actualMacro.addLine(line);
+    if (line.startsWith(".")) {
+      // process pre compiler part
+      String label = getLabel(line);
+      return precompiler(srcLineNumber, label);
     } else {
-      if (line.startsWith(":")) {
-        String label = getLabel(line);
-        if (labels.containsKey(label)) {
-          throw new SyntaxError(srcLineNumber,
-              String.format("Label \"%s\" already definied in line %d.", label, labels.get(label)));
-        }
-        labels.put(label, lineNumber);
-      } else if (line.startsWith(".")) {
-        // process pre compiler part
-        String label = getLabel(line);
-        precompiler(srcLineNumber, label);
+      if (inMacro) {
+        actualMacro.addLine(line);
       } else {
-        Mnemonic mnemonic = getMnemonic(line);
-        if (mnemonic != null) {
-          lineNumber++;
-          mnemonics.add(mnemonic);
+        if (line.startsWith(":")) {
+          String label = getLabel(line);
+          if (labels.containsKey(label)) {
+            throw new SyntaxError(srcLineNumber,
+                String.format("Label \"%s\" already definied in line %d.", label, labels.get(label)));
+          }
+          labels.put(label, lineNumber);
+        } else {
+          Mnemonic mnemonic = getMnemonic(line, srcLineNumber);
+          if (mnemonic != null) {
+            lineNumber++;
+            mnemonics.add(mnemonic);
+          }
         }
       }
     }
+    return null;
   }
 
-  private static void precompiler(int srcLineNumber, String value) {
+  private List<String> precompiler(int srcLineNumber, String value) throws IOException, SyntaxError {
     String label = value.trim().toLowerCase();
     String name = label;
     if (label.indexOf(" ") > 0) {
       name = label.substring(0, label.indexOf(" "));
     }
     if (INCLUDE_FILE.equals(name)) {
-      // proccess include file
+      includeFile(srcLineNumber, label);
     } else if (START_MACRO_DEFINITION.equals(name)) {
-      // macro definition
-      String[] arguments = label.split(" ");
-      String macroName = arguments[1];
-      String[] args = null;
-      if (arguments.length > 2) {
-        args = Arrays.copyOfRange(arguments, 2, arguments.length);
-      }
-      actualMacro = new Macro(macroName, args);
+      startMacroDefinition(srcLineNumber, label);
       inMacro = true;
     } else if (END_MACRO_DEFINITION.equalsIgnoreCase(label)) {
       // end of macro definition
@@ -368,10 +380,71 @@ public class SPSAssembler {
       macros.put(actualMacro.getName(), actualMacro);
     } else {
       // seems to be a macro usage
+      name = name.substring(1);
+      String[] arguments = label.split(" ");
+      if (arguments.length < 2) {
+        throw new IllegalArgument(srcLineNumber, "Need at least one argument for the macro name.");
+      }
+      String[] args = null;
+      if (arguments.length > 1) {
+        args = Arrays.copyOfRange(arguments, 1, arguments.length);
+      }
+      Macro macro = macros.get(name);
+      if (macro == null) {
+        throw new SyntaxError(srcLineNumber, String.format("macro with name %s not define.", name));
+      }
+      List<String> macroMnemonics = macro.processMacro(args, srcLineNumber);
+      return macroMnemonics;
+    }
+    return null;
+  }
+
+  /**
+   * @param srcLineNumber
+   * @param label
+   * @throws IllegalArgument
+   */
+  private void startMacroDefinition(int srcLineNumber, String label) throws IllegalArgument {
+    // macro definition
+    String[] arguments = label.split(" ");
+    if (arguments.length < 2) {
+      throw new IllegalArgument(srcLineNumber, "Need at least one argument for the macro name.");
+    }
+    String macroName = arguments[1];
+    String[] args = null;
+    if (arguments.length > 2) {
+      args = Arrays.copyOfRange(arguments, 2, arguments.length);
+    }
+    actualMacro = new Macro(macroName, args);
+  }
+
+  /**
+   * @param srcLineNumber
+   * @param label
+   * @throws IllegalArgument
+   * @throws IOException
+   * @throws SyntaxError
+   */
+  private void includeFile(int srcLineNumber, String label) throws IllegalArgument, IOException, SyntaxError {
+    String[] arguments = label.split(" ");
+    if (arguments.length < 2) {
+      throw new IllegalArgument(srcLineNumber, "Need at least one argument for the filename to include.");
+    }
+    File includeFile = new File(includes, String.format("%s.tps", arguments[1]));
+    if (!includeFile.exists()) {
+      throw new IllegalArgument(srcLineNumber, String.format("include file not found: %s", includeFile.getName()));
     }
+    System.out.println("=====");
+    System.out.printf("include file: %s \r\n", includeFile.getName());
+    SPSAssembler spsAssembler = new SPSAssembler();
+    spsAssembler.doWork(includeFile);
+    outputMnemonics(spsAssembler.getMnemonics());
+    outputLabels(spsAssembler);
+    outputMacros(spsAssembler);
+    System.out.println("=====");
   }
 
-  private static Mnemonic getMnemonic(String line) throws SyntaxError {
+  private Mnemonic getMnemonic(String line, int srcLineNumber) throws SyntaxError {
     String newLine = stripComments(line);
     if (StringUtils.isNotEmpty(newLine)) {
       Mnemonic mnemonic = MnemonicFactory.getMnemonic(newLine, srcLineNumber);
@@ -380,7 +453,7 @@ public class SPSAssembler {
     return null;
   }
 
-  private static String stripComments(String line) {
+  private String stripComments(String line) {
     if (line.indexOf("*/") >= 0) {
       inBlockComment = false;
       return null;
@@ -399,14 +472,20 @@ public class SPSAssembler {
     return line.trim();
   }
 
-  private static String getLabel(String line) {
+  private String getLabel(String line) {
     line = stripComments(line);
     return line;
   }
 
-  private static void showHelp() {
-    System.out.println("usage SPSAssembler <sorucefile> [<destination>]");
-    System.exit(0);
+  private List<Mnemonic> getMnemonics() {
+    return mnemonics;
   }
 
+  private Map<String, Macro> getMacros() {
+    return macros;
+  }
+
+  private Map<String, Integer> getLabels() {
+    return labels;
+  }
 }

+ 63 - 0
src/main/java/de/mcs/tools/sps/TPSTextOutputter.java

@@ -0,0 +1,63 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+
+import de.mcs.tools.sps.mnemonic.Mnemonic;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class TPSTextOutputter implements Outputter {
+
+  public final String FORMAT = "TPSTXT";
+
+  /**
+   * 
+   */
+  public TPSTextOutputter() {
+    // TODO Auto-generated constructor stub
+  }
+
+  /* (non-Javadoc)
+   * @see de.mcs.tools.sps.Outputter#output(java.util.List, java.io.OutputStream)
+   */
+  @Override
+  public void output(List<Mnemonic> mnemonics, OutputStream output) {
+    try (Writer writer = new BufferedWriter(new OutputStreamWriter(output))) {
+      writer.write("Addr   BD   Befehl   Daten     Kommentar\r\n");
+      int address = 0;
+      for (Mnemonic mnemonic : mnemonics) {
+        byte lowNibble = (byte) (mnemonic.getByte() & 0x0f);
+        byte highNibble = (byte) ((mnemonic.getByte() >> 4) & 0x0f);
+        writer.write(String.format("0x%03x  %02x   %4s     %4s      %s %s\r\n", address, mnemonic.getByte(),
+            nibbleToString(highNibble), nibbleToString(lowNibble), mnemonic.getName(),
+            StringUtils.isEmpty(mnemonic.getArgument()) ? "" : mnemonic.getArgument()));
+        address++;
+      }
+    } catch (IOException e) {
+      e.printStackTrace();
+    } finally {
+    }
+  }
+
+  private String nibbleToString(byte lowNibble) {
+    StringBuilder b = new StringBuilder();
+    b.append((lowNibble & 0x08) > 0 ? "X" : "0");
+    b.append((lowNibble & 0x04) > 0 ? "X" : "0");
+    b.append((lowNibble & 0x02) > 0 ? "X" : "0");
+    b.append((lowNibble & 0x01) > 0 ? "X" : "0");
+    return b.toString();
+  }
+
+}