Add aslshim which is just a subset of files from asl-current so far
authorNick Downing <nick@ndcode.org>
Sat, 18 Jun 2022 02:10:44 +0000 (12:10 +1000)
committerNick Downing <nick@ndcode.org>
Sat, 18 Jun 2022 02:19:33 +0000 (12:19 +1000)
68 files changed:
aslcop8/codecop8.c [new file with mode: 0644]
aslcop8/codecop8.h [new file with mode: 0644]
aslshim/addrspace.h [new file with mode: 0644]
aslshim/as.h [new file with mode: 0644]
aslshim/as.rsc [new file with mode: 0644]
aslshim/asmdebug.h [new file with mode: 0644]
aslshim/asmdef.c [new file with mode: 0644]
aslshim/asmdef.h [new file with mode: 0644]
aslshim/asmerr.c [new file with mode: 0644]
aslshim/asmerr.h [new file with mode: 0644]
aslshim/asmfnums.h [new file with mode: 0644]
aslshim/asmitree.c [new file with mode: 0644]
aslshim/asmitree.h [new file with mode: 0644]
aslshim/asmpars.c [new file with mode: 0644]
aslshim/asmpars.h [new file with mode: 0644]
aslshim/asmrelocs.h [new file with mode: 0644]
aslshim/asmstructs.h [new file with mode: 0644]
aslshim/asmsub.c [new file with mode: 0644]
aslshim/asmsub.h [new file with mode: 0644]
aslshim/bpemu.c [new file with mode: 0644]
aslshim/bpemu.h [new file with mode: 0644]
aslshim/chardefs.h [new file with mode: 0644]
aslshim/chunks.h [new file with mode: 0644]
aslshim/codepseudo.h [new file with mode: 0644]
aslshim/codevars.c [new file with mode: 0644]
aslshim/codevars.h [new file with mode: 0644]
aslshim/console.h [new file with mode: 0644]
aslshim/cppops.h [new file with mode: 0644]
aslshim/cpulist.c [new file with mode: 0644]
aslshim/cpulist.h [new file with mode: 0644]
aslshim/datatypes.h [new file with mode: 0644]
aslshim/dynstr.c [new file with mode: 0644]
aslshim/dynstr.h [new file with mode: 0644]
aslshim/endian.h [new file with mode: 0644]
aslshim/errmsg.c [new file with mode: 0644]
aslshim/errmsg.h [new file with mode: 0644]
aslshim/fileformat.h [new file with mode: 0644]
aslshim/function.h [new file with mode: 0644]
aslshim/ieeefloat.h [new file with mode: 0644]
aslshim/intformat.c [new file with mode: 0644]
aslshim/intformat.h [new file with mode: 0644]
aslshim/intpseudo.c [new file with mode: 0644]
aslshim/intpseudo.h [new file with mode: 0644]
aslshim/ioerrs.h [new file with mode: 0644]
aslshim/lstmacroexp.h [new file with mode: 0644]
aslshim/math64.h [new file with mode: 0644]
aslshim/natpseudo.c [new file with mode: 0644]
aslshim/natpseudo.h [new file with mode: 0644]
aslshim/nlmessages.h [new file with mode: 0644]
aslshim/nls.h [new file with mode: 0644]
aslshim/nonzstring.h [new file with mode: 0644]
aslshim/onoff_common.h [new file with mode: 0644]
aslshim/operator.h [new file with mode: 0644]
aslshim/pascstyle.h [new file with mode: 0644]
aslshim/stdhandl.h [new file with mode: 0644]
aslshim/stdinc.h [new file with mode: 0644]
aslshim/strcomp.c [new file with mode: 0644]
aslshim/strcomp.h [new file with mode: 0644]
aslshim/stringlists.h [new file with mode: 0644]
aslshim/strutil.c [new file with mode: 0644]
aslshim/strutil.h [new file with mode: 0644]
aslshim/symbolsize.h [new file with mode: 0644]
aslshim/symflags.h [new file with mode: 0644]
aslshim/sysdefs.h [new file with mode: 0644]
aslshim/tempresult.h [new file with mode: 0644]
aslshim/trees.h [new file with mode: 0644]
aslshim/version.h [new file with mode: 0644]
asxmak/linux/build/makefile

diff --git a/aslcop8/codecop8.c b/aslcop8/codecop8.c
new file mode 100644 (file)
index 0000000..e3a9a68
--- /dev/null
@@ -0,0 +1,727 @@
+/* codecop8.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Codegeneratormodul COP8-Familie                                           */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmitree.h"
+#include "codepseudo.h"
+#include "intpseudo.h"
+#include "natpseudo.h"
+#include "codevars.h"
+#include "errmsg.h"
+
+#include "codecop8.h"
+
+#define ModNone (-1)
+#define ModAcc 0
+#define MModAcc (1 << ModAcc)
+#define ModBInd 1
+#define MModBInd (1 << ModBInd)
+#define ModBInc 2
+#define MModBInc (1 << ModBInc)
+#define ModBDec 3
+#define MModBDec (1 << ModBDec)
+#define ModXInd 4
+#define MModXInd (1 << ModXInd)
+#define ModXInc 5
+#define MModXInc (1 << ModXInc)
+#define ModXDec 6
+#define MModXDec (1 << ModXDec)
+#define ModDir 7
+#define MModDir (1 << ModDir)
+#define ModImm 8
+#define MModImm (1 << ModImm)
+
+#define DirPrefix 0xbd
+#define BReg 0xfe
+
+#define BitOrderCnt 3
+
+static CPUVar CPUCOP87L84;
+
+typedef struct
+{
+  ShortInt Mode;
+  Byte Val;
+  tSymbolFlags ValSymFlags;
+} tAdrResult;
+
+/*---------------------------------------------------------------------------*/
+
+static ShortInt DecodeAdr(const tStrComp *pArg, Word Mask, tAdrResult *pResult)
+{
+  static const char ModStrings[ModXDec + 1][5] =
+  {
+    "A", "[B]", "[B+]", "[B-]",
+    "[X]", "[X+]", "[X-]"
+  };
+
+  int z;
+  tEvalResult EvalResult;
+
+  pResult->Mode = ModNone;
+
+   /* indirekt/Akku */
+
+  for (z = ModAcc; z <= ModXDec; z++)
+    if (!as_strcasecmp(pArg->str.p_str, ModStrings[z]))
+    {
+      pResult->Mode = z;
+      goto chk;
+    }
+
+  /* immediate */
+
+  if (*pArg->str.p_str == '#')
+  {
+    pResult->Val = EvalStrIntExpressionOffsWithResult(pArg, 1, Int8, &EvalResult);
+    if (EvalResult.OK)
+    {
+      pResult->Mode = ModImm;
+      pResult->ValSymFlags = EvalResult.Flags;
+    }
+    goto chk;
+  }
+
+  /* direkt */
+
+  pResult->Val = EvalStrIntExpressionWithResult(pArg, Int8, &EvalResult);
+  if (EvalResult.OK)
+  {
+    pResult->Mode = ModDir;
+    pResult->ValSymFlags = EvalResult.Flags;
+    ChkSpace(SegData, EvalResult.AddrSpaceMask);
+  }
+
+chk:
+  if ((pResult->Mode != ModNone) && !(Mask & (1 << pResult->Mode)))
+  {
+    pResult->Mode = ModNone; WrError(ErrNum_InvAddrMode);
+  }
+  return pResult->Mode;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void DecodeFixed(Word Code)
+{
+  if (ChkArgCnt(0, 0))
+  {
+    BAsmCode[0] = Code;
+    CodeLen = 1;
+  }
+}
+
+static void DecodeLD(Word Code)
+{
+  UNUSED(Code);
+
+  if (ChkArgCnt(2, 2))
+  {
+    tAdrResult DestResult;
+
+    switch (DecodeAdr(&ArgStr[1], MModAcc | MModDir | MModBInd | MModBInc | MModBDec, &DestResult))
+    {
+      case ModAcc:
+      {
+        tAdrResult SrcResult;
+
+        switch(DecodeAdr(&ArgStr[2], MModDir | MModImm | MModBInd | MModXInd | MModBInc | MModXInc | MModBDec | MModXDec, &SrcResult))
+        {
+          case ModDir:
+            BAsmCode[0] = 0x9d;
+            BAsmCode[1] = SrcResult.Val;
+            CodeLen = 2;
+            break;
+          case ModImm:
+            BAsmCode[0] = 0x98;
+            BAsmCode[1] = SrcResult.Val;
+            CodeLen = 2;
+            break;
+          case ModBInd:
+            BAsmCode[0] = 0xae;
+            CodeLen = 1;
+            break;
+          case ModXInd:
+            BAsmCode[0] = 0xbe;
+            CodeLen = 1;
+            break;
+          case ModBInc:
+            BAsmCode[0] = 0xaa;
+            CodeLen = 1;
+            break;
+          case ModXInc:
+            BAsmCode[0] = 0xba;
+            CodeLen = 1;
+            break;
+          case ModBDec:
+            BAsmCode[0] = 0xab;
+            CodeLen = 1;
+            break;
+          case ModXDec:
+            BAsmCode[0] = 0xbb;
+            CodeLen = 1;
+            break;
+        }
+        break;
+      }
+      case ModDir:
+      {
+        tAdrResult SrcResult;
+
+        if (DecodeAdr(&ArgStr[2], MModImm, &SrcResult) == ModImm)
+        {
+          if (DestResult.Val == BReg)
+          {
+            if (SrcResult.Val <= 15)
+            {
+              BAsmCode[0] = 0x5f - SrcResult.Val;
+              CodeLen = 1;
+            }
+            else
+            {
+              BAsmCode[0] = 0x9f;
+              BAsmCode[1] = SrcResult.Val;
+              CodeLen = 2;
+            }
+          }
+          else if (DestResult.Val >= 0xf0)
+          {
+            BAsmCode[0] = DestResult.Val - 0x20;
+            BAsmCode[1] = SrcResult.Val;
+            CodeLen = 2;
+          }
+          else
+          {
+            BAsmCode[0] = 0xbc;
+            BAsmCode[1] = DestResult.Val;
+            BAsmCode[2] = SrcResult.Val;
+            CodeLen = 3;
+          }
+        }
+        break;
+      }
+      case ModBInd:
+      {
+        tAdrResult SrcResult;
+
+        if (DecodeAdr(&ArgStr[2], MModImm, &SrcResult) != ModNone)
+        {
+          BAsmCode[0] = 0x9e;
+          BAsmCode[1] = SrcResult.Val;
+          CodeLen = 2;
+        }
+        break;
+      }
+      case ModBInc:
+      {
+        tAdrResult SrcResult;
+
+        if (DecodeAdr(&ArgStr[2], MModImm, &SrcResult) != ModNone)
+        {
+          BAsmCode[0] = 0x9a;
+          BAsmCode[1] = SrcResult.Val;
+          CodeLen = 2;
+        }
+        break;
+      }
+      case ModBDec:
+      {
+        tAdrResult SrcResult;
+
+        if (DecodeAdr(&ArgStr[2], MModImm, &SrcResult) != ModNone)
+        {
+          BAsmCode[0] = 0x9b;
+          BAsmCode[1] = SrcResult.Val;
+          CodeLen = 2;
+        }
+        break;
+      }
+    }
+  }
+}
+
+static void DecodeX(Word Code)
+{
+  UNUSED(Code);
+
+  if (ChkArgCnt(2, 2))
+  {
+    tStrComp *pAccArg, *pMemArg;
+    tAdrResult DestResult;
+
+    if (as_strcasecmp(ArgStr[1].str.p_str, "A"))
+    {
+      pAccArg = &ArgStr[2];
+      pMemArg = &ArgStr[1];
+    }
+    else
+    {
+      pAccArg = &ArgStr[1];
+      pMemArg = &ArgStr[2];
+    }
+    if (DecodeAdr(pAccArg, MModAcc, &DestResult) != ModNone)
+    {
+      tAdrResult SrcResult;
+
+      switch (DecodeAdr(pMemArg, MModDir | MModBInd | MModXInd | MModBInc | MModXInc | MModBDec | MModXDec, &SrcResult))
+      {
+        case ModDir:
+          BAsmCode[0] = 0x9c;
+          BAsmCode[1] = SrcResult.Val;
+          CodeLen = 2;
+          break;
+        case ModBInd:
+          BAsmCode[0] = 0xa6;
+          CodeLen = 1;
+          break;
+        case ModBInc:
+          BAsmCode[0] = 0xa2;
+          CodeLen = 1;
+          break;
+        case ModBDec:
+          BAsmCode[0] = 0xa3;
+          CodeLen = 1;
+          break;
+        case ModXInd:
+          BAsmCode[0] = 0xb6;
+          CodeLen = 1;
+          break;
+        case ModXInc:
+          BAsmCode[0] = 0xb2;
+          CodeLen = 1;
+          break;
+        case ModXDec:
+          BAsmCode[0] = 0xb3;
+          CodeLen = 1;
+          break;
+      }
+    }
+  }
+}
+
+static void DecodeAcc(Word Code)
+{
+  if (ChkArgCnt(1, 1))
+  {
+    tAdrResult DestResult;
+
+    if (DecodeAdr(&ArgStr[1], MModAcc, &DestResult) == ModAcc)
+    {
+      BAsmCode[0] = Code;
+      CodeLen = 1;
+    }
+  }
+}
+
+static void DecodeAccMem(Word Code)
+{
+  if (ChkArgCnt(2, 2))
+  {
+    tAdrResult DestResult;
+
+    if (DecodeAdr(&ArgStr[1], MModAcc, &DestResult) != ModNone)
+    {
+      tAdrResult SrcResult;
+
+      switch (DecodeAdr(&ArgStr[2], MModDir | MModImm | MModBInd, &SrcResult))
+      {
+        case ModBInd:
+          BAsmCode[0] = Code;
+          CodeLen = 1;
+          break;
+        case ModImm:
+          BAsmCode[0] = Code + 0x10;
+          BAsmCode[1] = SrcResult.Val;
+          CodeLen = 2;
+          break;
+        case ModDir:
+          BAsmCode[0] = DirPrefix;
+          BAsmCode[1] = SrcResult.Val;
+          BAsmCode[2] = Code;
+          CodeLen = 3;
+          break;
+      }
+    }
+  }
+}
+
+static void DecodeANDSZ(Word Code)
+{
+  UNUSED(Code);
+
+  if (ChkArgCnt(2, 2))
+  {
+    tAdrResult DestResult;
+
+    if (DecodeAdr(&ArgStr[1], MModAcc, &DestResult) != ModNone)
+    {
+      tAdrResult SrcResult;
+
+      if (DecodeAdr(&ArgStr[2], MModImm, &SrcResult) == ModImm)
+      {
+        BAsmCode[0] = 0x60;
+        BAsmCode[1] = SrcResult.Val;
+        CodeLen = 2;
+      }
+    }
+  }
+}
+
+static void DecodeIFEQ(Word Code)
+{
+  UNUSED(Code);
+
+  if (ChkArgCnt(2, 2))
+  {
+    tAdrResult DestResult;
+
+    switch (DecodeAdr(&ArgStr[1], MModAcc | MModDir, &DestResult))
+    {
+      case ModAcc:
+      {
+        tAdrResult SrcResult;
+
+        switch (DecodeAdr(&ArgStr[2], MModDir | MModBInd | MModImm, &SrcResult))
+        {
+          case ModDir:
+            BAsmCode[0] = DirPrefix;
+            BAsmCode[1] = SrcResult.Val;
+            BAsmCode[2] = 0x82;
+            CodeLen = 3;
+            break;
+          case ModBInd:
+            BAsmCode[0] = 0x82;
+            CodeLen = 1;
+            break;
+          case ModImm:
+            BAsmCode[0] = 0x92;
+            BAsmCode[1] = SrcResult.Val;
+            CodeLen = 2;
+            break;
+        }
+        break;
+      }
+      case ModDir:
+      {
+        tAdrResult SrcResult;
+
+        BAsmCode[1] = DestResult.Val;
+        if (DecodeAdr(&ArgStr[2], MModImm, &SrcResult) == ModImm)
+        {
+          BAsmCode[0] = 0xa9;
+          BAsmCode[2] = SrcResult.Val;
+          CodeLen = 3;
+        }
+        break;
+      }
+    }
+  }
+}
+
+static void DecodeIFNE(Word Code)
+{
+  UNUSED(Code);
+
+  if (ChkArgCnt(2, 2))
+  {
+    tAdrResult DestResult;
+
+    switch (DecodeAdr(&ArgStr[1], MModAcc, &DestResult))
+    {
+      case ModAcc:
+      {
+        tAdrResult SrcResult;
+
+        switch (DecodeAdr(&ArgStr[2], MModDir | MModBInd | MModImm, &SrcResult))
+        {
+          case ModDir:
+            BAsmCode[0] = DirPrefix;
+            BAsmCode[1] = SrcResult.Val;
+            BAsmCode[2] = 0xb9;
+            CodeLen = 3;
+            break;
+          case ModBInd:
+            BAsmCode[0] = 0xb9;
+            CodeLen = 1;
+            break;
+          case ModImm:
+            BAsmCode[0] = 0x99;
+            BAsmCode[1] = SrcResult.Val;
+            CodeLen = 2;
+            break;
+        }
+        break;
+      }
+    }
+  }
+}
+
+static void DecodeIFBNE(Word Code)
+{
+  UNUSED(Code);
+
+  if (!ChkArgCnt(1, 1));
+  else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_InvAddrMode);
+  else
+  {
+    Boolean OK;
+
+    BAsmCode[0] = EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt4, &OK);
+    if (OK)
+    {
+      BAsmCode[0] += 0x40;
+      CodeLen = 1;
+    }
+  }
+}
+
+static void DecodeBit(Word Code)
+{
+  if (ChkArgCnt(2, 2))
+  {
+    Boolean OK;
+
+    Byte HReg = EvalStrIntExpression(&ArgStr[1], UInt3, &OK);
+    if (OK)
+    {
+      tAdrResult DestResult;
+
+      switch (DecodeAdr(&ArgStr[2], MModDir | MModBInd, &DestResult))
+      {
+        case ModDir:
+          BAsmCode[0] = DirPrefix;
+          BAsmCode[1] = DestResult.Val;
+          BAsmCode[2] = Code + HReg;
+          CodeLen = 3;
+          break;
+        case ModBInd:
+          BAsmCode[0] = Code + HReg;
+          CodeLen = 1;
+          break;
+      }
+    }
+  }
+}
+
+static void DecodeJMP_JSR(Word Code)
+{
+  if (ChkArgCnt(1, 1))
+  {
+    tEvalResult EvalResult;
+    Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
+
+    if (EvalResult.OK && ChkSamePage(EProgCounter() + 2, AdrWord, 12, EvalResult.Flags))
+    {
+      ChkSpace(SegCode, EvalResult.AddrSpaceMask);
+      BAsmCode[0] = 0x20 + Code + ((AdrWord >> 8) & 15);
+      BAsmCode[1] = Lo(AdrWord);
+      CodeLen = 2;
+    }
+  }
+}
+
+static void DecodeJMPL_JSRL(Word Code)
+{
+  if (ChkArgCnt(1, 1))
+  {
+    tEvalResult EvalResult;
+    Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
+
+    if (EvalResult.OK)
+    {
+      ChkSpace(SegCode, EvalResult.AddrSpaceMask);
+      BAsmCode[0] = Code;
+      BAsmCode[1] = Hi(AdrWord);
+      BAsmCode[2] = Lo(AdrWord);
+      CodeLen = 3;
+    }
+  }
+}
+
+static void DecodeJP(Word Code)
+{
+  UNUSED(Code);
+
+  if (ChkArgCnt(1, 1))
+  {
+    Boolean OK;
+    tSymbolFlags Flags;
+
+    Integer AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt16, &OK, &Flags) - (EProgCounter() + 1);
+    if (OK)
+    {
+      if (AdrInt == 0)
+      {
+        BAsmCode[0] = NOPCode;
+        CodeLen = 1;
+        WrError(ErrNum_DistNull);
+      }
+      else if (((AdrInt > 31) || (AdrInt < -32)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
+      else
+      {
+        BAsmCode[0] = AdrInt & 0xff;
+        CodeLen = 1;
+      }
+    }
+  }
+  return;
+}
+
+static void DecodeDRSZ(Word Code)
+{
+  UNUSED(Code);
+
+  if (ChkArgCnt(1, 1))
+  {
+    tAdrResult DestResult;
+
+    if (DecodeAdr(&ArgStr[1], MModDir, &DestResult) == ModDir)
+    {
+      if (mFirstPassUnknown(DestResult.ValSymFlags))
+        DestResult.Val |= 0xf0;
+      if (DestResult.Val < 0xf0) WrError(ErrNum_UnderRange);
+      else
+      {
+        BAsmCode[0] = DestResult.Val - 0x30;
+        CodeLen = 1;
+      }
+    }
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void AddFixed(const char *NName, Byte NCode)
+{
+  AddInstTable(InstTable, NName, NCode, DecodeFixed);
+}
+
+static void AddAcc(const char *NName, Byte NCode)
+{
+  AddInstTable(InstTable, NName, NCode, DecodeAcc);
+}
+
+static void AddAccMem(const char *NName, Byte NCode)
+{
+  AddInstTable(InstTable, NName, NCode, DecodeAccMem);
+}
+
+static void AddBit(const char *NName, Byte NCode)
+{
+  AddInstTable(InstTable, NName, NCode, DecodeBit);
+}
+
+static void InitFields(void)
+{
+  InstTable = CreateInstTable(103);
+  AddInstTable(InstTable, "LD", 0, DecodeLD);
+  AddInstTable(InstTable, "X", 0, DecodeX);
+  AddInstTable(InstTable, "ANDSZ", 0, DecodeANDSZ);
+  AddInstTable(InstTable, "IFEQ", 0, DecodeIFEQ);
+  AddInstTable(InstTable, "IFNE", 0, DecodeIFNE);
+  AddInstTable(InstTable, "IFBNE", 0, DecodeIFBNE);
+  AddInstTable(InstTable, "JMP", 0, DecodeJMP_JSR);
+  AddInstTable(InstTable, "JSR", 0x10, DecodeJMP_JSR);
+  AddInstTable(InstTable, "JMPL", 0xac, DecodeJMPL_JSRL);
+  AddInstTable(InstTable, "JSRL", 0xad, DecodeJMPL_JSRL);
+  AddInstTable(InstTable, "JP", 0, DecodeJP);
+  AddInstTable(InstTable, "DRSZ", 0, DecodeDRSZ);
+
+  AddFixed("LAID" , 0xa4);  AddFixed("SC"   , 0xa1);  AddFixed("RC"   , 0xa0);
+  AddFixed("IFC"  , 0x88);  AddFixed("IFNC" , 0x89);  AddFixed("VIS"  , 0xb4);
+  AddFixed("JID"  , 0xa5);  AddFixed("RET"  , 0x8e);  AddFixed("RETSK", 0x8d);
+  AddFixed("RETI" , 0x8f);  AddFixed("INTR" , 0x00);  AddFixed("NOP"  , 0xb8);
+  AddFixed("RPND" , 0xb5);
+
+  AddAcc("CLR"  , 0x64);  AddAcc("INC"  , 0x8a);  AddAcc("DEC"  , 0x8b);
+  AddAcc("DCOR" , 0x66);  AddAcc("RRC"  , 0xb0);  AddAcc("RLC"  , 0xa8);
+  AddAcc("SWAP" , 0x65);  AddAcc("POP"  , 0x8c);  AddAcc("PUSH" , 0x67);
+
+  AddAccMem("ADD"  , 0x84);  AddAccMem("ADC"  , 0x80);  AddAccMem("SUBC" , 0x81);
+  AddAccMem("AND"  , 0x85);  AddAccMem("OR"   , 0x87);  AddAccMem("XOR"  , 0x86);
+  AddAccMem("IFGT" , 0x83);
+
+  AddBit("IFBIT", 0x70); AddBit("SBIT", 0x78); AddBit("RBIT", 0x68);
+}
+
+static void DeinitFields(void)
+{
+  DestroyInstTable(InstTable);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void MakeCode_COP8(void)
+{
+  CodeLen = 0; DontPrint = False;
+
+  /* zu ignorierendes */
+
+  if (Memo("")) return;
+
+  /* Pseudoanweisungen */
+
+  if (DecodeNatPseudo()) return;
+  if (DecodeIntelPseudo(False)) return;
+
+  if (!LookupInstTable(InstTable, OpPart.str.p_str))
+    WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
+}
+
+static Boolean IsDef_COP8(void)
+{
+  return (Memo("SFR"));
+}
+
+static void SwitchFrom_COP8(void)
+{
+  DeinitFields();
+}
+
+static void SwitchTo_COP8(void)
+{
+  TurnWords = False;
+  SetIntConstMode(eIntConstModeC);
+
+  PCSymbol = ".";
+  HeaderID = 0x6f;
+  NOPCode = 0xb8;
+  DivideChars = ",";
+  HasAttrs = False;
+
+  ValidSegs = (1 << SegCode) | (1 << SegData);
+  Grans[SegCode] = 1;
+  ListGrans[SegCode] = 1;
+  SegInits[SegCode]  =0;
+  SegLimits[SegCode] = 0x1fff;
+  Grans[SegData] = 1;
+  ListGrans[SegData] = 1;
+  SegInits[SegData] = 0;
+  SegLimits[SegData] = 0xff;
+
+  MakeCode = MakeCode_COP8;
+  IsDef = IsDef_COP8;
+  SwitchFrom = SwitchFrom_COP8;
+  InitFields();
+}
+
+void codecop8_init(void)
+{
+  CPUCOP87L84 = AddCPU("COP87L84", SwitchTo_COP8);
+}
diff --git a/aslcop8/codecop8.h b/aslcop8/codecop8.h
new file mode 100644 (file)
index 0000000..c084567
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _CODECOP8_H
+#define _CODECOP8_H
+/* codecop8.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Codegeneratormodul COP8-Familie                                           */
+/*                                                                           */
+/* Historie: 7.10.1996 Grundsteinlegung                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+extern void codecop8_init(void);
+#endif /* _CODECOP8_H */
diff --git a/aslshim/addrspace.h b/aslshim/addrspace.h
new file mode 100644 (file)
index 0000000..32b2396
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _ADDRSPACE_H
+#define _ADDRSPACE_H
+/* addrspace.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS                                                                        */
+/*                                                                           */
+/* Address Space enumeration                                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+/* NOTE: these constants are used in the .P files, so DO NOT CHANGE existing
+   enums; only attach new enums at the end! */
+
+typedef enum
+{
+  SegNone  = 0,
+  SegCode  = 1,
+  SegData  = 2,
+  SegIData = 3,
+  SegXData = 4,
+  SegYData = 5,
+  SegBData = 6,
+  SegIO    = 7,
+  SegReg   = 8,
+  SegRData = 9,
+  SegEEData = 10,
+  SegCount = 11,
+  StructSeg = SegCount,
+  SegCountPlusStruct = 12
+} as_addrspace_t;
+
+#ifdef __cplusplus
+#include "cppops.h"
+DefCPPOps_Enum(as_addrspace_t)
+#endif
+
+extern const char *SegNames[SegCountPlusStruct];
+extern char SegShorts[SegCountPlusStruct];
+
+extern as_addrspace_t addrspace_lookup(const char *p_name);
+
+#endif /* _ADDRSPACE_H */
diff --git a/aslshim/as.h b/aslshim/as.h
new file mode 100644 (file)
index 0000000..ebe4619
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _AS_H
+#define _AS_H
+/* as.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Hauptmodul                                                                */
+/*                                                                           */
+/*****************************************************************************/
+
+extern char *GetErrorPos(void);
+
+extern void WriteCode(void);
+
+#endif /* _AS_H */
diff --git a/aslshim/as.rsc b/aslshim/as.rsc
new file mode 100644 (file)
index 0000000..a9b0003
--- /dev/null
@@ -0,0 +1,352 @@
+#ifndef AS_RSC
+#define AS_RSC
+#define MsgId1 1647083959
+#define MsgId2 1634938482
+#define Num_ErrName 0
+#define Num_WarnName 1
+#define Num_InLineName 2
+#define Num_GNUErrorMsg1 3
+#define Num_GNUErrorMsgN 4
+#define Num_ErrMsgUselessDisp 5
+#define Num_ErrMsgShortAddrPossible 6
+#define Num_ErrMsgShortJumpPossible 7
+#define Num_ErrMsgNoShareFile 8
+#define Num_ErrMsgBigDecFloat 9
+#define Num_ErrMsgPrivOrder 10
+#define Num_ErrMsgDistNull 11
+#define Num_ErrMsgWrongSegment 12
+#define Num_ErrMsgInAccSegment 13
+#define Num_ErrMsgPhaseErr 14
+#define Num_ErrMsgOverlap 15
+#define Num_ErrMsgOverlapReg 16
+#define Num_ErrMsgNoCaseHit 17
+#define Num_ErrMsgInAccPage 18
+#define Num_ErrMsgRMustBeEven 19
+#define Num_ErrMsgObsolete 20
+#define Num_ErrMsgUnpredictable 21
+#define Num_ErrMsgAlphaNoSense 22
+#define Num_ErrMsgSenseless 23
+#define Num_ErrMsgRepassUnknown 24
+#define Num_ErrMsgAddrNotAligned 25
+#define Num_ErrMsgIOAddrNotAllowed 26
+#define Num_ErrMsgPipeline 27
+#define Num_ErrMsgDoubleAdrRegUse 28
+#define Num_ErrMsgNotBitAddressable 29
+#define Num_ErrMsgStackNotEmpty 30
+#define Num_ErrMsgNULCharacter 31
+#define Num_ErrMsgPageCrossing 32
+#define Num_ErrMsgWUnderRange 33
+#define Num_ErrMsgWOverRange 34
+#define Num_ErrMsgNegDUP 35
+#define Num_ErrMsgConvIndX 36
+#define Num_ErrMsgNullResMem 37
+#define Num_ErrMsgBitNumberTruncated 38
+#define Num_ErrMsgInvRegisterPointer 39
+#define Num_ErrMsgMacArgRedef 40
+#define Num_ErrMsgDeprecated 41
+#define Num_ErrMsgDeprecated_Instead 42
+#define Num_ErrMsgSrcLEThanDest 43
+#define Num_ErrMsgTrapValidInstruction 44
+#define Num_ErrMsgPaddingAdded 45
+#define Num_ErrMsgRegNumWraparound 46
+#define Num_ErrMsgIndexedForIndirect 47
+#define Num_ErrMsgDoubleDef 48
+#define Num_ErrMsgSymbolUndef 49
+#define Num_ErrMsgInvSymName 50
+#define Num_ErrMsgInvFormat 51
+#define Num_ErrMsgUseLessAttr 52
+#define Num_ErrMsgUndefAttr 53
+#define Num_ErrMsgTooLongAttr 54
+#define Num_ErrMsgWrongArgCnt 55
+#define Num_ErrMsgWrongOptCnt 56
+#define Num_ErrMsgOnlyImmAddr 57
+#define Num_ErrMsgInvOpSize 58
+#define Num_ErrMsgConfOpSizes 59
+#define Num_ErrMsgUndefOpSizes 60
+#define Num_ErrMsgStringOrIntButFloat 61
+#define Num_ErrMsgIntButFloat 62
+#define Num_ErrMsgFloatButString 63
+#define Num_ErrMsgOpTypeMismatch 64
+#define Num_ErrMsgStringButInt 65
+#define Num_ErrMsgStringButFloat 66
+#define Num_ErrMsgTooManyArgs 67
+#define Num_ErrMsgIntButString 68
+#define Num_ErrMsgIntOrFloatButString 69
+#define Num_ErrMsgExpectString 70
+#define Num_ErrMsgExpectInt 71
+#define Num_ErrMsgStringOrIntOrFloatButReg 72
+#define Num_ErrMsgExpectIntOrString 73
+#define Num_ErrMsgExpectReg 74
+#define Num_ErrMsgRegWrongTarget 75
+#define Num_ErrMsgUnknownInstruction 76
+#define Num_ErrMsgBrackErr 77
+#define Num_ErrMsgDivByZero 78
+#define Num_ErrMsgUnderRange 79
+#define Num_ErrMsgOverRange 80
+#define Num_ErrMsgNotPwr2 81
+#define Num_ErrMsgNotAligned 82
+#define Num_ErrMsgDistTooBig 83
+#define Num_ErrMsgInAccReg 84
+#define Num_ErrMsgNoShortAddr 85
+#define Num_ErrMsgInvAddrMode 86
+#define Num_ErrMsgAddrMustBeEven 87
+#define Num_ErrMsgAddrMustBeAligned 88
+#define Num_ErrMsgInvParAddrMode 89
+#define Num_ErrMsgUndefCond 90
+#define Num_ErrMsgIncompCond 91
+#define Num_ErrMsgUnknownFlag 92
+#define Num_ErrMsgDuplicateFlag 93
+#define Num_ErrMsgUnknownInt 94
+#define Num_ErrMsgDuplicateInt 95
+#define Num_ErrMsgJmpDistTooBig 96
+#define Num_ErrMsgDistIsOdd 97
+#define Num_ErrMsgSkipTargetMismatch 98
+#define Num_ErrMsgInvShiftArg 99
+#define Num_ErrMsgOnly1 100
+#define Num_ErrMsgRange18 101
+#define Num_ErrMsgShiftCntTooBig 102
+#define Num_ErrMsgInvRegList 103
+#define Num_ErrMsgInvCmpMode 104
+#define Num_ErrMsgInvCPUType 105
+#define Num_ErrMsgInvFPUType 106
+#define Num_ErrMsgInvPMMUType 107
+#define Num_ErrMsgInvCtrlReg 108
+#define Num_ErrMsgInvReg 109
+#define Num_ErrMsgDoubleReg 110
+#define Num_ErrMsgRegBankMismatch 111
+#define Num_ErrMsgUndefRegSize 112
+#define Num_ErrMsgInvOpOnReg 113
+#define Num_ErrMsgNoSaveFrame 114
+#define Num_ErrMsgNoRestoreFrame 115
+#define Num_ErrMsgUnknownMacArg 116
+#define Num_ErrMsgMissEndif 117
+#define Num_ErrMsgInvIfConst 118
+#define Num_ErrMsgDoubleSection 119
+#define Num_ErrMsgInvSection 120
+#define Num_ErrMsgMissingEndSect 121
+#define Num_ErrMsgWrongEndSect 122
+#define Num_ErrMsgNotInSection 123
+#define Num_ErrMsgUndefdForward 124
+#define Num_ErrMsgContForward 125
+#define Num_ErrMsgInvFuncArgCnt 126
+#define Num_ErrMsgMissingLTORG 127
+#define Num_ErrMsgInstructionNotOnThisCPUSupported 128
+#define Num_ErrMsgAddrModeNotOnThisCPUSupported 129
+#define Num_ErrMsgFPUNotEnabled 130
+#define Num_ErrMsgPMMUNotEnabled 131
+#define Num_ErrMsgFullPMMUNotEnabled 132
+#define Num_ErrMsgCustomNotEnabled 133
+#define Num_ErrMsgZ80SyntaxNotEnabled 134
+#define Num_ErrMsgZ80SyntaxExclusive 135
+#define Num_ErrMsgInstructionNotOnThisFPUSupported 136
+#define Num_ErrMsgInvBitPos 137
+#define Num_ErrMsgOnlyOnOff 138
+#define Num_ErrMsgStackEmpty 139
+#define Num_ErrMsgNotOneBit 140
+#define Num_ErrMsgMissingStruct 141
+#define Num_ErrMsgOpenStruct 142
+#define Num_ErrMsgWrongStruct 143
+#define Num_ErrMsgPhaseDisallowed 144
+#define Num_ErrMsgInvStructDir 145
+#define Num_ErrMsgDoubleStruct 146
+#define Num_ErrMsgUnresolvedStructRef 147
+#define Num_ErrMsgDuplicateStructElem 148
+#define Num_ErrMsgNotRepeatable 149
+#define Num_ErrMsgShortRead 150
+#define Num_ErrMsgUnknownCodepage 151
+#define Num_ErrMsgRomOffs063 152
+#define Num_ErrMsgInvFCode 153
+#define Num_ErrMsgInvFMask 154
+#define Num_ErrMsgInvMMUReg 155
+#define Num_ErrMsgLevel07 156
+#define Num_ErrMsgInvBitMask 157
+#define Num_ErrMsgInvRegPair 158
+#define Num_ErrMsgOpenMacro 159
+#define Num_ErrMsgOpenIRP 160
+#define Num_ErrMsgOpenIRPC 161
+#define Num_ErrMsgOpenREPT 162
+#define Num_ErrMsgOpenWHILE 163
+#define Num_ErrMsgDoubleMacro 164
+#define Num_ErrMsgTooManyMacParams 165
+#define Num_ErrMsgUndefKeyArg 166
+#define Num_ErrMsgNoPosArg 167
+#define Num_ErrMsgEXITMOutsideMacro 168
+#define Num_ErrMsgFirstPassCalc 169
+#define Num_ErrMsgTooManyNestedIfs 170
+#define Num_ErrMsgMissingIf 171
+#define Num_ErrMsgRekMacro 172
+#define Num_ErrMsgUnknownFunc 173
+#define Num_ErrMsgInvFuncArg 174
+#define Num_ErrMsgFloatOverflow 175
+#define Num_ErrMsgInvArgPair 176
+#define Num_ErrMsgNotOnThisAddress 177
+#define Num_ErrMsgNotFromThisAddress 178
+#define Num_ErrMsgTargOnDiffPage 179
+#define Num_ErrMsgTargOnDiffSection 180
+#define Num_ErrMsgCodeOverflow 181
+#define Num_ErrMsgMixDBDS 182
+#define Num_ErrMsgNotInStruct 183
+#define Num_ErrMsgParNotPossible 184
+#define Num_ErrMsgAdrOverflow 185
+#define Num_ErrMsgInvSegment 186
+#define Num_ErrMsgUnknownSegment 187
+#define Num_ErrMsgUnknownSegReg 188
+#define Num_ErrMsgInvString 189
+#define Num_ErrMsgInvRegName 190
+#define Num_ErrMsgInvArg 191
+#define Num_ErrMsgNoIndir 192
+#define Num_ErrMsgNotInThisSegment 193
+#define Num_ErrMsgNotInMaxmode 194
+#define Num_ErrMsgOnlyInMaxmode 195
+#define Num_ErrMsgPackCrossBoundary 196
+#define Num_ErrMsgUnitMultipleUsed 197
+#define Num_ErrMsgMultipleLongRead 198
+#define Num_ErrMsgMultipleLongWrite 199
+#define Num_ErrMsgLongReadWithStore 200
+#define Num_ErrMsgTooManyRegisterReads 201
+#define Num_ErrMsgOverlapDests 202
+#define Num_ErrMsgTooManyBranchesInExPacket 203
+#define Num_ErrMsgCannotUseUnit 204
+#define Num_ErrMsgInvEscSequence 205
+#define Num_ErrMsgInvPrefixCombination 206
+#define Num_ErrMsgConstantRedefinedAsVariable 207
+#define Num_ErrMsgVariableRedefinedAsConstant 208
+#define Num_ErrMsgStructNameMissing 209
+#define Num_ErrMsgEmptyArgument 210
+#define Num_ErrMsgUnimplemented 211
+#define Num_ErrMsgFreestandingUnnamedStruct 212
+#define Num_ErrMsgSTRUCTEndedByENDUNION 213
+#define Num_ErrMsgAddrOnDifferentPage 214
+#define Num_ErrMsgUnknownMacExpMod 215
+#define Num_ErrMsgTooManyMacExpMod 216
+#define Num_ErrMsgConflictingMacExpMod 217
+#define Num_ErrMsgInvalidPrepDir 218
+#define Num_ErrMsgExpectedError 219
+#define Num_ErrMsgNoNestExpect 220
+#define Num_ErrMsgMissingENDEXPECT 221
+#define Num_ErrMsgMissingEXPECT 222
+#define Num_ErrMsgNoDefCkptReg 223
+#define Num_ErrMsgInvBitField 224
+#define Num_ErrMsgArgValueMissing 225
+#define Num_ErrMsgUnknownArg 226
+#define Num_ErrMsgIndexRegMustBe16Bit 227
+#define Num_ErrMsgIOAddrRegMustBe16Bit 228
+#define Num_ErrMsgSegAddrRegMustBe32Bit 229
+#define Num_ErrMsgNonSegAddrRegMustBe16Bit 230
+#define Num_ErrMsgInvStructArgument 231
+#define Num_ErrMsgTooManyArrayDimensions 232
+#define Num_ErrMsgInvIntFormat 233
+#define Num_ErrMsgInvIntFormatList 234
+#define Num_ErrMsgInvScale 235
+#define Num_ErrMsgConfStringOpt 236
+#define Num_ErrMsgUnknownStringOpt 237
+#define Num_ErrMsgInvCacheInvMode 238
+#define Num_ErrMsgInvCfgList 239
+#define Num_ErrMsgConfBitBltOpt 240
+#define Num_ErrMsgUnknownBitBltOpt 241
+#define Num_ErrMsgInternalError 242
+#define Num_ErrMsgOpeningFile 243
+#define Num_ErrMsgListWrError 244
+#define Num_ErrMsgFileReadError 245
+#define Num_ErrMsgFileWriteError 246
+#define Num_ErrMsgIntError 247
+#define Num_ErrMsgHeapOvfl 248
+#define Num_ErrMsgStackOvfl 249
+#define Num_ErrMsgMaxIncLevelExceeded 250
+#define Num_ErrMsgTooManyErrors 251
+#define Num_ErrMsgIsFatal 252
+#define Num_ErrMsgOvlyError 253
+#define Num_PrevDefMsg 254
+#define Num_ErrMsgInvSwapSize 255
+#define Num_ErrMsgSwapTooBig 256
+#define Num_ErrMsgNoRelocs 257
+#define Num_ErrMsgUnresRelocs 258
+#define Num_ErrMsgUnexportable 259
+#define Num_ErrMsgArgCntZero 260
+#define Num_ErrMsgArgCntOne 261
+#define Num_ErrMsgArgCntMulti 262
+#define Num_ErrMsgArgCntFromTo 263
+#define Num_ErrMsgArgCntEitherOr 264
+#define Num_ErrMsgAddrArgCnt 265
+#define Num_ErrMsgCannotSplitArg 266
+#define Num_ErrMsgMinCPUSupported 267
+#define Num_ErrMsgMaxCPUSupported 268
+#define Num_ErrMsgRangeCPUSupported 269
+#define Num_ErrMsgOnlyCPUSupported1 270
+#define Num_ErrMsgOnlyCPUSupportedOr 271
+#define Num_ErrMsgOnlyCPUSupported2 272
+#define Num_HeadingFileNameLab 273
+#define Num_HeadingPageLab 274
+#define Num_ListSymListHead1 275
+#define Num_ListSymListHead2 276
+#define Num_ListSymSumMsg 277
+#define Num_ListSymSumsMsg 278
+#define Num_ListUSymSumMsg 279
+#define Num_ListUSymSumsMsg 280
+#define Num_ListRegDefListHead1 281
+#define Num_ListRegDefListHead2 282
+#define Num_ListRegDefSumMsg 283
+#define Num_ListRegDefSumsMsg 284
+#define Num_ListRegDefUSumMsg 285
+#define Num_ListRegDefUSumsMsg 286
+#define Num_ListCodepageListHead1 287
+#define Num_ListCodepageListHead2 288
+#define Num_ListCodepageChange 289
+#define Num_ListCodepagePChange 290
+#define Num_ListCodepageSumMsg 291
+#define Num_ListCodepageSumsMsg 292
+#define Num_ListMacListHead1 293
+#define Num_ListMacListHead2 294
+#define Num_ListMacSumMsg 295
+#define Num_ListMacSumsMsg 296
+#define Num_ListStructListHead1 297
+#define Num_ListStructListHead2 298
+#define Num_ListStructSumMsg 299
+#define Num_ListStructSumsMsg 300
+#define Num_ListFuncListHead1 301
+#define Num_ListFuncListHead2 302
+#define Num_ListDefListHead1 303
+#define Num_ListDefListHead2 304
+#define Num_ListSegListHead1 305
+#define Num_ListSegListHead2 306
+#define Num_ListCrossListHead1 307
+#define Num_ListCrossListHead2 308
+#define Num_ListSectionListHead1 309
+#define Num_ListSectionListHead2 310
+#define Num_ListIncludeListHead1 311
+#define Num_ListIncludeListHead2 312
+#define Num_ListCrossSymName 313
+#define Num_ListCrossFileName 314
+#define Num_ListPlurName 315
+#define Num_ListHourName 316
+#define Num_ListMinuName 317
+#define Num_ListSecoName 318
+#define Num_InfoMessAssembling 319
+#define Num_InfoMessPass 320
+#define Num_InfoMessPass1 321
+#define Num_InfoMessPass2 322
+#define Num_InfoMessAssTime 323
+#define Num_InfoMessAssLine 324
+#define Num_InfoMessAssLines 325
+#define Num_InfoMessPassCnt 326
+#define Num_InfoMessPPassCnt 327
+#define Num_InfoMessNoPass 328
+#define Num_InfoMessMacAssLine 329
+#define Num_InfoMessMacAssLines 330
+#define Num_InfoMessWarnCnt 331
+#define Num_InfoMessWarnPCnt 332
+#define Num_InfoMessErrCnt 333
+#define Num_InfoMessErrPCnt 334
+#define Num_InfoMessRemainMem 335
+#define Num_InfoMessRemainStack 336
+#define Num_InfoMessNFilesFound 337
+#define Num_InfoMessMacroAss 338
+#define Num_InfoMessVar 339
+#define Num_InfoMessHead1 340
+#define Num_InfoMessHead2 341
+#define Num_KeyWaitMsg 342
+#define Num_ErrMsgInvParam 343
+#define Num_ErrMsgInvEnvParam 344
+#define Num_InvMsgSource 345
+#define Num_InfoMessHelp 346
+#endif /* #ifndef AS_RSC */
diff --git a/aslshim/asmdebug.h b/aslshim/asmdebug.h
new file mode 100644 (file)
index 0000000..8f9f73f
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _ASMDEBUG_H
+#define _ASMDEBUG_H
+/* asmdebug.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Verwaltung der Debug-Informationen zur Assemblierzeit                     */
+/*                                                                           */
+/* Historie: 16. 5.1996 Grundsteinlegung                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+extern void AddLineInfo(Boolean InMacro, LongInt LineNum, char *FileName,
+                        ShortInt Space, LargeInt Address, LargeInt Len);
+
+extern void InitLineInfo(void);
+
+extern void ClearLineInfo(void);
+
+extern void DumpDebugInfo(void);
+
+extern void asmdebug_init(void);
+#endif /* _ASMDEBUG_H */
diff --git a/aslshim/asmdef.c b/aslshim/asmdef.c
new file mode 100644 (file)
index 0000000..232c713
--- /dev/null
@@ -0,0 +1,430 @@
+/* asmdef.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* global benutzte Variablen                                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include "strutil.h"
+#include "stringlists.h"
+#include "chunks.h"
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "errmsg.h"
+
+char SrcSuffix[] = ".asm";             /* Standardendungen: Hauptdatei */
+char IncSuffix[] = ".inc";             /* Includedatei */
+char PrgSuffix[] = ".p";               /* Programmdatei */
+char LstSuffix[] = ".lst";             /* Listingdatei */
+char MacSuffix[] = ".mac";             /* Makroausgabe */
+char PreSuffix[] = ".i";               /* Ausgabe Makroprozessor */
+char LogSuffix[] = ".log";             /* Fehlerdatei */
+char MapSuffix[] = ".map";             /* Debug-Info/Map-Format */
+char OBJSuffix[] = ".obj";
+
+const char *EnvName = "ASCMD";         /* Environment-Variable fuer Default-
+                                          Parameter */
+
+StringPtr SourceFile;                    /* Hauptquelldatei */
+
+StringPtr CursUp;                          /*   "     "  Cursor hoch */
+
+LargeWord *PCs;                          /* Programmzaehler */
+Boolean RelSegs;                         /* relokatibles Segment ? */
+LargeWord StartAdr;                      /* Programmstartadresse */
+Boolean StartAdrPresent;                 /*          "           definiert? */
+LargeWord AfterBSRAddr;                  /* address right behind last BSR */
+LargeWord *Phases;                       /* Verschiebungen */
+Word Grans[SegCountPlusStruct];          /* Groesse der Adressierungselemente */
+Word ListGrans[SegCountPlusStruct];      /* Wortgroesse im Listing */
+ChunkList SegChunks[SegCountPlusStruct]; /* Belegungen */
+Integer ActPC;                           /* gewaehlter Programmzaehler */
+Boolean PCsUsed[SegCountPlusStruct];     /* PCs bereits initialisiert ? */
+LargeWord *SegInits;                     /* Segmentstartwerte */
+LargeWord *SegLimits;                    /* Segmentgrenzwerte */
+LongInt ValidSegs;                       /* erlaubte Segmente */
+Boolean ENDOccured;                     /* END-Statement aufgetreten ? */
+Boolean Retracted;                      /* Codes zurueckgenommen ? */
+Boolean ListToStdout, ListToNull;        /* Listing auf Konsole/Nulldevice ? */
+
+unsigned ASSUMERecCnt;
+const ASSUMERec *pASSUMERecs;
+void (*pASSUMEOverride)(void);
+
+Integer PassNo;                          /* Durchlaufsnummer */
+Integer JmpErrors;                       /* Anzahl fraglicher Sprungfehler */
+Boolean ThrowErrors;                     /* Fehler verwerfen bei Repass ? */
+LongWord MaxErrors;                      /* terminate upon n errors? */
+Boolean TreatWarningsAsErrors;           /* treat warnings like erros? */
+Boolean Repass;                                 /* noch ein Durchlauf erforderlich */
+Byte MaxSymPass;                        /* Pass, nach dem Symbole definiert sein muessen */
+Byte ShareMode;                          /* 0=kein SHARED,1=Pascal-,2=C-Datei, 3=ASM-Datei */
+DebugType DebugMode;                     /* Ausgabeformat Debug-Datei */
+Word NoICEMask;                          /* which symbols to use in NoICE dbg file */
+Byte ListMode;                           /* 0=kein Listing,1=Konsole,2=auf Datei */
+Byte ListOn;                            /* Listing erzeugen ? */
+Integer MaxIncludeLevel;                 /* maximum include nesting level */
+Boolean MakeUseList;                     /* Belegungsliste ? */
+Boolean MakeCrossList;                  /* Querverweisliste ? */
+Boolean MakeSectionList;                 /* Sektionsliste ? */
+Boolean MakeIncludeList;                 /* Includeliste ? */
+Boolean DefRelaxedMode;                  /* alle Integer-Syntaxen zulassen ? */
+Boolean DefCompMode, CompMode;           /* enable compatibility mode */
+Word ListMask;                           /* Listingmaske */
+ShortInt ExtendErrors;                  /* erweiterte Fehlermeldungen */
+Integer EnumSegment;                     /* ENUM state & config */
+LongInt EnumIncrement, EnumCurrentValue;
+Boolean NumericErrors;                   /* Fehlermeldungen mit Nummer */
+Boolean CodeOutput;                     /* Code erzeugen */
+Boolean MacProOutput;                    /* Makroprozessorausgabe schreiben */
+Boolean MacroOutput;                     /* gelesene Makros schreiben */
+Boolean QuietMode;                       /* keine Meldungen */
+Boolean HardRanges;                      /* Bereichsfehler echte Fehler ? */
+const char *DivideChars;                 /* Trennzeichen fuer Parameter. Inhalt Read Only! */
+Boolean HasAttrs;                        /* Opcode hat Attribut */
+const char *AttrChars;                   /* Zeichen, mit denen Attribut abgetrennt wird */
+Boolean MsgIfRepass;                     /* Meldungen, falls neuer Pass erforderlich */
+Integer PassNoForMessage;                /* falls ja: ab welchem Pass ? */
+Boolean CaseSensitive;                   /* Gross/Kleinschreibung unterscheiden ? */
+LongInt NestMax;                         /* max. nesting level of a macro */
+Boolean GNUErrors;                       /* GNU-error-style messages ? */
+
+FILE *PrgFile = NULL;                    /* Codedatei */
+
+StringPtr ErrorPath, ErrorName;          /* Ausgabedatei Fehlermeldungen */
+StringPtr OutName;                       /* Name Code-Datei */
+Integer CurrIncludeLevel;                /* current include nesting level */
+StringPtr CurrFileName;                  /* mom. bearbeitete Datei */
+LongInt MomLineCounter;                  /* Position in mom. Datei */
+LongInt CurrLine;                       /* virtuelle Position */
+LongInt LineSum;                         /* Gesamtzahl Quellzeilen */
+LongInt MacLineSum;                      /* inkl. Makroexpansion */
+
+LongInt NOPCode;                         /* Maschinenbefehl NOP zum Stopfen */
+Boolean TurnWords;                       /* TRUE  = Motorola-Wortformat */
+                                         /* FALSE = Intel-Wortformat */
+Byte HeaderID;                          /* Kennbyte des Codeheaders */
+const char *PCSymbol;                   /* Symbol, womit Programmzaehler erreicht wird. Inhalt Read Only! */
+Boolean (*SetIsOccupiedFnc)(void),       /* TRUE: SET instr, to be parsed by code generator */
+        (*SaveIsOccupiedFnc)(void),      /* ditto for SAVE */
+        (*RestoreIsOccupiedFnc)(void);   /* ditto for RESTORE */
+Boolean SwitchIsOccupied,                /* TRUE: SWITCH/PAGE/SHIFT ist Prozessorbefehl */
+        PageIsOccupied,
+        ShiftIsOccupied;
+#ifdef __PROTOS__
+Boolean (*DecodeAttrPart)(void);         /* dissect attribute of instruction */
+void (*MakeCode)(void);                  /* Codeerzeugungsprozedur */
+Boolean (*ChkPC)(LargeWord Addr);        /* ueberprueft Codelaengenueberschreitungen */
+Boolean (*IsDef)(void);                         /* ist Label nicht als solches zu werten ? */
+void (*SwitchFrom)(void) = NULL;         /* bevor von einer CPU weggeschaltet wird */
+void (*InternSymbol)(char *Asc, TempResult *Erg); /* vordefinierte Symbole ? */
+#else
+Boolean (*DecodeAttrPart)();
+void (*MakeCode)();
+Boolean (*ChkPC)();
+Boolean (*IsDef)();
+void (*SwitchFrom)();
+void (*InternSymbol)();
+#endif
+DissectBitProc DissectBit;
+DissectRegProc DissectReg;
+tQualifyQuoteFnc QualifyQuote;
+
+StringPtr IncludeList;                 /* Suchpfade fuer Includedateien */
+Integer IncDepth, NextIncDepth;         /* Verschachtelungstiefe INCLUDEs */
+FILE *ErrorFile = NULL;                 /* Fehlerausgabe */
+FILE *LstFile = NULL;                   /* Listdatei */
+FILE *ShareFile = NULL;                 /* Sharefile */
+FILE *MacProFile = NULL;                /* Makroprozessorausgabe */
+FILE *MacroFile = NULL;                 /* Ausgabedatei Makroliste */
+Boolean InMacroFlag;                    /* momentan wird Makro expandiert */
+StringPtr LstName;                      /* Name der Listdatei */
+StringPtr MacroName, MacProName;
+tLstMacroExp DoLst, NextDoLst;          /* Listing an */
+StringPtr ShareName;                    /* Name des Sharefiles */
+
+CPUVar MomCPU, MomVirtCPU;              /* definierter/vorgegaukelter Prozessortyp */
+StringPtr MomCPUArgs;                   /* Arguments for Current Processor Type */
+char DefCPU[20];                        /* per Kommandozeile vorgegebene CPU */
+char MomCPUIdent[20],                   /* dessen Name in ASCII */
+     MomFPUIdent[20],                   /* ditto FPU */
+     MomPMMUIdent[20];                  /* ditto PMMU */
+
+Boolean DefSupAllowed;                  /* Supervisormode freigegeben */
+
+int OutRadixBase;                       /* dito fuer Ausgabe */
+int ListRadixBase;                      /* ditto for listing */
+const char *pCommentLeadIn;             /* list of comment lead-in sequences */
+
+tStrComp *ArgStr;                       /* Komponenten der Zeile */
+StringPtr pLOpPart;
+tStrComp LabPart, CommPart, ArgPart, OpPart, AttrPart;
+char AttrSplit;
+int ArgCnt;                             /* Argumentzahl */
+int AllocArgCnt;
+as_dynstr_t OneLine;                    /* eingelesene Zeile */
+#ifdef PROFILE_MEMO
+unsigned NumMemo;
+unsigned long NumMemoCnt, NumMemoSum;
+#endif
+
+Byte LstCounter;                        /* Zeilenzaehler fuer automatischen Umbruch */
+Word PageCounter[ChapMax + 1];          /* hierarchische Seitenzaehler */
+Byte ChapDepth;                         /* momentane Kapitelverschachtelung */
+StringPtr ListLine;                     /* alternative Ausgabe vor Listing fuer EQU */
+Byte PageLength, PageWidth;             /* Seitenlaenge/breite in Zeilen/Spalten */
+tLstMacroExpMod LstMacroExpModOverride, /* Override macro expansion ? */
+                LstMacroExpModDefault;
+Boolean DottedStructs;                  /* structure elements with dots */
+StringPtr PrtInitString;                /* Druckerinitialisierungsstring */
+StringPtr PrtExitString;                /* Druckerdeinitialisierungsstring */
+StringPtr PrtTitleString;               /* Titelzeile */
+
+LongInt MomSectionHandle;               /* mom. Namensraum */
+PSaveSection SectionStack;              /* gespeicherte Sektionshandles */
+tSavePhase *pPhaseStacks[SegCount];    /* saves nested PHASE values */
+
+tSymbolSize AttrPartOpSize;             /* instruction operand size deduced from insn attribute */
+LongWord MaxCodeLen = 0;                /* max. length of generated code */
+LongInt CodeLen;                        /* Laenge des erzeugten Befehls */
+LongWord *DAsmCode;                     /* Zwischenspeicher erzeugter Code */
+Word *WAsmCode;
+Byte *BAsmCode;
+
+Boolean DontPrint;                      /* Flag:PC veraendert, aber keinen Code erzeugt */
+Word ActListGran;                       /* uebersteuerte List-Granularitaet */
+
+Byte StopfZahl;                         /* Anzahl der im 2.Pass festgestellten
+                                           ueberfluessigen Worte, die mit NOP ge-
+                                           fuellt werden muessen */
+
+Boolean SuppWarns;
+
+PTransTable TransTables,                /* Liste mit Codepages */
+            CurrTransTable;             /* aktuelle Codepage */
+
+PDefinement FirstDefine;                /* Liste von Praeprozessor-Defines */
+
+PSaveState FirstSaveState;              /* gesicherte Zustaende */
+
+Boolean MakeDebug;                      /* Debugginghilfe */
+FILE *Debug;
+
+Boolean WasIF, WasMACRO;
+
+void AsmDefInit(void)
+{
+  LongInt z;
+
+  DoLst = eLstMacroExpAll;
+  PassNo = 1;
+  MaxSymPass = 1;
+
+  LineSum = 0;
+
+  for (z = 0; z <= ChapMax; PageCounter[z++] = 0);
+  LstCounter = 0;
+  ChapDepth = 0;
+
+  PrtInitString[0] = '\0';
+  PrtExitString[0] = '\0';
+  PrtTitleString[0] = '\0';
+
+  CurrFileName[0] = '\0';
+  MomLineCounter = 0;
+
+  FirstDefine = NULL;
+  FirstSaveState = NULL;
+}
+
+void NullProc(void)
+{
+}
+
+void Default_InternSymbol(char *Asc, TempResult *Erg)
+{
+  UNUSED(Asc);
+
+  Erg->Typ = TempNone;
+}
+
+void Default_DissectBit(char *pDest, size_t DestSize, LargeWord BitSpec)
+{
+  HexString(pDest, DestSize, BitSpec, 0);
+}
+
+static char *GetString(void)
+{
+  return (char*)malloc(STRINGSIZE * sizeof(char));
+}
+
+int SetMaxCodeLen(LongWord NewMaxCodeLen)
+{
+  if (NewMaxCodeLen > MaxCodeLen_Max)
+    return ENOMEM;
+  if (NewMaxCodeLen > MaxCodeLen)
+  {
+    void *pNewMem;
+
+    if (!MaxCodeLen)
+      pNewMem = (LongWord *) malloc(NewMaxCodeLen);
+    else
+      pNewMem = (LongWord *) realloc(DAsmCode, NewMaxCodeLen);
+    if (!pNewMem)
+      return ENOMEM;
+
+    DAsmCode = (LongWord *)pNewMem;
+    WAsmCode = (Word *) DAsmCode;
+    BAsmCode = (Byte *) DAsmCode;
+    MaxCodeLen = NewMaxCodeLen;
+  }
+  return 0;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     AppendArg(size_t ReqSize)
+ * \brief  extend list of arguments by one more at the end
+ * \param  ReqSize length of argument to store (excluding NUL at end)
+ * ------------------------------------------------------------------------ */
+
+/* NOTICE: Due to port from Pascal sources, ArgStr[] is still indexed starting at
+   one instead of zero:
+
+   - ArgStr[0] is unused.
+   - If ArgCnt == n, ArgStr[1] to ArgStr[n] are used.  */
+
+void AppendArg(size_t ReqSize)
+{
+  if (ArgCnt >= ArgCntMax)
+    WrXError(ErrNum_InternalError, "MaxArgCnt");
+  ++ArgCnt;
+
+  if (ArgCnt >= AllocArgCnt)
+  {
+    size_t NewArgStrSize = sizeof(*ArgStr) * (ArgCnt + 1); /* one more, [0] is unused */
+    int z;
+
+    ArgStr = ArgStr ? (tStrComp*)realloc(ArgStr, NewArgStrSize) : (tStrComp*)malloc(NewArgStrSize);
+    for (z = AllocArgCnt; z <= ArgCnt; z++)
+      StrCompAlloc(&ArgStr[z], STRINGSIZE);
+    AllocArgCnt = ArgCnt + 1;
+  }
+
+  if (ArgStr[ArgCnt].str.capacity <= ReqSize)
+  {
+    if (as_dynstr_realloc(&ArgStr[ArgCnt].str, as_dynstr_roundup_len(ReqSize)))
+      WrXError(ErrNum_InternalError, "out of memory");
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     InsertArg(unsigned Index, size_t ReqSize)
+ * \brief  insert one more arg @ given position
+ * \param  Index insertion position
+ * \param  ReqSize requested size of new arg
+ * ------------------------------------------------------------------------ */
+
+void InsertArg(int Index, size_t ReqSize)
+{
+  int z;
+
+  /* 0 should never be passed... */
+
+  if (Index < 1)
+    Index = 1;
+
+  /* Insertion beyond end means appending */
+
+  if (Index > ArgCnt)
+  {
+    AppendArg(ReqSize);
+    return;
+  }
+
+  /* current last arg dictates length of new last arg */
+
+  AppendArg(strlen(ArgStr[ArgCnt].str.p_str));
+  for (z = ArgCnt; z > Index; z--)
+  {
+    as_dynstr_copy(&ArgStr[z].str, &ArgStr[z - 1].str);
+    ArgStr[z].Pos = ArgStr[z - 1].Pos;
+  }
+  if (ArgStr[Index].str.capacity < ReqSize + 1)
+  {
+    if (as_dynstr_realloc(&ArgStr[Index].str, as_dynstr_roundup_len(ReqSize)))
+      WrXError(ErrNum_InternalError, "out of memory");
+  }
+}
+
+Boolean SetIsOccupied(void)
+{
+  return SetIsOccupiedFnc && SetIsOccupiedFnc();
+}
+
+Boolean SaveIsOccupied(void)
+{
+  return SaveIsOccupiedFnc && SaveIsOccupiedFnc();
+}
+
+Boolean RestoreIsOccupied(void)
+{
+  return RestoreIsOccupiedFnc && RestoreIsOccupiedFnc();
+}
+
+void asmdef_init(void)
+{
+  SwitchFrom = NullProc;
+  InternSymbol = Default_InternSymbol;
+  DissectBit = Default_DissectBit;
+  DissectReg = NULL;
+  QualifyQuote = NULL;
+
+  SetMaxCodeLen(MaxCodeLen_Ini);
+
+  /* auf diese Weise wird PCSymbol defaultmaessig nicht erreichbar
+     da das schon von den Konstantenparsern im Formelparser abgefangen
+     wuerde */
+
+  PCSymbol = "--PC--SYMBOL--";
+  *DefCPU = '\0';
+
+  ArgStr = NULL;
+  AllocArgCnt = 0;
+  SourceFile = GetString();
+  CursUp = GetString();
+  ErrorPath = GetString();
+  ErrorName = GetString();
+  OutName = GetString();
+  CurrFileName = GetString();
+  IncludeList = GetString();
+  LstName = GetString();
+  MacroName = GetString();
+  MacProName = GetString();
+  ShareName = GetString();
+  StrCompAlloc(&LabPart, STRINGSIZE);
+  StrCompAlloc(&OpPart, STRINGSIZE);
+  StrCompAlloc(&AttrPart, STRINGSIZE);
+  StrCompAlloc(&ArgPart, STRINGSIZE);
+  StrCompAlloc(&CommPart, STRINGSIZE);
+  pLOpPart = GetString();
+  as_dynstr_ini(&OneLine, STRINGSIZE);
+  ListLine = GetString();
+  PrtInitString = GetString();
+  PrtExitString = GetString();
+  PrtTitleString = GetString();
+  MomCPUArgs = GetString();
+
+  SegInits = (LargeWord*)calloc(SegCount, sizeof(*SegInits));
+  SegLimits = (LargeWord*)calloc(SegCount, sizeof(*SegLimits));
+  Phases = (LargeWord*)calloc(SegCountPlusStruct, sizeof(*Phases));
+  PCs = (LargeWord*)calloc(SegCountPlusStruct, sizeof(*PCs));
+}
diff --git a/aslshim/asmdef.h b/aslshim/asmdef.h
new file mode 100644 (file)
index 0000000..ba9b4c1
--- /dev/null
@@ -0,0 +1,397 @@
+#ifndef _ASMDEF_H
+#define _ASMDEF_H
+/* asmdef.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* global benutzte Variablen und Definitionen                                */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "chunks.h"
+#include "fileformat.h"
+#include "dynstr.h"
+#include "intformat.h"
+#include "strcomp.h"
+#include "lstmacroexp.h"
+#include "cpulist.h"
+#include "tempresult.h"
+#include "addrspace.h"
+
+typedef struct _TCrossRef
+{
+  struct _TCrossRef *Next;
+  Byte FileNum;
+  LongInt LineNum;
+  Integer OccNum;
+} TCrossRef,*PCrossRef;
+
+
+typedef struct _TPatchEntry
+{
+  struct _TPatchEntry *Next;
+  LargeWord Address;
+  char *Ref;
+  Word len;
+  LongWord RelocType;
+} TPatchEntry, *PPatchEntry;
+
+typedef struct _TExportEntry
+{
+  struct _TExportEntry *Next;
+  char *Name;
+  Word len;
+  LongWord Flags;
+  LargeWord Value;
+} TExportEntry, *PExportEntry;
+
+typedef enum
+{
+  DebugNone,
+  DebugMAP,
+  DebugAOUT,
+  DebugCOFF,
+  DebugELF,
+  DebugAtmel,
+  DebugNoICE
+} DebugType;
+
+#define Char_NUL 0
+#define Char_BEL '\a'
+#define Char_BS '\b'
+#define Char_HT 9
+#define Char_LF '\n'
+#define Char_FF 12
+#define Char_CR 13
+#define Char_ESC 27
+
+#define ListMask_FormFeed         (1 << 0)
+#define ListMask_SymbolList       (1 << 1)
+#define ListMask_MacroList        (1 << 2)
+#define ListMask_FunctionList     (1 << 3)
+#define ListMask_LineNums         (1 << 4)
+#define ListMask_DefineList       (1 << 5)
+#define ListMask_RegDefList       (1 << 6)
+#define ListMask_Codepages        (1 << 7)
+#define ListMask_StructList       (1 << 8)
+
+extern char SrcSuffix[],IncSuffix[],PrgSuffix[],LstSuffix[],
+            MacSuffix[],PreSuffix[],LogSuffix[],MapSuffix[],
+            OBJSuffix[];
+
+#define MomCPUName       "MOMCPU"     /* mom. Prozessortyp */
+#define MomCPUIdentName  "MOMCPUNAME" /* mom. Prozessortyp */
+#define MomFPUIdentName  "MOMFPUNAME" /* mom. Koprozessortyp */
+#define MomPMMUIdentName  "MOMPMMUNAME" /* mom. MMU-Typ */
+#define DoPaddingName    "PADDING"    /* Padding an */
+#define PackingName      "PACKING"    /* gepackte Ablage an */
+#define ListOnName       "LISTON"     /* Listing an/aus */
+#define RelaxedName      "RELAXED"    /* alle Zahlenschreibweisen zugelassen */
+#define BranchExtName    "BRANCHEXT"  /* Spruenge autom. verlaengern */
+#define FlagTrueName     "TRUE"              /* Flagkonstanten */
+#define FlagFalseName    "FALSE"
+#define PiName           "CONSTPI"    /* Zahl Pi */
+#define DateName         "DATE"       /* Datum & Zeit */
+#define TimeName         "TIME"
+#define VerName          "VERSION"    /* speichert Versionsnummer */
+#define CaseSensName     "CASESENSITIVE" /* zeigt Gross/Kleinunterscheidung an */
+#define Has64Name        "HAS64"         /* arbeitet Parser mit 64-Bit-Integers ? */
+#define ArchName         "ARCHITECTURE"  /* Zielarchitektur von AS */
+#define AttrName         "ATTRIBUTE"  /* Attributansprache in Makros */
+#define LabelName        "__LABEL__"  /* Labelansprache in Makros */
+#define ArgCName         "ARGCOUNT"   /* Argumentzahlansprache in Makros */
+#define AllArgName       "ALLARGS"    /* Ansprache Argumentliste in Makros */
+#define DefStackName     "DEFSTACK"   /* Default-Stack */
+#define NestMaxName      "NESTMAX"    /* max. nesting level of a macro */
+#define DottedStructsName "DOTTEDSTRUCTS" /* struct elements by default with . */
+#define CompModeName     "COMPMODE"   /* compatibility mode */
+
+extern const char *EnvName;
+
+/* This results from the tokenized representation of macro arguments
+   in macro bodys: (31*16) - 4 for special arguments: */
+
+#define ArgCntMax 476
+
+#define ChapMax 4
+
+#define AscOfs '0'
+
+#define MaxCodeLen_Ini 256
+#define MaxCodeLen_Max 65535
+extern LongWord MaxCodeLen;
+
+#define DEF_NESTMAX 256
+
+typedef void (*SimpProc)(
+#ifdef __PROTOS__
+void
+#endif
+);
+
+typedef void (*DissectBitProc)(
+#ifdef __PROTOS__
+char *pDest, size_t DestSize, LargeWord Inp
+#endif
+);
+
+typedef Boolean (*tQualifyQuoteFnc)(const char *pStart, const char *pQuotePos);
+
+typedef Word WordField[6];          /* fuer Zahlenumwandlung */
+typedef struct _TTransTable
+{
+  struct _TTransTable *Next;
+  char *Name;
+  unsigned char *Table;
+} TTransTable, *PTransTable;
+
+typedef struct _TSaveState
+{
+  struct _TSaveState *Next;
+  CPUVar SaveCPU;
+  char *pSaveCPUArgs;
+  Integer SavePC;
+  Byte SaveListOn;
+  tLstMacroExp SaveLstMacroExp;
+  tLstMacroExpMod SaveLstMacroExpModDefault,
+                  SaveLstMacroExpModOverride;
+  PTransTable SaveTransTable;
+  Integer SaveEnumSegment;
+  LongInt SaveEnumCurrentValue, SaveEnumIncrement;
+} TSaveState,*PSaveState;
+
+typedef struct _TForwardSymbol
+{
+  struct _TForwardSymbol *Next;
+  StringPtr Name;
+  LongInt DestSection;
+  StringPtr pErrorPos;
+} TForwardSymbol, *PForwardSymbol;
+
+typedef struct _TSaveSection
+{
+  struct _TSaveSection *Next;
+  PForwardSymbol LocSyms, GlobSyms, ExportSyms;
+  LongInt Handle;
+} TSaveSection, *PSaveSection;
+
+typedef struct sSavePhase
+{
+  struct sSavePhase *pNext;
+  LargeWord SaveValue;
+} tSavePhase;
+
+typedef struct _TDefinement
+{
+  struct _TDefinement *Next;
+  StringPtr TransFrom, TransTo;
+  Byte Compiled[256];
+} TDefinement, *PDefinement;
+
+typedef struct _ASSUMERec
+{
+  const char *Name;
+  LongInt *Dest;
+  LongInt Min,Max;
+  LongInt NothingVal;
+  void (*pPostProc)(void);
+} ASSUMERec;
+
+extern StringPtr SourceFile;
+
+extern StringPtr CursUp;
+
+extern LargeWord *PCs;
+extern Boolean RelSegs;
+extern LargeWord StartAdr;
+extern LargeWord AfterBSRAddr;
+extern Boolean StartAdrPresent;
+extern LargeWord *Phases;
+extern Word Grans[SegCountPlusStruct];
+extern Word ListGrans[SegCountPlusStruct];
+extern ChunkList SegChunks[SegCountPlusStruct];
+extern Integer ActPC;
+extern Boolean PCsUsed[SegCountPlusStruct];
+extern LargeWord *SegInits;
+extern LargeWord *SegLimits;
+extern LongInt ValidSegs;
+extern Boolean ENDOccured;
+extern Boolean Retracted;
+extern Boolean ListToStdout,ListToNull;
+
+extern unsigned ASSUMERecCnt;
+extern const ASSUMERec *pASSUMERecs;
+extern void (*pASSUMEOverride)(void);
+
+extern Integer PassNo;
+extern Integer JmpErrors;
+extern Boolean ThrowErrors;
+extern Boolean Repass;
+extern Byte MaxSymPass;
+extern Byte ShareMode;
+extern DebugType DebugMode;
+extern Word NoICEMask;
+extern Byte ListMode;
+extern Byte ListOn;
+extern Integer MaxIncludeLevel;
+extern Boolean MakeUseList;
+extern Boolean MakeCrossList;
+extern Boolean MakeSectionList;
+extern Boolean MakeIncludeList;
+extern Boolean DefRelaxedMode;
+extern Boolean CompMode, DefCompMode;
+extern Word ListMask;
+extern ShortInt ExtendErrors;
+extern Integer EnumSegment;
+extern LongInt EnumIncrement, EnumCurrentValue;
+extern LongWord MaxErrors;
+extern Boolean TreatWarningsAsErrors;
+
+extern LongInt MomSectionHandle;
+extern PSaveSection SectionStack;
+extern tSavePhase *pPhaseStacks[SegCount];
+
+extern tSymbolSize AttrPartOpSize;
+extern LongInt CodeLen;
+extern Byte *BAsmCode;
+extern Word *WAsmCode;
+extern LongWord *DAsmCode;
+
+extern Boolean DontPrint;
+extern Word ActListGran;
+
+extern Boolean NumericErrors;
+extern Boolean CodeOutput;
+extern Boolean MacProOutput;
+extern Boolean MacroOutput;
+extern Boolean QuietMode;
+extern Boolean HardRanges;
+extern const char *DivideChars;
+extern Boolean HasAttrs;
+extern const char *AttrChars;
+extern Boolean MsgIfRepass;
+extern Integer PassNoForMessage;
+extern Boolean CaseSensitive;
+extern LongInt NestMax;
+extern Boolean GNUErrors;
+
+extern FILE *PrgFile;
+
+extern StringPtr ErrorPath,ErrorName;
+extern StringPtr OutName;
+extern Integer CurrIncludeLevel;
+extern StringPtr CurrFileName;
+extern LongInt CurrLine;
+extern LongInt MomLineCounter;
+extern LongInt LineSum;
+extern LongInt MacLineSum;
+
+extern LongInt NOPCode;
+extern Boolean TurnWords;
+extern Byte HeaderID;
+extern const char *PCSymbol;
+extern tIntConstMode IntConstMode;
+extern Boolean IntConstModeIBMNoTerm;
+extern Boolean (*SetIsOccupiedFnc)(void),
+               (*SaveIsOccupiedFnc)(void),
+               (*RestoreIsOccupiedFnc)(void);
+extern Boolean SwitchIsOccupied, PageIsOccupied, ShiftIsOccupied;
+extern Boolean (*DecodeAttrPart)(void);
+extern void (*MakeCode)(void);
+extern Boolean (*ChkPC)(LargeWord Addr);
+extern Boolean (*IsDef)(void);
+extern void (*SwitchFrom)(void);
+extern void (*InternSymbol)(char *Asc, TempResult *Erg);
+extern DissectBitProc DissectBit;
+extern DissectRegProc DissectReg;
+extern tQualifyQuoteFnc QualifyQuote;
+
+extern StringPtr IncludeList;
+extern Integer IncDepth,NextIncDepth;
+extern FILE *ErrorFile;
+extern FILE *LstFile;
+extern FILE *ShareFile;
+extern FILE *MacProFile;
+extern FILE *MacroFile;
+extern Boolean InMacroFlag;
+extern StringPtr LstName, MacroName, MacProName;
+extern tLstMacroExp DoLst, NextDoLst;
+extern StringPtr ShareName;
+extern CPUVar MomCPU, MomVirtCPU;
+extern StringPtr MomCPUArgs;
+extern char DefCPU[20];
+extern char MomCPUIdent[20],
+            MomFPUIdent[20],
+            MomPMMUIdent[20];
+
+extern Boolean DefSupAllowed;
+
+extern int OutRadixBase, ListRadixBase;
+extern const char *pCommentLeadIn;
+
+extern tStrComp *ArgStr;
+extern StringPtr pLOpPart;
+extern tStrComp LabPart, CommPart, ArgPart, OpPart, AttrPart;
+extern char AttrSplit;
+extern int ArgCnt;
+extern as_dynstr_t OneLine;
+#ifdef PROFILE_MEMO
+extern unsigned NumMemo;
+extern unsigned long NumMemoSum, NumMemoCnt;
+#endif
+
+#define forallargs(pArg, cond) \
+        for (pArg = ArgStr + 1; (cond) && (pArg <= ArgStr + ArgCnt); pArg++)
+
+extern Byte LstCounter;
+extern Word PageCounter[ChapMax+1];
+extern Byte ChapDepth;
+extern StringPtr ListLine;
+extern Byte PageLength, PageWidth;
+extern tLstMacroExpMod LstMacroExpModOverride, LstMacroExpModDefault;
+extern Boolean DottedStructs;
+extern StringPtr PrtInitString;
+extern StringPtr PrtExitString;
+extern StringPtr PrtTitleString;
+
+extern Byte StopfZahl;
+
+extern Boolean SuppWarns;
+
+#define CharTransTable CurrTransTable->Table
+extern PTransTable TransTables, CurrTransTable;
+
+extern PDefinement FirstDefine;
+
+extern PSaveState FirstSaveState;
+
+extern Boolean MakeDebug;
+extern FILE *Debug;
+
+extern Boolean WasIF, WasMACRO;
+
+extern void AsmDefInit(void);
+
+extern void NullProc(void);
+
+extern int SetMaxCodeLen(LongWord NewMaxCodeLen);
+
+extern void Default_InternSymbol(char *Asc, TempResult *Erg);
+
+extern void Default_DissectBit(char *pDest, size_t DestSize, LargeWord BitSpec);
+
+extern void AppendArg(size_t ReqSize);
+extern void InsertArg(int Index, size_t ReqSize);
+
+
+extern Boolean SetIsOccupied(void);
+extern Boolean SaveIsOccupied(void);
+extern Boolean RestoreIsOccupied(void);
+
+extern void asmdef_init(void);
+#endif /* _ASMDEF_H */
diff --git a/aslshim/asmerr.c b/aslshim/asmerr.c
new file mode 100644 (file)
index 0000000..34cc3c4
--- /dev/null
@@ -0,0 +1,998 @@
+/* asmerr.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Error Message Writing                                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "console.h"
+#include "strutil.h"
+#include "nlmessages.h"
+#include "stdhandl.h"
+#include "as.h"
+#include "as.rsc"
+#include "ioerrs.h"
+#include "asmerr.h"
+
+typedef struct sExpectError
+{
+  struct sExpectError *pNext;
+  tErrorNum Num;
+} tExpectError;
+
+Word ErrorCount, WarnCount;
+static tExpectError *pExpectErrors = NULL;
+static Boolean InExpect = False;
+
+static void ClearExpectErrors(void)
+{
+  tExpectError *pOld;
+
+  while (pExpectErrors)
+  {
+    pOld = pExpectErrors;
+    pExpectErrors = pExpectErrors->pNext;
+    free(pOld);
+  }
+}
+
+static void AddExpectError(tExpectError *pExpectError)
+{
+  pExpectError->pNext = pExpectErrors;
+  pExpectErrors = pExpectError;
+}
+
+static tExpectError *FindAndTakeExpectError(tErrorNum Num)
+{
+  tExpectError *pRun, *pPrev;
+
+  for (pRun = pExpectErrors, pPrev = NULL; pRun; pPrev = pRun, pRun = pRun->pNext)
+    if (Num == pRun->Num)
+    {
+      if (pPrev)
+        pPrev->pNext = pRun->pNext;
+      else
+        pExpectErrors = pRun->pNext;
+      return pRun;
+    }
+  return NULL;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     GenLineMarker(char *pDest, unsigned DestSize, char Marker, const struct sLineComp *pLineComp, * const char *pPrefix)
+ * \brief  print a line, optionally with a marking of a component below
+ * \param  pDest where to write
+ * \param  DestSize destination buffer size
+ * \param  Marker character to use for marking
+ * \param  pLineComp position and length of optional marker
+ * \param  pPrefix what to print before (under)line
+ * ------------------------------------------------------------------------ */
+
+static void GenLineMarker(char *pDest, unsigned DestSize, char Marker, const struct sLineComp *pLineComp, const char *pPrefix)
+{
+  char *pRun;
+  int z;
+
+  strmaxcpy(pDest, pPrefix, DestSize);
+  pRun = pDest + strlen(pDest);
+
+  for (z = 0; (z < pLineComp->StartCol) && (pRun - pDest + 1 < (int)DestSize); z++)
+    *pRun++ = ' ';
+  for (z = 0; (z < (int)pLineComp->Len) && (pRun - pDest + 1 < (int)DestSize); z++)
+    *pRun++ = Marker;
+  *pRun = '\0';
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     GenLineForMarking(char *pDest, unsigned DestSize, const char *pSrc, const char *pPrefix)
+ * \brief  generate a line, in compressed form for optional marking of a component below
+ * \param  pDest where to write
+ * \param  DestSize destination buffer size
+ * \param  pSrc line to print/underline
+ * \param  pPrefix what to print before (under)line
+ * ------------------------------------------------------------------------ */
+
+static void GenLineForMarking(char *pDest, unsigned DestSize, const char *pSrc, const char *pPrefix)
+{
+  char *pRun;
+
+  strmaxcpy(pDest, pPrefix, DestSize);
+  pRun = pDest + strlen(pDest);
+
+  /* replace TABs in line with spaces - column counting counts TAB as one character */
+
+  for (; *pSrc && (pRun - pDest + 1 < (int)DestSize); pSrc++)
+    *pRun++ = TabCompressed(*pSrc);
+  *pRun = '\0';
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     EmergencyStop(void)
+ * \brief  instantly stop upon fatal error
+ * ------------------------------------------------------------------------ */
+
+static void EmergencyStop(void)
+{
+  CloseIfOpen(&ErrorFile);
+  CloseIfOpen(&LstFile);
+  if (ShareMode != 0)
+  {
+    CloseIfOpen(&ShareFile);
+    unlink(ShareName);
+  }
+  if (MacProOutput)
+  {
+    CloseIfOpen(&MacProFile);
+    unlink(MacProName);
+  }
+  if (MacroOutput)
+  {
+    CloseIfOpen(&MacroFile);
+    unlink(MacroName);
+  }
+  if (MakeDebug)
+    CloseIfOpen(&Debug);
+  if (CodeOutput)
+  {
+    CloseIfOpen(&PrgFile);
+    unlink(OutName);
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ErrorNum2String(tErrorNum Num, char Buf, int BufSize)
+ * \brief  convert error # to string
+ * \param  Num numeric error
+ * \param  Buf buffer for complex messages
+ * \param  BufSize capacity of Buf
+ * \return * to message
+ * ------------------------------------------------------------------------ */
+
+static const char *ErrorNum2String(tErrorNum Num, char *Buf, int BufSize)
+{
+  int msgno = -1;
+
+  *Buf = '\0';
+  switch (Num)
+  {
+    case ErrNum_UselessDisp:
+      msgno = Num_ErrMsgUselessDisp; break;
+    case ErrNum_ShortAddrPossible:
+      msgno = Num_ErrMsgShortAddrPossible; break;
+    case ErrNum_ShortJumpPossible:
+      msgno = Num_ErrMsgShortJumpPossible; break;
+    case ErrNum_NoShareFile:
+      msgno = Num_ErrMsgNoShareFile; break;
+    case ErrNum_BigDecFloat:
+      msgno = Num_ErrMsgBigDecFloat; break;
+    case ErrNum_PrivOrder:
+      msgno = Num_ErrMsgPrivOrder; break;
+    case ErrNum_DistNull:
+      msgno = Num_ErrMsgDistNull; break;
+    case ErrNum_WrongSegment:
+      msgno = Num_ErrMsgWrongSegment; break;
+    case ErrNum_InAccSegment:
+      msgno = Num_ErrMsgInAccSegment; break;
+    case ErrNum_PhaseErr:
+      msgno = Num_ErrMsgPhaseErr; break;
+    case ErrNum_Overlap:
+      msgno = Num_ErrMsgOverlap; break;
+    case ErrNum_OverlapReg:
+      msgno = Num_ErrMsgOverlapReg; break;
+    case ErrNum_NoCaseHit:
+      msgno = Num_ErrMsgNoCaseHit; break;
+    case ErrNum_InAccPage:
+      msgno = Num_ErrMsgInAccPage; break;
+    case ErrNum_RMustBeEven:
+      msgno = Num_ErrMsgRMustBeEven; break;
+    case ErrNum_Obsolete:
+      msgno = Num_ErrMsgObsolete; break;
+    case ErrNum_Unpredictable:
+      msgno = Num_ErrMsgUnpredictable; break;
+    case ErrNum_AlphaNoSense:
+      msgno = Num_ErrMsgAlphaNoSense; break;
+    case ErrNum_Senseless:
+      msgno = Num_ErrMsgSenseless; break;
+    case ErrNum_RepassUnknown:
+      msgno = Num_ErrMsgRepassUnknown; break;
+    case  ErrNum_AddrNotAligned:
+      msgno = Num_ErrMsgAddrNotAligned; break;
+    case ErrNum_IOAddrNotAllowed:
+      msgno = Num_ErrMsgIOAddrNotAllowed; break;
+    case ErrNum_Pipeline:
+      msgno = Num_ErrMsgPipeline; break;
+    case ErrNum_DoubleAdrRegUse:
+      msgno = Num_ErrMsgDoubleAdrRegUse; break;
+    case ErrNum_NotBitAddressable:
+      msgno = Num_ErrMsgNotBitAddressable; break;
+    case ErrNum_StackNotEmpty:
+      msgno = Num_ErrMsgStackNotEmpty; break;
+    case ErrNum_NULCharacter:
+      msgno = Num_ErrMsgNULCharacter; break;
+    case ErrNum_PageCrossing:
+      msgno = Num_ErrMsgPageCrossing; break;
+    case ErrNum_WUnderRange:
+      msgno = Num_ErrMsgWUnderRange; break;
+    case ErrNum_WOverRange:
+      msgno = Num_ErrMsgWOverRange; break;
+    case ErrNum_NegDUP:
+      msgno = Num_ErrMsgNegDUP; break;
+    case ErrNum_ConvIndX:
+      msgno = Num_ErrMsgConvIndX; break;
+    case ErrNum_NullResMem:
+      msgno = Num_ErrMsgNullResMem; break;
+    case ErrNum_BitNumberTruncated:
+      msgno = Num_ErrMsgBitNumberTruncated; break;
+    case ErrNum_InvRegisterPointer:
+      msgno = Num_ErrMsgInvRegisterPointer; break;
+    case ErrNum_MacArgRedef:
+      msgno = Num_ErrMsgMacArgRedef; break;
+    case ErrNum_Deprecated:
+      msgno = Num_ErrMsgDeprecated; break;
+    case ErrNum_SrcLEThanDest:
+      msgno = Num_ErrMsgSrcLEThanDest; break;
+    case ErrNum_TrapValidInstruction:
+      msgno = Num_ErrMsgTrapValidInstruction; break;
+    case ErrNum_PaddingAdded:
+      msgno = Num_ErrMsgPaddingAdded; break;
+    case ErrNum_RegNumWraparound:
+      msgno = Num_ErrMsgRegNumWraparound; break;
+    case ErrNum_IndexedForIndirect:
+      msgno = Num_ErrMsgIndexedForIndirect; break;
+    case ErrNum_DoubleDef:
+      msgno = Num_ErrMsgDoubleDef; break;
+    case ErrNum_SymbolUndef:
+      msgno = Num_ErrMsgSymbolUndef; break;
+    case ErrNum_InvSymName:
+      msgno = Num_ErrMsgInvSymName; break;
+    case ErrNum_InvFormat:
+      msgno = Num_ErrMsgInvFormat; break;
+    case ErrNum_UseLessAttr:
+      msgno = Num_ErrMsgUseLessAttr; break;
+    case ErrNum_TooLongAttr:
+      msgno = Num_ErrMsgTooLongAttr; break;
+    case ErrNum_UndefAttr:
+      msgno = Num_ErrMsgUndefAttr; break;
+    case ErrNum_WrongArgCnt:
+      msgno = Num_ErrMsgWrongArgCnt; break;
+    case ErrNum_CannotSplitArg:
+      msgno = Num_ErrMsgCannotSplitArg; break;
+    case ErrNum_WrongOptCnt:
+      msgno = Num_ErrMsgWrongOptCnt; break;
+    case ErrNum_OnlyImmAddr:
+      msgno = Num_ErrMsgOnlyImmAddr; break;
+    case ErrNum_InvOpSize:
+      msgno = Num_ErrMsgInvOpSize; break;
+    case ErrNum_ConfOpSizes:
+      msgno = Num_ErrMsgConfOpSizes; break;
+    case ErrNum_UndefOpSizes:
+      msgno = Num_ErrMsgUndefOpSizes; break;
+    case ErrNum_StringOrIntButFloat:
+      msgno = Num_ErrMsgStringOrIntButFloat; break;
+    case ErrNum_IntButFloat:
+      msgno = Num_ErrMsgIntButFloat; break;
+    case ErrNum_FloatButString:
+      msgno = Num_ErrMsgFloatButString; break;
+    case ErrNum_OpTypeMismatch:
+      msgno = Num_ErrMsgOpTypeMismatch; break;
+    case ErrNum_StringButInt:
+      msgno = Num_ErrMsgStringButInt; break;
+    case ErrNum_StringButFloat:
+      msgno = Num_ErrMsgStringButFloat; break;
+    case ErrNum_TooManyArgs:
+      msgno = Num_ErrMsgTooManyArgs; break;
+    case ErrNum_IntButString:
+      msgno = Num_ErrMsgIntButString; break;
+    case ErrNum_IntOrFloatButString:
+      msgno = Num_ErrMsgIntOrFloatButString; break;
+    case ErrNum_ExpectString:
+      msgno = Num_ErrMsgExpectString; break;
+    case ErrNum_ExpectInt:
+      msgno = Num_ErrMsgExpectInt; break;
+    case ErrNum_StringOrIntOrFloatButReg:
+      msgno = Num_ErrMsgStringOrIntOrFloatButReg; break;
+    case ErrNum_ExpectIntOrString:
+      msgno = Num_ErrMsgExpectIntOrString; break;
+    case ErrNum_ExpectReg:
+      msgno = Num_ErrMsgExpectReg; break;
+    case ErrNum_RegWrongTarget:
+      msgno = Num_ErrMsgRegWrongTarget; break;
+    case ErrNum_NoRelocs:
+      msgno = Num_ErrMsgNoRelocs; break;
+    case ErrNum_UnresRelocs:
+      msgno = Num_ErrMsgUnresRelocs; break;
+    case ErrNum_Unexportable:
+      msgno = Num_ErrMsgUnexportable; break;
+    case ErrNum_UnknownInstruction:
+      msgno = Num_ErrMsgUnknownInstruction; break;
+    case ErrNum_BrackErr:
+      msgno = Num_ErrMsgBrackErr; break;
+    case ErrNum_DivByZero:
+      msgno = Num_ErrMsgDivByZero; break;
+    case ErrNum_UnderRange:
+      msgno = Num_ErrMsgUnderRange; break;
+    case ErrNum_OverRange:
+      msgno = Num_ErrMsgOverRange; break;
+    case ErrNum_NotPwr2:
+      msgno = Num_ErrMsgNotPwr2; break;
+    case ErrNum_NotAligned:
+      msgno = Num_ErrMsgNotAligned; break;
+    case ErrNum_DistTooBig:
+      msgno = Num_ErrMsgDistTooBig; break;
+    case ErrNum_InAccReg:
+      msgno = Num_ErrMsgInAccReg; break;
+    case ErrNum_NoShortAddr:
+      msgno = Num_ErrMsgNoShortAddr; break;
+    case ErrNum_InvAddrMode:
+      msgno = Num_ErrMsgInvAddrMode; break;
+    case ErrNum_AddrMustBeEven:
+      msgno = Num_ErrMsgAddrMustBeEven; break;
+    case ErrNum_AddrMustBeAligned:
+      msgno = Num_ErrMsgAddrMustBeAligned; break;
+    case ErrNum_InvParAddrMode:
+      msgno = Num_ErrMsgInvParAddrMode; break;
+    case ErrNum_UndefCond:
+      msgno = Num_ErrMsgUndefCond; break;
+    case ErrNum_IncompCond:
+      msgno = Num_ErrMsgIncompCond; break;
+    case ErrNum_UnknownFlag:
+      msgno = Num_ErrMsgUnknownFlag; break;
+    case ErrNum_DuplicateFlag:
+      msgno = Num_ErrMsgDuplicateFlag; break;
+    case ErrNum_UnknownInt:
+      msgno = Num_ErrMsgUnknownInt; break;
+    case ErrNum_DuplicateInt:
+      msgno = Num_ErrMsgDuplicateInt; break;
+    case ErrNum_JmpDistTooBig:
+      msgno = Num_ErrMsgJmpDistTooBig; break;
+    case ErrNum_DistIsOdd:
+      msgno = Num_ErrMsgDistIsOdd; break;
+    case ErrNum_SkipTargetMismatch:
+      msgno = Num_ErrMsgSkipTargetMismatch; break;
+    case ErrNum_InvShiftArg:
+      msgno = Num_ErrMsgInvShiftArg; break;
+    case ErrNum_Only1:
+      msgno = Num_ErrMsgOnly1; break;
+    case ErrNum_Range18:
+      msgno = Num_ErrMsgRange18; break;
+    case ErrNum_ShiftCntTooBig:
+      msgno = Num_ErrMsgShiftCntTooBig; break;
+    case ErrNum_InvRegList:
+      msgno = Num_ErrMsgInvRegList; break;
+    case ErrNum_InvCmpMode:
+      msgno = Num_ErrMsgInvCmpMode; break;
+    case ErrNum_InvCPUType:
+      msgno = Num_ErrMsgInvCPUType; break;
+    case ErrNum_InvFPUType:
+      msgno = Num_ErrMsgInvFPUType; break;
+    case ErrNum_InvPMMUType:
+      msgno = Num_ErrMsgInvPMMUType; break;
+    case ErrNum_InvCtrlReg:
+      msgno = Num_ErrMsgInvCtrlReg; break;
+    case ErrNum_InvReg:
+      msgno = Num_ErrMsgInvReg; break;
+    case ErrNum_DoubleReg:
+      msgno = Num_ErrMsgDoubleReg; break;
+    case ErrNum_RegBankMismatch:
+      msgno = Num_ErrMsgRegBankMismatch; break;
+    case ErrNum_UndefRegSize:
+      msgno = Num_ErrMsgUndefRegSize; break;
+    case ErrNum_InvOpOnReg:
+      msgno = Num_ErrMsgInvOpOnReg; break;
+    case ErrNum_NoSaveFrame:
+      msgno = Num_ErrMsgNoSaveFrame; break;
+    case ErrNum_NoRestoreFrame:
+      msgno = Num_ErrMsgNoRestoreFrame; break;
+    case ErrNum_UnknownMacArg:
+      msgno = Num_ErrMsgUnknownMacArg; break;
+    case ErrNum_MissEndif:
+      msgno = Num_ErrMsgMissEndif; break;
+    case ErrNum_InvIfConst:
+      msgno = Num_ErrMsgInvIfConst; break;
+    case ErrNum_DoubleSection:
+      msgno = Num_ErrMsgDoubleSection; break;
+    case ErrNum_InvSection:
+      msgno = Num_ErrMsgInvSection; break;
+    case ErrNum_MissingEndSect:
+      msgno = Num_ErrMsgMissingEndSect; break;
+    case ErrNum_WrongEndSect:
+      msgno = Num_ErrMsgWrongEndSect; break;
+    case ErrNum_NotInSection:
+      msgno = Num_ErrMsgNotInSection; break;
+    case ErrNum_UndefdForward:
+      msgno = Num_ErrMsgUndefdForward; break;
+    case ErrNum_ContForward:
+      msgno = Num_ErrMsgContForward; break;
+    case ErrNum_InvFuncArgCnt:
+      msgno = Num_ErrMsgInvFuncArgCnt; break;
+    case ErrNum_MsgMissingLTORG:
+      msgno = Num_ErrMsgMissingLTORG; break;
+    case ErrNum_InstructionNotSupported:
+      as_snprintf(Buf, BufSize, getmessage(Num_ErrMsgInstructionNotOnThisCPUSupported), MomCPUIdent);
+      break;
+    case ErrNum_FPUNotEnabled:
+      msgno = Num_ErrMsgFPUNotEnabled; break;
+    case ErrNum_PMMUNotEnabled:
+      msgno = Num_ErrMsgPMMUNotEnabled; break;
+    case ErrNum_FullPMMUNotEnabled:
+      msgno = Num_ErrMsgFullPMMUNotEnabled; break;
+    case ErrNum_Z80SyntaxNotEnabled:
+      msgno = Num_ErrMsgZ80SyntaxNotEnabled; break;
+    case ErrNum_Z80SyntaxExclusive:
+      msgno = Num_ErrMsgZ80SyntaxExclusive; break;
+    case ErrNum_FPUInstructionNotSupported:
+      as_snprintf(Buf, BufSize, getmessage(Num_ErrMsgInstructionNotOnThisFPUSupported), MomFPUIdent);
+      break;
+    case ErrNum_AddrModeNotSupported:
+      as_snprintf(Buf, BufSize, getmessage(Num_ErrMsgAddrModeNotOnThisCPUSupported), MomCPUIdent);
+      break;
+    case ErrNum_CustomNotEnabled:
+      msgno = Num_ErrMsgCustomNotEnabled; break;
+    case ErrNum_InvBitPos:
+      msgno = Num_ErrMsgInvBitPos; break;
+    case ErrNum_OnlyOnOff:
+      msgno = Num_ErrMsgOnlyOnOff; break;
+    case ErrNum_StackEmpty:
+      msgno = Num_ErrMsgStackEmpty; break;
+    case ErrNum_NotOneBit:
+      msgno = Num_ErrMsgNotOneBit; break;
+    case ErrNum_MissingStruct:
+      msgno = Num_ErrMsgMissingStruct; break;
+    case ErrNum_OpenStruct:
+      msgno = Num_ErrMsgOpenStruct; break;
+    case ErrNum_WrongStruct:
+      msgno = Num_ErrMsgWrongStruct; break;
+    case ErrNum_PhaseDisallowed:
+      msgno = Num_ErrMsgPhaseDisallowed; break;
+    case ErrNum_InvStructDir:
+      msgno = Num_ErrMsgInvStructDir; break;
+    case ErrNum_DoubleStruct:
+      msgno = Num_ErrMsgDoubleStruct; break;
+    case ErrNum_UnresolvedStructRef:
+      msgno = Num_ErrMsgUnresolvedStructRef; break;
+    case ErrNum_DuplicateStructElem:
+      msgno = Num_ErrMsgDuplicateStructElem; break;
+    case ErrNum_NotRepeatable:
+      msgno = Num_ErrMsgNotRepeatable; break;
+    case ErrNum_ShortRead:
+      msgno = Num_ErrMsgShortRead; break;
+    case ErrNum_UnknownCodepage:
+      msgno = Num_ErrMsgUnknownCodepage; break;
+    case ErrNum_RomOffs063:
+      msgno = Num_ErrMsgRomOffs063; break;
+    case ErrNum_InvFCode:
+      msgno = Num_ErrMsgInvFCode; break;
+    case ErrNum_InvFMask:
+      msgno = Num_ErrMsgInvFMask; break;
+    case ErrNum_InvMMUReg:
+      msgno = Num_ErrMsgInvMMUReg; break;
+    case ErrNum_Level07:
+      msgno = Num_ErrMsgLevel07; break;
+    case ErrNum_InvBitMask:
+      msgno = Num_ErrMsgInvBitMask; break;
+    case ErrNum_InvRegPair:
+      msgno = Num_ErrMsgInvRegPair; break;
+    case ErrNum_OpenMacro:
+      msgno = Num_ErrMsgOpenMacro; break;
+    case ErrNum_OpenIRP:
+      msgno = Num_ErrMsgOpenIRP; break;
+    case ErrNum_OpenIRPC:
+      msgno = Num_ErrMsgOpenIRPC; break;
+    case ErrNum_OpenREPT:
+      msgno = Num_ErrMsgOpenREPT; break;
+    case ErrNum_OpenWHILE:
+      msgno = Num_ErrMsgOpenWHILE; break;
+    case ErrNum_EXITMOutsideMacro:
+      msgno = Num_ErrMsgEXITMOutsideMacro; break;
+    case ErrNum_TooManyMacParams:
+      msgno = Num_ErrMsgTooManyMacParams; break;
+    case ErrNum_UndefKeyArg:
+      msgno = Num_ErrMsgUndefKeyArg; break;
+    case ErrNum_NoPosArg:
+      msgno = Num_ErrMsgNoPosArg; break;
+    case ErrNum_DoubleMacro:
+      msgno = Num_ErrMsgDoubleMacro; break;
+    case ErrNum_FirstPassCalc:
+      msgno = Num_ErrMsgFirstPassCalc; break;
+    case ErrNum_TooManyNestedIfs:
+      msgno = Num_ErrMsgTooManyNestedIfs; break;
+    case ErrNum_MissingIf:
+      msgno = Num_ErrMsgMissingIf; break;
+    case ErrNum_RekMacro:
+      msgno = Num_ErrMsgRekMacro; break;
+    case ErrNum_UnknownFunc:
+      msgno = Num_ErrMsgUnknownFunc; break;
+    case ErrNum_InvFuncArg:
+      msgno = Num_ErrMsgInvFuncArg; break;
+    case ErrNum_FloatOverflow:
+      msgno = Num_ErrMsgFloatOverflow; break;
+    case ErrNum_InvArgPair:
+      msgno = Num_ErrMsgInvArgPair; break;
+    case ErrNum_NotOnThisAddress:
+      msgno = Num_ErrMsgNotOnThisAddress; break;
+    case ErrNum_NotFromThisAddress:
+      msgno = Num_ErrMsgNotFromThisAddress; break;
+    case ErrNum_TargOnDiffPage:
+      msgno = Num_ErrMsgTargOnDiffPage; break;
+    case ErrNum_TargOnDiffSection:
+      msgno = Num_ErrMsgTargOnDiffSection; break;
+    case ErrNum_CodeOverflow:
+      msgno = Num_ErrMsgCodeOverflow; break;
+    case ErrNum_AdrOverflow:
+      msgno = Num_ErrMsgAdrOverflow; break;
+    case ErrNum_MixDBDS:
+      msgno = Num_ErrMsgMixDBDS; break;
+    case ErrNum_NotInStruct:
+      msgno = Num_ErrMsgNotInStruct; break;
+    case ErrNum_ParNotPossible:
+      msgno = Num_ErrMsgParNotPossible; break;
+    case ErrNum_InvSegment:
+      msgno = Num_ErrMsgInvSegment; break;
+    case ErrNum_UnknownSegment:
+      msgno = Num_ErrMsgUnknownSegment; break;
+    case ErrNum_UnknownSegReg:
+      msgno = Num_ErrMsgUnknownSegReg; break;
+    case ErrNum_InvString:
+      msgno = Num_ErrMsgInvString; break;
+    case ErrNum_InvRegName:
+      msgno = Num_ErrMsgInvRegName; break;
+    case ErrNum_InvArg:
+      msgno = Num_ErrMsgInvArg; break;
+    case ErrNum_NoIndir:
+      msgno = Num_ErrMsgNoIndir; break;
+    case ErrNum_NotInThisSegment:
+      msgno = Num_ErrMsgNotInThisSegment; break;
+    case ErrNum_NotInMaxmode:
+      msgno = Num_ErrMsgNotInMaxmode; break;
+    case ErrNum_OnlyInMaxmode:
+      msgno = Num_ErrMsgOnlyInMaxmode; break;
+    case ErrNum_PackCrossBoundary:
+      msgno = Num_ErrMsgPackCrossBoundary; break;
+    case ErrNum_UnitMultipleUsed:
+      msgno = Num_ErrMsgUnitMultipleUsed; break;
+    case ErrNum_MultipleLongRead:
+      msgno = Num_ErrMsgMultipleLongRead; break;
+    case ErrNum_MultipleLongWrite:
+      msgno = Num_ErrMsgMultipleLongWrite; break;
+    case ErrNum_LongReadWithStore:
+      msgno = Num_ErrMsgLongReadWithStore; break;
+    case ErrNum_TooManyRegisterReads:
+      msgno = Num_ErrMsgTooManyRegisterReads; break;
+    case ErrNum_OverlapDests:
+      msgno = Num_ErrMsgOverlapDests; break;
+    case ErrNum_TooManyBranchesInExPacket:
+      msgno = Num_ErrMsgTooManyBranchesInExPacket; break;
+    case ErrNum_CannotUseUnit:
+      msgno = Num_ErrMsgCannotUseUnit; break;
+    case ErrNum_InvEscSequence:
+      msgno = Num_ErrMsgInvEscSequence; break;
+    case ErrNum_InvPrefixCombination:
+      msgno = Num_ErrMsgInvPrefixCombination; break;
+    case ErrNum_ConstantRedefinedAsVariable:
+      msgno = Num_ErrMsgConstantRedefinedAsVariable; break;
+    case ErrNum_VariableRedefinedAsConstant:
+      msgno = Num_ErrMsgVariableRedefinedAsConstant; break;
+    case ErrNum_StructNameMissing:
+      msgno = Num_ErrMsgStructNameMissing; break;
+    case ErrNum_EmptyArgument:
+      msgno = Num_ErrMsgEmptyArgument; break;
+    case ErrNum_Unimplemented:
+      msgno = Num_ErrMsgUnimplemented; break;
+    case ErrNum_FreestandingUnnamedStruct:
+      msgno = Num_ErrMsgFreestandingUnnamedStruct; break;
+    case ErrNum_STRUCTEndedByENDUNION:
+      msgno = Num_ErrMsgSTRUCTEndedByENDUNION; break;
+    case ErrNum_AddrOnDifferentPage:
+      msgno = Num_ErrMsgAddrOnDifferentPage; break;
+    case ErrNum_UnknownMacExpMod:
+      msgno = Num_ErrMsgUnknownMacExpMod; break;
+    case ErrNum_TooManyMacExpMod:
+      msgno = Num_ErrMsgTooManyMacExpMod; break;
+    case ErrNum_ConflictingMacExpMod:
+      msgno = Num_ErrMsgConflictingMacExpMod; break;
+    case ErrNum_InvalidPrepDir:
+      msgno = Num_ErrMsgInvalidPrepDir; break;
+    case ErrNum_ExpectedError:
+      msgno = Num_ErrMsgExpectedError; break;
+    case ErrNum_NoNestExpect:
+      msgno = Num_ErrMsgNoNestExpect; break;
+    case ErrNum_MissingENDEXPECT:
+      msgno = Num_ErrMsgMissingENDEXPECT; break;
+    case ErrNum_MissingEXPECT:
+      msgno = Num_ErrMsgMissingEXPECT; break;
+    case ErrNum_NoDefCkptReg:
+      msgno = Num_ErrMsgNoDefCkptReg; break;
+    case ErrNum_InvBitField:
+      msgno = Num_ErrMsgInvBitField; break;
+    case ErrNum_ArgValueMissing:
+      msgno = Num_ErrMsgArgValueMissing; break;
+    case ErrNum_UnknownArg:
+      msgno = Num_ErrMsgUnknownArg; break;
+    case ErrNum_IndexRegMustBe16Bit:
+      msgno = Num_ErrMsgIndexRegMustBe16Bit; break;
+    case ErrNum_IOAddrRegMustBe16Bit:
+      msgno = Num_ErrMsgIOAddrRegMustBe16Bit; break;
+    case ErrNum_SegAddrRegMustBe32Bit:
+      msgno = Num_ErrMsgSegAddrRegMustBe32Bit; break;
+    case ErrNum_NonSegAddrRegMustBe16Bit:
+      msgno = Num_ErrMsgNonSegAddrRegMustBe16Bit; break;
+    case ErrNum_InvStructArgument:
+      msgno = Num_ErrMsgInvStructArgument; break;
+    case ErrNum_TooManyArrayDimensions:
+      msgno = Num_ErrMsgTooManyArrayDimensions; break;
+    case ErrNum_InvIntFormat:
+      msgno = Num_ErrMsgInvIntFormat; break;
+    case ErrNum_InvIntFormatList:
+      msgno = Num_ErrMsgInvIntFormatList; break;
+    case ErrNum_InvScale:
+      msgno = Num_ErrMsgInvScale; break;
+    case ErrNum_ConfStringOpt:
+      msgno = Num_ErrMsgConfStringOpt; break;
+    case ErrNum_UnknownStringOpt:
+      msgno = Num_ErrMsgUnknownStringOpt; break;
+    case ErrNum_InvCacheInvMode:
+      msgno = Num_ErrMsgInvCacheInvMode; break;
+    case ErrNum_InvCfgList:
+      msgno = Num_ErrMsgInvCfgList; break;
+    case ErrNum_ConfBitBltOpt:
+      msgno = Num_ErrMsgConfBitBltOpt; break;
+    case ErrNum_UnknownBitBltOpt:
+      msgno = Num_ErrMsgUnknownBitBltOpt; break;
+    case ErrNum_InternalError:
+      msgno = Num_ErrMsgInternalError; break;
+    case ErrNum_OpeningFile:
+      msgno = Num_ErrMsgOpeningFile; break;
+    case ErrNum_ListWrError:
+      msgno = Num_ErrMsgListWrError; break;
+    case ErrNum_FileReadError:
+      msgno = Num_ErrMsgFileReadError; break;
+    case ErrNum_FileWriteError:
+      msgno = Num_ErrMsgFileWriteError; break;
+    case ErrNum_HeapOvfl:
+      msgno = Num_ErrMsgHeapOvfl; break;
+    case ErrNum_StackOvfl:
+      msgno = Num_ErrMsgStackOvfl; break;
+    case ErrNum_MaxIncLevelExceeded:
+      msgno = Num_ErrMsgMaxIncLevelExceeded; break;
+    default:
+      as_snprintf(Buf, BufSize, "%s %d", getmessage(Num_ErrMsgIntError), (int) Num);
+  }
+  return (msgno != -1) ? getmessage(msgno) : Buf;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     WrErrorString(const char *pMessage, const char *pAdd, Boolean Warning, Boolean Fatal,
+                         const char *pExtendError, const struct sLineComp *pLineComp)
+ * \brief  write error message, combined with string component of current src line
+ * \param  pMessage textual error message
+ * \param  Warning error is warning?
+ * \param  Fatal error is fatal?
+ * \param  pExtendError extended error explanation
+ * \param  pLineComp associated string component
+ * ------------------------------------------------------------------------ */
+
+void WrErrorString(const char *pMessage, const char *pAdd, Boolean Warning, Boolean Fatal,
+                   const char *pExtendError, const struct sLineComp *pLineComp)
+{
+  String ErrStr[4];
+  unsigned ErrStrCount = 0, z;
+  char *p;
+  int l;
+  const char *pLeadIn = GNUErrors ? "" : "> > > ";
+  FILE *pErrFile;
+  Boolean ErrorsWrittenToListing = False;
+
+  if (TreatWarningsAsErrors && Warning && !Fatal)
+    Warning = False;
+
+  strcpy(ErrStr[ErrStrCount], pLeadIn);
+  p = GetErrorPos();
+  if (p)
+  {
+    l = strlen(p) - 1;
+    if ((l >= 0) && (p[l] == ' '))
+      p[l] = '\0';
+    strmaxcat(ErrStr[ErrStrCount], p, STRINGSIZE);
+    free(p);
+  }
+  if (pLineComp)
+  {
+    char Num[20];
+
+    as_snprintf(Num, sizeof(Num), ":%d", pLineComp->StartCol + 1);
+    strmaxcat(ErrStr[ErrStrCount], Num, STRINGSIZE);
+  }
+  if (Warning || !GNUErrors)
+  {
+    strmaxcat(ErrStr[ErrStrCount], ": ", STRINGSIZE);
+    strmaxcat(ErrStr[ErrStrCount], getmessage(Warning ? Num_WarnName : Num_ErrName), STRINGSIZE);
+  }
+  strmaxcat(ErrStr[ErrStrCount], pAdd, STRINGSIZE);
+  strmaxcat(ErrStr[ErrStrCount], ": ", STRINGSIZE);
+  if (Warning)
+    WarnCount++;
+  else
+    ErrorCount++;
+
+  strmaxcat(ErrStr[ErrStrCount], pMessage, STRINGSIZE);
+  if ((ExtendErrors > 0) && pExtendError)
+  {
+    if (GNUErrors)
+      strmaxcat(ErrStr[ErrStrCount], " '", STRINGSIZE);
+    else
+      strcpy(ErrStr[++ErrStrCount], pLeadIn);
+    strmaxcat(ErrStr[ErrStrCount], pExtendError, STRINGSIZE);
+    if (GNUErrors)
+      strmaxcat(ErrStr[ErrStrCount], "'", STRINGSIZE);
+  }
+  if ((ExtendErrors > 1) || ((ExtendErrors > 0) && pLineComp))
+  {
+    strcpy(ErrStr[++ErrStrCount], "");
+    GenLineForMarking(ErrStr[ErrStrCount], STRINGSIZE, OneLine.p_str, pLeadIn);
+    if (pLineComp)
+    {
+      strcpy(ErrStr[++ErrStrCount], "");
+      GenLineMarker(ErrStr[ErrStrCount], STRINGSIZE, '~', pLineComp, pLeadIn);
+    }
+  }
+
+  if (strcmp(LstName, "/dev/null") && !Fatal)
+  {
+    for (z = 0; z <= ErrStrCount; z++)
+      WrLstLine(ErrStr[z]);
+    ErrorsWrittenToListing = True;
+  }
+
+  if (!ErrorFile)
+    OpenWithStandard(&ErrorFile, ErrorName);
+  pErrFile = ErrorFile ? ErrorFile : stdout;
+  if (strcmp(LstName, "!1") || !ListOn || !ErrorsWrittenToListing)
+  {
+    for (z = 0; z <= ErrStrCount; z++)
+      if (ErrorFile)
+        fprintf(pErrFile, "%s\n", ErrStr[z]);
+      else
+        WrConsoleLine(ErrStr[z], True);
+  }
+
+  if (Fatal)
+    fprintf(pErrFile, "%s\n", getmessage(Num_ErrMsgIsFatal));
+  else if (MaxErrors && (ErrorCount >= MaxErrors))
+  {
+    fprintf(pErrFile, "%s\n", getmessage(Num_ErrMsgTooManyErrors));
+    Fatal = True;
+  }
+
+  if (Fatal)
+  {
+    EmergencyStop();
+    exit(3);
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     WrXErrorPos(tErrorNum Num, const char *pExtendError, const struct sLineComp *pLineComp)
+ * \brief  write number-coded error message, combined with extended explamation and string component of current src line
+ * \param  Num error number
+ * \param  pExtendError extended error explanation
+ * \param  pLineComp associated string component
+ * ------------------------------------------------------------------------ */
+
+void WrXErrorPos(tErrorNum Num, const char *pExtendError, const struct sLineComp *pLineComp)
+{
+  String h;
+  char Add[11];
+  const char *pErrorMsg;
+  tExpectError *pExpectError;
+
+  pExpectError = FindAndTakeExpectError(Num);
+  if (pExpectError)
+  {
+    free(pExpectError);
+    return;
+  }
+
+  if (!CodeOutput && (Num == ErrNum_UnknownInstruction))
+    return;
+
+  if (SuppWarns && (Num < 1000))
+    return;
+
+  pErrorMsg = ErrorNum2String(Num, h, sizeof(h));
+
+  if (((Num == ErrNum_TargOnDiffPage) || (Num == ErrNum_JmpDistTooBig))
+   && !Repass)
+    JmpErrors++;
+
+  if (NumericErrors)
+    as_snprintf(Add, sizeof(Add), " #%d", (int)Num);
+  else
+    *Add = '\0';
+  WrErrorString(pErrorMsg, Add, Num < 1000, Num >= 10000, pExtendError, pLineComp);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     WrStrErrorPos(tErrorNum Num, const const struct sLineComp *pLineComp)
+ * \brief  write number-coded error message, combined with string component of current src line
+ * \param  Num error number
+ * \param  pStrComp associated string component
+ * ------------------------------------------------------------------------ */
+
+void WrStrErrorPos(tErrorNum Num, const struct sStrComp *pStrComp)
+{
+  WrXErrorPos(Num, pStrComp->str.p_str, &pStrComp->Pos);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     WrError(tErrorNum Num)
+ * \brief  write number-coded error message, without any explanation
+ * \param  Num error number
+ * ------------------------------------------------------------------------ */
+
+void WrError(tErrorNum Num)
+{
+  WrXErrorPos(Num, NULL, NULL);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     WrXError(tErrorNum Num, const char *pExtError)
+ * \brief  write number-coded error message with extended explanation
+ * \param  Num error number
+ * \param  pExtendError extended error explanation
+ * ------------------------------------------------------------------------ */
+
+void WrXError(tErrorNum Num, const char *pExtError)
+{
+  WrXErrorPos(Num, pExtError, NULL);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     void ChkIO(tErrorNum ErrNo)
+ * \brief  check for I/O error and report given error if yes
+ * \param  ErrNo error number to report if error occured
+ * ------------------------------------------------------------------------ */
+
+void ChkIO(tErrorNum ErrNo)
+{
+  int io;
+
+  io = errno;
+  if ((io == 0) || (io == 19) || (io == 25))
+    return;
+
+  WrXError(ErrNo, GetErrorMsg(io));
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkXIO(tErrorNum ErrNo, char *pExtError)
+ * \brief  check for I/O error and report given error if yes
+ * \param  ErrNo error number to report if error occured
+ * \param  pExtError, file name, as plain string
+ * ------------------------------------------------------------------------ */
+
+void ChkXIO(tErrorNum ErrNo, char *pExtError)
+{
+  tStrComp TmpComp;
+
+  StrCompMkTemp(&TmpComp, pExtError, 0);
+  ChkStrIO(ErrNo, &TmpComp);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     void ChkIO(tErrorNum ErrNo)
+ * \brief  check for I/O error and report given error if yes
+ * \param  ErrNo error number to report if error occured
+ * \param  pComp, file name, as string component with position
+ * ------------------------------------------------------------------------ */
+
+void ChkStrIO(tErrorNum ErrNo, const struct sStrComp *pComp)
+{
+  int io;
+  String s;
+
+  io = errno;
+  if ((io == 0) || (io == 19) || (io == 25))
+    return;
+
+  as_snprintf(s, STRINGSIZE, "%s: %s", pComp->str.p_str, GetErrorMsg(io));
+  if ((pComp->Pos.StartCol >= 0) || pComp->Pos.Len)
+    WrXErrorPos(ErrNo, s, &pComp->Pos);
+  else
+    WrXError(ErrNo, s);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     CodeEXPECT(Word Code)
+ * \brief  process EXPECT command
+ * ------------------------------------------------------------------------ */
+
+void CodeEXPECT(Word Code)
+{
+  UNUSED(Code);
+
+  if (!ChkArgCnt(1, ArgCntMax));
+  else if (InExpect) WrStrErrorPos(ErrNum_NoNestExpect, &OpPart);
+  else
+  {
+    int z;
+    Boolean OK;
+    tErrorNum Num;
+
+    for (z = 1; z <= ArgCnt; z++)
+    {
+      Num = (tErrorNum)EvalStrIntExpression(&ArgStr[z], UInt16, &OK);
+      if (OK)
+      {
+        tExpectError *pNew = (tExpectError*)calloc(1, sizeof(*pNew));
+        pNew->Num = Num;
+        AddExpectError(pNew);
+      }
+    }
+    InExpect = True;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     CodeENDEXPECT(Word Code)
+ * \brief  process ENDEXPECT command
+ * ------------------------------------------------------------------------ */
+
+void CodeENDEXPECT(Word Code)
+{
+  UNUSED(Code);
+
+  if (!ChkArgCnt(0, 0));
+  else if (!InExpect) WrStrErrorPos(ErrNum_MissingEXPECT, &OpPart);
+  else
+  {
+    tExpectError *pCurr;
+    String h;
+
+    while (pExpectErrors)
+    {
+      pCurr = pExpectErrors;
+      pExpectErrors = pCurr->pNext;
+      WrXError(ErrNum_ExpectedError, ErrorNum2String(pCurr->Num, h, sizeof(h)));
+      free(pCurr);
+    }
+    InExpect = False;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     AsmErrPassInit(void)
+ * \brief  module initialization prior to (another) pass through sources
+ * ------------------------------------------------------------------------ */
+
+void AsmErrPassInit(void)
+{
+  ErrorCount = 0;
+  WarnCount = 0;
+  ClearExpectErrors();
+  InExpect = False;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     AsmErrPassExit(void)
+ * \brief  module checks & cleanups after a pass through sources
+ * ------------------------------------------------------------------------ */
+
+void AsmErrPassExit(void)
+{
+  if (InExpect)
+    WrError(ErrNum_MissingENDEXPECT);
+  ClearExpectErrors();
+  InExpect = False;
+}
diff --git a/aslshim/asmerr.h b/aslshim/asmerr.h
new file mode 100644 (file)
index 0000000..ae41b6c
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _ASMERR_H
+#define _ASMERR_H
+/* asmerr.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Error Handling Functions                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "datatypes.h"
+#include "errmsg.h"
+
+extern Word ErrorCount, WarnCount;
+
+struct sLineComp;
+struct sStrComp;
+extern void WrErrorString(const char *Message, const char *Add, Boolean Warning, Boolean Fatal,
+                          const char *pExtendError, const struct sLineComp *pLineComp);
+
+extern void WrError(tErrorNum Num);
+
+extern void WrXError(tErrorNum Num, const char *pExtError);
+
+extern void WrXErrorPos(tErrorNum Num, const char *pExtError, const struct sLineComp *pLineComp);
+
+extern void WrStrErrorPos(tErrorNum Num, const struct sStrComp *pStrComp);
+
+
+extern void CodeEXPECT(Word Code);
+extern void CodeENDEXPECT(Word Code);
+
+
+extern void AsmErrPassInit(void);
+extern void AsmErrPassExit(void);
+
+extern void ChkIO(tErrorNum ErrNo);
+extern void ChkXIO(tErrorNum ErrNo, char *pExtError);
+extern void ChkStrIO(tErrorNum ErrNo, const struct sStrComp *pComp);
+
+#endif /* _ASMERR_H */
+
diff --git a/aslshim/asmfnums.h b/aslshim/asmfnums.h
new file mode 100644 (file)
index 0000000..ddc9533
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _ASMFNUMS_H
+#define _ASMFNUMS_H
+/* asmfnums.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Verwaltung von Datei-Nummern                                              */
+/*                                                                           */
+/* Historie: 15. 5.96 Grundsteinlegung                                       */
+/*                                                                           */
+/*****************************************************************************/
+
+extern void InitFileList(void);
+
+extern void ClearFileList(void);
+
+extern void AddFile(char *FName);
+
+extern Integer GetFileNum(char *Name);
+
+extern const char *GetFileName(int Num);
+
+extern Integer GetFileCount(void);
+
+extern void AddAddressRange(int File, LargeWord Start, LargeWord Len);
+
+extern void GetAddressRange(int File, LargeWord *Start, LargeWord *End);
+
+extern void ResetAddressRanges(void);
+
+extern void asmfnums_init(void);
+#endif /* _ASMFNUMS_H */
diff --git a/aslshim/asmitree.c b/aslshim/asmitree.c
new file mode 100644 (file)
index 0000000..e9f469e
--- /dev/null
@@ -0,0 +1,311 @@
+/* asmitree.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Opcode-Abfrage als Binaerbaum                                             */
+/*                                                                           */
+/* Historie: 30.10.1996 Grundsteinlegung                                     */
+/*            8.10.1997 Hash-Tabelle                                         */
+/*            6.12.1998 dynamisches Kopieren der Namen                       */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "chunks.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+
+#include "asmitree.h"
+
+/*---------------------------------------------------------------------------*/
+
+static Boolean AddSingle(PInstTreeNode *Node, char *NName, InstProc NProc, Word NIndex)
+{
+  PInstTreeNode p1, p2;
+  Boolean Result = False;
+
+  ChkStack();
+
+  if (!*Node)
+  {
+    *Node = (PInstTreeNode) malloc(sizeof(TInstTreeNode));
+    (*Node)->Left = NULL;
+    (*Node)->Right = NULL;
+    (*Node)->Proc = NProc;
+    (*Node)->Index = NIndex;
+    (*Node)->Balance = 0;
+    (*Node)->Name = as_strdup(NName);
+    Result = True;
+  }
+  else if (strcmp(NName, (*Node)->Name) < 0)
+  {
+    if (AddSingle(&((*Node)->Left), NName, NProc, NIndex))
+      switch ((*Node)->Balance)
+      {
+        case 1:
+          (*Node)->Balance = 0;
+          break;
+        case 0:
+          (*Node)->Balance = -1;
+          Result = True;
+          break;
+        case -1:
+          p1 = (*Node)->Left;
+          if (p1->Balance == -1)
+          {
+            (*Node)->Left = p1->Right;
+            p1->Right = (*Node);
+            (*Node)->Balance = 0;
+            *Node = p1;
+          }
+         else
+         {
+           p2 = p1->Right;
+           p1->Right = p2->Left;
+           p2->Left = p1;
+           (*Node)->Left = p2->Right;
+           p2->Right = (*Node);
+           (*Node)->Balance = (p2->Balance == -1) ? 1 : 0;
+           p1->Balance = (p2->Balance == 1) ? -1 : 0;
+           *Node = p2;
+         }
+         (*Node)->Balance = 0;
+         break;
+     }
+  }
+  else
+  {
+    if (AddSingle(&((*Node)->Right), NName, NProc, NIndex))
+      switch ((*Node)->Balance)
+      {
+        case -1:
+          (*Node)->Balance = 0;
+          break;
+        case 0:
+          (*Node)->Balance = 1;
+          Result = True;
+          break;
+        case 1:
+          p1 = (*Node)->Right;
+          if (p1->Balance == 1)
+          {
+            (*Node)->Right = p1->Left;
+            p1->Left = (*Node);
+            (*Node)->Balance = 0;
+            *Node = p1;
+          }
+          else
+          {
+            p2 = p1->Left;
+            p1->Left = p2->Right;
+            p2->Right = p1;
+            (*Node)->Right = p2->Left;
+            p2->Left = (*Node);
+            (*Node)->Balance = (p2->Balance == 1) ? -1 : 0;
+            p1->Balance = (p2->Balance == -1) ? 1 : 0;
+            *Node = p2;
+          }
+          (*Node)->Balance = 0;
+          break;
+      }
+  }
+  return Result;
+}
+
+void AddInstTree(PInstTreeNode *Root, char *NName, InstProc NProc, Word NIndex)
+{
+  AddSingle(Root, NName, NProc, NIndex);
+}
+
+static void ClearSingle(PInstTreeNode *Node)
+{
+  ChkStack();
+
+  if (*Node)
+  {
+    free((*Node)->Name);
+    ClearSingle(&((*Node)->Left));
+    ClearSingle(&((*Node)->Right));
+    free(*Node);
+    *Node = NULL;
+  }
+}
+
+void ClearInstTree(PInstTreeNode *Root)
+{
+  ClearSingle(Root);
+}
+
+Boolean SearchInstTree(PInstTreeNode Root, char *OpPart)
+{
+  int z;
+
+  z = 0;
+  while ((Root) && (strcmp(Root->Name, OpPart)))
+  {
+    Root = (strcmp(OpPart, Root->Name) < 0) ? Root->Left : Root->Right;
+    z++;
+  }
+
+  if (!Root)
+    return False;
+  else
+  {
+    Root->Proc(Root->Index);
+    return True;
+  }
+}
+
+static void PNode(PInstTreeNode Node, Word Lev)
+{
+  ChkStack();
+  if (Node)
+  {
+    PNode(Node->Left, Lev + 1);
+    printf("%*s %s %p %p %d\n", 5 * Lev, "", Node->Name, (void*)Node->Left, (void*)Node->Right, Node->Balance);
+    PNode(Node->Right, Lev + 1);
+  }
+}
+
+void PrintInstTree(PInstTreeNode Root)
+{
+  PNode(Root, 0);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int GetKey(const char *Name, LongWord TableSize)
+{
+  register unsigned char *p;
+  LongWord tmp = 0;
+
+  for (p = (unsigned char *)Name; *p != '\0'; p++)
+    tmp = (tmp << 2) + ((LongWord)*p);
+  return tmp % TableSize;
+}
+
+PInstTable CreateInstTable(int TableSize)
+{
+  int z;
+  PInstTableEntry tmp;
+  PInstTable tab;
+
+  tmp = (PInstTableEntry) malloc(sizeof(TInstTableEntry) * TableSize);
+  for (z = 0; z < TableSize; z++)
+    tmp[z].Name = NULL;
+  tab = (PInstTable) malloc(sizeof(TInstTable));
+  tab->Fill = 0;
+  tab->Size = TableSize;
+  tab->Entries = tmp;
+  tab->Dynamic = FALSE;
+  return tab;
+}
+
+void SetDynamicInstTable(PInstTable Table)
+{
+  Table->Dynamic = TRUE;
+}
+
+void DestroyInstTable(PInstTable tab)
+{
+  int z;
+
+  if (tab->Dynamic)
+    for (z = 0; z < tab->Size; z++)
+      free(tab->Entries[z].Name);
+
+  free(tab->Entries);
+  free(tab);
+}
+
+void AddInstTable(PInstTable tab, const char *Name, Word Index, InstProc Proc)
+{
+  LongWord h0 = GetKey(Name, tab->Size), z = 0;
+
+  /* mindestens ein freies Element lassen, damit der Sucher garantiert terminiert */
+
+  if (tab->Size - 1 <= tab->Fill)
+  {
+    fprintf(stderr, "\nhash table overflow\n");
+    exit(255);
+  }
+  while (1)
+  {
+    if (!tab->Entries[h0].Name)
+    {
+      tab->Entries[h0].Name = (tab->Dynamic) ? as_strdup(Name) : (char*)Name;
+      tab->Entries[h0].Proc = Proc;
+      tab->Entries[h0].Index = Index;
+      tab->Entries[h0].Coll = z;
+      tab->Fill++;
+      return;
+    }
+    if (!strcmp(tab->Entries[h0].Name, Name))
+    {
+      printf("%s double in table\n", Name);
+      exit(255);
+    }
+    z++;
+    if ((LongInt)(++h0) == tab->Size)
+      h0 = 0;
+  }
+}
+
+void RemoveInstTable(PInstTable tab, const char *Name)
+{
+  LongWord h0 = GetKey(Name, tab->Size);
+
+  while (1)
+  {
+    if (!tab->Entries[h0].Name)
+      return;
+    else if (!strcmp(tab->Entries[h0].Name, Name))
+    {
+      tab->Entries[h0].Name = NULL;
+      tab->Entries[h0].Proc = NULL;
+      tab->Fill--;
+      return;
+    }
+    if ((LongInt)(++h0) == tab->Size)
+      h0 = 0;
+  }
+}
+
+Boolean LookupInstTable(PInstTable tab, const char *Name)
+{
+  LongWord h0 = GetKey(Name, tab->Size);
+
+  while (1)
+  {
+    if (!tab->Entries[h0].Name)
+      return False;
+    else if (!strcmp(tab->Entries[h0].Name, Name))
+    {
+      tab->Entries[h0].Proc(tab->Entries[h0].Index);
+      return True;
+    }
+    if ((LongInt)(++h0) == tab->Size)
+      h0 = 0;
+  }
+}
+
+void PrintInstTable(FILE *stream, PInstTable tab)
+{
+  int z;
+
+  for (z = 0; z < tab->Size; z++)
+    if (tab->Entries[z].Name)
+      fprintf(stream, "[%3d]: %-10s Index %4d Coll %2d\n", z,
+             tab->Entries[z].Name, tab->Entries[z].Index, tab->Entries[z].Coll);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void asmitree_init(void)
+{
+}
diff --git a/aslshim/asmitree.h b/aslshim/asmitree.h
new file mode 100644 (file)
index 0000000..f653596
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef _ASMITREE_H
+#define _ASMITREE_H
+/* asmitree.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Opcode-Abfrage als Binaerbaum                                             */
+/*                                                                           */
+/* Historie: 30.10.1996 Grundsteinlegung                                     */
+/*            6.12.1998 dynamische Variante                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+typedef void (*InstProc)(
+#ifdef __PROTOS__
+Word Index
+#endif
+);
+
+typedef struct _TInstTreeNode
+{
+  struct _TInstTreeNode *Left,*Right;
+  InstProc Proc;
+  char *Name;
+  Word Index;
+  ShortInt Balance;
+} TInstTreeNode,*PInstTreeNode;
+
+typedef struct _TInstTableEntry
+{
+  InstProc Proc;
+  char *Name;
+  Word Index;
+  int Coll;
+}
+TInstTableEntry,*PInstTableEntry;
+
+struct sInstTable
+{
+  int Fill,Size;
+  Boolean Dynamic;
+  PInstTableEntry Entries;
+};
+typedef struct sInstTable TInstTable;
+typedef struct sInstTable *PInstTable;
+
+extern void AddInstTree(PInstTreeNode *Root, char *NName, InstProc NProc, Word NIndex);
+
+extern void ClearInstTree(PInstTreeNode *Root);
+
+extern Boolean SearchInstTree(PInstTreeNode Root, char *OpPart);
+
+extern void PrintInstTree(PInstTreeNode Root);
+
+
+extern PInstTable CreateInstTable(int TableSize);
+
+extern void SetDynamicInstTable(PInstTable Table);
+
+extern void DestroyInstTable(PInstTable tab);
+
+extern void AddInstTable(PInstTable tab, const char *Name, Word Index, InstProc Proc);
+
+extern void RemoveInstTable(PInstTable tab, const char *Name);
+
+extern Boolean LookupInstTable(PInstTable tab, const char *Name);
+
+extern void PrintInstTable(FILE *stream, PInstTable tab);
+
+extern void asmitree_init(void);
+
+#endif /* _ASMITREE_H */
diff --git a/aslshim/asmpars.c b/aslshim/asmpars.c
new file mode 100644 (file)
index 0000000..5e7dc03
--- /dev/null
@@ -0,0 +1,4199 @@
+/* asmpars.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Verwaltung von Symbolen und das ganze Drumherum...                        */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "endian.h"
+#include "bpemu.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "as.rsc"
+#include "strutil.h"
+#include "strcomp.h"
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "errmsg.h"
+#include "asmfnums.h"
+#include "asmrelocs.h"
+#include "asmstructs.h"
+#include "chunks.h"
+#include "trees.h"
+#include "operator.h"
+#include "function.h"
+#include "intformat.h"
+#include "ieeefloat.h"
+
+#include "asmpars.h"
+
+#define LOCSYMSIGHT 3       /* max. sight for nameless temporary symbols */
+
+#define LEAVE  goto func_exit
+#define LEAVE2 goto func_exit2
+
+/* Mask, Min & Max are computed at initialization */
+
+tIntTypeDef IntTypeDefs[IntTypeCnt] =
+{
+  { 0x0001, 0, 0, 0 }, /* UInt1 */
+  { 0x0002, 0, 0, 0 }, /* UInt2 */
+  { 0x0003, 0, 0, 0 }, /* UInt3 */
+  { 0x8004, 0, 0, 0 }, /* SInt4 */
+  { 0x0004, 0, 0, 0 }, /* UInt4 */
+  { 0xc004, 0, 0, 0 }, /* Int4 */
+  { 0x8005, 0, 0, 0 }, /* SInt5 */
+  { 0x0005, 0, 0, 0 }, /* UInt5 */
+  { 0xc005, 0, 0, 0 }, /* Int5 */
+  { 0x8006, 0, 0, 0 }, /* SInt6 */
+  { 0x0006, 0, 0, 0 }, /* UInt6 */
+  { 0x8007, 0, 0, 0 }, /* SInt7 */
+  { 0x0007, 0, 0, 0 }, /* UInt7 */
+  { 0x8008, 0, 0, 0 }, /* SInt8 */
+  { 0x0008, 0, 0, 0 }, /* UInt8 */
+  { 0xc008, 0, 0, 0 }, /* Int8 */
+  { 0x8009, 0, 0, 0 }, /* SInt9 */
+  { 0x0009, 0, 0, 0 }, /* UInt9 */
+  { 0x000a, 0, 0, 0 }, /* UInt10 */
+  { 0xc00a, 0, 0, 0 }, /* Int10 */
+  { 0x000b, 0, 0, 0 }, /* UInt11 */
+  { 0x000c, 0, 0, 0 }, /* UInt12 */
+  { 0xc00c, 0, 0, 0 }, /* Int12 */
+  { 0x000d, 0, 0, 0 }, /* UInt13 */
+  { 0x000e, 0, 0, 0 }, /* UInt14 */
+  { 0xc00e, 0, 0, 0 }, /* Int14 */
+  { 0x800f, 0, 0, 0 }, /* SInt15 */
+  { 0x000f, 0, 0, 0 }, /* UInt15 */
+  { 0x8010, 0, 0, 0 }, /* SInt16 */
+  { 0x0010, 0, 0, 0 }, /* UInt16 */
+  { 0xc010, 0, 0, 0 }, /* Int16 */
+  { 0x0011, 0, 0, 0 }, /* UInt17 */
+  { 0x0012, 0, 0, 0 }, /* UInt18 */
+  { 0x0013, 0, 0, 0 }, /* UInt19 */
+  { 0x8014, 0, 0, 0 }, /* SInt20 */
+  { 0x0014, 0, 0, 0 }, /* UInt20 */
+  { 0xc014, 0, 0, 0 }, /* Int20 */
+  { 0x0015, 0, 0, 0 }, /* UInt21 */
+  { 0x0016, 0, 0, 0 }, /* UInt22 */
+  { 0x0017, 0, 0, 0 }, /* UInt23 */
+  { 0x8018, 0, 0, 0 }, /* SInt24 */
+  { 0x0018, 0, 0, 0 }, /* UInt24 */
+  { 0xc018, 0, 0, 0 }, /* Int24 */
+  { 0x801e, 0, 0, 0 }, /* SInt30 */
+  { 0x001e, 0, 0, 0 }, /* UInt30 */
+  { 0xc01e, 0, 0, 0 }, /* Int30 */
+  { 0x8020, 0, 0, 0 }, /* SInt32 */
+  { 0x0020, 0, 0, 0 }, /* UInt32 */
+  { 0xc020, 0, 0, 0 }, /* Int32 */
+#ifdef HAS64
+  { 0x8040, 0, 0, 0 }, /* SInt64 */
+  { 0x0040, 0, 0, 0 }, /* UInt64 */
+  { 0xc040, 0, 0, 0 }, /* Int64 */
+#endif
+};
+
+typedef struct
+{
+  Boolean Back;
+  LongInt Counter;
+} TTmpSymLog;
+
+LongInt MomLocHandle;          /* Merker, den lokale Symbole erhalten        */
+LongInt TmpSymCounter,         /* counters for local symbols                 */
+        FwdSymCounter,
+        BackSymCounter;
+char TmpSymCounterVal[10];     /* representation as string                   */
+TTmpSymLog TmpSymLog[LOCSYMSIGHT];
+LongInt TmpSymLogDepth;
+
+LongInt LocHandleCnt;          /* mom. verwendeter lokaler Handle            */
+
+typedef struct sSymbolEntry
+{
+  TTree Tree;
+  Boolean Defined, Used, Changeable, changed;
+  TempResult SymWert;
+  LargeInt unchanged_value;
+  PCrossRef RefList;
+  Byte FileNum;
+  LongInt LineNum;
+} TSymbolEntry, *PSymbolEntry;
+
+typedef struct sSymbolStackEntry
+{
+  struct sSymbolStackEntry *Next;
+  TempResult Contents;
+} TSymbolStackEntry, *PSymbolStackEntry;
+
+typedef struct sSymbolStack
+{
+  struct sSymbolStack *Next;
+  char *Name;
+  PSymbolStackEntry Contents;
+} TSymbolStack, *PSymbolStack;
+
+typedef struct sDefSymbol
+{
+  struct sDefSymbol *Next;
+  char *SymName;
+  TempResult Wert;
+} TDefSymbol, *PDefSymbol;
+
+typedef struct sCToken
+{
+  struct sCToken *Next;
+  char *Name;
+  LongInt Parent;
+  ChunkList Usage;
+} TCToken, *PCToken;
+
+typedef struct sLocHeap
+{
+  struct sLocHeap *Next;
+  LongInt Cont;
+} TLocHeap, *PLocHandle;
+
+typedef struct sRegDefList
+{
+  struct sRegDefList *Next;
+  LongInt Section;
+  char *Value;
+  Boolean Used;
+} TRegDefList, *PRegDefList;
+
+typedef struct sRegDef
+{
+  struct sRegDef *Left, *Right;
+  char *Orig;
+  PRegDefList Defs, DoneDefs;
+} TRegDef, *PRegDef;
+
+static PSymbolEntry FirstSymbol, FirstLocSymbol;
+static PDefSymbol FirstDefSymbol;
+/*static*/ PCToken FirstSection;
+static Boolean DoRefs,              /* Querverweise protokollieren */
+               RegistersDefined;
+static PLocHandle FirstLocHandle;
+static PSymbolStack FirstStack;
+static PCToken MomSection;
+static char *LastGlobSymbol;
+static PFunction FirstFunction;                /* Liste definierter Funktionen */
+
+void AsmParsInit(void)
+{
+  FirstSymbol = NULL;
+
+  FirstLocSymbol = NULL; MomLocHandle = -1; SetMomSection(-1);
+  FirstSection = NULL;
+  FirstLocHandle = NULL;
+  FirstStack = NULL;
+  FirstFunction = NULL;
+  DoRefs = True;
+  RadixBase = 10;
+  OutRadixBase = 16;
+  RegistersDefined = False;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     range_not_checkable(IntType type)
+ * \brief  can integer type's range not be checked on host system?
+ * \param  type integer type
+ * \return true if range can NOT be checked
+ * ------------------------------------------------------------------------ */
+
+static Boolean range_not_checkable(IntType type)
+{
+#ifndef HAS64
+  return (((int)type) >= ((int)SInt32));
+#else
+  return (((int)type) >= ((int)SInt64));
+#endif
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     RangeCheck(LargeInt Wert, IntType Typ)
+ * \brief  check whether value is within integer type's ranges
+ * \param  Wert value to check
+ * \param  Typ integer type giving range
+ * \return true if within range
+ * ------------------------------------------------------------------------ */
+
+Boolean RangeCheck(LargeInt Wert, IntType Typ)
+{
+  return range_not_checkable(Typ) || ((Wert >= IntTypeDefs[(int)Typ].Min) && (Wert <= IntTypeDefs[(int)Typ].Max));
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkRangeByType(LargeInt value, IntType type, const struct sStrComp *p_comp)
+ * \brief  check whether value is within integer type's ranges, and throw error if not
+ * \param  value value to check
+ * \param  type integer type giving range
+ * \param  p_comp corresponding source argument
+ * \return true if within range
+ * ------------------------------------------------------------------------ */
+
+Boolean ChkRangeByType(LargeInt value, IntType type, const struct sStrComp *p_comp)
+{
+  return range_not_checkable(type) || ChkRangePos(value, IntTypeDefs[(int)type].Min, IntTypeDefs[(int)type].Max, p_comp);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkRangeWarnByType(LargeInt value, IntType type, const struct sStrComp *p_comp)
+ * \brief  check whether value is within integer type's ranges, and throw warning if not
+ * \param  value value to check
+ * \param  type integer type giving range
+ * \param  p_comp corresponding source argument
+ * \return true if within range
+ * ------------------------------------------------------------------------ */
+
+Boolean ChkRangeWarnByType(LargeInt value, IntType type, const struct sStrComp *p_comp)
+{
+  return range_not_checkable(type) || ChkRangeWarnPos(value, IntTypeDefs[(int)type].Min, IntTypeDefs[(int)type].Max, p_comp);
+}
+
+Boolean FloatRangeCheck(Double Wert, FloatType Typ)
+{
+  /* NaN/Infinity is representable in all formats */
+
+  int numclass = as_fpclassify(Wert);
+  if ((numclass == AS_FP_NAN) || (numclass == AS_FP_INFINITE))
+    return True;
+
+  switch (Typ)
+  {
+    case Float16:
+      return (fabs(Wert) <= 65504.0);
+    case Float32:
+      return (fabs(Wert) <= 3.4e38);
+    case Float64:
+      return (fabs(Wert) <= 1.7e308);
+/**     case FloatCo: return fabs(Wert) <= 9.22e18; */
+    case Float80:
+      return True;
+    case FloatDec:
+      return True;
+    default:
+      return False;
+  }
+/**   if (Typ == FloatDec) && (fabs(Wert) > 1e1000) WrError(ErrNum_BigDecFloat);**/
+}
+
+Boolean SingleBit(LargeInt Inp, LargeInt *Erg)
+{
+  *Erg = 0;
+  do
+  {
+    if (!Odd(Inp))
+      (*Erg)++;
+    if (!Odd(Inp))
+      Inp = Inp >> 1;
+  }
+  while ((*Erg != LARGEBITS) && (!Odd(Inp)));
+  return (*Erg != LARGEBITS) && (Inp == 1);
+}      
+
+IntType GetSmallestUIntType(LargeWord MaxValue)
+{
+  IntType Result;
+
+  Result = (IntType) 0;
+  for (Result = (IntType) 0; Result < IntTypeCnt; Result++)
+  {
+    if (IntTypeDefs[Result].Min < 0)
+      continue;
+    if (IntTypeDefs[Result].Max >= (LargeInt)MaxValue)
+      return Result;
+  }
+  return UInt32;
+}
+
+IntType GetUIntTypeByBits(unsigned Bits)
+{
+  IntType Result;
+  for (Result = (IntType) 0; Result < IntTypeCnt; Result++)
+  {
+    if (IntTypeDefs[Result].SignAndWidth & 0x8000)
+      continue;
+    if (Lo(IntTypeDefs[Result].SignAndWidth) == Bits)
+      return Result;
+  }
+  fprintf(stderr, "define unsigned int type with %u bits\n", Bits);
+  exit(255);
+}
+
+static Boolean ProcessBk(char **Start, char *Erg)
+{
+  LongInt System = 0, Acc = 0, Digit = 0;
+  char ch;
+  int cnt;
+  Boolean Finish;
+
+  switch (as_toupper(**Start))
+  {
+    case '\'': case '\\': case '"':
+      *Erg = **Start;
+      (*Start)++;
+      return True;
+    case 'H':
+      *Erg = '\'';
+      (*Start)++;
+      return True;
+    case 'I':
+      *Erg = '"';
+      (*Start)++;
+    return True;
+    case 'B':
+      *Erg = Char_BS;
+      (*Start)++;
+      return True;
+    case 'A':
+      *Erg = Char_BEL;
+      (*Start)++;
+      return True;
+    case 'E':
+      *Erg = Char_ESC;
+      (*Start)++;
+       return True;
+    case 'T':
+      *Erg = Char_HT;
+      (*Start)++;
+       return True;
+    case 'N':
+      *Erg = Char_LF;
+      (*Start)++;
+      return True;
+    case 'R':
+      *Erg = Char_CR;
+      (*Start)++;
+      return True;
+    case 'X':
+      System = 16;
+      (*Start)++;
+      /* fall-through */
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      if (System == 0)
+        System = (**Start == '0') ? 8 : 10;
+      cnt = (System == 16) ? 1 : ((System == 10) ? 0 : -1);
+      do
+      {
+        ch = as_toupper(**Start);
+        Finish = False;
+        if ((ch >= '0') && (ch <= '9'))
+          Digit = ch - '0';
+        else if ((System == 16) && (ch >= 'A') && (ch <= 'F'))
+          Digit = (ch - 'A') + 10;
+        else
+          Finish = True;
+        if (!Finish)
+        {
+          (*Start)++;
+          cnt++;
+          if (Digit >= System)
+          {
+            WrError(ErrNum_OverRange);
+            return False;
+          }
+          Acc = (Acc * System) + Digit;
+        }
+      }
+      while ((!Finish) && (cnt < 3));
+      if (!ChkRange(Acc, 0, 255))
+        return False;
+      *Erg = Acc;
+      return True;
+    default:
+      WrError(ErrNum_InvEscSequence);
+      return False;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     NonZString2Int(const struct as_nonz_dynstr *p_str)
+ * \brief  convert string to its "ASCII representation"
+ * \param  p_str string containing characters
+ * \return -1 or converted int
+ * ------------------------------------------------------------------------ */
+
+LargeInt NonZString2Int(const struct as_nonz_dynstr *p_str)
+{
+  if ((p_str->len > 0) && (p_str->len <= 4))
+  {
+    const char *pRun;
+    Byte Digit;
+    LargeInt Result;
+
+    Result = 0;
+    for (pRun = p_str->p_str;
+         pRun < p_str->p_str + p_str->len;
+         pRun++)
+    {
+      Digit = (usint) *pRun;
+      Result = (Result << 8) | CharTransTable[Digit & 0xff];
+    }
+    return Result;
+  }
+  return -1;
+}
+
+Boolean Int2NonZString(struct as_nonz_dynstr *p_str, LargeInt Src)
+{
+  int Search;
+  Byte Digit;
+  char *pDest;
+
+  if (p_str->capacity < 32)
+    as_nonz_dynstr_realloc(p_str, 32);
+  p_str->len = 0;
+  pDest = &p_str->p_str[p_str->capacity];
+  while (Src && (p_str->len < p_str->capacity))
+  {
+    Digit = Src & 0xff;
+    Src = (Src >> 8) & 0xfffffful;
+    for (Search = 0; Search < 256; Search++)
+      if (CharTransTable[Search] == Digit)
+      {
+        *(--pDest) = Search;
+        p_str->len++;
+        break;
+      }
+  }
+  memmove(p_str->p_str, pDest, p_str->len);
+  return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     TempResultToInt(TempResult *pResult)
+ * \brief  convert TempResult to integer
+ * \param  pResult tempresult to convert
+ * \return 0 or error code
+ * ------------------------------------------------------------------------ */
+
+int TempResultToInt(TempResult *pResult)
+{
+  switch (pResult->Typ)
+  {
+    case TempInt:
+      break;
+    case TempString:
+    {
+      LargeInt Result = NonZString2Int(&pResult->Contents.str);
+      if (Result >= 0)
+      {
+        as_tempres_set_int(pResult, Result);
+        break;
+      }
+      /* else */
+    }
+    /* fall-through */
+    default:
+      pResult->Typ = TempNone;
+      return -1;
+  }
+  return 0;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     MultiCharToInt(TempResult *pResult, unsigned MaxLen)
+ * \brief  optionally convert multi-character constant to integer
+ * \param  pResult holding value
+ * \param  MaxLen maximum lenght of multi-character constant
+ * \return True if converted
+ * ------------------------------------------------------------------------ */
+
+Boolean MultiCharToInt(TempResult *pResult, unsigned MaxLen)
+{
+  if ((pResult->Typ == TempString)
+   && (pResult->Contents.str.len <= MaxLen)
+   && (pResult->Flags & eSymbolFlag_StringSingleQuoted))
+  {
+    TempResultToInt(pResult);
+    return True;
+  }
+  return False;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ExpandStrSymbol(char *pDest, size_t DestSize, const tStrComp *pSrc)
+ * \brief  expand symbol name from string component
+ * \param  pDest dest buffer
+ * \param  DestSize size of dest buffer
+ * \param  pSrc source component
+ * \return True if success
+ * ------------------------------------------------------------------------ */
+
+Boolean ExpandStrSymbol(char *pDest, size_t DestSize, const tStrComp *pSrc)
+{
+  tStrComp SrcComp;
+  const char *pStart;
+
+  *pDest = '\0'; StrCompRefRight(&SrcComp, pSrc, 0);
+  while (True)
+  {
+    pStart = QuotPos(SrcComp.str.p_str, '{');
+    if (pStart)
+    {
+      unsigned ls = pStart - SrcComp.str.p_str, ld = strlen(pDest);
+      String Expr, Result;
+      tStrComp ExprComp;
+      tEvalResult EvalResult;
+      const char *pStop;
+
+      if (ld + ls + 1 > DestSize)
+        ls = DestSize - 1 - ld;
+      memcpy(pDest + ld, SrcComp.str.p_str, ls);
+      pDest[ld + ls] = '\0';
+
+      pStop = QuotPos(pStart + 1, '}');
+      if (!pStop)
+      {
+        WrStrErrorPos(ErrNum_InvSymName, pSrc);
+        return False;
+      }
+      StrCompMkTemp(&ExprComp, Expr, sizeof(Expr));
+      StrCompCopySub(&ExprComp, &SrcComp, pStart + 1 - SrcComp.str.p_str, pStop - pStart - 1);
+      EvalStrStringExpressionWithResult(&ExprComp, &EvalResult, Result);
+      if (!EvalResult.OK)
+        return False;
+      if (mFirstPassUnknown(EvalResult.Flags))
+      {
+        WrStrErrorPos(ErrNum_FirstPassCalc, &ExprComp);
+        return False;
+      }
+      if (!CaseSensitive)
+        UpString(Result);
+      strmaxcat(pDest, Result, DestSize);
+      StrCompIncRefLeft(&SrcComp, pStop + 1 - SrcComp.str.p_str);
+    }
+    else
+    {
+      strmaxcat(pDest, SrcComp.str.p_str, DestSize);
+      return True;
+    }
+  }
+}
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+/* check whether this is a local symbol and expand local counter if yes.  They
+   have to be handled in different places of the parser, therefore two separate
+   functions */
+
+void InitTmpSymbols(void)
+{
+  TmpSymCounter = FwdSymCounter = BackSymCounter = 0;
+  *TmpSymCounterVal = '\0';
+  TmpSymLogDepth = 0;
+  *LastGlobSymbol = '\0';
+}
+
+static void AddTmpSymLog(Boolean Back, LongInt Counter)
+{
+  /* shift out oldest value */
+
+  if (TmpSymLogDepth)
+  {
+    LongInt ShiftCnt = min(TmpSymLogDepth, LOCSYMSIGHT - 1);
+
+    memmove(TmpSymLog + 1, TmpSymLog, sizeof(TTmpSymLog) * (ShiftCnt));
+  }
+
+  /* insert new one */
+
+  TmpSymLog[0].Back = Back;
+  TmpSymLog[0].Counter = Counter;
+  if (TmpSymLogDepth < LOCSYMSIGHT)
+    TmpSymLogDepth++;
+}
+
+static Boolean ChkTmp1(char *Name, as_symbol_source_t symbol_source)
+{
+  char *Src, *Dest;
+  Boolean Result = FALSE;
+
+  /* $$-Symbols: append current $$-counter */
+
+  if (!strncmp(Name, "$$", 2))
+  {
+    /* manually copy since this will implicitly give us the point to append
+       the number */
+
+    for (Src = Name + 2, Dest = Name; *Src; *(Dest++) = *(Src++));
+
+    /* append number. only generate the number once */
+
+    if (*TmpSymCounterVal == '\0')
+      as_snprintf(TmpSymCounterVal, sizeof(TmpSymCounterVal), "%d", TmpSymCounter);
+    strcpy(Dest, TmpSymCounterVal);
+    Result = TRUE;
+  }
+
+  /* no special local symbol: increment $$-counter */
+
+  else if (symbol_source != e_symbol_source_none)
+  {
+    TmpSymCounter++;
+    *TmpSymCounterVal = '\0';
+  }
+
+  return Result;
+}
+
+static Boolean ChkTmp2(char *pDest, const char *pSrc, as_symbol_source_t symbol_source)
+{
+  const char *pRun, *pBegin, *pEnd;
+  int Cnt;
+  Boolean Result = FALSE;
+
+  for (pBegin = pSrc; as_isspace(*pBegin); pBegin++);
+  for (pEnd = pSrc + strlen(pSrc); (pEnd > pBegin) && as_isspace(*(pEnd - 1)); pEnd--);
+
+  /* Note: We have to deal with three symbol definitions:
+
+      "-" for backward-only referencing
+      "+" for forward-only referencing
+      "/" for either way of referencing
+
+      "/" and "+" are both expanded to forward symbol names, so the
+      forward refencing to both types is unproblematic, however
+      only "/" and "-" are stored in the backlog of the three
+      most-recent symbols for backward referencing.
+  */
+
+  /* backward references ? */
+
+  if (*pBegin == '-')
+  {
+    for (pRun = pBegin; *pRun; pRun++)
+      if (*pRun != '-')
+        break;
+    Cnt = pRun - pBegin;
+    if (pRun == pEnd)
+    {
+      if ((symbol_source != e_symbol_source_none) && (Cnt == 1))
+      {
+        as_snprintf(pDest, STRINGSIZE, "__back%d", (int)BackSymCounter);
+        AddTmpSymLog(TRUE, BackSymCounter);
+        BackSymCounter++;
+        Result = TRUE;
+      }
+
+      /* TmpSymLogDepth cannot become larger than LOCSYMSIGHT, so we only
+         have to check against the log's actual depth. */
+
+      else if (Cnt <= TmpSymLogDepth)
+      {
+        Cnt--;
+        as_snprintf(pDest, STRINGSIZE, "__%s%d",
+                    TmpSymLog[Cnt].Back ? "back" : "forw",
+                    (int)TmpSymLog[Cnt].Counter);
+        Result = TRUE;
+      }
+    }
+  }
+
+  /* forward references ? */
+
+  else if (*pBegin == '+')
+  {
+    for (pRun = pBegin; *pRun; pRun++)
+      if (*pRun != '+')
+        break;
+    Cnt = pRun - pBegin;
+    if (pRun == pEnd)
+    {
+      if ((symbol_source != e_symbol_source_none) && (Cnt == 1))
+      {
+        as_snprintf(pDest, STRINGSIZE, "__forw%d", (int)FwdSymCounter++);
+        Result = TRUE;
+      }
+      else if (Cnt <= LOCSYMSIGHT)
+      {
+        as_snprintf(pDest, STRINGSIZE, "__forw%d", (int)(FwdSymCounter + (Cnt - 1)));
+        Result = TRUE;
+      }
+    }
+  }
+
+  /* slash: only allowed for definition, but add to log for backward ref. */
+
+  else if ((pEnd - pBegin == 1) && (*pBegin == '/') && (symbol_source != e_symbol_source_none))
+  {
+    AddTmpSymLog(FALSE, FwdSymCounter);
+    as_snprintf(pDest, STRINGSIZE, "__forw%d", (int)FwdSymCounter);
+    FwdSymCounter++;
+    Result = TRUE;
+  }
+
+  return Result;
+}
+
+static Boolean ChkTmp3(char *Name, as_symbol_source_t symbol_source)
+{
+  if ('.' == *Name)
+  {
+    strmaxprep2(Name, LastGlobSymbol, STRINGSIZE);
+    return True;
+  }
+
+#if 0
+  if (symbol_source == e_symbol_source_label)
+#else
+  if (symbol_source != e_symbol_source_none)
+#endif
+    strmaxcpy(LastGlobSymbol, Name, STRINGSIZE);
+  return False;
+}
+
+static Boolean ChkTmp(char *Name, as_symbol_source_t symbol_source)
+{
+  Boolean IsTmp1, IsTmp2, IsTmp3;
+
+  IsTmp1 = ChkTmp1(Name, symbol_source);
+  IsTmp2 = ChkTmp2(Name, Name, symbol_source);
+  IsTmp3 = ChkTmp3(Name, IsTmp2 ? e_symbol_source_none : symbol_source);
+  return IsTmp1 || IsTmp2 || IsTmp3;
+}
+
+Boolean IdentifySection(const tStrComp *pName, LongInt *Erg)
+{
+  PSaveSection SLauf;
+  String ExpName;
+  sint Depth;
+
+  if (!ExpandStrSymbol(ExpName, sizeof(ExpName), pName))
+    return False;
+  if (!CaseSensitive)
+    NLS_UpString(ExpName);
+
+  if (*ExpName == '\0')
+  {
+    *Erg = -1;
+    return True;
+  }
+  else if (((strlen(ExpName) == 6) || (strlen(ExpName) == 7))
+       && (!as_strncasecmp(ExpName, "PARENT", 6))
+       && ((strlen(ExpName) == 6) || ((ExpName[6] >= '0') && (ExpName[6] <= '9'))))
+  {
+    Depth = (strlen(ExpName) == 6) ? 1 : ExpName[6] - AscOfs;
+    SLauf = SectionStack;
+    *Erg = MomSectionHandle;
+    while ((Depth > 0) && (*Erg != -2))
+    {
+      if (!SLauf) *Erg = -2;
+      else
+      {
+        *Erg = SLauf->Handle;
+        SLauf = SLauf->Next;
+      }
+      Depth--;
+    }
+    if (*Erg == -2)
+    {
+      WrError(ErrNum_InvSection);
+      return False;
+    }
+    else
+      return True;
+  }
+  else if (!strcmp(ExpName, GetSectionName(MomSectionHandle)))
+  {
+    *Erg = MomSectionHandle;
+    return True;
+  }
+  else
+  {
+    SLauf = SectionStack;
+    while ((SLauf) && (strcmp(GetSectionName(SLauf->Handle), ExpName)))
+      SLauf = SLauf->Next;
+    if (!SLauf)
+    {
+      WrError(ErrNum_InvSection);
+      return False;
+    }
+    else
+    {
+      *Erg = SLauf->Handle;
+      return True;
+    }
+  }
+}
+
+static Boolean GetSymSection(char *Name, LongInt *Erg, const tStrComp *pUnexpComp)
+{
+  String Part;
+  tStrComp TmpComp;
+  char *q;
+  int l = strlen(Name);
+
+  if (!l || (Name[l - 1] != ']'))
+  {
+    *Erg = -2;
+    return True;
+  }
+
+  Name[l - 1] = '\0';
+  q = RQuotPos(Name, '[');
+  Name[l - 1] = ']';
+  if (Name + l - q <= 1)
+  {
+    if (pUnexpComp)
+      WrStrErrorPos(ErrNum_InvSymName, pUnexpComp);
+    else
+      WrXError(ErrNum_InvSymName, Name);
+    return False;
+  }
+
+  Name[l - 1] = '\0';
+  strmaxcpy(Part, q + 1, STRINGSIZE);
+  *q = '\0';
+
+  StrCompMkTemp(&TmpComp, Part, sizeof(Part));
+  return IdentifySection(&TmpComp, Erg);
+}
+
+/*****************************************************************************
+ * Function:    ConstIntVal
+ * Purpose:     evaluate integer constant
+ * Result:      integer value
+ *****************************************************************************/
+
+static LargeInt ConstIntVal(const char *pExpr, IntType Typ, Boolean *pResult)
+{
+  LargeInt Wert;
+  Boolean NegFlag = False;
+  int Digit;
+  tIntCheckCtx Ctx;
+  const tIntFormatList *pIntFormat;
+
+  /* empty string is interpreted as 0 */
+
+  if (!*pExpr)
+  {
+    *pResult = True;
+    return 0;
+  }
+
+  *pResult = False;
+
+  /* sign: */
+
+  switch (*pExpr)
+  {
+    case '-':
+      NegFlag = True;
+      /* else fall-through */
+    case '+':
+      pExpr++;
+      break;
+  }
+  Ctx.pExpr = pExpr;
+  Ctx.ExprLen = strlen(pExpr);
+  Ctx.Base = -1;
+
+  for (pIntFormat = IntFormatList; pIntFormat->Check; pIntFormat++)
+    if (pIntFormat->Check(&Ctx, pIntFormat->Ch))
+    {
+      Ctx.Base = (pIntFormat->Base > 0) ? pIntFormat->Base : RadixBase;
+      break;
+    }
+  if (Ctx.Base <= 0)
+    return -1;
+
+  /* we may have decremented Ctx.ExprLen, so do not run until string end */
+
+  Wert = 0;
+  while (Ctx.ExprLen > 0)
+  {
+    Digit = DigitVal(as_toupper(*Ctx.pExpr), Ctx.Base);
+    if (Digit == -1)
+      return -1;
+    Wert = Wert * Ctx.Base + Digit;
+    Ctx.pExpr++; Ctx.ExprLen--;
+  }
+
+  if (NegFlag)
+    Wert = -Wert;
+
+  /* post-processing, range check */
+
+  *pResult = RangeCheck(Wert, Typ);
+  if (*pResult)
+    return Wert;
+  else if (HardRanges)
+  {
+    WrError(ErrNum_OverRange);
+    return -1;
+  }
+  else
+  {
+    *pResult = True;
+    WrError(ErrNum_WOverRange);
+    return Wert & IntTypeDefs[(int)Typ].Mask;
+  }
+}
+
+/*****************************************************************************
+ * Function:    ConstFloatVal
+ * Purpose:     evaluate floating point constant
+ * Result:      value
+ *****************************************************************************/
+
+static Double ConstFloatVal(const char *pExpr, FloatType Typ, Boolean *pResult)
+{
+  Double Erg;
+  char *pEnd;
+
+  UNUSED(Typ);
+
+  if (*pExpr)
+  {
+    /* Some strtod() implementations interpret hex constants starting with '0x'.  We
+       don't want this here.  Either 0x for hex constants is allowed, then it should
+       have been parsed before by ConstIntVal(), or not, then we don't want the constant
+       be stored as float. */
+
+    if ((strlen(pExpr) >= 2)
+     && (pExpr[0] == '0')
+     && (toupper(pExpr[1]) == 'X'))
+    {
+      Erg = 0;
+      *pResult = False;
+    }
+
+    else
+    {
+      Erg = strtod(pExpr, &pEnd);
+      *pResult = (*pEnd == '\0');
+    }
+  }
+  else
+  {
+    Erg = 0.0;
+    *pResult = True;
+  }
+  return Erg;
+}
+
+/*****************************************************************************
+ * Function:    ConstStringVal
+ * Purpose:     evaluate string constant
+ * Result:      value
+ *****************************************************************************/
+
+static void ConstStringVal(const tStrComp *pExpr, TempResult *pDest, Boolean *pResult)
+{
+  tStrComp Raw, Copy, Remainder;
+  char *pPos, QuoteChar;
+  int l, TLen;
+
+  *pResult = False;
+
+  l = strlen(pExpr->str.p_str);
+  if (l < 2)
+    return;
+  switch (*pExpr->str.p_str)
+  {
+    case '"':
+    case '\'':
+      QuoteChar = *pExpr->str.p_str;
+      if (pExpr->str.p_str[l - 1] == QuoteChar)
+      {
+        if ('\'' == QuoteChar)
+          pDest->Flags |= eSymbolFlag_StringSingleQuoted;
+        break;
+      }
+      /* conditional fall-through */
+    default:
+      return;
+  }
+
+  StrCompAlloc(&Raw, STRINGSIZE);
+  StrCompCopySub(&Raw, pExpr, 1, l - 2);
+  /* use LEAVE from now on instead of return */
+
+  /* go through source */
+
+  as_tempres_set_c_str(pDest, "");
+  StrCompRefRight(&Copy, &Raw, 0);
+  while (1)
+  {
+    pPos = strchr(Copy.str.p_str, '\\');
+    if (pPos)
+      StrCompSplitRef(&Copy, &Remainder, &Copy, pPos);
+
+    /* " before \ -> not a simple string but something like "...." ... " */
+
+    if (strchr(Copy.str.p_str, QuoteChar))
+    {
+      as_tempres_set_none(pDest);
+      LEAVE;
+    }
+
+    /* copy part up to next '\' verbatim: */
+
+    as_nonz_dynstr_append_raw(&pDest->Contents.str, Copy.str.p_str, strlen(Copy.str.p_str));
+
+    /* are we done? If not, advance pointer to behind '\' */
+
+    if (!pPos)
+      break;
+    Copy = Remainder;
+
+    /* treat escaped section: stringification? */
+
+    if (*Copy.str.p_str == '{')
+    {
+      TempResult t;
+      char *pStr;
+      String Str;
+      Boolean OK = True;
+
+      as_tempres_ini(&t);
+      StrCompIncRefLeft(&Copy, 1);
+
+      /* cut out part in {...} */
+
+      pPos = QuotPos(Copy.str.p_str, '}');
+      if (!pPos)
+      {
+        OK = False;
+        LEAVE2;
+      }
+      StrCompSplitRef(&Copy, &Remainder, &Copy, pPos);
+      KillPrefBlanksStrCompRef(&Copy);
+      KillPostBlanksStrComp(&Copy);
+
+      /* evaluate expression */
+
+      EvalStrExpression(&Copy, &t);
+      if (t.Relocs)
+      {
+        WrStrErrorPos(ErrNum_NoRelocs, &Copy);
+        FreeRelocs(&t.Relocs);
+        as_tempres_set_none(&t);
+      }
+
+      /* append result */
+
+      switch (t.Typ)
+      {
+        case TempInt:
+          TLen = SysString(Str, sizeof(Str), t.Contents.Int, OutRadixBase, 0, False, HexStartCharacter, SplitByteCharacter);
+          pStr = Str;
+          break;
+        case TempFloat:
+          FloatString(Str, sizeof(Str), t.Contents.Float);
+          pStr = Str;
+          TLen = strlen(pStr);
+          break;
+        case TempString:
+          pStr = t.Contents.str.p_str;
+          TLen = t.Contents.str.len;
+          break;
+        default:
+          *pResult = True;
+          OK = False;
+      }
+      if (OK)
+      {
+        as_nonz_dynstr_append_raw(&pDest->Contents.str, pStr, TLen);
+        pDest->Flags |= t.Flags & eSymbolFlags_Promotable;
+      }
+
+      /* advance source pointer to behind '}' */
+
+      Copy = Remainder;
+
+   func_exit2:
+      as_tempres_free(&t);
+      if (!OK)
+      {
+        as_tempres_set_none(pDest);
+        LEAVE;
+      }
+    }
+
+    /* simple character escape: */
+
+    else
+    {
+      char Res, *pNext = Copy.str.p_str;
+
+      if (!ProcessBk(&pNext, &Res))
+      {
+        as_tempres_set_none(pDest);
+        LEAVE;
+      }
+      as_nonz_dynstr_append_raw(&pDest->Contents.str, &Res, 1);
+      StrCompIncRefLeft(&Copy, pNext - Copy.str.p_str);
+    }
+  }
+
+  *pResult = True;
+func_exit:
+  StrCompFree(&Raw);
+}
+
+
+static PSymbolEntry FindLocNode(
+#ifdef __PROTOS__
+const char *Name, TempType SearchType
+#endif
+);
+
+static PSymbolEntry FindNode(
+#ifdef __PROTOS__
+const char *Name, TempType SearchType
+#endif
+);
+
+/*!------------------------------------------------------------------------
+ * \fn     EvalResultClear(tEvalResult *pResult)
+ * \brief  reset all elements of EvalResult
+ * ------------------------------------------------------------------------ */
+
+void EvalResultClear(tEvalResult *pResult)
+{
+  pResult->OK = False;
+  pResult->Flags = eSymbolFlag_None;
+  pResult->AddrSpaceMask = 0;
+  pResult->DataSize = eSymbolSizeUnknown;
+}
+
+/*****************************************************************************
+ * Function:    EvalStrExpression
+ * Purpose:     evaluate expression
+ * Result:      implicitly in pErg
+ *****************************************************************************/
+
+#define LEAVE goto func_exit
+
+static tErrorNum DeduceExpectTypeErrMsgMask(unsigned Mask, TempType ActType)
+{
+  switch (ActType)
+  {
+    case TempInt:
+      switch (Mask)
+      {
+        case TempString:
+          return ErrNum_StringButInt;
+        /* int is convertible to float, so combinations are impossible: */
+        case TempFloat:
+        case TempFloat | TempString:
+        default:
+          return ErrNum_InternalError;
+      }
+    case TempFloat:
+      switch (Mask)
+      {
+        case TempInt:
+          return ErrNum_IntButFloat;
+        case TempString:
+          return ErrNum_StringButFloat;
+        case TempInt | TempString:
+          return ErrNum_StringOrIntButFloat;
+        default:
+          return ErrNum_InternalError;
+      }
+    case TempString:
+      switch (Mask)
+      {
+        case TempInt:
+          return ErrNum_IntButString;
+        case TempFloat:
+          return ErrNum_FloatButString;
+        case TempInt | TempFloat:
+          return ErrNum_IntOrFloatButString;
+        default:
+          return ErrNum_InternalError;
+      }
+    case TempReg:
+      switch (Mask)
+      {
+        case TempInt:
+          return ErrNum_ExpectInt;
+        case TempString:
+          return ErrNum_ExpectString;
+        case TempInt | TempString:
+          return ErrNum_ExpectIntOrString;
+        case TempInt | TempFloat | TempString:
+          return ErrNum_StringOrIntOrFloatButReg;
+        default:
+          return ErrNum_InternalError;
+      }
+    default:
+      return ErrNum_InternalError;
+  }
+}
+
+static Byte GetOpTypeMask(Byte TotMask, int OpIndex)
+{
+  return (TotMask >> (OpIndex * 4)) & 15;
+}
+
+static Byte TryConvert(Byte TypeMask, TempType ActType, int OpIndex)
+{
+  if (TypeMask & ActType)
+    return 0 << (4 * OpIndex);
+  if ((TypeMask & TempFloat) && (ActType == TempInt))
+    return 1 << (4 * OpIndex);
+  if ((TypeMask & TempInt) && (ActType == TempString))
+    return 2 << (4 * OpIndex);
+  if ((TypeMask & TempFloat) && (ActType == TempString))
+    return (1|2) << (4 * OpIndex);
+  return 255;
+}
+
+void EvalStrExpression(const tStrComp *pExpr, TempResult *pErg)
+{
+  const Operator *pOp;
+  const Operator *FOps[OPERATOR_MAXCNT];
+  LongInt FOpCnt = 0;
+
+  Boolean OK;
+  tStrComp InArgs[3];
+  TempResult InVals[3];
+  int z1, cnt;
+  char Save = '\0';
+  sint LKlamm, RKlamm, WKlamm, zop;
+  sint OpMax, OpPos = -1;
+  Boolean InSgl, InDbl, NextEscaped, ThisEscaped;
+  PFunction ValFunc;
+  tStrComp CopyComp, STempComp;
+  char *KlPos, *zp, *pOpPos;
+  const tFunction *pFunction;
+  PRelocEntry TReloc;
+  tSymbolFlags PromotedFlags;
+  unsigned PromotedAddrSpaceMask;
+  tSymbolSize PromotedDataSize;
+
+  ChkStack();
+
+  for (z1 = 0; z1 < 3; z1++)
+    as_tempres_ini(&InVals[z1]);
+  StrCompAlloc(&CopyComp, STRINGSIZE);
+  StrCompAlloc(&STempComp, STRINGSIZE);
+
+  if (MakeDebug)
+    fprintf(Debug, "Parse '%s'\n", pExpr->str.p_str);
+
+  /* Annahme Fehler */
+
+  as_tempres_set_none(pErg);
+  pErg->Relocs = NULL;
+  pErg->Flags = eSymbolFlag_None;
+  pErg->AddrSpaceMask = 0;
+  pErg->DataSize = eSymbolSizeUnknown;
+
+  StrCompCopy(&CopyComp, pExpr);
+  KillPrefBlanksStrComp(&CopyComp);
+  KillPostBlanksStrComp(&CopyComp);
+
+  /* sort out local symbols like - and +++.  Do it now to get them out of the
+     formula parser's way. */
+
+  ChkTmp2(CopyComp.str.p_str, CopyComp.str.p_str, e_symbol_source_none);
+  StrCompCopy(&STempComp, &CopyComp);
+
+  /* Programmzaehler ? */
+
+  if (PCSymbol && (!as_strcasecmp(CopyComp.str.p_str, PCSymbol)))
+  {
+    as_tempres_set_int(pErg, EProgCounter());
+    pErg->Relocs = NULL;
+    pErg->AddrSpaceMask |= 1 << ActPC;
+    LEAVE;
+  }
+
+  /* Konstanten ? */
+
+  pErg->Contents.Int = ConstIntVal(CopyComp.str.p_str, (IntType) (IntTypeCnt - 1), &OK);
+  if (OK)
+  {
+    pErg->Typ = TempInt;
+    pErg->Relocs = NULL;
+    LEAVE;
+  }
+
+  pErg->Contents.Float = ConstFloatVal(CopyComp.str.p_str, Float80, &OK);
+  if (OK)
+  {
+    pErg->Typ = TempFloat;
+    pErg->Relocs = NULL;
+    LEAVE;
+  }
+
+  ConstStringVal(&CopyComp, pErg, &OK);
+  if (OK)
+  {
+    pErg->Relocs = NULL;
+    LEAVE;
+  }
+
+  /* durch Codegenerator gegebene Konstanten ? */
+
+  pErg->Relocs = NULL;
+  InternSymbol(CopyComp.str.p_str, pErg);
+  if (pErg->Typ != TempNone)
+  {
+    LEAVE;
+  }
+
+  /* find out which operators *might* occur in expression */
+
+  OpMax = 0;
+  LKlamm = 0;
+  RKlamm = 0;
+  WKlamm = 0;
+  InSgl =
+  InDbl =
+  ThisEscaped =
+  NextEscaped = False;
+  for (pOp = Operators + 1; pOp->Id; pOp++)
+  {
+    pOpPos = (pOp->IdLen == 1) ? (strchr(CopyComp.str.p_str, *pOp->Id)) : (strstr(CopyComp.str.p_str, pOp->Id));
+    if (pOpPos)
+      FOps[FOpCnt++] = pOp;
+  }
+
+  /* nach Operator hoechster Rangstufe ausserhalb Klammern suchen */
+
+  for (zp = CopyComp.str.p_str; *zp; zp++, ThisEscaped = NextEscaped)
+  {
+    NextEscaped = False;
+    switch (*zp)
+    {
+      case '(':
+        if (!(InSgl || InDbl))
+          LKlamm++;
+        break;
+      case ')':
+        if (!(InSgl || InDbl))
+          RKlamm++;
+        break;
+      case '{':
+        if (!(InSgl || InDbl))
+          WKlamm++;
+        break;
+      case '}':
+        if (!(InSgl || InDbl))
+          WKlamm--;
+        break;
+      case '"':
+        if (!InSgl && !ThisEscaped)
+          InDbl = !InDbl;
+        break;
+      case '\'':
+        if (!InDbl && !ThisEscaped)
+        {
+          if (InSgl || !QualifyQuote || QualifyQuote(CopyComp.str.p_str, zp))
+            InSgl = !InSgl;
+        }
+        break;
+      case '\\':
+        if ((InDbl || InSgl) && !ThisEscaped)
+          NextEscaped = True;
+        break;
+      default:
+        if ((LKlamm == RKlamm) && (WKlamm == 0) && (!InSgl) && (!InDbl))
+        {
+          Boolean OpFnd = False;
+          sint OpLen = 0, LocOpMax = 0;
+
+          for (zop = 0; zop < FOpCnt; zop++)
+          {
+            pOp = FOps[zop];
+            if ((!strncmp(zp, pOp->Id, pOp->IdLen)) && (pOp->IdLen >= OpLen))
+            {
+              OpFnd = True;
+              OpLen = pOp->IdLen;
+              LocOpMax = pOp - Operators;
+              if (Operators[LocOpMax].Priority >= Operators[OpMax].Priority)
+              {
+                OpMax = LocOpMax;
+                OpPos = zp - CopyComp.str.p_str;
+              }
+            }
+          }
+          if (OpFnd)
+            zp += Operators[LocOpMax].IdLen - 1;
+        }
+    }
+  }
+
+  /* Klammerfehler ? */
+
+  if (LKlamm != RKlamm)
+  {
+    WrStrErrorPos(ErrNum_BrackErr, &CopyComp);
+    LEAVE;
+  }
+
+  /* Operator gefunden ? */
+
+  if (OpMax)
+  {
+    int ThisArgCnt, CompLen, z, z2;
+    Byte ThisOpMatch, BestOpMatch, BestOpMatchIdx, SumCombinations, TypeMask;
+
+    pOp = Operators + OpMax;
+
+    /* Minuszeichen sowohl mit einem als auch 2 Operanden */
+
+    if (!strcmp(pOp->Id, "-"))
+    {
+      if (!OpPos)
+        pOp = &MinusMonadicOperator;
+    }
+
+    else if (!strcmp(pOp->Id, "^"))
+    {
+      if (!OpPos && pPotMonadicOperator)
+        pOp = pPotMonadicOperator;
+    }
+
+    /* Operandenzahl pruefen */
+
+    CompLen = strlen(CopyComp.str.p_str);
+    if (CompLen <= 1)
+      ThisArgCnt = 0;
+    else if (!OpPos || (OpPos == (int)strlen(CopyComp.str.p_str) - 1))
+      ThisArgCnt = 1;
+    else
+      ThisArgCnt = 2;
+    if (!ChkArgCntExtPos(ThisArgCnt, pOp->Dyadic ? 2 : 1, pOp->Dyadic ? 2 : 1, &CopyComp.Pos))
+      LEAVE;
+
+    /* Teilausdruecke rekursiv auswerten */
+
+    Save = StrCompSplitRef(&InArgs[0], &InArgs[1], &CopyComp, CopyComp.str.p_str + OpPos);
+    StrCompIncRefLeft(&InArgs[1], strlen(pOp->Id) - 1);
+    EvalStrExpression(&InArgs[1], &InVals[1]);
+    if (pOp->Dyadic)
+      EvalStrExpression(&InArgs[0], &InVals[0]);
+    else if (InVals[1].Typ == TempFloat)
+      as_tempres_set_float(&InVals[0], 0.0);
+    else
+    {
+      as_tempres_set_int(&InVals[0], 0);
+      InVals[0].Relocs = NULL;
+    }
+    CopyComp.str.p_str[OpPos] = Save;
+
+    /* Abbruch, falls dabei Fehler */
+
+    if ((InVals[0].Typ == TempNone) || (InVals[1].Typ == TempNone))
+      LEAVE;
+
+    /* relokatible Symbole nur fuer + und - erlaubt */
+
+    if ((OpMax != 12) && (OpMax != 13) && (InVals[0].Relocs || InVals[1].Relocs))
+    {
+      WrStrErrorPos(ErrNum_NoRelocs, &CopyComp);
+      LEAVE;
+    }
+
+    /* see whether data types match operator's restrictions: */
+
+    BestOpMatch = 255; BestOpMatchIdx = OPERATOR_MAXCOMB;
+    SumCombinations = 0;
+    for (z = 0; z < OPERATOR_MAXCOMB; z++)
+    {
+      if (!pOp->TypeCombinations[z])
+        break;
+      SumCombinations |= pOp->TypeCombinations[z];
+
+      ThisOpMatch = 0;
+      for (z2 = pOp->Dyadic ? 0 : 1; z2 < 2; z2++)
+        ThisOpMatch |= TryConvert(GetOpTypeMask(pOp->TypeCombinations[z], z2), InVals[z2].Typ, z2);
+      if (ThisOpMatch < BestOpMatch)
+      {
+        BestOpMatch = ThisOpMatch;
+        BestOpMatchIdx = z;
+      }
+      if (!BestOpMatch)
+        break;
+    }
+
+    /* did not find a way to satisfy restrictions, even by conversions? */
+
+    if (BestOpMatch >= 255)
+    {
+      for (z2 = pOp->Dyadic ? 0 : 1; z2 < 2; z2++)
+      {
+        TypeMask = GetOpTypeMask(SumCombinations, z2);
+        if (!(TypeMask & InVals[z2].Typ))
+          WrStrErrorPos(DeduceExpectTypeErrMsgMask(TypeMask, InVals[z2].Typ), &InArgs[z2]);
+      }
+      LEAVE;
+    }
+
+    /* necessary conversions: */
+
+    for (z2 = pOp->Dyadic ? 0 : 1; z2 < 2; z2++)
+    {
+      TypeMask = (BestOpMatch >> (z2 * 4)) & 15;
+      if (TypeMask & 2)  /* String -> Int */
+        TempResultToInt(&InVals[z2]);
+      if (TypeMask & 1) /* Int -> Float */
+        TempResultToFloat(&InVals[z2]);
+    }
+
+    /* actual operation */
+
+    (void)BestOpMatchIdx;
+    pOp->pFunc(pErg, &InVals[0], &InVals[1]);
+    LEAVE;
+  } /* if (OpMax) */
+
+  /* kein Operator gefunden: Klammerausdruck ? */
+
+  if (LKlamm != 0)
+  {
+    tStrComp FName, FArg, Remainder;
+
+    /* erste Klammer suchen, Funktionsnamen abtrennen */
+
+    KlPos = strchr(CopyComp.str.p_str, '(');
+
+    /* Funktionsnamen abschneiden */
+
+    StrCompSplitRef(&FName, &FArg, &CopyComp, KlPos);
+    StrCompShorten(&FArg, 1);
+    KillPostBlanksStrComp(&FName);
+
+    /* Nullfunktion: nur Argument */
+
+    if (*FName.str.p_str == '\0')
+    {
+      EvalStrExpression(&FArg, pErg);
+      LEAVE;
+    }
+
+    /* selbstdefinierte Funktion ? */
+
+    ValFunc = FindFunction(FName.str.p_str);
+    if (ValFunc)
+    {
+      as_dynstr_t CompArgStr;
+      tStrComp CompArg;
+      as_dynstr_t stemp;
+
+      PromotedFlags = eSymbolFlag_None;
+      PromotedAddrSpaceMask = 0;
+      PromotedDataSize = eSymbolSizeUnknown;
+      as_dynstr_ini_c_str(&CompArgStr, ValFunc->Definition);
+      as_dynstr_ini(&stemp, STRINGSIZE);
+      for (z1 = 1; z1 <= ValFunc->ArguCnt; z1++)
+      {
+        if (!*FArg.str.p_str)
+        {
+          WrError(ErrNum_InvFuncArgCnt);
+          LEAVE2;
+        }
+
+        KlPos = QuotPos(FArg.str.p_str, ',');
+        if (KlPos)
+          StrCompSplitRef(&FArg, &Remainder, &FArg, KlPos);
+
+        EvalStrExpression(&FArg, &InVals[0]);
+        if (InVals[0].Relocs)
+        {
+          WrStrErrorPos(ErrNum_NoRelocs, &FArg);
+          FreeRelocs(&InVals[0].Relocs);
+          LEAVE2;
+        }
+        PromotedFlags |= InVals[0].Flags & eSymbolFlags_Promotable;
+        PromotedAddrSpaceMask |= InVals[0].AddrSpaceMask;
+        if (PromotedDataSize == eSymbolSizeUnknown) PromotedDataSize = InVals[0].DataSize;
+
+        if (KlPos)
+          FArg = Remainder;
+        else
+          StrCompReset(&FArg);
+
+        as_sdprintf(&stemp, "(");
+        if (as_tempres_append_dynstr(&stemp, &InVals[0]))
+          LEAVE2;
+        as_sdprcatf(&stemp, ")");
+        ExpandLine(stemp.p_str, z1, &CompArgStr);
+      }
+      if (*FArg.str.p_str)
+      {
+        WrError(ErrNum_InvFuncArgCnt);
+        LEAVE2;
+      }
+      StrCompMkTemp(&CompArg, CompArgStr.p_str, CompArgStr.capacity);
+      EvalStrExpression(&CompArg, pErg);
+      pErg->Flags |= PromotedFlags;
+      pErg->AddrSpaceMask |= PromotedAddrSpaceMask;
+      if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = PromotedDataSize;
+func_exit2:
+      as_dynstr_free(&stemp);
+      as_dynstr_free(&CompArgStr);
+      LEAVE;
+    }
+
+    /* hier einmal umwandeln ist effizienter */
+
+    NLS_UpString(FName.str.p_str);
+
+    /* symbolbezogene Funktionen */
+
+    if (!strcmp(FName.str.p_str, "SYMTYPE"))
+    {
+      as_tempres_set_int(pErg, GetSymbolType(&FArg));
+      LEAVE;
+    }
+
+    else if (!strcmp(FName.str.p_str, "DEFINED"))
+    {
+      as_tempres_set_int(pErg, !!IsSymbolDefined(&FArg));
+      LEAVE;
+    }
+
+    else if (!strcmp(FName.str.p_str, "ASSUMEDVAL"))
+    {
+      unsigned IdxAssume;
+
+      for (IdxAssume = 0; IdxAssume < ASSUMERecCnt; IdxAssume++)
+        if (!as_strcasecmp(FArg.str.p_str, pASSUMERecs[IdxAssume].Name))
+        {
+          as_tempres_set_int(pErg, *(pASSUMERecs[IdxAssume].Dest));
+          LEAVE;
+        }
+      WrStrErrorPos(ErrNum_SymbolUndef, &FArg);
+      LEAVE;
+    }
+
+    /* Unterausdruck auswerten (interne Funktionen maxmimal mit drei Argumenten) */
+
+    cnt = 0;
+    PromotedFlags = eSymbolFlag_None;
+    PromotedAddrSpaceMask = 0;
+    PromotedDataSize = eSymbolSizeUnknown;
+    do
+    {
+      zp = QuotPos(FArg.str.p_str, ',');
+      if (zp)
+        StrCompSplitRef(&InArgs[cnt], &Remainder, &FArg, zp);
+      else
+        InArgs[cnt] = FArg;
+      if (cnt < 3)
+      {
+        EvalStrExpression(&InArgs[cnt], &InVals[cnt]);
+        if (InVals[cnt].Typ == TempNone)
+          LEAVE;
+        TReloc = InVals[cnt].Relocs;
+      }
+      else
+      {
+        WrError(ErrNum_InvFuncArgCnt);
+        LEAVE;
+      }
+      if (TReloc)
+      {
+        WrStrErrorPos(ErrNum_NoRelocs, &InArgs[cnt]);
+        FreeRelocs(&TReloc);
+        LEAVE;
+      }
+      if (zp)
+        FArg = Remainder;
+      PromotedFlags |= InVals[cnt].Flags & eSymbolFlags_Promotable;
+      PromotedAddrSpaceMask |= InVals[cnt].AddrSpaceMask;
+      if (PromotedDataSize == eSymbolSizeUnknown) PromotedDataSize = InVals[0].DataSize;
+      cnt++;
+    }
+    while (zp);
+
+    /* search function */
+
+    for (pFunction = Functions; pFunction->pName; pFunction++)
+      if (!strcmp(FName.str.p_str, pFunction->pName))
+        break;
+    if (!pFunction->pName)
+    {
+      WrStrErrorPos(ErrNum_UnknownFunc, &FName);
+      LEAVE;
+    }
+
+    /* argument checking */
+
+    if ((cnt < pFunction->MinNumArgs) || (cnt > pFunction->MaxNumArgs))
+    {
+      WrError(ErrNum_InvFuncArgCnt);
+      LEAVE;
+    }
+    for (z1 = 0; z1 < cnt; z1++)
+    {
+      if ((InVals[z1].Typ == TempInt) && (!(pFunction->ArgTypes[z1] & (1 << TempInt))))
+        TempResultToFloat(&InVals[z1]);
+      if (!(pFunction->ArgTypes[z1] & (1 << InVals[z1].Typ)))
+      {
+        WrStrErrorPos(DeduceExpectTypeErrMsgMask(pFunction->ArgTypes[z1], InVals[z1].Typ), &InArgs[z1]);
+        LEAVE;
+      }
+    }
+    pFunction->pFunc(pErg, InVals, cnt);
+    pErg->Flags |= PromotedFlags;
+    pErg->AddrSpaceMask |= PromotedAddrSpaceMask;
+    if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = PromotedDataSize;
+
+    LEAVE;
+  }
+
+  /* nichts dergleichen, dann einfaches Symbol: urspruenglichen Wert wieder
+     herstellen, dann Pruefung auf $$-temporaere Symbole */
+
+  StrCompCopy(&CopyComp, &STempComp);
+  KillPrefBlanksStrComp(&CopyComp);
+  KillPostBlanksStrComp(&CopyComp);
+
+  ChkTmp1(CopyComp.str.p_str, e_symbol_source_none);
+
+  /* interne Symbole ? */
+
+  if (!as_strcasecmp(CopyComp.str.p_str, "MOMFILE"))
+  {
+    as_tempres_set_c_str(pErg, CurrFileName);
+    LEAVE;
+  }
+
+  if (!as_strcasecmp(CopyComp.str.p_str, "MOMLINE"))
+  {
+    as_tempres_set_int(pErg, CurrLine);
+    LEAVE;
+  }
+
+  if (!as_strcasecmp(CopyComp.str.p_str, "MOMPASS"))
+  {
+    as_tempres_set_int(pErg, PassNo);
+    LEAVE;
+  }
+
+  if (!as_strcasecmp(CopyComp.str.p_str, "MOMSECTION"))
+  {
+    as_tempres_set_c_str(pErg, GetSectionName(MomSectionHandle));
+    LEAVE;
+  }
+
+  if (!as_strcasecmp(CopyComp.str.p_str, "MOMSEGMENT"))
+  {
+    as_tempres_set_c_str(pErg, SegNames[ActPC]);
+    LEAVE;
+  }
+
+  /* plain symbol */
+
+  LookupSymbol(&CopyComp, pErg, True, TempAll);
+
+func_exit:
+
+  StrCompFree(&CopyComp);
+  StrCompFree(&STempComp);
+
+  for (z1 = 0; z1 < 3; z1++)
+  {
+    if (InVals[z1].Relocs)
+      FreeRelocs(&InVals[z1].Relocs);
+    as_tempres_free(&InVals[z1]);
+  }
+}
+
+void EvalExpression(const char *pExpr, TempResult *pErg)
+{
+  tStrComp Expr;
+
+  StrCompMkTemp(&Expr, (char*)pExpr, 0);
+  EvalStrExpression(&Expr, pErg);
+}
+
+LargeInt EvalStrIntExpressionWithResult(const tStrComp *pComp, IntType Type, tEvalResult *pResult)
+{
+  TempResult t;
+  LargeInt Result = -1;
+
+  as_tempres_ini(&t);
+  EvalResultClear(pResult);
+
+  EvalStrExpression(pComp, &t);
+  SetRelocs(t.Relocs);
+
+  switch (t.Typ)
+  {
+    case TempInt:
+      Result = t.Contents.Int;
+      pResult->Flags = t.Flags;
+      pResult->AddrSpaceMask = t.AddrSpaceMask;
+      pResult->DataSize = t.DataSize;
+      break;
+    case TempString:
+    {
+      int l = t.Contents.str.len;
+
+      if ((l > 0) && (l <= 4))
+      {
+        char *pRun;
+        Byte Digit;
+
+        Result = 0;
+        for (pRun = t.Contents.str.p_str;
+             pRun < t.Contents.str.p_str + l;
+             pRun++)
+        {
+          Digit = (usint) *pRun;
+          Result = (Result << 8) | CharTransTable[Digit & 0xff];
+        }
+        pResult->Flags = t.Flags;
+        pResult->AddrSpaceMask = t.AddrSpaceMask;
+        pResult->DataSize = t.DataSize;
+        break;
+      }
+      else
+      {
+        WrStrErrorPos(ErrNum_IntButString, pComp);
+        FreeRelocs(&LastRelocs);
+        LEAVE;
+      }
+    }
+    /* else fall-through */
+    default:
+      if (t.Typ != TempNone)
+        WrStrErrorPos(DeduceExpectTypeErrMsgMask(TempInt | TempString, t.Typ), pComp);
+      FreeRelocs(&LastRelocs);
+      LEAVE;
+  }
+
+  if (mFirstPassUnknown(t.Flags))
+    Result &= IntTypeDefs[(int)Type].Mask;
+
+  pResult->OK = HardRanges ? ChkRangeByType(Result, Type, pComp) : ChkRangeWarnByType(Result, Type, pComp);
+  if (!pResult->OK)
+  {
+    if (HardRanges)
+    {
+      FreeRelocs(&LastRelocs);
+      Result = -1;
+      LEAVE;
+    }
+    else
+    {
+      pResult->OK = True;
+      Result &= IntTypeDefs[(int)Type].Mask;
+    }
+  }
+
+func_exit:
+  as_tempres_free(&t);
+  return Result;
+}
+
+LargeInt EvalStrIntExpressionWithFlags(const tStrComp *pComp, IntType Type, Boolean *pResult, tSymbolFlags *pFlags)
+{
+  tEvalResult EvalResult;
+  LargeInt Result = EvalStrIntExpressionWithResult(pComp, Type, &EvalResult);
+
+  *pResult = EvalResult.OK;
+  if (pFlags)
+    *pFlags = EvalResult.Flags;
+  return Result;
+}
+
+LargeInt EvalStrIntExpression(const tStrComp *pComp, IntType Type, Boolean *pResult)
+{
+  tEvalResult EvalResult;
+  LargeInt Result = EvalStrIntExpressionWithResult(pComp, Type, &EvalResult);
+
+  *pResult = EvalResult.OK;
+  return Result;
+}
+
+LargeInt EvalStrIntExpressionOffsWithResult(const tStrComp *pExpr, int Offset, IntType Type, tEvalResult *pResult)
+{
+  if (Offset)
+  {
+    tStrComp Comp;
+
+    StrCompRefRight(&Comp, pExpr, Offset);
+    return EvalStrIntExpressionWithResult(&Comp, Type, pResult);
+  }
+  else
+    return EvalStrIntExpressionWithResult(pExpr, Type, pResult);
+}
+
+LargeInt EvalStrIntExpressionOffsWithFlags(const tStrComp *pComp, int Offset, IntType Type, Boolean *pResult, tSymbolFlags *pFlags)
+{
+  tEvalResult EvalResult;
+  LargeInt Result = EvalStrIntExpressionOffsWithResult(pComp, Offset, Type, &EvalResult);
+
+  *pResult = EvalResult.OK;
+  if (pFlags)
+    *pFlags = EvalResult.Flags;
+  return Result;
+}
+
+LargeInt EvalStrIntExpressionOffs(const tStrComp *pComp, int Offset, IntType Type, Boolean *pResult)
+{
+  tEvalResult EvalResult;
+  LargeInt Result = EvalStrIntExpressionOffsWithResult(pComp, Offset, Type, &EvalResult);
+
+  *pResult = EvalResult.OK;
+  return Result;
+}
+
+Double EvalStrFloatExpressionWithResult(const tStrComp *pExpr, FloatType Type, tEvalResult *pResult)
+{
+  TempResult t;
+  Double Result = -1;
+
+  as_tempres_ini(&t);
+  EvalResultClear(pResult);
+
+  EvalStrExpression(pExpr, &t);
+  switch (t.Typ)
+  {
+    case TempNone:
+      LEAVE;
+    case TempInt:
+      Result = t.Contents.Int;
+      pResult->Flags = t.Flags;
+      pResult->AddrSpaceMask = t.AddrSpaceMask;
+      pResult->DataSize = t.DataSize;
+      break;
+    case TempString:
+    {
+      WrStrErrorPos(ErrNum_FloatButString, pExpr);
+      LEAVE;
+    }
+    default:
+      Result = t.Contents.Float;
+  }
+
+  if (!FloatRangeCheck(Result, Type))
+  {
+    WrStrErrorPos(ErrNum_OverRange, pExpr);
+    LEAVE;
+  }
+
+  pResult->OK = True;
+func_exit:
+  as_tempres_free(&t);
+  return Result;
+}
+
+Double EvalStrFloatExpression(const tStrComp *pExpr, FloatType Type, Boolean *pResult)
+{
+  Double Ret;
+  tEvalResult Result;
+
+  Ret = EvalStrFloatExpressionWithResult(pExpr, Type, &Result);
+  *pResult = Result.OK;
+  return Ret;
+}
+
+void EvalStrStringExpressionWithResult(const tStrComp *pExpr, tEvalResult *pResult, char *pEvalResult)
+{
+  TempResult t;
+
+  as_tempres_ini(&t);
+  EvalResultClear(pResult);
+
+  EvalStrExpression(pExpr, &t);
+  if (t.Typ != TempString)
+  {
+    *pEvalResult = '\0';
+    if (t.Typ != TempNone)
+    {
+      if (mFirstPassUnknown(t.Flags))
+      {
+        *pEvalResult = '\0';
+        pResult->Flags = t.Flags;
+        pResult->AddrSpaceMask = t.AddrSpaceMask;
+        pResult->DataSize = t.DataSize;
+        pResult->OK = True;
+      }
+      else
+        WrStrErrorPos(DeduceExpectTypeErrMsgMask(TempString, t.Typ), pExpr);
+    }
+  }
+  else
+  {
+    as_nonz_dynstr_to_c_str(pEvalResult, &t.Contents.str, STRINGSIZE);
+    pResult->Flags = t.Flags;
+    pResult->AddrSpaceMask = t.AddrSpaceMask;
+    pResult->DataSize = t.DataSize;
+    pResult->OK = True;
+  }
+  as_tempres_free(&t);
+}
+
+void EvalStrStringExpression(const tStrComp *pExpr, Boolean *pResult, char *pEvalResult)
+{
+  tEvalResult Result;
+
+  EvalStrStringExpressionWithResult(pExpr, &Result, pEvalResult);
+  *pResult = Result.OK;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     EvalStrRegExpressionWithResult(const struct sStrComp *pExpr, struct sRegDescr *pResult, struct sEvalResult *pEvalResult, Boolean IssueErrors)
+ * \brief  retrieve/evaluate register expression
+ * \param  pExpr source code expression
+ * \param  pResult retrieved register
+ * \param  pEvalResult success flag, symbol size & flags
+ * \param  IssueErrors print errors at all?
+ * \return occured error
+ * ------------------------------------------------------------------------ */
+
+PSymbolEntry ExpandAndFindNode(const struct sStrComp *pComp, TempType SearchType)
+{
+  PSymbolEntry pEntry;
+  String ExpName;
+  const char *pKlPos;
+
+  if (!ExpandStrSymbol(ExpName, sizeof(ExpName), pComp))
+    return NULL;
+
+  /* just [...] without symbol name itself is not valid */
+
+  pKlPos = strchr(ExpName, '[');
+  if ((pKlPos == ExpName) || (ChkSymbNameUpTo(ExpName, pKlPos) != pKlPos))
+    return NULL;
+
+  pEntry = FindLocNode(ExpName, SearchType);
+  if (!pEntry)
+    pEntry = FindNode(ExpName, SearchType);
+  return pEntry;
+}
+
+tErrorNum EvalStrRegExpressionWithResult(const struct sStrComp *pExpr, tRegDescr *pResult, tEvalResult *pEvalResult)
+{
+  PSymbolEntry pEntry;
+
+  EvalResultClear(pEvalResult);
+
+  pEntry = ExpandAndFindNode(pExpr, TempReg);
+  if (!pEntry)
+    return ErrNum_SymbolUndef;
+
+  pEntry->Used = True;
+  pEvalResult->DataSize = pEntry->SymWert.DataSize;
+
+  if (pEntry->SymWert.Typ != TempReg)
+    return ErrNum_ExpectReg;
+  *pResult = pEntry->SymWert.Contents.RegDescr;
+
+  if (pEntry->SymWert.Contents.RegDescr.Dissect != DissectReg)
+    return ErrNum_RegWrongTarget;
+
+  pEvalResult->OK = True;
+  return ErrNum_None;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     EvalStrRegExpressionAsOperand(const tStrComp *pArg, struct sRegDescr *pResult, struct sEvalResult *pEvalResult, tSymbolSize ReqSize, Boolean MustBeReg)
+ * \brief  check for possible register in instruction operand
+ * \param  pArg source argument
+ * \param  ReqSize possible fixed operand size
+ * \param  MustBeReg operand cannot be anything else but register
+ * \return eIsReg: argument is a register
+           eIsNoReg: argument is no register
+           eRegAbort: argument is faulty, abort anyway (only if !MustBeReg)
+ * ------------------------------------------------------------------------ */
+
+tRegEvalResult EvalStrRegExpressionAsOperand(const tStrComp *pArg, struct sRegDescr *pResult, struct sEvalResult *pEvalResult, tSymbolSize ReqSize, Boolean MustBeReg)
+{
+  tErrorNum ErrorNum;
+
+  ErrorNum = EvalStrRegExpressionWithResult(pArg, pResult, pEvalResult);
+  if (pEvalResult->OK && (ReqSize != eSymbolSizeUnknown) && (pEvalResult->DataSize != ReqSize))
+  {
+    pEvalResult->OK = False;
+    ErrorNum = ErrNum_InvOpSize;
+  }
+  switch (ErrorNum)
+  {
+    case ErrNum_None:
+      return eIsReg;
+    case ErrNum_SymbolUndef:
+      if (MustBeReg)
+      {
+        if (PassNo <= MaxSymPass)
+        {
+          pResult->Reg = 0;
+          pResult->Dissect = NULL;
+          Repass = True;
+          return eIsReg;
+        }
+        else
+        {
+          WrStrErrorPos(ErrNum_InvReg, pArg);
+          return eIsNoReg;
+        }
+      }
+      else
+        return eIsNoReg;
+    case ErrNum_ExpectReg:
+      if (MustBeReg)
+        WrStrErrorPos(ErrorNum, pArg);
+      return eIsNoReg;
+    default:
+      WrStrErrorPos(ErrorNum, pArg);
+      return MustBeReg ? eIsNoReg : eRegAbort;
+  }
+}
+
+static void FreeSymbolEntry(PSymbolEntry *Node, Boolean Destroy)
+{
+  PCrossRef Lauf;
+
+  if ((*Node)->Tree.Name)
+  {
+    free((*Node)->Tree.Name);
+   (*Node)->Tree.Name = NULL;
+  }
+
+  as_tempres_free(&(*Node)->SymWert);
+
+  while ((*Node)->RefList)
+  {
+    Lauf = (*Node)->RefList->Next;
+    free((*Node)->RefList);
+    (*Node)->RefList = Lauf;
+  }
+
+  FreeRelocs(&((*Node)->SymWert.Relocs));
+
+  if (Destroy)
+  {
+    free(*Node);
+    Node = NULL;
+  }
+}
+
+static char *serr, *snum;
+typedef struct
+{
+  Boolean MayChange, DoCross;
+} TEnterStruct, *PEnterStruct;
+
+static Boolean SymbolAdder(PTree *PDest, PTree Neu, void *pData)
+{
+  PSymbolEntry NewEntry = (PSymbolEntry)Neu, *Node;
+  PEnterStruct EnterStruct = (PEnterStruct) pData;
+
+  /* added to an empty leaf ? */
+
+  if (!PDest)
+  {
+    NewEntry->Defined = True;
+    NewEntry->Used = False;
+    NewEntry->Changeable = EnterStruct->MayChange;
+    NewEntry->RefList = NULL;
+    if (EnterStruct->DoCross)
+    {
+      NewEntry->FileNum = GetFileNum(CurrFileName);
+      NewEntry->LineNum = CurrLine;
+    }
+    return True;
+  }
+
+  /* replace en entry: check for validity */
+
+  Node = (PSymbolEntry*)PDest;
+
+  /* tried to redefine a symbol with EQU ? */
+
+  if (((*Node)->Defined) && (!(*Node)->Changeable) && (!EnterStruct->MayChange))
+  {
+    strmaxcpy(serr, (*Node)->Tree.Name, STRINGSIZE);
+    if (EnterStruct->DoCross)
+      as_snprcatf(serr, STRINGSIZE, ",%s %s:%ld",
+                  getmessage(Num_PrevDefMsg),
+                  GetFileName((*Node)->FileNum), (long)((*Node)->LineNum));
+    WrXError(ErrNum_DoubleDef, serr);
+    FreeSymbolEntry(&NewEntry, TRUE);
+    return False;
+  }
+
+  /* tried to reassign a constant (EQU) a value with SET and vice versa ? */
+
+  else if ( ((*Node)->Defined) && (EnterStruct->MayChange != (*Node)->Changeable) )
+  {
+    strmaxcpy(serr, (*Node)->Tree.Name, STRINGSIZE);
+    if (EnterStruct->DoCross)
+      as_snprcatf(serr, STRINGSIZE, ",%s %s:%ld",
+                  getmessage(Num_PrevDefMsg),
+                  GetFileName((*Node)->FileNum), (long)((*Node)->LineNum));
+    WrXError((*Node)->Changeable ? ErrNum_VariableRedefinedAsConstant : ErrNum_ConstantRedefinedAsVariable, serr);
+    FreeSymbolEntry(&NewEntry, TRUE);
+    return False;
+  }
+
+  else
+  {
+    if (!EnterStruct->MayChange)
+    {
+      Boolean value_changed;
+
+#if 0
+      if (NewEntry->SymWert.Typ == TempInt)
+        fprintf(stderr, "NewEntry 0x%lx Node 0x%lx Node changed %d\n",
+                NewEntry->SymWert.Contents.Int, (*Node)->SymWert.Contents.Int, (*Node)->changed);
+#endif
+
+      /* If the symbol value was changed after entry (padding of label),
+         compare to the originally set value, because this is what we get
+         here as initial value to set (before padding) in the next pass: */
+
+      if (NewEntry->SymWert.Typ != (*Node)->SymWert.Typ)
+        value_changed = True;
+      else switch (NewEntry->SymWert.Typ)
+      {
+        case TempInt:
+          value_changed = NewEntry->SymWert.Contents.Int != ((*Node)->changed ? (*Node)->unchanged_value : (*Node)->SymWert.Contents.Int);
+          break;
+        default:
+          value_changed = !!as_tempres_cmp(&NewEntry->SymWert, &(*Node)->SymWert);
+      }
+      if (value_changed)
+      {
+        if (!Repass && (JmpErrors > 0))
+        {
+          if (ThrowErrors)
+            ErrorCount -= JmpErrors;
+          JmpErrors = 0;
+        }
+        Repass = True;
+        if (MsgIfRepass && (PassNo >= PassNoForMessage))
+        {
+          strmaxcpy(serr, Neu->Name, STRINGSIZE);
+          if (Neu->Attribute != -1)
+          {
+            strmaxcat(serr, "[", STRINGSIZE);
+            strmaxcat(serr, GetSectionName(Neu->Attribute), STRINGSIZE);
+            strmaxcat(serr, "]", STRINGSIZE);
+          }
+          WrXError(ErrNum_PhaseErr, serr);
+        }
+      }
+    }
+    if (EnterStruct->DoCross)
+    {
+      NewEntry->LineNum = (*Node)->LineNum;
+      NewEntry->FileNum = (*Node)->FileNum;
+    }
+
+    /* take over values from existing node that shall be kept */
+
+    NewEntry->RefList = (*Node)->RefList;
+    (*Node)->RefList = NULL;
+    NewEntry->Defined = True;
+    NewEntry->Used = (*Node)->Used;
+    NewEntry->Changeable = EnterStruct->MayChange;
+
+    /* since NewEntry will be copied over Node, free the latter's dynamic data: */
+
+    FreeSymbolEntry(Node, False);
+    return True;
+  }
+}
+
+static void EnterLocSymbol(PSymbolEntry Neu)
+{
+  TEnterStruct EnterStruct;
+  PTree TreeRoot;
+
+  Neu->Tree.Attribute = MomLocHandle;
+  if (!CaseSensitive)
+    NLS_UpString(Neu->Tree.Name);
+  EnterStruct.MayChange = EnterStruct.DoCross = FALSE;
+  TreeRoot = &FirstLocSymbol->Tree;
+  EnterTree(&TreeRoot, (&Neu->Tree), SymbolAdder, &EnterStruct);
+  FirstLocSymbol = (PSymbolEntry)TreeRoot;
+}
+
+static void EnterSymbol_Search(PForwardSymbol *Lauf, PForwardSymbol *Prev,
+                               PForwardSymbol **RRoot, PSymbolEntry Neu,
+                               PForwardSymbol *Root, Byte ResCode, Byte *SearchErg)
+{
+  *Lauf = (*Root);
+  *Prev = NULL;
+  *RRoot = Root;
+  while ((*Lauf) && (strcmp((*Lauf)->Name, Neu->Tree.Name)))
+  {
+    *Prev = (*Lauf);
+    *Lauf = (*Lauf)->Next;
+  }
+  if (*Lauf)
+    *SearchErg = ResCode;
+}
+
+static void EnterSymbol(PSymbolEntry Neu, Boolean MayChange, LongInt ResHandle)
+{
+  PForwardSymbol Lauf, Prev;
+  PForwardSymbol *RRoot;
+  Byte SearchErg;
+  String CombName;
+  PSaveSection RunSect;
+  LongInt MSect;
+  PSymbolEntry Copy;
+  TEnterStruct EnterStruct;
+  PTree TreeRoot = &(FirstSymbol->Tree);
+
+  if (!CaseSensitive)
+    NLS_UpString(Neu->Tree.Name);
+
+  SearchErg = 0;
+  EnterStruct.MayChange = MayChange;
+  EnterStruct.DoCross = MakeCrossList;
+  Neu->Tree.Attribute = (ResHandle == -2) ? MomSectionHandle : ResHandle;
+  if ((SectionStack) && (Neu->Tree.Attribute == MomSectionHandle))
+  {
+    EnterSymbol_Search(&Lauf, &Prev, &RRoot, Neu, &(SectionStack->LocSyms),
+                       1, &SearchErg);
+    if (!Lauf)
+      EnterSymbol_Search(&Lauf, &Prev, &RRoot, Neu,
+                         &(SectionStack->GlobSyms), 2, &SearchErg);
+    if (!Lauf)
+      EnterSymbol_Search(&Lauf, &Prev, &RRoot, Neu,
+                         &(SectionStack->ExportSyms), 3, &SearchErg);
+    if (SearchErg == 2)
+      Neu->Tree.Attribute = Lauf->DestSection;
+    if (SearchErg == 3)
+    {
+      strmaxcpy(CombName, Neu->Tree.Name, STRINGSIZE);
+      RunSect = SectionStack;
+      MSect = MomSectionHandle;
+      while ((MSect != Lauf->DestSection) && (RunSect))
+      {
+        strmaxprep(CombName, "_", STRINGSIZE);
+        strmaxprep(CombName, GetSectionName(MSect), STRINGSIZE);
+        MSect = RunSect->Handle;
+        RunSect = RunSect->Next;
+      }
+      Copy = (PSymbolEntry) calloc(1, sizeof(TSymbolEntry));
+      *Copy = (*Neu);
+      Copy->Tree.Name = as_strdup(CombName);
+      Copy->Tree.Attribute = Lauf->DestSection;
+      Copy->SymWert.Relocs = DupRelocs(Neu->SymWert.Relocs);
+      if (Copy->SymWert.Typ == TempString)
+      {
+        size_t l = Neu->SymWert.Contents.str.len;
+        Copy->SymWert.Contents.str.p_str = (char*)malloc(l);
+        memcpy(Copy->SymWert.Contents.str.p_str, Neu->SymWert.Contents.str.p_str,
+               Copy->SymWert.Contents.str.len = Copy->SymWert.Contents.str.capacity = l);
+      }
+      EnterTree(&TreeRoot, &(Copy->Tree), SymbolAdder, &EnterStruct);
+    }
+    if (Lauf)
+    {
+      free(Lauf->Name);
+      free(Lauf->pErrorPos);
+      if (!Prev)
+        *RRoot = Lauf->Next;
+      else
+        Prev->Next = Lauf->Next;
+      free(Lauf);
+    }
+  }
+  EnterTree(&TreeRoot, &(Neu->Tree), SymbolAdder, &EnterStruct);
+  FirstSymbol = (PSymbolEntry)TreeRoot;
+}
+
+void PrintSymTree(char *Name)
+{
+  fprintf(Debug, "---------------------\n");
+  fprintf(Debug, "Enter Symbol %s\n\n", Name);
+  PrintSymbolTree();
+  PrintSymbolDepth();
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChangeSymbol(PSymbolEntry pEntry, LargeInt Value)
+ * \brief  change value of symbol in symbol table (use with caution)
+ * \param  pEntry symbol entry to modify
+ * \param  Value new (integer)value
+ * ------------------------------------------------------------------------ */
+
+void ChangeSymbol(PSymbolEntry pEntry, LargeInt Value)
+{
+  if (!pEntry->changed)
+  {
+    pEntry->unchanged_value = (pEntry->SymWert.Typ == TempInt) ? pEntry->SymWert.Contents.Int : 0;
+    pEntry->changed = True;
+  }
+  as_tempres_set_int(&pEntry->SymWert, Value);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     CreateSymbolEntry(const tStrComp *pName, LongInt *pDestHandle, tSymbolFlags symbol_flags)
+ * \brief  create empty container for symbol tabl eentry
+ * \param  pName unexpanded symbol name
+ * \param  pDestHandle section handle (out)
+ * \param  symbol_flags symbol flags
+ * \return * to container or NULL
+ * ------------------------------------------------------------------------ */
+
+PSymbolEntry CreateSymbolEntry(const tStrComp *pName, LongInt *pDestHandle, tSymbolFlags symbol_flags)
+{
+  PSymbolEntry pNeu;
+  String ExtName;
+
+  if (!ExpandStrSymbol(ExtName, sizeof(ExtName), pName))
+    return NULL;
+  if (!GetSymSection(ExtName, pDestHandle, pName))
+    return NULL;
+  (void)ChkTmp(ExtName, (symbol_flags & eSymbolFlag_Label) ? e_symbol_source_label : e_symbol_source_define);
+  if (!ChkSymbName(ExtName))
+  {
+    WrStrErrorPos(ErrNum_InvSymName, pName);
+    return NULL;
+  }
+  pNeu = (PSymbolEntry) calloc(1, sizeof(TSymbolEntry));
+  pNeu->Tree.Name = as_strdup(ExtName);
+  as_tempres_ini(&pNeu->SymWert);
+  return pNeu;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     EnterIntSymbolWithFlags(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange, tSymbolFlags Flags)
+ * \brief  add integer symbol to symbol table
+ * \param  pName unexpanded name
+ * \param  Wert integer value
+ * \param  addrspace symbol's address space
+ * \param  MayChange constant or variable?
+ * \param  Flags additional flags
+ * \return * to newly created entry in tree
+ * ------------------------------------------------------------------------ */
+
+PSymbolEntry EnterIntSymbolWithFlags(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange, tSymbolFlags Flags)
+{
+  LongInt DestHandle;
+  PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, Flags);
+
+  if (!pNeu)
+    return NULL;
+
+  as_tempres_set_int(&pNeu->SymWert, Wert);
+  pNeu->SymWert.AddrSpaceMask = (addrspace != SegNone) ? 1 << addrspace : 0;
+  pNeu->SymWert.Flags = Flags;
+  pNeu->SymWert.DataSize = eSymbolSizeUnknown;
+  pNeu->RefList = NULL;
+  pNeu->SymWert.Relocs = NULL;
+
+  if ((MomLocHandle == -1) || (DestHandle != -2))
+  {
+    EnterSymbol(pNeu, MayChange, DestHandle);
+    if (MakeDebug)
+      PrintSymTree(pNeu->Tree.Name);
+  }
+  else
+    EnterLocSymbol(pNeu);
+  return pNeu;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     EnterExtSymbol(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange)
+ * \brief  create extended symbol
+ * \param  pName unexpanded name
+ * \param  Wert symbol value
+ * \param  AddrSpace symbol's address space
+ * \param  MayChange variable or constant?
+ * ------------------------------------------------------------------------ */
+
+void EnterExtSymbol(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange)
+{
+  LongInt DestHandle;
+  PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, eSymbolFlag_None);
+
+  if (!pNeu)
+    return;
+
+  as_tempres_set_int(&pNeu->SymWert, Wert);  
+  pNeu->SymWert.AddrSpaceMask = (addrspace != SegNone) ? 1 << addrspace : 0;
+  pNeu->SymWert.Flags = eSymbolFlag_None;
+  pNeu->SymWert.DataSize = eSymbolSizeUnknown;
+  pNeu->RefList = NULL;
+  pNeu->SymWert.Relocs = (PRelocEntry) malloc(sizeof(TRelocEntry));
+  pNeu->SymWert.Relocs->Next = NULL;
+  pNeu->SymWert.Relocs->Ref = as_strdup(pNeu->Tree.Name);
+  pNeu->SymWert.Relocs->Add = True;
+
+  if ((MomLocHandle == -1) || (DestHandle != -2))
+  {
+    EnterSymbol(pNeu, MayChange, DestHandle);
+    if (MakeDebug)
+      PrintSymTree(pNeu->Tree.Name);
+  }
+  else
+    EnterLocSymbol(pNeu);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     EnterRelSymbol(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange)
+ * \brief  enter relocatable symbol
+ * \param  pName unexpanded name
+ * \param  Wert symbol value
+ * \param  addrspace symbol's address space
+ * \param  MayChange variable or constant?
+ * \return * to created entry in tree
+ * ------------------------------------------------------------------------ */
+
+PSymbolEntry EnterRelSymbol(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange)
+{
+  LongInt DestHandle;
+  PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, eSymbolFlag_None);
+
+  if (!pNeu)
+    return NULL;
+
+  as_tempres_set_int(&pNeu->SymWert, Wert);
+  pNeu->SymWert.AddrSpaceMask = (addrspace != SegNone) ? 1 << addrspace : 0;
+  pNeu->SymWert.Flags = eSymbolFlag_None;
+  pNeu->SymWert.DataSize = eSymbolSizeUnknown;
+  pNeu->RefList = NULL;
+  pNeu->SymWert.Relocs = (PRelocEntry) malloc(sizeof(TRelocEntry));
+  pNeu->SymWert.Relocs->Next = NULL;
+  pNeu->SymWert.Relocs->Ref = as_strdup(RelName_SegStart);
+  pNeu->SymWert.Relocs->Add = True;
+
+  if ((MomLocHandle == -1) || (DestHandle != -2))
+  {
+    EnterSymbol(pNeu, MayChange, DestHandle);
+    if (MakeDebug)
+      PrintSymTree(pNeu->Tree.Name);
+  }
+  else
+    EnterLocSymbol(pNeu);
+
+  return pNeu;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     EnterFloatSymbol(const tStrComp *pName, Double Wert, Boolean MayChange)
+ * \brief  enter floating point symbol
+ * \param  pName unexpanded name
+ * \param  Wert symbol value
+ * \param  MayChange variable or constant?
+ * ------------------------------------------------------------------------ */
+
+void EnterFloatSymbol(const tStrComp *pName, Double Wert, Boolean MayChange)
+{
+  LongInt DestHandle;
+  PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, eSymbolFlag_None);
+
+  if (!pNeu)
+    return;
+
+  as_tempres_set_float(&pNeu->SymWert, Wert);
+  pNeu->SymWert.AddrSpaceMask = 0;
+  pNeu->SymWert.Flags = eSymbolFlag_None;
+  pNeu->SymWert.DataSize = eSymbolSizeUnknown;
+  pNeu->RefList = NULL;
+  pNeu->SymWert.Relocs = NULL;
+
+  if ((MomLocHandle == -1) || (DestHandle != -2))
+  {
+    EnterSymbol(pNeu, MayChange, DestHandle);
+    if (MakeDebug)
+      PrintSymTree(pNeu->Tree.Name);
+  }
+  else
+    EnterLocSymbol(pNeu);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     EnterNonZStringSymbolWithFlags(const tStrComp *pName, const as_nonz_dynstr_t *p_value, Boolean MayChange, tSymbolFlags Flags)
+ * \brief  enter string symbol
+ * \param  pName unexpanded name
+ * \param  pValue symbol value
+ * \param  MayChange variable or constant?
+ * \param  Flags special symbol flags to store
+ * ------------------------------------------------------------------------ */
+
+void EnterNonZStringSymbolWithFlags(const tStrComp *pName, const as_nonz_dynstr_t *p_value, Boolean MayChange, tSymbolFlags Flags)
+{
+  LongInt DestHandle;
+  PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, Flags);
+
+  if (!pNeu)
+    return;
+
+  /* TODO: TempRes alloc exact len */
+  pNeu->SymWert.Contents.str.p_str = (char*)malloc(p_value->len);
+  memcpy(pNeu->SymWert.Contents.str.p_str, p_value->p_str, p_value->len);
+  pNeu->SymWert.Contents.str.len =
+  pNeu->SymWert.Contents.str.capacity = p_value->len;
+  pNeu->SymWert.Typ = TempString;
+  pNeu->SymWert.AddrSpaceMask = 0;
+  pNeu->SymWert.Flags = Flags;
+  pNeu->SymWert.DataSize = eSymbolSizeUnknown;
+  pNeu->RefList = NULL;
+  pNeu->SymWert.Relocs = NULL;
+
+  if ((MomLocHandle == -1) || (DestHandle != -2))
+  {
+    EnterSymbol(pNeu, MayChange, DestHandle);
+    if (MakeDebug)
+      PrintSymTree(pNeu->Tree.Name);
+  }
+  else
+    EnterLocSymbol(pNeu);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     EnterStringSymbol(const tStrComp *pName, const char *pValue, Boolean MayChange)
+ * \brief  enter string symbol
+ * \param  pName unexpanded name
+ * \param  pValue symbol value
+ * \param  MayChange variable or constant?
+ * ------------------------------------------------------------------------ */
+
+void EnterStringSymbol(const tStrComp *pName, const char *pValue, Boolean MayChange)
+{
+  as_nonz_dynstr_t NonZString;
+
+  as_nonz_dynstr_ini_c_str(&NonZString, pValue);
+  EnterNonZStringSymbol(pName, &NonZString, MayChange);
+  as_nonz_dynstr_free(&NonZString);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     EnterRegSymbol(const struct sStrComp *pName, const tRegDescr *pDescr, tSymbolSize Size, Boolean MayChange, Boolean AddList)
+ * \brief  enter register symbol
+ * \param  pName unexpanded name
+ * \param  pDescr register's numeric value & associated dissector
+ * \param  Size register's data size
+ * \param  MayChange variable or constant?
+ * \param  AddList add value to listing?
+ * ------------------------------------------------------------------------ */
+
+void EnterRegSymbol(const struct sStrComp *pName, const tRegDescr *pDescr, tSymbolSize Size, Boolean MayChange, Boolean AddList)
+{
+  LongInt DestHandle;
+  PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, eSymbolFlag_None);
+
+  if (!pNeu)
+    return;
+
+  as_tempres_set_reg(&pNeu->SymWert, pDescr);
+  pNeu->SymWert.AddrSpaceMask = 0;
+  pNeu->SymWert.Flags = eSymbolFlag_None;
+  pNeu->SymWert.DataSize = Size;
+  pNeu->RefList = NULL;
+  pNeu->SymWert.Relocs = NULL;
+
+  if ((MomLocHandle == -1) || (DestHandle != -2))
+  {
+    EnterSymbol(pNeu, MayChange, DestHandle);
+    if (MakeDebug)
+      PrintSymTree(pNeu->Tree.Name);
+    RegistersDefined = True;
+  }
+  else
+    EnterLocSymbol(pNeu);
+
+  if (AddList)
+  {
+    *ListLine = '=';
+    pDescr->Dissect(&ListLine[1], STRINGSIZE - 1, pDescr->Reg, Size);
+  }
+}
+
+static void AddReference(PSymbolEntry Node)
+{
+  PCrossRef Lauf, Neu;
+
+  /* Speicher belegen */
+
+  Neu = (PCrossRef) malloc(sizeof(TCrossRef));
+  Neu->LineNum = CurrLine;
+  Neu->OccNum = 1;
+  Neu->Next = NULL;
+
+  /* passende Datei heraussuchen */
+
+  Neu->FileNum = GetFileNum(CurrFileName);
+
+  /* suchen, ob Eintrag schon existiert */
+
+  Lauf = Node->RefList;
+  while ((Lauf)
+     && ((Lauf->FileNum != Neu->FileNum) || (Lauf->LineNum != Neu->LineNum)))
+   Lauf = Lauf->Next;
+
+  /* schon einmal in dieser Datei in dieser Zeile aufgetaucht: nur Zaehler
+    rauf: */
+
+  if (Lauf)
+  {
+    Lauf->OccNum++;
+   free(Neu);
+  }
+
+  /* ansonsten an Kettenende anhaengen */
+
+  else if (!Node->RefList) Node->RefList = Neu;
+
+  else
+  {
+    Lauf = Node->RefList;
+    while (Lauf->Next)
+      Lauf = Lauf->Next;
+    Lauf->Next = Neu;
+  }
+}
+
+static PSymbolEntry FindNode_FNode(char *Name, TempType SearchType, LongInt Handle)
+{
+  PSymbolEntry Lauf;
+
+  Lauf = (PSymbolEntry) SearchTree((PTree)FirstSymbol, Name, Handle);
+
+  if (Lauf)
+  {
+    if (Lauf->SymWert.Typ & SearchType)
+    {
+      if (MakeCrossList && DoRefs)
+        AddReference(Lauf);
+    }
+    else
+      Lauf = NULL;
+  }
+
+  return Lauf;
+}
+
+static Boolean FindNode_FSpec(char *Name, PForwardSymbol Root)
+{
+  while ((Root) && (strcmp(Root->Name, Name)))
+    Root = Root->Next;
+  return (Root != NULL);
+}
+
+static PSymbolEntry FindNode(const char *Name_O, TempType SearchType)
+{
+  PSaveSection Lauf;
+  LongInt DestSection;
+  PSymbolEntry Result = NULL;
+  String Name;
+
+  strmaxcpy(Name, Name_O, STRINGSIZE);
+  ChkTmp3(Name, e_symbol_source_none);
+
+  /* TODO: pass StrComp */
+  if (!GetSymSection(Name, &DestSection, NULL))
+    return NULL;
+
+  if (!CaseSensitive)
+    NLS_UpString(Name);
+
+  if (SectionStack)
+    if (PassNo <= MaxSymPass)
+      if (FindNode_FSpec(Name, SectionStack->LocSyms)) DestSection = MomSectionHandle;
+
+  if (DestSection == -2)
+  {
+    Result = FindNode_FNode(Name, SearchType, MomSectionHandle);
+    if (Result)
+      return Result;
+    Lauf = SectionStack;
+    while (Lauf)
+    {
+      Result = FindNode_FNode(Name, SearchType, Lauf->Handle);
+      if (Result)
+        break;
+      Lauf = Lauf->Next;
+    }
+  }
+  else
+    Result = FindNode_FNode(Name, SearchType, DestSection);
+
+  return Result;
+}
+
+static PSymbolEntry FindLocNode_FNode(char *Name, TempType SearchType, LongInt Handle)
+{
+  PSymbolEntry Lauf;
+
+  Lauf = (PSymbolEntry) SearchTree((PTree)FirstLocSymbol, Name, Handle);
+
+  if (Lauf)
+  {
+    if (!(Lauf->SymWert.Typ & SearchType))
+      Lauf = NULL;
+  }
+
+  return Lauf;
+}
+
+static PSymbolEntry FindLocNode(const char *Name_O, TempType SearchType)
+{
+  PLocHandle RunLocHandle;
+  PSymbolEntry Result = NULL;
+  String Name;
+
+  strmaxcpy(Name, Name_O, STRINGSIZE);
+  ChkTmp3(Name, e_symbol_source_none);
+  if (!CaseSensitive)
+    NLS_UpString(Name);
+
+  if (MomLocHandle == -1)
+    return NULL;
+
+  Result = FindLocNode_FNode(Name, SearchType, MomLocHandle);
+  if (Result)
+    return Result;
+
+  RunLocHandle = FirstLocHandle;
+  while ((RunLocHandle) && (RunLocHandle->Cont != -1))
+  {
+    Result = FindLocNode_FNode(Name, SearchType, RunLocHandle->Cont);
+    if (Result)
+      break;
+    RunLocHandle = RunLocHandle->Next;
+  }
+
+  return Result;
+}
+/**
+void SetSymbolType(const tStrComp *pName, Byte NTyp)
+{
+  PSymbolEntry Lauf;
+  Boolean HRef;
+  String ExpName;
+
+  if (!ExpandStrSymbol(ExpName, sizeof(ExpName), pName))
+    return;
+  HRef = DoRefs;
+  DoRefs = False;
+  Lauf = FindLocNode(ExpName, TempInt);
+  if (!Lauf)
+    Lauf = FindNode(ExpName, TempInt);
+  if (Lauf)
+    Lauf->SymType = NTyp;
+  DoRefs = HRef;
+}
+**/
+
+void LookupSymbol(const struct sStrComp *pComp, TempResult *pValue, Boolean WantRelocs, TempType ReqType)
+{
+  PSymbolEntry pEntry;
+  String ExpName;
+  const char *pKlPos;
+
+  if (!ExpandStrSymbol(ExpName, sizeof(ExpName), pComp))
+  {
+    pValue->Typ = TempNone;
+    return;
+  }
+
+  pKlPos = strchr(ExpName, '[');
+  if (ChkSymbNameUpTo(ExpName, pKlPos) != pKlPos)
+  {
+    WrStrErrorPos(ErrNum_InvSymName, pComp);
+    pValue->Typ = TempNone;
+    return;
+  }
+
+  pEntry = FindLocNode(ExpName, ReqType);
+  if (!pEntry)
+    pEntry = FindNode(ExpName, ReqType);
+  if (pEntry)
+  {
+    as_tempres_copy_value(pValue, &pEntry->SymWert);
+    if (pValue->Typ != TempNone)
+    {
+      if (WantRelocs)
+        pValue->Relocs = DupRelocs(pEntry->SymWert.Relocs);
+      pValue->Flags = pEntry->SymWert.Flags;
+    }
+    pValue->AddrSpaceMask = pEntry->SymWert.AddrSpaceMask;
+    if ((pEntry->SymWert.DataSize != eSymbolSizeUnknown) && (pValue->DataSize == eSymbolSizeUnknown))
+      pValue->DataSize = pEntry->SymWert.DataSize;
+    if (!pEntry->Defined)
+    {
+      if (Repass)
+        pValue->Flags |= eSymbolFlag_Questionable;
+      pValue->Flags |= eSymbolFlag_UsesForwards;
+    }
+    pEntry->Used = True;
+  }
+
+  /* Symbol evtl. im ersten Pass unbekannt */
+
+  else if (PassNo <= MaxSymPass) /* !pEntry */
+  {
+    as_tempres_set_int(pValue, EProgCounter());
+    Repass = True;
+    if ((MsgIfRepass) && (PassNo >= PassNoForMessage))
+      WrStrErrorPos(ErrNum_RepassUnknown, pComp);
+    pValue->Flags |= eSymbolFlag_FirstPassUnknown;
+  }
+  else
+    WrStrErrorPos(ErrNum_SymbolUndef, pComp);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     SetSymbolOrStructElemSize(const struct sStrComp *pName, tSymbolSize Size)
+ * \brief  set (integer) data size associated with a symbol
+ * \param  pName unexpanded name of symbol
+ * \param  Size operand size to set
+ * ------------------------------------------------------------------------ */
+
+void SetSymbolOrStructElemSize(const struct sStrComp *pName, tSymbolSize Size)
+{
+  if (pInnermostNamedStruct)
+    SetStructElemSize(pInnermostNamedStruct->StructRec, pName->str.p_str, Size);
+  else
+  {
+    PSymbolEntry pEntry;
+    Boolean HRef;
+    String ExpName;
+
+    if (!ExpandStrSymbol(ExpName, sizeof(ExpName), pName))
+      return;
+    HRef = DoRefs;
+    DoRefs = False;
+    pEntry = FindLocNode(ExpName, TempInt);
+    if (!pEntry)
+      pEntry = FindNode(ExpName, TempInt);
+    if (pEntry)
+      pEntry->SymWert.DataSize = Size;
+    DoRefs = HRef;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     GetSymbolSize(const struct sStrComp *pName)
+ * \brief  get symbol's integer size
+ * \param  pName unexpanded symbol name
+ * \return symbol size or -1 if symbol does not exist
+ * ------------------------------------------------------------------------ */
+
+ShortInt GetSymbolSize(const struct sStrComp *pName)
+{
+  PSymbolEntry pEntry;
+  String ExpName;
+
+  if (!ExpandStrSymbol(ExpName, sizeof(ExpName), pName))
+     return -1;
+  pEntry = FindLocNode(ExpName, TempInt);
+  if (!pEntry)
+    pEntry = FindNode(ExpName, TempInt);
+  return pEntry ? pEntry->SymWert.DataSize : eSymbolSizeUnknown;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     IsSymbolDefined(const struct sStrComp *pName)
+ * \brief  check whether symbol nas been used so far
+ * \param  pName unexpanded symbol name
+ * \return true if symbol exists and has been defined so far
+ * ------------------------------------------------------------------------ */
+
+Boolean IsSymbolDefined(const struct sStrComp *pName)
+{
+  PSymbolEntry pEntry;
+  String ExpName;
+
+  if (!ExpandStrSymbol(ExpName, sizeof(ExpName), pName))
+    return False;
+
+  pEntry = FindLocNode(ExpName, TempAll);
+  if (!pEntry)
+    pEntry = FindNode(ExpName, TempAll);
+  return pEntry && pEntry->Defined;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     IsSymbolUsed(const struct sStrComp *pName)
+ * \brief  check whether symbol nas been used so far
+ * \param  pName unexpanded symbol name
+ * \return true if symbol exists and has been used
+ * ------------------------------------------------------------------------ */
+
+Boolean IsSymbolUsed(const struct sStrComp *pName)
+{
+  PSymbolEntry pEntry;
+  String ExpName;
+
+  if (!ExpandStrSymbol(ExpName, sizeof(ExpName), pName))
+    return False;
+
+  pEntry = FindLocNode(ExpName, TempAll);
+  if (!pEntry)
+    pEntry = FindNode(ExpName, TempAll);
+  return pEntry && pEntry->Used;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     IsSymbolChangeable(const struct sStrComp *pName)
+ * \brief  check whether symbol's value may be changed or is constant
+ * \param  pName unexpanded symbol name
+ * \return true if symbol exists and is changeable
+ * ------------------------------------------------------------------------ */
+
+Boolean IsSymbolChangeable(const struct sStrComp *pName)
+{
+  PSymbolEntry pEntry;
+  String ExpName;
+
+  if (!ExpandStrSymbol(ExpName, sizeof(ExpName), pName))
+    return False;
+
+  pEntry = FindLocNode(ExpName, TempAll);
+  if (!pEntry)
+    pEntry = FindNode(ExpName, TempAll);
+  return pEntry && pEntry->Changeable;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     GetSymbolType(const struct sStrComp *pName)
+ * \brief  retrieve type (int/float/string) of symbol
+ * \param  pName unexpanded name
+ * \return type or -1 if non-existent
+ * ------------------------------------------------------------------------ */
+
+as_addrspace_t addrspace_from_mask(unsigned mask)
+{
+  as_addrspace_t space;
+
+  for (space = SegCode; space < SegCount; space++)
+    if (mask & (1 << space))
+      return space;
+  return SegNone;
+}
+
+Integer GetSymbolType(const struct sStrComp *pName)
+{
+  PSymbolEntry pEntry;
+  String ExpName;
+
+  if (!ExpandStrSymbol(ExpName, sizeof(ExpName), pName))
+    return -1;
+
+  pEntry = FindLocNode(ExpName, TempAll);
+  if (!pEntry)
+    pEntry = FindNode(ExpName, TempAll);
+
+  if (!pEntry)
+    return -1;
+  else if (pEntry->SymWert.Typ == TempReg)
+    return 0x80;
+  else
+    return addrspace_from_mask(pEntry->SymWert.AddrSpaceMask);
+}
+
+typedef struct
+{
+  int Width, cwidth;
+  LongInt Sum, USum;
+  as_dynstr_t Zeilenrest;
+  int ZeilenrestLen,
+      ZeilenrestVisibleLen;
+  as_dynstr_t s1, sh;
+} TListContext;
+
+static void PrintSymbolList_AddOut(char *s, TListContext *pContext)
+{
+  int AddVisibleLen = visible_strlen(s),
+      AddLen = strlen(s);
+
+  if (AddVisibleLen + pContext->ZeilenrestVisibleLen > pContext->Width)
+  {
+    pContext->Zeilenrest.p_str[pContext->ZeilenrestLen - 1] = '\0';
+    WrLstLine(pContext->Zeilenrest.p_str);
+    as_dynstr_copy_c_str(&pContext->Zeilenrest, s);
+    pContext->ZeilenrestLen = AddLen;
+    pContext->ZeilenrestVisibleLen = AddVisibleLen;
+  }
+  else
+  {
+    as_dynstr_append_c_str(&pContext->Zeilenrest, s);
+    pContext->ZeilenrestLen += AddLen;
+    pContext->ZeilenrestVisibleLen += AddVisibleLen;
+  }
+}
+
+static void PrintSymbolList_PNode(PTree Tree, void *pData)
+{
+  PSymbolEntry Node = (PSymbolEntry) Tree;
+
+  if (Node->SymWert.Typ != TempReg)
+  {
+    TListContext *pContext = (TListContext*) pData;
+    int l1, nBlanks;
+    const TempResult *pValue = &Node->SymWert;
+
+    if ((pValue->Typ == TempInt) && DissectBit && (pValue->AddrSpaceMask & (1 << SegBData)))
+      DissectBit(pContext->s1.p_str, pContext->s1.capacity, pValue->Contents.Int);
+    else
+      StrSym(pValue, False, &pContext->s1, ListRadixBase);
+
+    as_sdprintf(&pContext->sh, "%c%s : ", Node->Used ? ' ' : '*', Tree->Name);
+    if (Tree->Attribute != -1)
+      as_sdprcatf(&pContext->sh, " [%s]", GetSectionName(Tree->Attribute));
+    l1 = (strlen(pContext->s1.p_str) + visible_strlen(pContext->sh.p_str) + 4);
+    for (nBlanks = pContext->cwidth - 1 - l1; nBlanks < 0; nBlanks += pContext->cwidth);
+    as_sdprcatf(&pContext->sh, "%s%s %c | ", Blanks(nBlanks), pContext->s1.p_str, SegShorts[addrspace_from_mask(pValue->AddrSpaceMask)]);
+    PrintSymbolList_AddOut(pContext->sh.p_str, pContext);
+    pContext->Sum++;
+    if (!Node->Used)
+      pContext->USum++;
+  }
+}
+
+void PrintSymbolList(void)
+{
+  int ActPageWidth;
+  TListContext Context;
+
+  as_dynstr_ini(&Context.Zeilenrest, STRINGSIZE);
+  as_dynstr_ini(&Context.s1, STRINGSIZE);
+  as_dynstr_ini(&Context.sh, STRINGSIZE);
+  Context.Width = (PageWidth == 0) ? 80 : PageWidth;
+  NewPage(ChapDepth, True);
+  WrLstLine(getmessage(Num_ListSymListHead1));
+  WrLstLine(getmessage(Num_ListSymListHead2));
+  WrLstLine("");
+
+  Context.ZeilenrestLen =
+  Context.ZeilenrestVisibleLen = 0;
+  Context.Sum = Context.USum = 0;
+  ActPageWidth = (PageWidth == 0) ? 80 : PageWidth;
+  Context.cwidth = ActPageWidth >> 1;
+  IterTree((PTree)FirstSymbol, PrintSymbolList_PNode, &Context);
+  if (Context.Zeilenrest.p_str[0] != '\0')
+  {
+    Context.Zeilenrest.p_str[strlen(Context.Zeilenrest.p_str) - 1] = '\0';
+    WrLstLine(Context.Zeilenrest.p_str);
+  }
+  WrLstLine("");
+  as_sdprintf(&Context.Zeilenrest, "%7lu%s",
+              (unsigned long)Context.Sum,
+              getmessage((Context.Sum == 1) ? Num_ListSymSumMsg : Num_ListSymSumsMsg));
+  WrLstLine(Context.Zeilenrest.p_str);
+  as_sdprintf(&Context.Zeilenrest, "%7lu%s",
+              (unsigned long)Context.USum,
+              getmessage((Context.USum == 1) ? Num_ListUSymSumMsg : Num_ListUSymSumsMsg));
+  WrLstLine(Context.Zeilenrest.p_str);
+  WrLstLine("");
+  as_dynstr_free(&Context.s1);
+  as_dynstr_free(&Context.sh);
+  as_dynstr_free(&Context.Zeilenrest);
+}
+
+typedef struct
+{
+  FILE *f;
+  Boolean HWritten;
+  as_addrspace_t Space;
+  as_dynstr_t s;
+} TDebContext;
+
+static Boolean match_space_mask(unsigned mask, as_addrspace_t space)
+{
+  if (SegNone == space)
+    return !mask;
+  else
+    return !!((mask >> space) & 1);
+}
+
+static void PrintDebSymbols_PNode(PTree Tree, void *pData)
+{
+  PSymbolEntry Node = (PSymbolEntry) Tree;
+  TDebContext *DebContext = (TDebContext*) pData;
+  int l1;
+
+  if (!match_space_mask(Node->SymWert.AddrSpaceMask, DebContext->Space))
+    return;
+
+  if (!DebContext->HWritten)
+  {
+    fprintf(DebContext->f, "\n"); ChkIO(ErrNum_FileWriteError);
+    fprintf(DebContext->f, "Symbols in Segment %s\n", SegNames[DebContext->Space]); ChkIO(ErrNum_FileWriteError);
+    DebContext->HWritten = True;
+  }
+
+  fprintf(DebContext->f, "%s", Node->Tree.Name); ChkIO(ErrNum_FileWriteError);
+  l1 = strlen(Node->Tree.Name);
+  if (Node->Tree.Attribute != -1)
+  {
+    as_sdprintf(&DebContext->s, "[%d]", (int)Node->Tree.Attribute);
+    fprintf(DebContext->f, "%s", DebContext->s.p_str); ChkIO(ErrNum_FileWriteError);
+    l1 += strlen(DebContext->s.p_str);
+  }
+  fprintf(DebContext->f, "%s ", Blanks(37 - l1)); ChkIO(ErrNum_FileWriteError);
+  switch (Node->SymWert.Typ)
+  {
+    case TempInt:
+      fprintf(DebContext->f, "Int    ");
+      break;
+    case TempFloat:
+      fprintf(DebContext->f, "Float  ");
+      break;
+    case TempString:
+      fprintf(DebContext->f, "String ");
+      break;
+    default:
+      break;
+  }
+  ChkIO(ErrNum_FileWriteError);
+  if (Node->SymWert.Typ == TempString)
+  {
+    errno = 0;
+    l1 = fstrlenprint(DebContext->f, Node->SymWert.Contents.str.p_str, Node->SymWert.Contents.str.len);
+    ChkIO(ErrNum_FileWriteError);
+  }
+  else
+  {
+    StrSym(&Node->SymWert, False, &DebContext->s, 16);
+    l1 = strlen(DebContext->s.p_str);
+    fprintf(DebContext->f, "%s", DebContext->s.p_str); ChkIO(ErrNum_FileWriteError);
+  }
+  fprintf(DebContext->f, "%s %-3d %d %d\n", Blanks(25 - l1), Node->SymWert.DataSize, (int)Node->Used, (int)Node->Changeable);
+  ChkIO(ErrNum_FileWriteError);
+}
+
+void PrintDebSymbols(FILE *f)
+{
+  TDebContext DebContext;
+
+  as_dynstr_ini(&DebContext.s, 256);
+  DebContext.f = f;
+  for (DebContext.Space = SegNone; DebContext.Space < SegCount; DebContext.Space++)
+  {
+    DebContext.HWritten = False;
+    IterTree((PTree)FirstSymbol, PrintDebSymbols_PNode, &DebContext);
+  }
+  as_dynstr_free(&DebContext.s);
+}
+
+typedef struct
+{
+  FILE *f;
+  LongInt Handle;
+} TNoISymContext;
+
+static void PrNoISection(PTree Tree, void *pData)
+{
+  PSymbolEntry Node = (PSymbolEntry)Tree;
+  TNoISymContext *pContext = (TNoISymContext*) pData;
+
+  if ((Node->SymWert.AddrSpaceMask & NoICEMask) && (Node->Tree.Attribute == pContext->Handle) && (Node->SymWert.Typ == TempInt))
+  {
+    errno = 0; fprintf(pContext->f, "DEFINE %s 0x", Node->Tree.Name); ChkIO(ErrNum_FileWriteError);
+    errno = 0; fprintf(pContext->f, LargeHIntFormat, Node->SymWert.Contents.Int); ChkIO(ErrNum_FileWriteError);
+    errno = 0; fprintf(pContext->f, "\n"); ChkIO(ErrNum_FileWriteError);
+  }
+}
+
+void PrintNoISymbols(FILE *f)
+{
+  PCToken CurrSection;
+  TNoISymContext Context;
+
+  Context.f = f;
+  Context.Handle = -1;
+  IterTree((PTree)FirstSymbol, PrNoISection, &Context);
+  Context.Handle++;
+  for (CurrSection = FirstSection; CurrSection; CurrSection = CurrSection->Next)
+   if (ChunkSum(&CurrSection->Usage)>0)
+   {
+     fprintf(f, "FUNCTION %s ", CurrSection->Name); ChkIO(ErrNum_FileWriteError);
+     fprintf(f, LargeIntFormat, ChunkMin(&CurrSection->Usage)); ChkIO(ErrNum_FileWriteError);
+     fprintf(f, "\n"); ChkIO(ErrNum_FileWriteError);
+     IterTree((PTree)FirstSymbol, PrNoISection, &Context);
+     Context.Handle++;
+     fprintf(f, "}FUNC "); ChkIO(ErrNum_FileWriteError);
+     fprintf(f, LargeIntFormat, ChunkMax(&CurrSection->Usage)); ChkIO(ErrNum_FileWriteError);
+     fprintf(f, "\n"); ChkIO(ErrNum_FileWriteError);
+   }
+}
+
+void PrintSymbolTree(void)
+{
+  DumpTree((PTree)FirstSymbol);
+}
+
+static void ClearSymbolList_ClearNode(PTree Node, void *pData)
+{
+  PSymbolEntry SymbolEntry = (PSymbolEntry) Node;
+  UNUSED(pData);
+
+  FreeSymbolEntry(&SymbolEntry, FALSE);
+}
+
+void ClearSymbolList(void)
+{
+  PTree TreeRoot;
+
+  TreeRoot = &(FirstSymbol->Tree);
+  FirstSymbol = NULL;
+  DestroyTree(&TreeRoot, ClearSymbolList_ClearNode, NULL);
+  TreeRoot = &(FirstLocSymbol->Tree);
+  FirstLocSymbol = NULL;
+  DestroyTree(&TreeRoot, ClearSymbolList_ClearNode, NULL);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Stack-Verwaltung */
+
+Boolean PushSymbol(const tStrComp *pSymName, const tStrComp *pStackName)
+{
+  PSymbolEntry pSrc;
+  PSymbolStack LStack, NStack, PStack;
+  PSymbolStackEntry Elem;
+  String ExpSymName, ExpStackName;
+
+  if (!ExpandStrSymbol(ExpSymName, sizeof(ExpSymName), pSymName))
+    return False;
+
+  pSrc = FindNode(ExpSymName, TempAll);
+  if (!pSrc)
+  {
+    WrStrErrorPos(ErrNum_SymbolUndef, pSymName);
+    return False;
+  }
+
+  if (*pStackName->str.p_str)
+  {
+    if (!ExpandStrSymbol(ExpStackName, sizeof(ExpStackName), pStackName))
+      return False;
+  }
+  else
+    strmaxcpy(ExpStackName, DefStackName, STRINGSIZE);
+  if (!ChkSymbName(ExpStackName))
+  {
+    WrStrErrorPos(ErrNum_InvSymName, pStackName);
+    return False;
+  }
+
+  LStack = FirstStack;
+  PStack = NULL;
+  while ((LStack) && (strcmp(LStack->Name, ExpStackName) < 0))
+  {
+    PStack = LStack;
+    LStack = LStack->Next;
+  }
+
+  if ((!LStack) || (strcmp(LStack->Name, ExpStackName) > 0))
+  {
+    NStack = (PSymbolStack) malloc(sizeof(TSymbolStack));
+    NStack->Name = as_strdup(ExpStackName);
+    NStack->Contents = NULL;
+    NStack->Next = LStack;
+    if (!PStack)
+      FirstStack = NStack;
+    else
+      PStack->Next = NStack;
+    LStack = NStack;
+  }
+
+  Elem = (PSymbolStackEntry) malloc(sizeof(TSymbolStackEntry));
+  Elem->Next = LStack->Contents;
+  Elem->Contents = pSrc->SymWert;
+  LStack->Contents = Elem;
+
+  return True;
+}
+
+Boolean PopSymbol(const tStrComp *pSymName, const tStrComp *pStackName)
+{
+  PSymbolEntry pDest;
+  PSymbolStack LStack, PStack;
+  PSymbolStackEntry Elem;
+  String ExpSymName, ExpStackName;
+
+  if (!ExpandStrSymbol(ExpSymName, sizeof(ExpSymName), pSymName))
+    return False;
+
+  pDest = FindNode(ExpSymName, TempAll);
+  if (!pDest)
+  {
+    WrStrErrorPos(ErrNum_SymbolUndef, pSymName);
+    return False;
+  }
+
+  if (*pStackName->str.p_str)
+  {
+    if (!ExpandStrSymbol(ExpStackName, sizeof(ExpStackName), pStackName))
+      return False;
+  }
+  else
+    strmaxcpy(ExpStackName, DefStackName, STRINGSIZE);
+  if (!ChkSymbName(ExpStackName))
+  {
+    WrStrErrorPos(ErrNum_InvSymName, pStackName);
+    return False;
+  }
+
+  LStack = FirstStack;
+  PStack = NULL;
+  while ((LStack) && (strcmp(LStack->Name, ExpStackName) < 0))
+  {
+    PStack = LStack;
+    LStack = LStack->Next;
+  }
+
+  if ((!LStack) || (strcmp(LStack->Name, ExpStackName) > 0))
+  {
+    WrStrErrorPos(ErrNum_StackEmpty, pStackName);
+    return False;
+  }
+
+  Elem = LStack->Contents;
+  pDest->SymWert = Elem->Contents;
+  LStack->Contents = Elem->Next;
+  if (!LStack->Contents)
+  {
+    if (!PStack)
+      FirstStack = LStack->Next;
+    else
+      PStack->Next = LStack->Next;
+    free(LStack->Name);
+    free(LStack);
+  }
+  free(Elem);
+
+  return True;
+}
+
+void ClearStacks(void)
+{
+  PSymbolStack Act;
+  PSymbolStackEntry Elem;
+  int z;
+  String s;
+
+  while (FirstStack)
+  {
+    z = 0;
+    Act = FirstStack;
+    while (Act->Contents)
+    {
+      Elem = Act->Contents;
+      Act->Contents = Elem->Next;
+      free(Elem);
+      z++;
+    }
+    as_snprintf(s, sizeof(s), "%s(%d)", Act->Name, z);
+    WrXError(ErrNum_StackNotEmpty, s);
+    free(Act->Name);
+    FirstStack = Act->Next;
+    free(Act);
+  }
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funktionsverwaltung */
+
+void EnterFunction(const tStrComp *pComp, char *FDefinition, Byte NewCnt)
+{
+  PFunction Neu;
+  String FName_N;
+  const char *pFName;
+
+  if (!CaseSensitive)
+  {
+    strmaxcpy(FName_N, pComp->str.p_str, STRINGSIZE);
+    NLS_UpString(FName_N);
+    pFName = FName_N;
+  }
+  else
+     pFName = pComp->str.p_str;
+
+  if (!ChkSymbName(pFName))
+  {
+    WrStrErrorPos(ErrNum_InvSymName, pComp);
+    return;
+  }
+
+  if (FindFunction(pFName))
+  {
+    if (PassNo == 1)
+      WrStrErrorPos(ErrNum_DoubleDef, pComp);
+    return;
+  }
+
+  Neu = (PFunction) malloc(sizeof(TFunction));
+  Neu->Next = FirstFunction;
+  Neu->ArguCnt = NewCnt;
+  Neu->Name = as_strdup(pFName);
+  Neu->Definition = as_strdup(FDefinition);
+  FirstFunction = Neu;
+}
+
+PFunction FindFunction(const char *Name)
+{
+  PFunction Lauf = FirstFunction;
+  String Name_N;
+
+  if (!CaseSensitive)
+  {
+    strmaxcpy(Name_N, Name, STRINGSIZE);
+    NLS_UpString(Name_N);
+    Name = Name_N;
+  }
+
+  while ((Lauf) && (strcmp(Lauf->Name, Name)))
+    Lauf = Lauf->Next;
+  return Lauf;
+}
+
+void PrintFunctionList(void)
+{
+  PFunction Lauf;
+  String OneS;
+  Boolean cnt;
+
+  if (!FirstFunction)
+    return;
+
+  NewPage(ChapDepth, True);
+  WrLstLine(getmessage(Num_ListFuncListHead1));
+  WrLstLine(getmessage(Num_ListFuncListHead2));
+  WrLstLine("");
+
+  OneS[0] = '\0';
+  Lauf = FirstFunction;
+  cnt = False;
+  while (Lauf)
+  {
+    strmaxcat(OneS, Lauf->Name, STRINGSIZE);
+    if (strlen(Lauf->Name) < 37)
+      strmaxcat(OneS, Blanks(37-strlen(Lauf->Name)), STRINGSIZE);
+    if (!cnt) strmaxcat(OneS, " | ", STRINGSIZE);
+    else
+    {
+      WrLstLine(OneS);
+      OneS[0] = '\0';
+    }
+    cnt = !cnt;
+    Lauf = Lauf->Next;
+  }
+  if (cnt)
+  {
+    OneS[strlen(OneS)-1] = '\0';
+    WrLstLine(OneS);
+  }
+  WrLstLine("");
+}
+
+void ClearFunctionList(void)
+{
+  PFunction Lauf;
+
+  while (FirstFunction)
+  {
+    Lauf = FirstFunction->Next;
+    free(FirstFunction->Name);
+    free(FirstFunction->Definition);
+    free(FirstFunction);
+    FirstFunction = Lauf;
+  }
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void ResetSymbolDefines_ResetNode(PTree Node, void *pData)
+{
+  PSymbolEntry SymbolEntry = (PSymbolEntry) Node;
+  UNUSED(pData);
+
+  SymbolEntry->Defined = False;
+  SymbolEntry->Used = False;
+}
+
+void ResetSymbolDefines(void)
+{
+  IterTree(&(FirstSymbol->Tree), ResetSymbolDefines_ResetNode, NULL);
+  IterTree(&(FirstLocSymbol->Tree), ResetSymbolDefines_ResetNode, NULL);
+}
+
+void SetFlag(Boolean *Flag, const char *Name, Boolean Wert)
+{
+  tStrComp TmpComp;
+
+  *Flag = Wert;
+  StrCompMkTemp(&TmpComp, (char*)Name, 0);
+  EnterIntSymbol(&TmpComp, *Flag ? 1 : 0, SegNone, True);
+}
+
+void AddDefSymbol(char *Name, TempResult *Value)
+{
+  PDefSymbol Neu;
+
+  Neu = FirstDefSymbol;
+  while (Neu)
+  {
+    if (!strcmp(Neu->SymName, Name))
+      return;
+    Neu = Neu->Next;
+  }
+
+  Neu = (PDefSymbol) malloc(sizeof(TDefSymbol));
+  Neu->Next = FirstDefSymbol;
+  Neu->SymName = as_strdup(Name);
+  Neu->Wert = (*Value);
+  FirstDefSymbol = Neu;
+}
+
+void RemoveDefSymbol(char *Name)
+{
+  PDefSymbol Save, Lauf;
+
+  if (!FirstDefSymbol)
+    return;
+
+  if (!strcmp(FirstDefSymbol->SymName, Name))
+  {
+    Save = FirstDefSymbol;
+    FirstDefSymbol = FirstDefSymbol->Next;
+  }
+  else
+  {
+    Lauf = FirstDefSymbol;
+    while ((Lauf->Next) && (strcmp(Lauf->Next->SymName, Name)))
+      Lauf = Lauf->Next;
+    if (!Lauf->Next)
+      return;
+    Save = Lauf->Next;
+    Lauf->Next = Lauf->Next->Next;
+  }
+  free(Save->SymName);
+  free(Save);
+}
+
+void CopyDefSymbols(void)
+{
+  PDefSymbol Lauf;
+  tStrComp TmpComp;
+
+  Lauf = FirstDefSymbol;
+  while (Lauf)
+  {
+    StrCompMkTemp(&TmpComp, Lauf->SymName, 0);
+    switch (Lauf->Wert.Typ)
+    {
+      case TempInt:
+        EnterIntSymbol(&TmpComp, Lauf->Wert.Contents.Int, SegNone, True);
+        break;
+      case TempFloat:
+        EnterFloatSymbol(&TmpComp, Lauf->Wert.Contents.Float, True);
+        break;
+      case TempString:
+      {
+        EnterNonZStringSymbol(&TmpComp, &Lauf->Wert.Contents.str, True);
+        break;
+      }
+      default:
+        break;
+    }
+    Lauf = Lauf->Next;
+  }
+}
+
+const TempResult *FindDefSymbol(const char *pName)
+{
+  PDefSymbol pRun;
+
+  for (pRun = FirstDefSymbol; pRun; pRun = pRun->Next)
+    if (!strcmp(pName, pRun->SymName))
+      return &pRun->Wert;
+  return NULL;
+}
+
+void PrintSymbolDepth(void)
+{
+  LongInt TreeMin, TreeMax;
+
+  GetTreeDepth(&(FirstSymbol->Tree), &TreeMin, &TreeMax);
+  fprintf(Debug, " MinTree %ld\n", (long)TreeMin);
+  fprintf(Debug, " MaxTree %ld\n", (long)TreeMax);
+}
+
+LongInt GetSectionHandle(char *SName_O, Boolean AddEmpt, LongInt Parent)
+{
+  PCToken Lauf, Prev;
+  LongInt z;
+  String SName;
+
+  strmaxcpy(SName, SName_O, STRINGSIZE);
+  if (!CaseSensitive)
+    NLS_UpString(SName);
+
+  Lauf = FirstSection;
+  Prev = NULL;
+  z = 0;
+  while ((Lauf) && ((strcmp(Lauf->Name, SName)) || (Lauf->Parent != Parent)))
+  {
+    z++;
+    Prev = Lauf;
+    Lauf = Lauf->Next;
+  }
+
+  if (!Lauf)
+  {
+    if (AddEmpt)
+    {
+      Lauf = (PCToken) malloc(sizeof(TCToken));
+      Lauf->Parent = MomSectionHandle;
+      Lauf->Name = as_strdup(SName);
+      Lauf->Next = NULL;
+      InitChunk(&(Lauf->Usage));
+      if (!Prev)
+        FirstSection = Lauf;
+      else
+        Prev->Next = Lauf;
+    }
+    else
+      z = -2;
+  }
+  return z;
+}
+
+const char *GetSectionName(LongInt Handle)
+{
+  PCToken Lauf = FirstSection;
+  static const char *Dummy = "";
+
+  if (Handle == -1)
+    return Dummy;
+  while ((Handle > 0) && (Lauf))
+  {
+    Lauf = Lauf->Next;
+    Handle--;
+  }
+  return Lauf ? Lauf->Name : Dummy;
+}
+
+void SetMomSection(LongInt Handle)
+{
+  LongInt z;
+
+  MomSectionHandle = Handle;
+  if (Handle < 0)
+    MomSection = NULL;
+  else
+  {
+    MomSection = FirstSection;
+    for (z = 1; z <= Handle; z++)
+      if (MomSection)
+        MomSection = MomSection->Next;
+  }
+}
+
+void AddSectionUsage(LongInt Start, LongInt Length)
+{
+  if ((ActPC != SegCode) || (!MomSection))
+    return;
+  AddChunk(&(MomSection->Usage), Start, Length, False);
+}
+
+void ClearSectionUsage(void)
+{
+  PCToken Tmp;
+
+  for (Tmp = FirstSection; Tmp; Tmp = Tmp->Next)
+    ClearChunk(&(Tmp->Usage));
+}
+
+static void PrintSectionList_PSection(LongInt Handle, int Indent)
+{
+  PCToken Lauf;
+  LongInt Cnt;
+  String h;
+
+  ChkStack();
+  if (Handle != -1)
+  {
+    strmaxcpy(h, Blanks(Indent << 1), STRINGSIZE);
+    strmaxcat(h, GetSectionName(Handle), STRINGSIZE);
+    WrLstLine(h);
+  }
+  Lauf = FirstSection;
+  Cnt = 0;
+  while (Lauf)
+  {
+    if (Lauf->Parent == Handle)
+      PrintSectionList_PSection(Cnt, Indent + 1);
+    Lauf = Lauf->Next;
+    Cnt++;
+  }
+}
+
+void PrintSectionList(void)
+{
+  if (!FirstSection)
+    return;
+
+  NewPage(ChapDepth, True);
+  WrLstLine(getmessage(Num_ListSectionListHead1));
+  WrLstLine(getmessage(Num_ListSectionListHead2));
+  WrLstLine("");
+  PrintSectionList_PSection(-1, 0);
+}
+
+void PrintDebSections(FILE *f)
+{
+  PCToken Lauf;
+  LongInt Cnt, z, l, s;
+  char Str[30];
+
+  Lauf = FirstSection; Cnt = 0;
+  while (Lauf)
+  {
+    fputs("\nInfo for Section ", f); ChkIO(ErrNum_FileWriteError);
+    fprintf(f, LongIntFormat, Cnt); ChkIO(ErrNum_FileWriteError);
+    fputc(' ', f); ChkIO(ErrNum_FileWriteError);
+    fputs(GetSectionName(Cnt), f); ChkIO(ErrNum_FileWriteError);
+    fputc(' ', f); ChkIO(ErrNum_FileWriteError);
+    fprintf(f, LongIntFormat, Lauf->Parent); ChkIO(ErrNum_FileWriteError);
+    fputc('\n', f); ChkIO(ErrNum_FileWriteError);
+    for (z = 0; z < Lauf->Usage.RealLen; z++)
+    {
+      l = Lauf->Usage.Chunks[z].Length;
+      s = Lauf->Usage.Chunks[z].Start;
+      HexString(Str, sizeof(Str), s, 0);
+      fputs(Str, f);
+      ChkIO(ErrNum_FileWriteError);
+      if (l == 1)
+        fprintf(f, "\n");
+      else
+      {
+        HexString(Str, sizeof(Str), s + l - 1, 0);
+        fprintf(f, "-%s\n", Str);
+      }
+      ChkIO(ErrNum_FileWriteError);
+    }
+    Lauf = Lauf->Next;
+    Cnt++;
+  }
+}
+
+void ClearSectionList(void)
+{
+  PCToken Tmp;
+
+  while (FirstSection)
+  {
+    Tmp = FirstSection;
+    free(Tmp->Name);
+    ClearChunk(&(Tmp->Usage));
+    FirstSection = Tmp->Next; free(Tmp);
+  }
+}
+
+/*---------------------------------------------------------------------------------*/
+
+/*!------------------------------------------------------------------------
+ * \fn     PrintCrossList_PNode(PTree Node, void *pData)
+ * \brief  printf cross refence list of a single symbol table entry
+ * \param  Node node base object
+ * \param  pData actual symbol entry
+ * \return
+ * ------------------------------------------------------------------------ */
+
+static void PrintCrossList_PNode(PTree Node, void *pData)
+{
+  int FileZ;
+  PCrossRef pCross;
+  String LineAcc;
+  String h;
+  char LineStr[30];
+  PSymbolEntry SymbolEntry = (PSymbolEntry) Node;
+  as_dynstr_t *p_val_str = (as_dynstr_t*)pData;
+  Boolean First;
+
+  if (!SymbolEntry->RefList)
+    return;
+
+  StrSym(&SymbolEntry->SymWert, False, p_val_str, ListRadixBase);
+  as_snprintf(LineStr, sizeof(LineStr), LongIntFormat, SymbolEntry->LineNum);
+
+  as_snprintf(h, sizeof(h), "%s%s",
+              getmessage(Num_ListCrossSymName), Node->Name);
+  if (Node->Attribute != -1)
+    as_snprcatf(h, sizeof(h), "[%s]", GetSectionName(Node->Attribute));
+  as_snprcatf(h, sizeof(h), " (=%s, %s:%s):",
+              p_val_str->p_str, GetFileName(SymbolEntry->FileNum), LineStr);
+
+  WrLstLine(h);
+
+  for (FileZ = 0; FileZ < GetFileCount(); FileZ++)
+  {
+    First = True;
+    strcpy(LineAcc, "  ");
+    for (pCross = SymbolEntry->RefList; pCross; pCross = pCross->Next)
+      if (pCross->FileNum == FileZ)
+      {
+        if (First)
+        {
+          strcpy(h, " ");
+          strmaxcat(h, getmessage(Num_ListCrossFileName), STRINGSIZE);
+          strmaxcat(h, GetFileName(FileZ), STRINGSIZE);
+          strmaxcat(h, " :", STRINGSIZE);
+          WrLstLine(h);
+          First = False;
+        }
+        as_snprcatf(LineAcc, sizeof(LineAcc), "%5ld", (long)pCross->LineNum);
+        if (pCross->OccNum != 1)
+          as_snprcatf(LineAcc, sizeof(LineAcc), "(%2ld)", (long)pCross->OccNum);
+        else
+          strmaxcat(LineAcc, "    ", STRINGSIZE);
+        if (strlen(LineAcc) >= 72)
+        {
+          WrLstLine(LineAcc);
+          strcpy(LineAcc, "  ");
+        }
+      }
+    if (strcmp(LineAcc, "  "))
+      WrLstLine(LineAcc);
+  }
+  WrLstLine("");
+}
+
+void PrintCrossList(void)
+{
+  as_dynstr_t val_str;
+
+  as_dynstr_ini(&val_str, 256);
+  WrLstLine("");
+  WrLstLine(getmessage(Num_ListCrossListHead1));
+  WrLstLine(getmessage(Num_ListCrossListHead2));
+  WrLstLine("");
+  IterTree(&(FirstSymbol->Tree), PrintCrossList_PNode, &val_str);
+  WrLstLine("");
+  as_dynstr_free(&val_str);
+}
+
+static void ClearCrossList_CNode(PTree Tree, void *pData)
+{
+  PCrossRef Lauf;
+  PSymbolEntry SymbolEntry = (PSymbolEntry) Tree;
+  UNUSED(pData);
+
+  while (SymbolEntry->RefList)
+  {
+    Lauf = SymbolEntry->RefList->Next;
+    free(SymbolEntry->RefList);
+    SymbolEntry->RefList = Lauf;
+  }
+}
+
+void ClearCrossList(void)
+{
+  IterTree(&(FirstSymbol->Tree), ClearCrossList_CNode, NULL);
+}
+
+/*--------------------------------------------------------------------------*/
+
+LongInt GetLocHandle(void)
+{
+  return LocHandleCnt++;
+}
+
+void PushLocHandle(LongInt NewLoc)
+{
+  PLocHandle NewLocHandle;
+
+  NewLocHandle = (PLocHandle) malloc(sizeof(TLocHeap));
+  NewLocHandle->Cont = MomLocHandle;
+  NewLocHandle->Next = FirstLocHandle;
+  FirstLocHandle = NewLocHandle; MomLocHandle = NewLoc;
+}
+
+void PopLocHandle(void)
+{
+  PLocHandle OldLocHandle;
+
+  OldLocHandle = FirstLocHandle;
+  if (!OldLocHandle) return;
+  MomLocHandle = OldLocHandle->Cont;
+  FirstLocHandle = OldLocHandle->Next;
+  free(OldLocHandle);
+}
+
+void ClearLocStack()
+{
+  while (MomLocHandle != -1)
+    PopLocHandle();
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void PrintRegList_PNode(PTree Tree, void *pData)
+{
+  PSymbolEntry Node = (PSymbolEntry) Tree;
+
+  if (Node->SymWert.Typ == TempReg)
+  {
+    TListContext *pContext = (TListContext*) pData;
+    String tmp, tmp2;
+
+    if (Node->SymWert.Contents.RegDescr.Dissect)
+      Node->SymWert.Contents.RegDescr.Dissect(tmp2, sizeof(tmp2), Node->SymWert.Contents.RegDescr.Reg, Node->SymWert.DataSize);
+    else
+      *tmp2 = '\0';
+    *tmp = '\0';
+    if (Tree->Attribute != -1)
+      as_snprcatf(tmp, sizeof(tmp), "[%s]", GetSectionName(Tree->Attribute));
+    as_snprcatf(tmp, sizeof(tmp), "%c%s --> %s", Node->Used ? ' ' : '*', Tree->Name, tmp2);
+    if ((int)strlen(tmp) > pContext->cwidth - 3)
+    {
+      if (*pContext->Zeilenrest.p_str)
+        WrLstLine(pContext->Zeilenrest.p_str);
+      *pContext->Zeilenrest.p_str = '\0';
+      WrLstLine(tmp);
+    }
+    else
+    {
+      strmaxcat(tmp, Blanks(pContext->cwidth - 3 - strlen(tmp)), STRINGSIZE);
+      if (!*pContext->Zeilenrest.p_str)
+        as_dynstr_copy_c_str(&pContext->Zeilenrest, tmp);
+      else
+      {
+        as_sdprcatf(&pContext->Zeilenrest, " | %s", tmp);
+        WrLstLine(pContext->Zeilenrest.p_str);
+        *pContext->Zeilenrest.p_str = '\0';
+      }
+    }
+    pContext->Sum++;
+    if (!Node->Used)
+      pContext->USum++;
+  }
+}
+
+void PrintRegDefs(void)
+{
+  String buf;
+  LongInt ActPageWidth;
+  TListContext Context;
+
+  if (!RegistersDefined)
+    return;
+
+  NewPage(ChapDepth, True);
+  WrLstLine(getmessage(Num_ListRegDefListHead1));
+  WrLstLine(getmessage(Num_ListRegDefListHead2));
+  WrLstLine("");
+
+  as_dynstr_ini(&Context.Zeilenrest, STRINGSIZE);
+  as_dynstr_ini(&Context.s1, 1);
+  as_dynstr_ini(&Context.sh, 1);
+  Context.Sum = Context.USum = 0;
+  ActPageWidth = (PageWidth == 0) ? 80 : PageWidth;
+  Context.cwidth = ActPageWidth >> 1;
+  IterTree((PTree)FirstSymbol, PrintRegList_PNode, &Context);
+
+  if (*Context.Zeilenrest.p_str)
+    WrLstLine(Context.Zeilenrest.p_str);
+  WrLstLine("");
+  as_snprintf(buf, sizeof(buf), "%7ld%s",
+              (long) Context.Sum,
+              getmessage((Context.Sum == 1) ? Num_ListRegDefSumMsg : Num_ListRegDefSumsMsg));
+  WrLstLine(buf);
+  as_snprintf(buf, sizeof(buf), "%7ld%s",
+              (long)Context.USum,
+              getmessage((Context.USum == 1) ? Num_ListRegDefUSumMsg : Num_ListRegDefUSumsMsg));
+  WrLstLine("");
+  as_dynstr_free(&Context.Zeilenrest);
+  as_dynstr_free(&Context.s1);
+  as_dynstr_free(&Context.sh);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void ClearCodepages(void)
+{
+  PTransTable Old;
+
+  while (TransTables)
+  {
+    Old = TransTables;
+    TransTables = Old->Next;
+    free(Old->Name);
+    free(Old->Table);
+    free(Old);
+  }
+}
+
+void PrintCodepages(void)
+{
+  char buf[500];
+  PTransTable Table;
+  int z, cnt, cnt2;
+
+  NewPage(ChapDepth, True);
+  WrLstLine(getmessage(Num_ListCodepageListHead1));
+  WrLstLine(getmessage(Num_ListCodepageListHead2));
+  WrLstLine("");
+
+  cnt2 = 0;
+  for (Table = TransTables; Table; Table = Table->Next)
+  {
+    for (z = cnt = 0; z < 256; z++)
+      if (Table->Table[z] != z)
+        cnt++;
+    as_snprintf(buf, sizeof(buf), "%s (%d%s)", Table->Name, cnt,
+                getmessage((cnt == 1) ? Num_ListCodepageChange : Num_ListCodepagePChange));
+    WrLstLine(buf);
+    cnt2++;
+  }
+  WrLstLine("");
+  as_snprintf(buf, sizeof(buf), "%d%s", cnt2,
+              getmessage((cnt2 == 1) ? Num_ListCodepageSumMsg : Num_ListCodepageSumsMsg));
+  WrLstLine(buf);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void asmpars_init(void)
+{
+  tIntTypeDef *pCurr;
+
+  serr = (char*)malloc(sizeof(char) * STRINGSIZE);
+  snum = (char*)malloc(sizeof(char) * STRINGSIZE);
+  FirstDefSymbol = NULL;
+  FirstFunction = NULL;
+  BalanceTrees = False;
+
+  for (pCurr = IntTypeDefs; pCurr < IntTypeDefs + (sizeof(IntTypeDefs) / sizeof(*IntTypeDefs)); pCurr++)
+  {
+    unsigned SignType = Hi(pCurr->SignAndWidth);
+    unsigned Bits, Cnt;
+
+    Bits = Lo(pCurr->SignAndWidth) - ((SignType == 0x80) ? 1 : 0);
+    for (Cnt = 0, pCurr->Mask = 0; Cnt < Bits; Cnt++)
+      pCurr->Mask = (pCurr->Mask << 1) | 1;
+
+    pCurr->Max = (LargeInt)pCurr->Mask;
+
+    switch (SignType & 0xc0)
+    {
+      case 0x80:
+        pCurr->Min = -pCurr->Max - 1;
+        break;
+      case 0xc0:
+        pCurr->Min = (LargeInt)(pCurr->Mask / 2);
+        pCurr->Min = -pCurr->Min - 1;
+        break;
+      default:
+        pCurr->Min = 0;
+        break;
+    }
+  }
+
+  LastGlobSymbol = (char*)malloc(sizeof(char) * STRINGSIZE);
+}
diff --git a/aslshim/asmpars.h b/aslshim/asmpars.h
new file mode 100644 (file)
index 0000000..a2c0491
--- /dev/null
@@ -0,0 +1,305 @@
+#ifndef _ASMPARS_H
+#define _ASMPARS_H
+/* asmpars.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Verwaltung von Symbolen und das ganze Drumherum...                        */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stddef.h>
+
+#include "symbolsize.h"
+#include "symflags.h"
+#include "tempresult.h"
+#include "intformat.h"
+#include "lstmacroexp.h"
+#include "errmsg.h"
+#include "addrspace.h"
+
+typedef enum
+{
+  UInt1    ,
+  UInt2    ,
+  UInt3    ,
+  SInt4    , UInt4   , Int4    ,
+  SInt5    , UInt5   , Int5    ,
+  SInt6    , UInt6   ,
+  SInt7    , UInt7   ,
+  SInt8    , UInt8   , Int8    ,
+  SInt9    , UInt9    ,
+  UInt10   , Int10   ,
+  UInt11   ,
+  UInt12   , Int12   ,
+  UInt13   ,
+  UInt14   , Int14   ,
+  SInt15   , UInt15  ,
+  SInt16   , UInt16  , Int16   ,
+  UInt17   ,
+  UInt18   ,
+  UInt19   ,
+  SInt20   , UInt20  , Int20   ,
+  UInt21   ,
+  UInt22   ,
+  UInt23   ,
+  SInt24   , UInt24  , Int24   ,
+  SInt30   , UInt30  , Int30   ,
+  SInt32   , UInt32  , Int32   ,
+#ifdef HAS64
+  SInt64   , UInt64  , Int64   ,
+#endif
+  IntTypeCnt
+} IntType;
+
+#ifdef __cplusplus
+# include "cppops.h"
+DefCPPOps_Enum(IntType)
+#endif
+
+#ifdef HAS64
+#define LargeUIntType UInt64
+#define LargeSIntType SInt64
+#define LargeIntType Int64
+#else
+#define LargeUIntType UInt32
+#define LargeSIntType SInt32
+#define LargeIntType Int32
+#endif
+
+typedef struct
+{
+  Word SignAndWidth;
+  LargeWord Mask;
+  LargeInt Min, Max;
+} tIntTypeDef;
+
+typedef enum
+{
+  Float32,
+  Float64,
+  Float80,
+  FloatDec,
+  FloatCo,
+  Float16,
+  FloatTypeCnt
+} FloatType;
+
+typedef enum
+{
+  e_symbol_source_none,
+  e_symbol_source_label,
+  e_symbol_source_define
+} as_symbol_source_t;
+
+typedef struct _TFunction
+{
+  struct _TFunction *Next;
+  Byte ArguCnt;
+  StringPtr Name, Definition;
+} TFunction, *PFunction;
+
+typedef struct sEvalResult
+{
+  Boolean OK;
+  tSymbolFlags Flags;
+  unsigned AddrSpaceMask; /* Welche Adressraeume genutzt ? */
+  tSymbolSize DataSize;
+} tEvalResult;
+
+struct sStrComp;
+struct as_nonz_dynstr;
+struct sRelocEntry;
+struct sSymbolEntry;
+
+extern tIntTypeDef IntTypeDefs[IntTypeCnt];
+extern LongInt MomLocHandle;
+extern LongInt TmpSymCounter,
+               FwdSymCounter,
+               BackSymCounter;
+extern char TmpSymCounterVal[10];
+extern LongInt LocHandleCnt;
+extern LongInt MomLocHandle;
+
+
+extern void AsmParsInit(void);
+
+extern void InitTmpSymbols(void);
+
+extern Boolean SingleBit(LargeInt Inp, LargeInt *Erg);
+
+
+extern IntType GetSmallestUIntType(LargeWord MaxValue);
+
+extern IntType GetUIntTypeByBits(unsigned Bits);
+
+extern LargeInt NonZString2Int(const struct as_nonz_dynstr *p_str);
+
+extern Boolean Int2NonZString(struct as_nonz_dynstr *p_str, LargeInt Src);
+
+extern int TempResultToInt(TempResult *pResult);
+
+extern Boolean MultiCharToInt(TempResult *pResult, unsigned MaxLen);
+
+
+extern Boolean RangeCheck(LargeInt Wert, IntType Typ);
+
+extern Boolean ChkRangeByType(LargeInt value, IntType type, const struct sStrComp *p_comp);
+extern Boolean ChkRangeWarnByType(LargeInt value, IntType type, const struct sStrComp *p_comp);
+
+extern Boolean FloatRangeCheck(Double Wert, FloatType Typ);
+
+
+extern Boolean IdentifySection(const struct sStrComp *pName, LongInt *Erg);
+
+
+extern Boolean ExpandStrSymbol(char *pDest, size_t DestSize, const struct sStrComp *pSrc);
+
+extern void ChangeSymbol(struct sSymbolEntry *pEntry, LargeInt Value);
+
+extern struct sSymbolEntry *EnterIntSymbolWithFlags(const struct sStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange, tSymbolFlags Flags);
+
+#define EnterIntSymbol(pName, Wert, addrspace, MayChange) EnterIntSymbolWithFlags(pName, Wert, addrspace, MayChange, eSymbolFlag_None)
+
+extern void EnterExtSymbol(const struct sStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange);
+
+extern struct sSymbolEntry *EnterRelSymbol(const struct sStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange);
+
+extern void EnterFloatSymbol(const struct sStrComp *pName, Double Wert, Boolean MayChange);
+
+extern void EnterStringSymbol(const struct sStrComp *pName, const char *pValue, Boolean MayChange);
+
+extern void EnterNonZStringSymbolWithFlags(const struct sStrComp *pName, const struct as_nonz_dynstr *p_value, Boolean MayChange, tSymbolFlags Flags);
+
+extern void EnterRegSymbol(const struct sStrComp *pName, const tRegDescr *Value, tSymbolSize Size, Boolean MayChange, Boolean AddList);
+
+#define EnterNonZStringSymbol(pName, pValue, MayChange) EnterNonZStringSymbolWithFlags(pName, pValue, MayChange, eSymbolFlag_None)
+
+extern void LookupSymbol(const struct sStrComp *pName, TempResult *pValue, Boolean WantRelocs, TempType ReqType);
+
+extern void PrintSymbolList(void);
+
+extern void PrintDebSymbols(FILE *f);
+
+extern void PrintNoISymbols(FILE *f);
+
+extern void PrintSymbolTree(void);
+
+extern void ClearSymbolList(void);
+
+extern void ResetSymbolDefines(void);
+
+extern void PrintSymbolDepth(void);
+
+
+extern void EvalResultClear(tEvalResult *pResult);
+
+
+extern void SetSymbolOrStructElemSize(const struct sStrComp *pName, tSymbolSize Size);
+
+extern ShortInt GetSymbolSize(const struct sStrComp *pName);
+
+extern Boolean IsSymbolDefined(const struct sStrComp *pName);
+
+extern Boolean IsSymbolUsed(const struct sStrComp *pName);
+
+extern Boolean IsSymbolChangeable(const struct sStrComp *pName);
+
+extern Integer GetSymbolType(const struct sStrComp *pName);
+
+extern void EvalExpression(const char *pExpr, TempResult *Erg);
+
+extern void EvalStrExpression(const struct sStrComp *pExpr, TempResult *pErg);
+
+extern void SetIntConstModeByMask(LongWord Mask);
+extern void SetIntConstMode(tIntConstMode Mode);
+extern void SetIntConstRelaxedMode(Boolean NewRelaxedMode);
+
+extern LargeInt EvalStrIntExpression(const struct sStrComp *pExpr, IntType Type, Boolean *pResult);
+extern LargeInt EvalStrIntExpressionWithFlags(const struct sStrComp *pExpr, IntType Type, Boolean *pResult, tSymbolFlags *pFlags);
+extern LargeInt EvalStrIntExpressionWithResult(const struct sStrComp *pExpr, IntType Type, struct sEvalResult *pResult);
+extern LargeInt EvalStrIntExpressionOffs(const struct sStrComp *pExpr, int Offset, IntType Type, Boolean *pResult);
+extern LargeInt EvalStrIntExpressionOffsWithFlags(const struct sStrComp *pExpr, int Offset, IntType Type, Boolean *pResult, tSymbolFlags *pFlags);
+extern LargeInt EvalStrIntExpressionOffsWithResult(const struct sStrComp *pExpr, int Offset, IntType Type, struct sEvalResult *pResult);
+
+extern Double EvalStrFloatExpressionWithResult(const struct sStrComp *pExpr, FloatType Typ, struct sEvalResult *pResult);
+extern Double EvalStrFloatExpression(const struct sStrComp *pExpr, FloatType Typ, Boolean *pResult);
+
+extern void EvalStrStringExpressionWithResult(const struct sStrComp *pExpr, struct sEvalResult *pResult, char *pEvalResult);
+extern void EvalStrStringExpression(const struct sStrComp *pExpr, Boolean *pResult, char *pEvalResult);
+
+extern tErrorNum EvalStrRegExpressionWithResult(const struct sStrComp *pExpr, struct sRegDescr *pResult, struct sEvalResult *pEvalResult);
+typedef enum { eIsNoReg, eIsReg, eRegAbort } tRegEvalResult;
+extern tRegEvalResult EvalStrRegExpressionAsOperand(const struct sStrComp *pArg, struct sRegDescr *pResult, struct sEvalResult *pEvalResult, tSymbolSize ReqSize, Boolean MustBeReg);
+
+
+extern Boolean PushSymbol(const struct sStrComp *pSymName, const struct sStrComp *pStackName);
+
+extern Boolean PopSymbol(const struct sStrComp *pSymName, const struct sStrComp *pStackName);
+
+extern void ClearStacks(void);
+
+
+extern void EnterFunction(const struct sStrComp *pComp, char *FDefinition, Byte NewCnt);
+
+extern PFunction FindFunction(const char *Name);
+
+extern void PrintFunctionList(void);
+
+extern void ClearFunctionList(void);
+
+
+extern void AddDefSymbol(char *Name, TempResult *Value);
+
+extern void RemoveDefSymbol(char *Name);
+
+extern void CopyDefSymbols(void);
+
+extern const TempResult *FindDefSymbol(const char *pName);
+
+extern void PrintCrossList(void);
+
+extern void ClearCrossList(void);
+
+
+extern LongInt GetSectionHandle(char *SName_O, Boolean AddEmpt, LongInt Parent);
+
+extern const char *GetSectionName(LongInt Handle);
+
+extern void SetMomSection(LongInt Handle);
+
+extern void AddSectionUsage(LongInt Start, LongInt Length);
+
+extern void ClearSectionUsage(void);
+
+extern void PrintSectionList(void);
+
+extern void PrintDebSections(FILE *f);
+
+extern void ClearSectionList(void);
+
+
+extern void SetFlag(Boolean *Flag, const char *Name, Boolean Wert);
+
+extern LongInt GetLocHandle(void);
+
+extern void PushLocHandle(LongInt NewLoc);
+
+extern void PopLocHandle(void);
+
+extern void ClearLocStack(void);
+
+
+extern void PrintRegDefs(void);
+
+
+extern void ClearCodepages(void);
+
+extern void PrintCodepages(void);
+
+
+extern void asmpars_init(void);
+
+#endif /* _ASMPARS_H */
diff --git a/aslshim/asmrelocs.h b/aslshim/asmrelocs.h
new file mode 100644 (file)
index 0000000..25ba1f7
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _ASMRELOCS_H
+#define _ASMRELOCS_H
+/* asmrelocs.h */
+/****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                    */
+/*                                                                          */
+/* AS-Portierung                                                            */
+/*                                                                          */
+/* Verwaltung von Relokationslisten                                         */
+/*                                                                          */
+/* Historie: 25. 7.1999 Grundsteinlegung                                    */
+/*            8. 8.1999 Reloc-Liste gespeichert                             */
+/*           19. 1.2000 TransferRelocs begonnen                             */
+/*           26. 6.2000 added exports                                       */
+/*                                                                          */
+/****************************************************************************/
+
+struct sRelocEntry
+{
+  struct sRelocEntry *Next;
+  char *Ref;
+  Byte Add;
+};
+typedef struct sRelocEntry TRelocEntry, *PRelocEntry;
+
+
+extern PRelocEntry LastRelocs;
+
+extern PRelocEntry MergeRelocs(PRelocEntry *list1, PRelocEntry *list2,
+                                Boolean Add);
+
+extern void InvertRelocs(PRelocEntry *erg, PRelocEntry *src);
+
+extern void FreeRelocs(PRelocEntry *list);
+
+extern PRelocEntry DupRelocs(PRelocEntry src);
+
+extern void SetRelocs(PRelocEntry List);
+
+extern void TransferRelocs(LargeWord Addr, LongWord Type);
+
+extern void TransferRelocs2(PRelocEntry RelocList, LargeWord Addr, LongWord Type);
+
+extern void SubPCRefReloc(void);
+
+extern void AddExport(char *Name, LargeInt Value, LongWord Flags);
+#endif /* _ASMRELOCS_H */
diff --git a/aslshim/asmstructs.h b/aslshim/asmstructs.h
new file mode 100644 (file)
index 0000000..f5b0abd
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef _ASMSTRUCTS_H
+#define _ASMSTRUCTS_H
+/* asmstructs.h  */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* functions for structure handling                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+#include "symbolsize.h"
+
+struct sStructElem;
+struct sStrComp;
+
+typedef void (*tStructElemExpandFnc)(const struct sStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base);
+
+typedef struct sStructElem
+{
+  struct sStructElem *Next;
+  char *pElemName, *pRefElemName;
+  Boolean IsStruct;
+  tStructElemExpandFnc ExpandFnc;
+  LongInt Offset;
+  ShortInt BitPos; /* -1 -> no bit position */
+  ShortInt BitWidthM1; /* -1 -> no bit field, otherwise actual width minus one */
+  tSymbolSize OpSize;
+} TStructElem, *PStructElem;
+
+typedef struct sStructRec
+{
+  LongInt TotLen;
+  PStructElem Elems;
+  char ExtChar;
+  Boolean DoExt;
+  Boolean IsUnion;
+} TStructRec, *PStructRec;
+
+typedef struct sStructStack
+{
+  struct sStructStack *Next;
+  char *Name, *pBaseName;
+  LargeWord SaveCurrPC, SaveOffsetToInnermost;
+  PStructRec StructRec;
+} TStructStack, *PStructStack;
+
+extern PStructStack StructStack, pInnermostNamedStruct;
+extern int StructSaveSeg;
+
+extern PStructRec CreateStructRec(void);
+
+extern void DestroyStructElem(PStructElem pStructElem);
+
+extern void DestroyStructRec(PStructRec StructRec);
+
+extern void BuildStructName(char *pResult, unsigned ResultLen, const char *pName);
+
+extern PStructElem CreateStructElem(const struct sStrComp *pElemName);
+
+extern PStructElem CloneStructElem(const struct sStrComp *pCloneElemName, const struct sStructElem *pSrc);
+
+extern Boolean AddStructElem(PStructRec pStructRec, PStructElem pElement);
+
+extern void SetStructElemSize(PStructRec pStructRec, const char *pElemName, tSymbolSize Size);
+
+extern void AddStructSymbol(const char *pName, LargeWord Value);
+
+extern void ResolveStructReferences(PStructRec pStructRec);
+
+extern void BumpStructLength(PStructRec StructRec, LongInt Length);
+
+extern void AddStruct(PStructRec StructRec, char *Name, Boolean Protest);
+
+extern Boolean FoundStruct(PStructRec *Erg, const char *pName);
+
+extern void ResetStructDefines(void);
+
+extern void PrintStructList(void);
+
+extern void ClearStructList(void);
+
+extern void ExpandStruct(PStructRec StructRec);
+
+extern void asmstruct_init(void);
+
+#endif /* _ASMSTRUCTS_H */
diff --git a/aslshim/asmsub.c b/aslshim/asmsub.c
new file mode 100644 (file)
index 0000000..bcfc7e8
--- /dev/null
@@ -0,0 +1,1961 @@
+/* asmsub.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Unterfunktionen, vermischtes                                              */
+/*                                                                           */
+/*****************************************************************************/
+
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include "version.h"
+#include "endian.h"
+#include "stdhandl.h"
+#include "console.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "as.rsc"
+#include "strutil.h"
+#include "stringlists.h"
+#include "chunks.h"
+#include "ioerrs.h"
+#include "intformat.h"
+#include "errmsg.h"
+#include "asmdef.h"
+#include "asmpars.h"
+#include "asmdebug.h"
+#include "as.h"
+
+#include "asmsub.h"
+
+
+#ifdef __TURBOC__
+#ifdef __DPMI16__
+#define STKSIZE 35072
+#else
+#define STKSIZE 49152
+#endif
+#endif
+
+#define VALID_S1 1
+#define VALID_SN 2
+#define VALID_M1 4
+#define VALID_MN 8
+
+static StringList CopyrightList, OutList, ShareOutList, ListOutList;
+
+static LongWord StartStack, MinStack, LowStack;
+
+static unsigned ValidSymCharLen;
+static Byte *ValidSymChar;
+
+/****************************************************************************/
+/* Modulinitialisierung */
+
+void AsmSubPassInit(void)
+{
+  PageLength = 60;
+  PageWidth = 0;
+}
+
+/****************************************************************************/
+/* Copyrightlistenverwaltung */
+
+void AddCopyright(const char *NewLine)
+{
+  AddStringListLast(&CopyrightList, NewLine);
+}
+
+void WriteCopyrights(TSwitchProc NxtProc)
+{
+  StringRecPtr Lauf;
+
+  if (!StringListEmpty(CopyrightList))
+  {
+    WrConsoleLine(GetStringListFirst(CopyrightList, &Lauf), True);
+    NxtProc();
+    while (Lauf)
+    {
+      WrConsoleLine(GetStringListNext(&Lauf), True);
+      NxtProc();
+    }
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+/* ermittelt das erste/letzte Auftauchen eines Zeichens ausserhalb */
+/* "geschuetzten" Bereichen */
+
+static char *QuotPosCore(const char *s, int (*SearchFnc)(const char*, const char*), const char *pSearch, tQualifyQuoteFnc QualifyQuoteFnc)
+{
+  register ShortInt Brack = 0, AngBrack = 0;
+  register const char *i;
+  Boolean InSglQuot = False, InDblQuot = False, ThisEscaped = False, NextEscaped = False;
+
+  for (i = s; *i; i++, ThisEscaped = NextEscaped)
+  {
+    NextEscaped = False;
+    if (!SearchFnc(i, pSearch))
+    {
+      if (!AngBrack && !Brack && !InSglQuot && !InDblQuot)
+        return (char*)i;
+    }
+    switch (*i)
+    {
+      case '"':
+        if (!InSglQuot && !ThisEscaped)
+          InDblQuot = !InDblQuot;
+        break;
+      case '\'':
+        if (!InDblQuot && !ThisEscaped)
+        {
+          if (InSglQuot || !QualifyQuoteFnc || QualifyQuoteFnc(s, i))
+            InSglQuot = !InSglQuot;
+        }
+        break;
+      case '\\':
+        if ((InSglQuot || InDblQuot) && !ThisEscaped)
+          NextEscaped = True;
+        break;
+      case '(':
+        if (!AngBrack && !InDblQuot && !InSglQuot)
+          Brack++;
+        break;
+      case ')':
+        if (!AngBrack && !InDblQuot && !InSglQuot)
+          Brack--;
+        break;
+      case '[':
+        if (!Brack && !InDblQuot && !InSglQuot)
+          AngBrack++;
+        break;
+      case ']':
+        if (!Brack && !InDblQuot && !InSglQuot)
+          AngBrack--;
+        break;
+    }
+  }
+
+  return NULL;
+}
+
+static int SearchSingleChar(const char *pPos, const char *pSearch)
+{
+  return ((int)*pSearch) - ((int)*pPos);
+}
+
+static int SearchMultChar(const char *pPos, const char *pSearch)
+{
+  return !strchr(pSearch, *pPos);
+}
+
+static int SearchMultString(const char *pPos, const char *pSearch)
+{
+  int len;
+
+  while (True)
+  {
+    if (!(len = strlen(pSearch)))
+      return 1;
+    if (!strncmp(pPos, pSearch, len))
+      return 0;
+    pSearch += len + 1;
+  }
+}
+
+char *QuotMultPosQualify(const char *s, const char *pSearch, tQualifyQuoteFnc QualifyQuoteFnc)
+{
+  return QuotPosCore(s, SearchMultChar, pSearch, QualifyQuoteFnc);
+}
+
+char *QuotPosQualify(const char *s, char Zeichen, tQualifyQuoteFnc QualifyQuoteFnc)
+{
+  return QuotPosCore(s, SearchSingleChar, &Zeichen, QualifyQuoteFnc);
+}
+
+char *QuotSMultPosQualify(const char *s, const char *pStrs, tQualifyQuoteFnc QualifyQuoteFnc)
+{
+  return QuotPosCore(s, SearchMultString, pStrs, QualifyQuoteFnc);
+}
+
+char *RQuotPos(char *s, char Zeichen)
+{
+  ShortInt Brack = 0, AngBrack = 0;
+  char *i;
+  Boolean Quot = False, Paren = False;
+
+  for (i = s + strlen(s) - 1; i >= s; i--)
+    if (*i == Zeichen)
+    {
+      if ((!AngBrack) && (!Brack) && (!Paren) && (!Quot))
+        return i;
+    }
+    else switch (*i)
+    {
+      case '"':
+        if ((!Brack) && (!AngBrack) && (!Quot))
+          Paren = !Paren;
+        break;
+      case '\'':
+        if ((!Brack) && (!AngBrack) && (!Paren))
+          Quot = !Quot;
+        break;
+      case ')':
+        if ((!AngBrack) && (!Paren) && (!Quot))
+          Brack++;
+        break;
+      case '(':
+        if ((!AngBrack) && (!Paren) && (!Quot))
+          Brack--;
+        break;
+      case ']':
+        if ((!Brack) && (!Paren) && (!Quot))
+          AngBrack++;
+        break;
+      case '[':
+        if ((!Brack) && (!Paren) && (!Quot))
+          AngBrack--;
+        break;
+    }
+
+  return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* ermittelt das erste (nicht-) Leerzeichen in einem String */
+
+char *FirstBlank(const char *s)
+{
+  const char *h, *Min = NULL;
+
+  h = strchr(s, ' ');
+  if (h)
+    if ((!Min) || (h < Min))
+      Min = h;
+  h = strchr(s, Char_HT);
+  if (h)
+    if ((!Min) || (h < Min))
+      Min = h;
+  return (char*)Min;
+}
+
+/*--------------------------------------------------------------------------*/
+/* einen String in zwei Teile zerlegen */
+
+void SplitString(char *Source, char *Left, char *Right, char *Trenner)
+{
+  char Save;
+  LongInt slen = strlen(Source);
+
+  if ((!Trenner) || (Trenner >= Source + slen))
+    Trenner = Source + slen;
+  Save = (*Trenner);
+  *Trenner = '\0';
+  strmov(Left, Source);
+  *Trenner = Save;
+  if (Trenner >= Source + slen)
+    *Right = '\0';
+  else
+    strmov(Right, Trenner + 1);
+}
+
+/*--------------------------------------------------------------------------*/
+/* verbesserte Grossbuchstabenfunktion */
+
+/* einen String in Grossbuchstaben umwandeln.  Dabei Stringkonstanten in Ruhe */
+/* lassen */
+
+void UpString(char *s)
+{
+  char *z;
+  int hypquot = 0;
+  Boolean LastBk = FALSE, ThisBk;
+
+  for (z = s; *z != '\0'; z++)
+  {
+    ThisBk = FALSE;
+    switch (*z)
+    {
+      case '\\':
+        ThisBk = TRUE;
+        break;
+      case '\'':
+        if ((!(hypquot & 2)) && (!LastBk))
+          hypquot ^= 1;
+        break;
+      case '"':
+        if ((!(hypquot & 1)) && (!LastBk))
+          hypquot ^= 2;
+        break;
+      default:
+        if (!hypquot)
+          *z = UpCaseTable[(int)*z];
+    }
+    LastBk = ThisBk;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     MatchChars(const char *pStr, const char *pPattern, ...)
+ * \brief  see if beginning of string matches given pattern
+ * \param  pStr string to check
+ * \param  pPattern expected pattern
+ * \return * to character following match or NULL if no match
+ * ------------------------------------------------------------------------ */
+
+char *MatchChars(const char *pStr, const char *pPattern, ...)
+{
+  va_list ap;
+  char *pResult = NULL;
+
+  va_start(ap, pPattern);
+  for (; *pPattern; pPattern++)
+    switch (*pPattern)
+    {
+      /* single space in pattern matches arbitrary # of spaces in string */
+      case ' ':
+        for (; as_isspace(*pStr); pStr++);
+        break;
+      case '?':
+      {
+        const char *pPatternStr = va_arg(ap, const char*);
+        char *pSave = va_arg(ap, char*);
+
+        if (!strchr(pPatternStr, as_toupper(*pStr)))
+          goto func_exit;
+        if (pSave)
+          *pSave = *pStr;
+        pStr++;
+        break;
+      }
+      default:
+        if (as_toupper(*pStr) != as_toupper(*pPattern))
+          goto func_exit;
+        pStr++;
+    }
+  pResult = (char*)pStr;
+func_exit:
+  va_end(ap);
+  return pResult;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     MatchCharsRev(const char *pStr, const char *pPattern, ...)
+ * \brief  see if end of string matches given pattern
+ * \param  pStr string to check
+ * \param  pPattern expected pattern
+ * \return * to trailing string matching pattern or NULL if no match
+ * ------------------------------------------------------------------------ */
+
+char *MatchCharsRev(const char *pStr, const char *pPattern, ...)
+{
+  va_list ap;
+  char *pResult = NULL;
+  const char *pPatternRun = pPattern + strlen(pPattern) - 1,
+             *pStrRun = pStr + strlen(pStr) - 1;
+
+  va_start(ap, pPattern);
+  for (; pPatternRun >= pPattern; pPatternRun--)
+    switch (*pPatternRun)
+    {
+      /* single space in pattern matches arbitrary # of spaces in string */
+      case ' ':
+        for (; (pStrRun >= pStr) && as_isspace(*pStrRun); pStrRun--);
+        break;
+      case '?':
+      {
+        const char *pPatternStr = va_arg(ap, const char*);
+        char *pSave = va_arg(ap, char*);
+
+        if (!strchr(pPatternStr, as_toupper(*pStrRun)))
+          goto func_exit;
+        if (pSave)
+          *pSave = *pStrRun;
+        pStrRun--;
+        break;
+      }
+      default:
+        if ((pStrRun < pStr) || (as_toupper(*pStrRun) != as_toupper(*pPatternRun)))
+          goto func_exit;
+        pStrRun--;
+    }
+  pResult = (char*)(pStrRun + 1);
+func_exit:
+  va_end(ap);
+  return pResult;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     FindClosingParenthese(const char *pStr)
+ * \brief  find matching closing parenthese
+ * \param  pStr * to string right after opening parenthese
+ * \return * to closing parenthese or NULL
+ * ------------------------------------------------------------------------ */
+
+char *FindClosingParenthese(const char *pStr)
+{
+  int Nest = 1;
+  Boolean InSgl = False, InDbl = False;
+
+  for (; *pStr; pStr++)
+  {
+    switch (*pStr)
+    {
+      case '\'':
+        if (!InDbl) InSgl = !InSgl;
+        break;
+      case '"':
+        if (!InSgl) InDbl = !InDbl;
+        break;
+      case '(':
+        if (!InSgl && !InDbl) Nest++;
+        break;
+      case ')':
+        if (!InSgl && !InDbl) Nest--;
+        if (!Nest)
+          return (char*)pStr;
+        break;
+      default:
+        break;
+    }
+  }
+  return NULL;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     FindOpeningParenthese(const char *pStrBegin, const char *pStrEnd, const char Bracks[2])
+ * \brief  find matching opening parenthese in string
+ * \param  pStrBegin start of string
+ * \param  pStrEnd end of string, preceding closing parenthese in question
+ * \param  Bracks opening & closing parenthese
+ * \return * to opening parenthese or NULL if not found
+ * ------------------------------------------------------------------------ */
+
+char *FindOpeningParenthese(const char *pStrBegin, const char *pStrEnd, const char Bracks[2])
+{
+  int Nest = 1;
+  Boolean InSgl = False, InDbl = False;
+
+  for (; pStrEnd >= pStrBegin; pStrEnd--)
+  {
+    if (*pStrEnd == Bracks[1])
+    {
+      if (!InSgl && !InDbl) Nest++;
+    }
+    else if (*pStrEnd == Bracks[0])
+    {
+      if (!InSgl && !InDbl) Nest--;
+      if (!Nest)
+        return (char*)pStrEnd;
+    }
+    else switch (*pStrEnd)
+    {
+      case '\'':
+        if (!InDbl) InSgl = !InSgl;
+        break;
+      case '"':
+        if (!InSgl) InDbl = !InDbl;
+        break;
+      default:
+        break;
+    }
+  }
+  return NULL;
+}
+
+/****************************************************************************/
+
+void TranslateString(char *s, int Length)
+{
+  char *pRun, *pEnd;
+
+  if (Length < 0)
+    Length = strlen(s);
+  for (pRun = s, pEnd = pRun + Length; pRun < pEnd; pRun++)
+    *pRun = CharTransTable[((usint)(*pRun)) & 0xff];
+}
+
+ShortInt StrCaseCmp(const char *s1, const char *s2, LongInt Hand1, LongInt Hand2)
+{
+  int tmp;
+
+  tmp = as_toupper(*s1) - as_toupper(*s2);
+  if (!tmp)
+    tmp = as_strcasecmp(s1, s2);
+  if (!tmp)
+    tmp = Hand1 - Hand2;
+  if (tmp < 0)
+    return -1;
+  if (tmp > 0)
+    return 1;
+  return 0;
+}
+
+/****************************************************************************/
+/* an einen Dateinamen eine Endung anhaengen */
+
+void AddSuffix(char *s, const char *Suff)
+{
+  char *p, *z, *Part;
+
+  p = NULL;
+  for (z = s; *z != '\0'; z++)
+    if (*z == '\\')
+      p = z;
+  Part = p ? p : s;
+  if (!strchr(Part, '.'))
+    strmaxcat(s, Suff, STRINGSIZE);
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* von einem Dateinamen die Endung loeschen */
+
+void KillSuffix(char *s)
+{
+  char *p, *z, *Part;
+
+  p = NULL;
+  for (z = s; *z != '\0'; z++)
+    if (*z == '\\')
+      p = z;
+  Part = p ? p : s;
+  Part = strchr(Part, '.');
+  if (Part)
+    *Part = '\0';
+}
+
+/*--------------------------------------------------------------------------*/
+/* Pfadanteil (Laufwerk+Verzeichnis) von einem Dateinamen abspalten */
+
+char *PathPart(char *Name)
+{
+  static String s;
+  char *p;
+
+  strmaxcpy(s, Name, STRINGSIZE);
+
+  p = strrchr(Name, PATHSEP);
+#ifdef DRSEP
+  if (!p)
+    p = strrchr(Name, DRSEP);
+#endif
+
+  if (!p)
+    *s = '\0';
+  else
+    s[1] = '\0';
+
+  return s;
+}
+
+/*--------------------------------------------------------------------------*/
+/* Namensanteil von einem Dateinamen abspalten */
+
+const char *NamePart(const char *Name)
+{
+  const char *p = strrchr(Name, PATHSEP);
+
+#ifdef DRSEP
+  if (!p)
+    p = strrchr(Name, DRSEP);
+#endif
+
+  return p ? p + 1 : Name;
+}
+
+/****************************************************************************/
+/* eine Gleitkommazahl in einen String umwandeln */
+
+void FloatString(char *pDest, size_t DestSize, Double f)
+{
+#define MaxLen 18
+  char *p, *d, ExpChar = HexStartCharacter + ('E' - 'A');
+  sint n, ExpVal, nzeroes;
+  Boolean WithE, OK;
+
+  /* 1. mit Maximallaenge wandeln, fuehrendes Vorzeichen weg */
+
+  (void)DestSize;
+  as_snprintf(pDest, DestSize, "%27.15e", f);
+  for (p = pDest; (*p == ' ') || (*p == '+'); p++);
+  if (p != pDest)
+    strmov(pDest, p);
+
+  /* 2. Exponenten soweit als moeglich kuerzen, evtl. ganz streichen */
+
+  p = strchr(pDest, ExpChar);
+  if (!p)
+    return;
+  switch (*(++p))
+  {
+    case '+':
+      strmov(p, p + 1);
+      break;
+    case '-':
+      p++;
+      break;
+  }
+
+  while (*p == '0')
+    strmov(p, p + 1);
+  WithE = (*p != '\0');
+  if (!WithE)
+    pDest[strlen(pDest) - 1] = '\0';
+
+  /* 3. Nullen am Ende der Mantisse entfernen, Komma bleibt noch */
+
+  p = WithE ? strchr(pDest, ExpChar) : pDest + strlen(pDest);
+  p--;
+  while (*p == '0')
+  {
+    strmov(p, p + 1);
+    p--;
+  }
+
+  /* 4. auf die gewuenschte Maximalstellenzahl begrenzen */
+
+  p = WithE ? strchr(pDest, ExpChar) : pDest + strlen(pDest);
+  d = strchr(pDest, '.');
+  n = p - d - 1;
+
+  /* 5. Maximallaenge ueberschritten ? */
+
+  if (strlen(pDest) > MaxLen)
+    strmov(d + (n - (strlen(pDest) - MaxLen)), d + n);
+
+  /* 6. Exponentenwert berechnen */
+
+  if (WithE)
+  {
+    p = strchr(pDest, ExpChar);
+    ExpVal = ConstLongInt(p + 1, &OK, 10);
+  }
+  else
+  {
+    p = pDest + strlen(pDest);
+    ExpVal = 0;
+  }
+
+  /* 7. soviel Platz, dass wir den Exponenten weglassen und evtl. Nullen
+       anhaengen koennen ? */
+
+  if (ExpVal > 0)
+  {
+    nzeroes = ExpVal - (p - strchr(pDest, '.') - 1); /* = Zahl von Nullen, die anzuhaengen waere */
+
+    /* 7a. nur Kommaverschiebung erforderlich. Exponenten loeschen und
+          evtl. auch Komma */
+
+    if (nzeroes <= 0)
+    {
+      *p = '\0';
+      d = strchr(pDest, '.');
+      strmov(d, d + 1);
+      if (nzeroes != 0)
+      {
+        memmove(pDest + strlen(pDest) + nzeroes + 1, pDest + strlen(pDest) + nzeroes, -nzeroes);
+        pDest[strlen(pDest) - 1 + nzeroes] = '.';
+      }
+    }
+
+    /* 7b. Es muessen Nullen angehaengt werden. Schauen, ob nach Loeschen von
+          Punkt und E-Teil genuegend Platz ist */
+
+    else
+    {
+      n = strlen(p) + 1 + (MaxLen - strlen(pDest)); /* = Anzahl freizubekommender Zeichen+Gutschrift */
+      if (n >= nzeroes)
+      {
+        *p = '\0';
+        d = strchr(pDest, '.');
+        strmov(d, d + 1);
+        d = pDest + strlen(pDest);
+        for (n = 0; n < nzeroes; n++)
+          *(d++) = '0';
+        *d = '\0';
+      }
+    }
+  }
+
+  /* 8. soviel Platz, dass Exponent wegkann und die Zahl mit vielen Nullen
+       vorne geschrieben werden kann ? */
+
+  else if (ExpVal < 0)
+  {
+    n = (-ExpVal) - (strlen(p)); /* = Verlaengerung nach Operation */
+    if (strlen(pDest) + n <= MaxLen)
+    {
+      *p = '\0';
+      d = strchr(pDest, '.');
+      strmov(d, d + 1);
+      d = (pDest[0] == '-') ? pDest + 1 : pDest;
+      memmove(d - ExpVal + 1, d, strlen(pDest) + 1);
+      *(d++) = '0';
+      *(d++) = '.';
+      for (n = 0; n < -ExpVal - 1; n++)
+        *(d++) = '0';
+    }
+  }
+
+
+  /* 9. Ueberfluessiges Komma entfernen */
+
+  if (WithE)
+    p = strchr(pDest, ExpChar);
+  else
+    p = pDest + strlen(pDest);
+  if (p && (*(p - 1) == '.'))
+    strmov(p - 1, p);
+}
+
+/****************************************************************************/
+/* Symbol in String wandeln */
+
+void StrSym(const TempResult *t, Boolean WithSystem, as_dynstr_t *p_dest, unsigned Radix)
+{
+  LargeInt IntVal;
+
+  if (p_dest->capacity)
+    p_dest->p_str[0] = '\0';
+  switch (t->Typ)
+  {
+    case TempInt:
+      IntVal = t->Contents.Int;
+    IsInt:
+    {
+      String Buf;
+
+      if (WithSystem)
+      {
+        switch (IntConstMode)
+        {
+          case eIntConstModeMoto:
+            as_sdprcatf(p_dest, "%s", GetIntConstMotoPrefix(Radix));
+            break;
+          case eIntConstModeC:
+            as_sdprcatf(p_dest, "%s", GetIntConstCPrefix(Radix));
+            break;
+          case eIntConstModeIBM:
+            as_sdprcatf(p_dest, "%s", GetIntConstIBMPrefix(Radix));
+            break;
+          default:
+            break;
+        }
+      }
+      SysString(Buf, sizeof(Buf), IntVal, Radix,
+                1, (16 == Radix) && (IntConstMode == eIntConstModeIntel),
+                HexStartCharacter, SplitByteCharacter);
+      as_sdprcatf(p_dest, "%s", Buf);
+      if (WithSystem)
+      {
+        switch (IntConstMode)
+        {
+          case eIntConstModeIntel:
+            as_sdprcatf(p_dest, GetIntConstIntelSuffix(Radix));
+            break;
+          case eIntConstModeIBM:
+            as_sdprcatf(p_dest, GetIntConstIBMSuffix(Radix));
+            break;
+          default:
+            break;
+        }
+      }
+      break;
+    }
+    case TempFloat:
+      FloatString(p_dest->p_str, p_dest->capacity, t->Contents.Float);
+      break;
+    case TempString:
+      as_tempres_append_dynstr(p_dest, t);
+      break;
+    case TempReg:
+      if (t->Contents.RegDescr.Dissect)
+        t->Contents.RegDescr.Dissect(p_dest->p_str, p_dest->capacity, t->Contents.RegDescr.Reg, t->DataSize);
+      else
+      {
+        IntVal = t->Contents.RegDescr.Reg;
+        goto IsInt;
+      }
+      break;
+    default:
+      as_sdprintf(p_dest, "???");
+  }
+}
+
+/****************************************************************************/
+/* Listingzaehler zuruecksetzen */
+
+void ResetPageCounter(void)
+{
+  int z;
+
+  for (z = 0; z <= ChapMax; z++)
+    PageCounter[z] = 0;
+  LstCounter = 0;
+  ChapDepth = 0;
+}
+
+/*--------------------------------------------------------------------------*/
+/* eine neue Seite im Listing beginnen */
+
+void NewPage(ShortInt Level, Boolean WithFF)
+{
+  ShortInt z;
+  String Header, s;
+  char Save;
+
+  if (ListOn == 0)
+    return;
+
+  LstCounter = 0;
+
+  if (ChapDepth < (Byte) Level)
+  {
+    memmove(PageCounter + (Level - ChapDepth), PageCounter, (ChapDepth + 1) * sizeof(Word));
+    for (z = 0; z <= Level - ChapDepth; PageCounter[z++] = 1);
+    ChapDepth = Level;
+  }
+  for (z = 0; z <= Level - 1; PageCounter[z++] = 1);
+  PageCounter[Level]++;
+
+  if ((WithFF) && (!ListToNull))
+  {
+    errno = 0;
+    fprintf(LstFile, "%c", Char_FF);
+    ChkIO(ErrNum_ListWrError);
+  }
+
+  as_snprintf(Header, sizeof(Header), " AS V%s%s%s",
+              Version,
+              getmessage(Num_HeadingFileNameLab),
+              NamePart(SourceFile));
+  if (strcmp(CurrFileName, "INTERNAL")
+   && *CurrFileName
+   && strcmp(NamePart(CurrFileName), NamePart(SourceFile)))
+  {
+    strmaxcat(Header, "(", STRINGSIZE);
+    strmaxcat(Header, NamePart(CurrFileName), STRINGSIZE);
+    strmaxcat(Header, ")", STRINGSIZE);
+  }
+  strmaxcat(Header, getmessage(Num_HeadingPageLab), STRINGSIZE);
+
+  for (z = ChapDepth; z >= 0; z--)
+  {
+    as_snprintf(s, sizeof(s), IntegerFormat, PageCounter[z]);
+    strmaxcat(Header, s, STRINGSIZE);
+    if (z != 0)
+      strmaxcat(Header, ".", STRINGSIZE);
+  }
+
+  strmaxcat(Header, " - ", STRINGSIZE);
+  NLS_CurrDateString(s, sizeof(s));
+  strmaxcat(Header, s, STRINGSIZE);
+  strmaxcat(Header, " ", STRINGSIZE);
+  NLS_CurrTimeString(False, s, sizeof(s));
+  strmaxcat(Header, s, STRINGSIZE);
+
+  if (PageWidth != 0)
+    while (strlen(Header) > PageWidth)
+    {
+      Save = Header[PageWidth];
+      Header[PageWidth] = '\0';
+      if (!ListToNull)
+      {
+        errno = 0;
+        fprintf(LstFile, "%s\n", Header);
+        ChkIO(ErrNum_ListWrError);
+      }
+      Header[PageWidth] = Save;
+      strmov(Header, Header + PageWidth);
+    }
+
+  if (!ListToNull)
+  {
+    errno = 0;
+    fprintf(LstFile, "%s\n", Header);
+    ChkIO(ErrNum_ListWrError);
+
+    if (PrtTitleString[0])
+    {
+      errno = 0;
+      fprintf(LstFile, "%s\n", PrtTitleString);
+      ChkIO(ErrNum_ListWrError);
+    }
+
+    errno = 0;
+    fprintf(LstFile, "\n\n");
+    ChkIO(ErrNum_ListWrError);
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+/* eine Zeile ins Listing schieben */
+
+void WrLstLine(const char *Line)
+{
+  int LLength;
+  char bbuf[2500];
+  String LLine;
+  int blen = 0, hlen, z, Start;
+
+  if ((ListOn == 0) || (ListToNull))
+    return;
+
+  if (PageLength == 0)
+  {
+    errno = 0;
+    fprintf(LstFile, "%s\n", Line);
+    ChkIO(ErrNum_ListWrError);
+  }
+  else
+  {
+    if ((PageWidth == 0) || ((strlen(Line) << 3) < PageWidth))
+      LLength = 1;
+    else
+    {
+      blen = 0;
+      for (z = 0; z < (int)strlen(Line);  z++)
+        if (Line[z] == Char_HT)
+        {
+          memset(bbuf + blen, ' ', 8 - (blen & 7));
+          blen += 8 - (blen&7);
+        }
+        else
+          bbuf[blen++] = Line[z];
+      LLength = blen / PageWidth;
+      if (blen % PageWidth)
+        LLength++;
+    }
+    if (LLength == 1)
+    {
+      errno = 0;
+      fprintf(LstFile, "%s\n", Line);
+      ChkIO(ErrNum_ListWrError);
+      if ((++LstCounter) == PageLength)
+        NewPage(0, True);
+    }
+    else
+    {
+      Start = 0;
+      for (z = 1; z <= LLength; z++)
+      {
+        hlen = PageWidth;
+        if (blen - Start < hlen)
+          hlen = blen - Start;
+        memcpy(LLine, bbuf + Start, hlen);
+        LLine[hlen] = '\0';
+        errno = 0;
+        fprintf(LstFile, "%s\n", LLine);
+        if ((++LstCounter) == PageLength)
+          NewPage(0, True);
+        Start += hlen;
+      }
+    }
+  }
+}
+
+/*****************************************************************************/
+/* Ausdruck in Spalte vor Listing */
+
+void SetListLineVal(TempResult *t)
+{
+  as_dynstr_t str;
+
+  as_dynstr_ini(&str, STRINGSIZE);
+  StrSym(t, True, &str, ListRadixBase);
+  as_snprintf(ListLine, STRINGSIZE, "=%s", str.p_str);
+  LimitListLine();
+  as_dynstr_free(&str);
+}
+
+void LimitListLine(void)
+{
+  if (strlen(ListLine) + 1 > LISTLINESPACE)
+  {
+    ListLine[LISTLINESPACE - 4] = '\0';
+    strmaxcat(ListLine, "..", STRINGSIZE);
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     PrintOneLineMuted(FILE *pFile, const char *pLine,
+                             const struct sLineComp *pMuteComponent,
+                             const struct sLineComp *pMuteComponent2)
+ * \brief  print a line, with a certain component muted out (i.e. replaced by spaces)
+ * \param  pFile where to write
+ * \param  pLine line to print
+ * \param  pMuteComponent component to mute in printout
+ * ------------------------------------------------------------------------ */
+
+static Boolean CompMatch(int Col, const struct sLineComp *pComp)
+{
+  return (pComp
+       && (pComp->StartCol >= 0)
+       && (Col >= pComp->StartCol)
+       && (Col < pComp->StartCol + (int)pComp->Len));
+}
+
+void PrintOneLineMuted(FILE *pFile, const char *pLine,
+                       const struct sLineComp *pMuteComponent,
+                       const struct sLineComp *pMuteComponent2)
+{
+  int z, Len = strlen(pLine);
+  Boolean Match;
+
+  errno = 0;
+  for (z = 0; z < Len; z++)
+  {
+    Match = CompMatch(z, pMuteComponent) || CompMatch(z, pMuteComponent2);
+    fputc(Match ? ' ' : pLine[z], pFile);
+  }
+  fputc('\n', pFile);
+  ChkIO(ErrNum_ListWrError);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     PrLineMarker(FILE *pFile, const char *pLine, const char *pPrefix, const char *pTrailer,
+                        char Marker, const struct sLineComp *pLineComp)
+ * \brief  print a line, optionally with a marking of a component below
+ * \param  pFile where to write
+ * \param  pLine line to print/underline
+ * \param  pPrefix what to print before (under)line
+ * \param  pTrailer what to print after (under)line
+ * \param  Marker character to use for marking
+ * \param  pLineComp position and length of optional marker
+ * ------------------------------------------------------------------------ */
+
+void PrLineMarker(FILE *pFile, const char *pLine, const char *pPrefix, const char *pTrailer,
+                  char Marker, const struct sLineComp *pLineComp)
+{
+  const char *pRun;
+  int z;
+
+  fputs(pPrefix, pFile);
+  for (pRun = pLine; *pRun; pRun++)
+    fputc(TabCompressed(*pRun), pFile);
+  fprintf(pFile, "%s\n", pTrailer);
+
+  if (pLineComp && (pLineComp->StartCol >= 0) && (pLineComp->Len > 0))
+  {
+    fputs(pPrefix, pFile);
+    if (pLineComp->StartCol > 0)
+      fprintf(pFile, "%*s", pLineComp->StartCol, "");
+    for (z = 0; z < (int)pLineComp->Len; z++)
+      fputc(Marker, pFile);
+    fprintf(pFile, "%s\n", pTrailer);
+  }
+}
+
+/****************************************************************************/
+/* einen Symbolnamen auf Gueltigkeit ueberpruefen */
+
+static Byte GetValidSymChar(unsigned Ch)
+{
+  return (Ch < ValidSymCharLen) ? ValidSymChar[Ch] : 0;
+}
+
+static char *ChkNameUpTo(const char *pSym, const char *pUpTo, Byte _Mask)
+{
+  Byte Mask = _Mask;
+  unsigned Ch;
+  const char *pPrev;
+
+  if (!*pSym)
+    return (char*)pSym;
+
+  while (*pSym && (pSym != pUpTo))
+  {
+    pPrev = pSym;
+    if (ValidSymCharLen > 256)
+      Ch = UTF8ToUnicode(&pSym);
+    else
+      Ch = ((unsigned int)*pSym++) & 0xff;
+
+    if (!(GetValidSymChar(Ch) & Mask))
+      return (char*)pPrev;
+    Mask = _Mask << 1;
+  }
+  return (char*)pSym;
+}
+
+char *ChkSymbNameUpTo(const char *pSym, const char *pUpTo)
+{
+  char *pResult = ChkNameUpTo(pSym, pUpTo, VALID_S1);
+
+  /* If NULL as UpTo was given, and all is fine up to end of string,
+     also return NULL as result.  So Equation 'Result==UpTo' is fulfilled: */
+
+  if (!pUpTo && !*pResult)
+     pResult= NULL;
+  return pResult;
+}
+
+Boolean ChkSymbName(const char *pSym)
+{
+  const char *pEnd = ChkSymbNameUpTo(pSym, NULL);
+  return *pSym && !pEnd;
+}
+
+char *ChkMacSymbNameUpTo(const char *pSym, const char *pUpTo)
+{
+  char *pResult = ChkNameUpTo(pSym, pUpTo, VALID_M1);
+
+  /* If NULL as UpTo was given, and all is fine up to end of string,
+     also return NULL as result.  So Equation 'Result==UpTo' is fulfilled: */
+
+  if (!pUpTo && !*pResult)
+     pResult= NULL;
+  return pResult;
+}
+
+Boolean ChkMacSymbName(const char *pSym)
+{
+  const char *pEnd = ChkMacSymbNameUpTo(pSym, NULL);
+  return *pSym && !pEnd;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     visible_strlen(const char *pSym)
+ * \brief  retrieve 'visible' length of string, regarding multi-by sequences for UTF-8
+ * \param  pSym symbol name
+ * \return visible length in characters
+ * ------------------------------------------------------------------------ */
+
+unsigned visible_strlen(const char *pSym)
+{
+  if (ValidSymCharLen > 256)
+  {
+    unsigned Result = 0;
+
+    while (*pSym)
+    {
+      (void)UTF8ToUnicode(&pSym);
+      Result++;
+    }
+    return Result;
+  }
+  else
+    return strlen(pSym);
+}
+
+/****************************************************************************/
+
+LargeWord ProgCounter(void)
+{
+  return PCs[ActPC];
+}
+
+/*--------------------------------------------------------------------------*/
+/* aktuellen Programmzaehler mit Phasenverschiebung holen */
+
+LargeWord EProgCounter(void)
+{
+  return PCs[ActPC] + Phases[ActPC];
+}
+
+/*--------------------------------------------------------------------------*/
+/* Granularitaet des aktuellen Segments holen */
+
+Word Granularity(void)
+{
+  return Grans[ActPC];
+}
+
+/*--------------------------------------------------------------------------*/
+/* Linstingbreite des aktuellen Segments holen */
+
+Word ListGran(void)
+{
+  return ListGrans[ActPC];
+}
+
+/*--------------------------------------------------------------------------*/
+/* pruefen, ob alle Symbole einer Formel im korrekten Adressraum lagen */
+
+void ChkSpace(Byte AddrSpace, unsigned AddrSpaceMask)
+{
+  AddrSpaceMask &= ~(1 << AddrSpace);
+
+  if (AddrSpaceMask) WrError(ErrNum_WrongSegment);
+}
+
+/****************************************************************************/
+/* eine Chunkliste im Listing ausgeben & Speicher loeschen */
+
+void PrintChunk(ChunkList *NChunk, DissectBitProc Dissect, int ItemsPerLine)
+{
+  LargeWord NewMin, FMin;
+  Boolean Found;
+  Word p = 0, z;
+  int BufferZ;
+  String BufferS;
+  int MaxItemLen = 79 / ItemsPerLine;
+
+  NewMin = 0;
+  BufferZ = 0;
+  *BufferS = '\0';
+
+  do
+  {
+    /* niedrigsten Start finden, der ueberhalb des letzten Endes liegt */
+
+    Found = False;
+    FMin = IntTypeDefs[LargeUIntType].Max;
+    for (z = 0; z < NChunk->RealLen; z++)
+      if (NChunk->Chunks[z].Start >= NewMin)
+        if (FMin > NChunk->Chunks[z].Start)
+        {
+          Found = True;
+          FMin = NChunk->Chunks[z].Start;
+          p = z;
+        }
+
+    if (Found)
+    {
+      char Num[30];
+
+      Dissect(Num, sizeof(Num), NChunk->Chunks[p].Start);
+      strmaxcat(BufferS, Num, STRINGSIZE);
+      if (NChunk->Chunks[p].Length != 1)
+      {
+        strmaxcat(BufferS, "-", STRINGSIZE);
+        Dissect(Num, sizeof(Num), NChunk->Chunks[p].Start + NChunk->Chunks[p].Length - 1);
+        strmaxcat(BufferS, Num, STRINGSIZE);
+      }
+      strmaxcat(BufferS, Blanks(MaxItemLen - strlen(BufferS) % MaxItemLen), STRINGSIZE);
+      if (++BufferZ == ItemsPerLine)
+      {
+        WrLstLine(BufferS);
+        *BufferS = '\0';
+        BufferZ = 0;
+      }
+      NewMin = NChunk->Chunks[p].Start + NChunk->Chunks[p].Length;
+    }
+  }
+  while (Found);
+
+  if (BufferZ != 0)
+    WrLstLine(BufferS);
+}
+
+/*--------------------------------------------------------------------------*/
+/* Listen ausgeben */
+
+void PrintUseList(void)
+{
+  int z, z2, l;
+  String s;
+
+  for (z = 1; z < SegCount; z++)
+    if (SegChunks[z].Chunks)
+    {
+      as_snprintf(s, sizeof(s), "  %s%s%s",
+                  getmessage(Num_ListSegListHead1), SegNames[z],
+                  getmessage(Num_ListSegListHead2));
+      WrLstLine(s);
+      strcpy(s, "  ");
+      l = strlen(SegNames[z]) + strlen(getmessage(Num_ListSegListHead1)) + strlen(getmessage(Num_ListSegListHead2));
+      for (z2 = 0; z2 < l; z2++)
+        strmaxcat(s, "-", STRINGSIZE);
+      WrLstLine(s);
+      WrLstLine("");
+      PrintChunk(SegChunks + z,
+                 (z == SegBData) ? DissectBit : Default_DissectBit,
+                 (z == SegBData) ? 3 : 4);
+      WrLstLine("");
+    }
+}
+
+void ClearUseList(void)
+{
+  int z;
+
+  for (z = 1; z < SegCount; z++)
+    ClearChunk(SegChunks + z);
+}
+
+/****************************************************************************/
+/* Include-Pfadlistenverarbeitung */
+
+static char *GetPath(char *Acc)
+{
+  char *p;
+  static String tmp;
+
+  p = strchr(Acc, DIRSEP);
+  if (!p)
+  {
+    strmaxcpy(tmp, Acc, STRINGSIZE);
+    Acc[0] = '\0';
+  }
+  else
+  {
+    *p = '\0';
+    strmaxcpy(tmp, Acc, STRINGSIZE);
+    strmov(Acc, p + 1);
+  }
+  return tmp;
+}
+
+void AddIncludeList(char *NewPath)
+{
+  String Test;
+
+  strmaxcpy(Test, IncludeList, STRINGSIZE);
+  while (*Test != '\0')
+    if (!strcmp(GetPath(Test), NewPath))
+      return;
+  if (*IncludeList != '\0')
+    strmaxprep(IncludeList, SDIRSEP, STRINGSIZE);
+  strmaxprep(IncludeList, NewPath, STRINGSIZE);
+}
+
+
+void RemoveIncludeList(char *RemPath)
+{
+  String Save;
+  char *Part;
+
+  strmaxcpy(IncludeList, Save, STRINGSIZE);
+  IncludeList[0] = '\0';
+  while (Save[0] != '\0')
+  {
+    Part = GetPath(Save);
+    if (strcmp(Part, RemPath))
+    {
+      if (IncludeList[0] != '\0')
+        strmaxcat(IncludeList, SDIRSEP, STRINGSIZE);
+      strmaxcat(IncludeList, Part, STRINGSIZE);
+    }
+  }
+}
+
+/****************************************************************************/
+/* Listen mit Ausgabedateien */
+
+void ClearOutList(void)
+{
+  ClearStringList(&OutList);
+}
+
+void AddToOutList(const char *NewName)
+{
+  AddStringListLast(&OutList, NewName);
+}
+
+void RemoveFromOutList(const char *OldName)
+{
+  RemoveStringList(&OutList, OldName);
+}
+
+char *GetFromOutList(void)
+{
+  return GetAndCutStringList(&OutList);
+}
+
+void ClearShareOutList(void)
+{
+  ClearStringList(&ShareOutList);
+}
+
+void AddToShareOutList(const char *NewName)
+{
+  AddStringListLast(&ShareOutList, NewName);
+}
+
+void RemoveFromShareOutList(const char *OldName)
+{
+  RemoveStringList(&ShareOutList, OldName);
+}
+
+char *GetFromShareOutList(void)
+{
+  return GetAndCutStringList(&ShareOutList);
+}
+
+void ClearListOutList(void)
+{
+  ClearStringList(&ListOutList);
+}
+
+void AddToListOutList(const char *NewName)
+{
+  AddStringListLast(&ListOutList, NewName);
+}
+
+void RemoveFromListOutList(const char *OldName)
+{
+  RemoveStringList(&ListOutList, OldName);
+}
+
+char *GetFromListOutList(void)
+{
+  return GetAndCutStringList(&ListOutList);
+}
+
+/****************************************************************************/
+/* Tokenverarbeitung */
+
+static Boolean CompressLine_NErl(char ch)
+{
+  return (((ch >= 'A') && (ch <= 'Z'))
+       || ((ch >= 'a') && (ch <= 'z'))
+       || ((ch >= '0') && (ch <= '9')));
+}
+
+typedef int (*tCompareFnc)(const char *s1, const char *s2, size_t n);
+
+int ReplaceLine(as_dynstr_t *p_str, const char *pSearch, const char *pReplace, Boolean CaseSensitive)
+{
+  int SearchLen = strlen(pSearch), ReplaceLen = strlen(pReplace), StrLen = strlen(p_str->p_str), DeltaLen = ReplaceLen - SearchLen;
+  int NumReplace = 0, Pos, End, CmpRes, Avail, nCopy, nMove;
+  tCompareFnc Compare = CaseSensitive ? strncmp : as_strncasecmp;
+
+  Pos = 0;
+  while (Pos <= StrLen - SearchLen)
+  {
+    End = Pos + SearchLen;
+    CmpRes = Compare(&p_str->p_str[Pos], pSearch, SearchLen);
+    if ((!CmpRes)
+     && ((Pos == 0) || (!CompressLine_NErl(p_str->p_str[Pos - 1])))
+     && ((End >= StrLen) || (!CompressLine_NErl(p_str->p_str[End]))))
+    {
+      if (StrLen + DeltaLen + 1 > (int)p_str->capacity)
+        as_dynstr_realloc(p_str, as_dynstr_roundup_len(p_str->capacity + DeltaLen));
+      Avail = p_str->capacity - 1 - Pos;
+      nCopy = ReplaceLen; if (nCopy > Avail) nCopy = Avail;
+      Avail -= nCopy;
+      nMove = StrLen - (Pos + SearchLen); if (nMove > Avail) nMove = Avail;
+      memmove(&p_str->p_str[Pos + nCopy], &p_str->p_str[Pos + SearchLen], nMove);
+      memcpy(&p_str->p_str[Pos], pReplace, nCopy);
+      p_str->p_str[Pos + nCopy + nMove] = '\0';
+      Pos += nCopy;
+      StrLen += DeltaLen;
+      NumReplace++;
+    }
+    else
+      Pos++;
+  }
+  return NumReplace;
+}
+
+static void SetToken(char *Token, unsigned TokenNum)
+{
+  Token[0] = (TokenNum >> 4) + 1;
+  Token[1] = (TokenNum & 15) + 1;
+  Token[2] = 0;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     CompressLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str, Boolean ThisCaseSensitive)
+ * \brief  compress tokens in line
+ * \param  TokNam name to compress into token
+ * \param  TokenNum token #
+ * \param  p_str string to work on
+ * \param  ThisCaseSensitive operate case sensitive?
+ * ------------------------------------------------------------------------ */
+
+int CompressLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str, Boolean ThisCaseSensitive)
+{
+  char Token[3];
+  SetToken(Token, TokenNum);
+  return ReplaceLine(p_str, TokNam, Token, ThisCaseSensitive);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ExpandLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str)
+ * \brief  expand tokens in line
+ * \param  TokNam name to expand token to
+ * \param  TokenNum token #
+ * \param  p_str string to work on
+ * ------------------------------------------------------------------------ */
+
+void ExpandLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str)
+{
+  char Token[3];
+  SetToken(Token, TokenNum);
+  (void)ReplaceLine(p_str, Token, TokNam, True);
+}
+
+void KillCtrl(char *Line)
+{
+  char *z;
+
+  if (*(z = Line) == '\0')
+    return;
+  do
+  {
+    if (*z == '\0');
+    else if (*z == Char_HT)
+    {
+      strmov(z, z + 1);
+      strprep(z, Blanks(8 - ((z - Line) % 8)));
+    }
+    else if ((*z & 0xe0) == 0)
+      *z = ' ';
+    z++;
+  }
+  while (*z != '\0');
+}
+
+/****************************************************************************/
+/* Buchhaltung */
+
+void BookKeeping(void)
+{
+  if (MakeUseList)
+    if (AddChunk(SegChunks + ActPC, ProgCounter(), CodeLen, ActPC == SegCode))
+      WrError(ErrNum_Overlap);
+  if (DebugMode != DebugNone)
+  {
+    AddSectionUsage(ProgCounter(), CodeLen);
+    AddLineInfo(InMacroFlag, CurrLine, CurrFileName, ActPC, PCs[ActPC], CodeLen);
+  }
+}
+
+/****************************************************************************/
+/* Differenz zwischen zwei Zeiten mit Tagesueberlauf berechnen */
+
+long DTime(long t1, long t2)
+{
+  LongInt d;
+
+  d = t2 - t1;
+  if (d < 0) d += (24*360000);
+  return (d > 0) ? d : -d;
+}
+
+/*--------------------------------------------------------------------------*/
+/* Init/Deinit passes */
+
+typedef struct sProcStore
+{
+  struct sProcStore *pNext;
+  SimpProc Proc;
+} tProcStore;
+
+static tProcStore *pInitPassProcStore = NULL,
+                  *pClearUpProcStore = NULL;
+
+void InitPass(void)
+{
+  tProcStore *pStore;
+
+  for (pStore = pInitPassProcStore; pStore; pStore = pStore->pNext)
+    pStore->Proc();
+}
+
+void ClearUp(void)
+{
+  tProcStore *pStore;
+
+  for (pStore = pClearUpProcStore; pStore; pStore = pStore->pNext)
+    pStore->Proc();
+}
+
+void AddInitPassProc(SimpProc NewProc)
+{
+  tProcStore *pNewStore = (tProcStore*)calloc(1, sizeof(*pNewStore));
+
+  pNewStore->pNext = pInitPassProcStore;
+  pNewStore->Proc = NewProc;
+  pInitPassProcStore = pNewStore;
+}
+
+void AddClearUpProc(SimpProc NewProc)
+{
+  tProcStore *pNewStore = (tProcStore*)calloc(1, sizeof(*pNewStore));
+
+  pNewStore->pNext = pClearUpProcStore;
+  pNewStore->Proc = NewProc;
+  pClearUpProcStore = pNewStore;
+}
+
+/*--------------------------------------------------------------------------*/
+/* Zeit holen */
+
+#ifdef __MSDOS__
+
+#include <dos.h>
+
+long GTime(void)
+{
+  struct time tbuf;
+  long result;
+
+  gettime(&tbuf);
+  result = tbuf.ti_hour;
+  result = (result * 60) + tbuf.ti_min;
+  result = (result * 60) + tbuf.ti_sec;
+  result = (result * 100) + tbuf.ti_hund;
+  return result;
+}
+
+#elif __IBMC__
+
+#include <time.h>
+#define INCL_DOSDATETIME
+#include <os2.h>
+
+long GTime(void)
+{
+  DATETIME dt;
+  struct tm ts;
+  DosGetDateTime(&dt);
+  memset(&ts, 0, sizeof(ts));
+  ts.tm_year = dt.year - 1900;
+  ts.tm_mon  = dt.month - 1;
+  ts.tm_mday = dt.day;
+  ts.tm_hour = dt.hours;
+  ts.tm_min  = dt.minutes;
+  ts.tm_sec  = dt.seconds;
+  return (mktime(&ts) * 100) + (dt.hundredths);
+}
+
+#elif __MINGW32__
+
+/* distribution by Gunnar Wallmann */
+
+#include <sys/time.h>
+#include "math64.h"
+
+/*time from 1 Jan 1601 to 1 Jan 1970 in 100ns units */
+
+typedef struct _FILETIME
+{
+  unsigned long dwLowDateTime;
+  unsigned long dwHighDateTime;
+} FILETIME;
+
+void __stdcall GetSystemTimeAsFileTime(FILETIME*);
+
+long GTime(void)
+{
+  union
+  {
+#ifndef NOLONGLONG
+    long long ns100; /*time since 1 Jan 1601 in 100ns units */
+#endif
+    FILETIME ft;
+  } _now;
+
+  GetSystemTimeAsFileTime(&(_now.ft));
+#ifdef NOLONGLONG
+  {
+    static const t64 offs = { 0xd53e8000, 0x019db1de },
+                     div = { 100000, 0 };
+    t64 acc;
+
+    acc.low = _now.ft.dwLowDateTime;
+    acc.high = _now.ft.dwHighDateTime;
+    sub64(&acc, &acc, &offs);
+    div64(&acc, &acc, &div);
+    return acc.low;
+  }
+#else
+# define _W32_FT_OFFSET (116444736000000000LL)
+  return (_now.ns100 - _W32_FT_OFFSET) / 100000LL;
+#endif
+}
+
+#else
+
+#include <sys/time.h>
+
+long GTime(void)
+{
+  struct timeval tv;
+
+  gettimeofday(&tv, NULL);
+  return (tv.tv_sec*100) + (tv.tv_usec/10000);
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Stackfehler abfangen - bis auf DOS nur Dummies */
+
+#ifdef __TURBOC__
+
+#ifdef __DPMI16__
+#else
+unsigned _stklen = STKSIZE;
+unsigned _ovrbuffer = 64*48;
+#endif
+#include <malloc.h>
+
+void ChkStack(void)
+{
+  LongWord avail = stackavail();
+  if (avail < MinStack)
+    WrError(ErrNum_StackOvfl);
+  if (avail < LowStack)
+    LowStack = avail;
+}
+
+void ResetStack(void)
+{
+  LowStack = stackavail();
+}
+
+LongWord StackRes(void)
+{
+  return LowStack - MinStack;
+}
+#endif /* __TURBOC__ */
+
+#ifdef CKMALLOC
+#undef malloc
+#undef realloc
+
+void *ckmalloc(size_t s)
+{
+  void *tmp;
+
+#ifdef __TURBOC__
+  if (coreleft() < HEAPRESERVE + s)
+    WrError(ErrNum_HeapOvfl);
+#endif
+
+  tmp = malloc(s);
+  if (!tmp && (s > 0))
+    WrError(ErrNum_HeapOvfl);
+  return tmp;
+}
+
+void *ckrealloc(void *p, size_t s)
+{
+  void *tmp;
+
+#ifdef __TURBOC__
+  if (coreleft() < HEAPRESERVE + s)
+    WrError(ErrNum_HeapOvfl);
+#endif
+
+  tmp = realloc(p, s);
+  if (!tmp)
+    WrError(ErrNum_HeapOvfl);
+  return tmp;
+}
+#endif
+
+static void SetValidSymChar(unsigned Ch, Byte Value)
+{
+  ValidSymChar[Ch] = Value;
+}
+
+static void SetValidSymChars(unsigned Start, unsigned Stop, Byte Value)
+{
+  for (; Start <= Stop; Start++)
+    SetValidSymChar(Start, Value);
+}
+
+void asmsub_init(void)
+{
+#ifdef __TURBOC__
+#ifdef __MSDOS__
+#ifdef __DPMI16__
+  char *MemFlag, *p;
+  String MemVal, TempName;
+  unsigned long FileLen;
+#else
+  char *envval;
+  int ovrerg;
+#endif
+#endif
+#endif
+
+  InitStringList(&CopyrightList);
+  InitStringList(&OutList);
+  InitStringList(&ShareOutList);
+  InitStringList(&ListOutList);
+
+#ifdef __TURBOC__
+#ifdef __MSDOS__
+#ifdef __DPMI16__
+  /* Fuer DPMI evtl. Swapfile anlegen */
+
+  MemFlag = getenv("ASXSWAP");
+  if (MemFlag)
+  {
+    strmaxcpy(MemVal, MemFlag, STRINGSIZE);
+    p = strchr(MemVal, ',');
+    if (!p)
+      strcpy(TempName, "ASX.TMP");
+    else
+    {
+      *p = NULL;
+      strcpy(TempName, MemVal);
+      strmov(MemVal, p + 1);
+    };
+    KillBlanks(TempName);
+    KillBlanks(MemVal);
+    FileLen = strtol(MemFlag, &p, 0);
+    if (*p != '\0')
+    {
+      fputs(getmessage(Num_ErrMsgInvSwapSize), stderr);
+      exit(4);
+    }
+    if (MEMinitSwapFile(TempName, FileLen << 20) != RTM_OK)
+    {
+      fputs(getmessage(Num_ErrMsgSwapTooBig), stderr);
+      exit(4);
+    }
+  }
+#else
+  /* Bei DOS Auslagerung Overlays in XMS/EMS versuchen */
+
+  envval = getenv("USEXMS");
+  if ((envval) && (as_toupper(*envval) == 'N'))
+    ovrerg = -1;
+  else
+    ovrerg = _OvrInitExt(0, 0);
+  if (ovrerg != 0)
+  {
+    envval = getenv("USEEMS");
+    if ((!envval) || (as_toupper(*envval) != 'N'))
+      _OvrInitEms(0, 0, 0);
+  }
+#endif
+#endif
+#endif
+
+#ifdef __TURBOC__
+  StartStack = stackavail();
+  LowStack = stackavail();
+  MinStack = StartStack - STKSIZE + 0x800;
+#else
+  StartStack = LowStack = MinStack = 0;
+#endif
+
+  /* initialize array of valid characters */
+
+  ValidSymCharLen = (NLS_GetCodepage() == eCodepageUTF8) ? 1280 : 256;
+  ValidSymChar = (Byte*) calloc(ValidSymCharLen, sizeof(Byte));
+
+  /* The basic ASCII stuff: letters, dot and underbar are allowed
+     anwhere, numbers not at beginning: */
+
+  SetValidSymChars('a', 'z', VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+  SetValidSymChars('A', 'Z', VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+  SetValidSymChars('0', '9',            VALID_SN |            VALID_MN);
+  SetValidSymChar ('.'     , VALID_S1 | VALID_SN                      );
+  SetValidSymChar ('_'     , VALID_S1 | VALID_SN                      );
+
+  /* Extensions, depending on character set: */
+
+  switch (NLS_GetCodepage())
+  {
+    case eCodepage1251:
+      SetValidSymChar (0xa3      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xb3      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xa8      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xb8      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xaa      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xba      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xaf      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xbf      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xbd      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xbe      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      goto iso8859_1;
+    case eCodepage1252:
+      SetValidSymChar (0x8a      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0x9a      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0x8c      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0x9c      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0x8e      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0x9e      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0x9f      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      goto iso8859_1;
+    case eCodepage850:
+      SetValidSymChars(0xb5, 0xb7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChars(0xc6, 0xc7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChars(0xd0, 0xd9, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xde      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChars(0xe0, 0xed, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      /* fall-through */
+    case eCodepage437:
+      SetValidSymChars(128, 165, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (225     , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      break;
+    case eCodepage866:
+      SetValidSymChars(0x80, 0xaf, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChars(0xe0, 0xf7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      break;
+    case eCodepageISO8859_15:
+      SetValidSymChar (0xa6      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xa8      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xb4      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xb8      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xbc      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xbd      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xbe      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      /* fall-through */
+    case eCodepageISO8859_1:
+    iso8859_1:
+      SetValidSymChar (0xa1      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xa2      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChars(0xc0, 0xff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      break;
+    case eCodepageKOI8_R:
+      SetValidSymChar (0xa3      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (0xb3      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChars(0xc0, 0xff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      break;
+    case eCodepageUTF8:
+    {
+      const tNLSCharacterTab *pTab = GetCharacterTab(eCodepageUTF8);
+      tNLSCharacter ch;
+      unsigned Unicode;
+      const char *pCh;
+
+      for (ch = (tNLSCharacter)0; ch < eCH_cnt; ch++)
+      {
+        if ((ch == eCH_e2) || (ch == eCH_mu) || (ch == eCH_iquest) || (ch == eCH_iexcl))
+          continue;
+        pCh = &((*pTab)[ch][0]);
+        Unicode = UTF8ToUnicode(&pCh);
+        if (Unicode < ValidSymCharLen)
+          SetValidSymChar (Unicode, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      }
+
+      /* Greek */
+
+      SetValidSymChar ( 895      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar ( 902      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (1011      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (1016      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (1018      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChar (1019      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChars( 904,  974, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChars( 984, 1007, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+
+      /* Cyrillic */
+
+      SetValidSymChars(0x400, 0x481, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+      SetValidSymChars(0x48a, 0x4ff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
+    }
+    default:
+      break;
+  }
+
+#if 0
+  for (z = 0; z < ValidSymCharLen; z++)
+  {
+    if (!(z & 15))
+      fprintf(stderr, "%02x:", z);
+    fprintf(stderr, " %x", ValidSymChar[z]);
+    if ((z & 15) == 15)
+      fprintf(stderr, "\n");
+  }
+#endif
+
+  version_init();
+}
diff --git a/aslshim/asmsub.h b/aslshim/asmsub.h
new file mode 100644 (file)
index 0000000..53eb246
--- /dev/null
@@ -0,0 +1,198 @@
+#ifndef _ASMSUB_H
+#define _ASMSUB_H
+/* asmsub.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Unterfunktionen, vermischtes                                              */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stddef.h>
+
+#define LISTLINESPACE 20
+
+struct sLineComp;
+struct sStrComp;
+struct as_dynstr;
+
+typedef void (*TSwitchProc)(
+#ifdef __PROTOS__
+void
+#endif
+);
+
+
+extern void AsmSubPassInit(void);
+
+
+extern long GTime(void);
+
+
+extern void UpString(char *s);
+
+extern char *QuotPosQualify(const char *s, char Zeichen, tQualifyQuoteFnc QualifyQuoteFnc);
+#define QuotPos(s, Zeichen) QuotPosQualify(s, Zeichen, NULL)
+extern char *QuotMultPosQualify(const char *s, const char *pSearch, tQualifyQuoteFnc QualifyQuoteFnc);
+#define QuotMultPos(s, pSearch) QuotMultPosQualify(s, pSearch, NULL)
+extern char *QuotSMultPosQualify(const char *s, const char *pStrs, tQualifyQuoteFnc QualifyQuoteFnc);
+#define QuotSMultPos(s, pStrs) QuotSMultPosQualify(s, pStrs, NULL)
+
+extern char *RQuotPos(char *s, char Zeichen);
+
+extern char *FirstBlank(const char *s);
+
+extern void SplitString(char *Source, char *Left, char *Right, char *Trenner);
+
+extern void TranslateString(char *s, int Length);
+
+extern ShortInt StrCaseCmp(const char *s1, const char *s2, LongInt Hand1, LongInt Hand2);
+
+extern char *MatchChars(const char *pStr, const char *pPattern, ...);
+extern char *MatchCharsRev(const char *pStr, const char *pPattern, ...);
+
+extern char *FindClosingParenthese(const char *pStr);
+
+extern char *FindOpeningParenthese(const char *pStrBegin, const char *pStrEnd, const char Bracks[2]);
+
+#ifdef PROFILE_MEMO
+static inline Boolean Memo(const char *s)
+{
+  NumMemo++;
+  return !strcmp(OpPart.str.p_str, s);
+}
+#else
+# define Memo(s) (!strcmp(OpPart.str.p_str, (s)))
+#endif
+
+
+extern void AddSuffix(char *s, const char *Suff);
+
+extern void KillSuffix(char *s);
+
+extern const char *NamePart(const char *Name);
+
+extern char *PathPart(char *Name);
+
+
+extern void FloatString(char *pDest, size_t DestSize, Double f);
+
+extern void StrSym(const TempResult *t, Boolean WithSystem, struct as_dynstr *p_dest, unsigned Radix);
+
+
+extern void ResetPageCounter(void);
+
+extern void NewPage(ShortInt Level, Boolean WithFF);
+
+extern void WrLstLine(const char *Line);
+
+extern void SetListLineVal(TempResult *t);
+
+extern void LimitListLine(void);
+
+extern void PrintOneLineMuted(FILE *pFile, const char *pLine,
+                              const struct sLineComp *pMuteComponent,
+                              const struct sLineComp *pMuteComponent2);
+extern void PrLineMarker(FILE *pFile, const char *pLine, const char *pPrefix, const char *pTrailer,
+                         char Marker, const struct sLineComp *pLineComp);
+
+extern LargeWord ProgCounter(void);
+
+extern LargeWord EProgCounter(void);
+
+extern Word Granularity(void);
+
+extern Word ListGran(void);
+
+extern void ChkSpace(Byte AddrSpace, unsigned AddrSpaceMask);
+
+
+extern void PrintUseList(void);
+
+extern void ClearUseList(void);
+
+
+extern int CompressLine(const char *TokNam, unsigned TokenNum, struct as_dynstr *p_str, Boolean CaseSensitive);
+
+extern void ExpandLine(const char *TokNam, unsigned TokenNum, struct as_dynstr *p_str);
+
+extern void KillCtrl(char *Line);
+
+#ifdef __TURBOC__
+extern void ChkStack(void);
+
+extern void ResetStack(void);
+
+extern LongWord StackRes(void);
+#else
+#define ChkStack() {}
+#define ResetStack() {}
+#define StackRes() 0
+#endif
+
+
+extern void AddCopyright(const char *NewLine);
+
+extern void WriteCopyrights(TSwitchProc NxtProc);
+
+
+extern char *ChkSymbNameUpTo(const char *pSym, const char *pUpTo);
+extern Boolean ChkSymbName(const char *pSym);
+
+extern char *ChkMacSymbNameUpTo(const char *pSym, const char *pUpTo);
+extern Boolean ChkMacSymbName(const char *pSym);
+
+extern unsigned visible_strlen(const char *pSym);
+
+
+extern void AddIncludeList(char *NewPath);
+
+extern void RemoveIncludeList(char *RemPath);
+
+
+extern void ClearOutList(void);
+
+extern void AddToOutList(const char *NewName);
+
+extern void RemoveFromOutList(const char *OldName);
+
+extern char *GetFromOutList(void);
+
+
+extern void ClearShareOutList(void);
+
+extern void AddToShareOutList(const char *NewName);
+
+extern void RemoveFromShareOutList(const char *OldName);
+
+extern char *GetFromShareOutList(void);
+
+
+extern void ClearListOutList(void);
+
+extern void AddToListOutList(const char *NewName);
+
+extern void RemoveFromListOutList(const char *OldName);
+
+extern char *GetFromListOutList(void);
+
+
+extern void BookKeeping(void);
+
+
+extern long DTime(long t1, long t2);
+
+
+extern void InitPass(void);
+extern void AddInitPassProc(SimpProc NewProc);
+
+extern void ClearUp(void);
+extern void AddClearUpProc(SimpProc NewProc);
+
+extern void asmsub_init(void);
+
+#include "asmerr.h"
+
+#endif /* _ASMSUB_H */
diff --git a/aslshim/bpemu.c b/aslshim/bpemu.c
new file mode 100644 (file)
index 0000000..5d776d9
--- /dev/null
@@ -0,0 +1,407 @@
+/* bpemu.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Emulation einiger Borland-Pascal-Funktionen                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#include "strutil.h"
+#include "bpemu.h"
+
+#ifdef __MSDOS__
+#include <dos.h>
+#include <dir.h>
+#endif
+
+#if defined( __EMX__ ) || defined( __IBMC__ )
+#include <os2.h>
+#endif
+
+#ifdef __MINGW32__
+#include <direct.h>
+#endif
+
+char *FExpand(char *Src)
+{
+  static String CurrentDir;
+  String Copy;
+#ifdef DRSEP
+  String DrvPart;
+#endif /* DRSEP */
+  char *p, *p2;
+
+  strmaxcpy(Copy, Src, STRINGSIZE);
+
+#ifdef DRSEP
+  p = strchr(Copy,DRSEP);
+  if (p)
+  {
+    memcpy(DrvPart, Copy, p - Copy);
+    DrvPart[p - Copy] = '\0';
+    strmov(Copy, p + 1);
+  }
+  else
+    *DrvPart = '\0';
+#endif
+
+#if (defined __MSDOS__)
+  {
+    int DrvNum;
+
+    if (*DrvPart == '\0')
+    {
+      DrvNum = getdisk();
+      *DrvPart = DrvNum + 'A';
+      DrvPart[1] = '\0';
+      DrvNum++;
+    }
+    else
+      DrvNum = toupper(*DrvPart) - '@';
+    getcurdir(DrvNum, CurrentDir);
+  }
+#elif (defined __EMX__) || (defined __IBMC__)
+  {
+    ULONG DrvNum, Dummy;
+
+    if (*DrvPart == '\0')
+    {
+      DosQueryCurrentDisk(&DrvNum, &Dummy);
+      *DrvPart = DrvNum + '@';
+      DrvPart[1] = '\0';
+    }
+    else
+      DrvNum = toupper(*DrvPart) - '@';
+    Dummy = 255;
+    DosQueryCurrentDir(DrvNum, (PBYTE) CurrentDir, &Dummy);
+  }
+#elif (defined __MINGW32__)
+  {
+    int DrvNum;
+
+    if (!*DrvPart)
+    {
+      DrvNum = _getdrive();
+      *DrvPart = DrvNum + '@';
+      DrvPart[1] = '\0';
+    }
+    else
+      DrvNum = toupper(*DrvPart) - '@';
+    _getdcwd(DrvNum, CurrentDir, STRINGSIZE);
+    if (CurrentDir[1] == ':')
+      strmov(CurrentDir, CurrentDir + 2);
+  }
+#elif (defined _WIN32) /* CygWIN */
+  if (!getcwd(CurrentDir, STRINGSIZE))
+    0[CurrentDir] = '\0';
+  for (p = CurrentDir; *p; p++)
+    if (*p == '/') *p = '\\';
+#else /* UNIX */
+  if (!getcwd(CurrentDir, STRINGSIZE))
+    0[CurrentDir] = '\0';
+#endif
+
+  if ((*CurrentDir) && (CurrentDir[strlen(CurrentDir) - 1] != PATHSEP))
+    strmaxcat(CurrentDir, SPATHSEP, STRINGSIZE);
+  if (*CurrentDir!=PATHSEP)
+    strmaxprep(CurrentDir, SPATHSEP, STRINGSIZE);
+
+  if (*Copy == PATHSEP)
+  {
+    strmaxcpy(CurrentDir, SPATHSEP, STRINGSIZE);
+    strmov(Copy, Copy + 1);
+  }
+
+#ifdef DRSEP
+#ifdef __CYGWIN32__
+  /* win32 getcwd() does not deliver current drive letter, therefore only prepend a drive letter
+     if there was one before. */
+  if (*DrvPart)
+#endif
+  {
+    strmaxprep(CurrentDir, SDRSEP, STRINGSIZE);
+    strmaxprep(CurrentDir, DrvPart, STRINGSIZE);
+  }
+#endif
+
+  while (True)
+  {
+    p = strchr(Copy, PATHSEP);
+    if (!p)
+      break;
+    *p = '\0';
+    if (!strcmp(Copy, "."));
+    else if ((!strcmp(Copy, "..")) && (strlen(CurrentDir) > 1))
+    {
+      CurrentDir[strlen(CurrentDir) - 1] = '\0';
+      p2 = strrchr(CurrentDir, PATHSEP); p2[1] = '\0';
+    }
+    else
+    {
+      strmaxcat(CurrentDir, Copy, STRINGSIZE);
+      strmaxcat(CurrentDir, SPATHSEP, STRINGSIZE);
+    }
+    strmov(Copy, p + 1);
+  }
+
+  strmaxcat(CurrentDir, Copy, STRINGSIZE);
+
+  return CurrentDir;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     FSearch(char *pDest, size_t DestSize, const char *pFileToSearch, const char *pCurrFileName, const char *pSearchPath)
+ * \brief  search for file in given path(s)
+ * \param  pDest where to put result
+ * \param  DestSize size of result buffer
+ * \param  pFileToSearch file to search for
+ * \param  pCurrFileName file this file was referenced from
+ * \param  pSearchPath list of directories to search
+ * \return 0 if found or error code
+ * ------------------------------------------------------------------------ */
+
+static int AssembleAndCheck(char *pDest, size_t DestSize, const char *pPath, unsigned PathLen, const char *pFileToSearch)
+{
+  FILE *pDummy;
+
+  if (PathLen > DestSize - 1)
+    PathLen = DestSize - 1;
+  memcpy(pDest, pPath, PathLen);
+  pDest[PathLen] = '\0';
+#ifdef __CYGWIN32__
+  DeCygwinPath(pDest);
+#endif
+  if (PathLen > 0)
+    strmaxcat(pDest, SPATHSEP, DestSize);
+  strmaxcat(pDest, pFileToSearch, DestSize);
+  pDummy = fopen(pDest, "r");
+  if (pDummy)
+  {
+    fclose(pDummy);
+    return 0;
+  }
+  else
+    return 2;
+}
+
+int FSearch(char *pDest, size_t DestSize, const char *pFileToSearch, const char *pCurrFileName, const char *pSearchPath)
+{
+  /* If the file has an absolute path ('/....', '\....', 'X:....'), do not search relative
+     to current file's directory: */
+
+  Boolean Absolute = (*pFileToSearch == '/');
+  const char *pPos, *pStart;
+
+#if (defined _WIN32) || (defined __EMX__) || (defined __IBMC__) || (defined __MSDOS__)
+  if (*pFileToSearch == PATHSEP)
+    Absolute = True;
+#endif
+#ifdef DRSEP
+  if ((as_islower(*pFileToSearch) || as_isupper(*pFileToSearch))
+   && (pFileToSearch[1] == DRSEP))
+    Absolute = True;
+#endif
+
+  if (pCurrFileName && !Absolute)
+  {
+#if (defined _WIN32) || (defined __EMX__) || (defined __IBMC__) || (defined __MSDOS__)
+    /* On systems with \ as path separator, we may get a mixture of / and \ in the path.
+       Assure we find the last one of either: */
+
+    pPos = strrmultchr(pCurrFileName, SPATHSEP "/");
+#else
+    pPos = strrchr(pCurrFileName, PATHSEP);
+#endif
+    if (!AssembleAndCheck(pDest, DestSize, pCurrFileName, pPos ? pPos - pCurrFileName : 0, pFileToSearch))
+      return 0;
+  }
+  else
+  {
+    if (!AssembleAndCheck(pDest, DestSize, NULL, 0, pFileToSearch))
+      return 0;
+  }
+
+  /* TODO: if the file has an absolute path, searching the include path should be pointless: */
+
+  pStart = pSearchPath;
+  while (True)
+  {
+    pPos = strchr(pStart, DIRSEP);
+
+    if (!AssembleAndCheck(pDest, DestSize, pStart, pPos ? pPos - pStart : (int)strlen(pStart), pFileToSearch))
+      return 0;
+    if (pPos)
+      pStart =  pPos+ 1;
+    else
+      break;
+  }
+
+  *pDest = '\0';
+  return 2;
+}
+
+long FileSize(FILE *file)
+{
+  long Save = ftell(file), Size;
+
+  fseek(file, 0, SEEK_END);
+  Size=ftell(file);
+  fseek(file, Save, SEEK_SET);
+  return Size;
+}
+
+Byte Lo(Word inp)
+{
+  return (inp & 0xff);
+}
+
+Byte Hi(Word inp)
+{
+  return ((inp >> 8) & 0xff);
+}
+
+unsigned LoWord(LongWord Src)
+{
+  return (Src & 0xffff);
+}
+
+unsigned HiWord(LongWord Src)
+{
+  return ((Src >> 16) & 0xffff);
+}
+
+unsigned long LoDWord(LargeWord Src)
+{
+  return Src & 0xfffffffful;
+}
+
+Boolean Odd(int inp)
+{
+  return ((inp & 1) == 1);
+}
+
+Boolean DirScan(char *Mask, charcallback callback)
+{
+  char Name[1024];
+
+#ifdef __MSDOS__
+  struct ffblk blk;
+  int res;
+  char *pos;
+
+  res = findfirst(Mask, &blk, FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_LABEL | FA_DIREC | FA_ARCH);
+  if (res < 0)
+    return False;
+  pos = strrchr(Mask, PATHSEP);
+  if (!pos)
+    pos = strrchr(Mask, DRSEP);
+  pos = pos ? pos + 1 : Mask;
+  memcpy(Name, Mask, pos - Mask);
+  while (res==0)
+  {
+    if ((blk.ff_attrib & (FA_LABEL|FA_DIREC)) == 0)
+    {
+      strcpy(Name + (pos - Mask), blk.ff_name);
+      callback(Name);
+    }
+    res = findnext(&blk);
+  }
+  return True;
+#else
+#if defined ( __EMX__ ) || defined ( __IBMC__ )
+  HDIR hdir = 1;
+  FILEFINDBUF3 buf;
+  ULONG rescnt;
+  USHORT res;
+  char *pos;
+
+  rescnt = 1;
+  res = DosFindFirst(Mask, &hdir, 0x16, &buf, sizeof(buf), &rescnt, 1);
+  if (res)
+    return False;
+  pos = strrchr(Mask, PATHSEP);
+  if (!pos)
+    pos = strrchr(Mask, DRSEP);
+  pos = pos ? pos + 1 : Mask;
+  memcpy(Name, Mask, pos - Mask);
+  while (res == 0)
+  {
+    strcpy(Name + (pos - Mask), buf.achName);
+    callback(Name);
+    res = DosFindNext(hdir, &buf, sizeof(buf), &rescnt);
+  }
+  return True;
+#else
+  strmaxcpy(Name, Mask, sizeof(Name));
+  callback(Name);
+  return True;
+#endif
+#endif
+}
+
+LongInt MyGetFileTime(char *Name)
+{
+  struct stat st;
+
+  if (stat(Name, &st) == -1)
+    return 0;
+  else
+    return st.st_mtime;
+}
+
+#ifdef __CYGWIN32__
+
+/* convert CygWin-style paths back to something usable by other Win32 apps */
+
+char *DeCygWinDirList(char *pStr)
+{
+  char *pRun;
+
+  for (pRun = pStr; *pRun; pRun++)
+    if (*pRun == ':')
+      *pRun = ';';
+
+  return pStr;
+}
+
+char *DeCygwinPath(char *pStr)
+{
+  char *pRun;
+
+  if ((strlen(pStr) >= 4)
+   && (pStr[0] =='/') && (pStr[1] == '/') && (pStr[3] == '/')
+   && (isalpha(pStr[2])))
+  {
+    strmov(pStr, pStr + 1);
+    pStr[0] = pStr[1];
+    pStr[1] = ':';
+  }
+
+  if ((strlen(pStr) >= 4)
+   && (pStr[0] =='\\') && (pStr[1] == '\\') && (pStr[3] == '\\')
+   && (isalpha(pStr[2])))
+  {
+    strmov(pStr, pStr + 1);
+    pStr[0] = pStr[1];
+    pStr[1] = ':';
+  }
+
+  for (pRun = pStr; *pRun; pRun++)
+    if (*pRun == '/')
+      *pRun = '\\';
+
+  return pStr;
+}
+#endif /* __CYGWIN32__ */
+
+void bpemu_init(void)
+{
+}
diff --git a/aslshim/bpemu.h b/aslshim/bpemu.h
new file mode 100644 (file)
index 0000000..f7aae2d
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _BPEMU_H
+#define _BPEMU_H
+/* bpemu.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Emulation einiger Borland-Pascal-Funktionen                               */
+/*                                                                           */
+/* Historie: 20. 5.1996 Grundsteinlegung                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+typedef void (*charcallback)(
+#ifdef __PROTOS__
+char *Name
+#endif
+);
+
+extern char *FExpand(char *Src);
+
+extern int FSearch(char *pDest, size_t DestSize, const char *FileToSearch, const char *pCurrFileName, const char *SearchPath);
+
+extern long FileSize(FILE *file);
+
+extern Byte Lo(Word inp);
+
+extern Byte Hi(Word inp);
+
+extern unsigned LoWord(LongWord Src);
+
+extern unsigned HiWord(LongWord Src);
+
+extern unsigned long LoDWord(LargeWord Src);
+
+extern Boolean Odd (int inp);
+
+extern Boolean DirScan(char *Mask, charcallback callback);
+
+extern LongInt MyGetFileTime(char *Name);
+
+#ifdef __CYGWIN32__
+extern char *DeCygWinDirList(char *pStr);
+
+extern char *DeCygwinPath(char *pStr);
+#endif
+
+extern void bpemu_init(void);
+#endif /* _BPEMU_H */
diff --git a/aslshim/chardefs.h b/aslshim/chardefs.h
new file mode 100644 (file)
index 0000000..239928d
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef _CHARDEFS_H
+#define _CHARDEFS_H
+/* chardefs.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* system-dependant definition of national-specific characters               */
+/*                                                                           */
+/* History:  2001-10-13 /AArnold - created this header                       */
+/*                                                                           */
+/*****************************************************************************/
+
+typedef enum
+{
+  eCH_ae,
+  eCH_ee,
+  eCH_ie,
+  eCH_oe,
+  eCH_ue,
+  eCH_Ae,
+  eCH_Ee,
+  eCH_Ie,
+  eCH_Oe,
+  eCH_Ue,
+  eCH_sz,
+  eCH_e2,
+  eCH_mu,
+  eCH_agrave,
+  eCH_Agrave,
+  eCH_egrave,
+  eCH_Egrave,
+  eCH_igrave,
+  eCH_Igrave,
+  eCH_ograve,
+  eCH_Ograve,
+  eCH_ugrave,
+  eCH_Ugrave,
+  eCH_aacute,
+  eCH_Aacute,
+  eCH_eacute,
+  eCH_Eacute,
+  eCH_iacute,
+  eCH_Iacute,
+  eCH_oacute,
+  eCH_Oacute,
+  eCH_uacute,
+  eCH_Uacute,
+  eCH_acirc,
+  eCH_Acirc,
+  eCH_ecirc,
+  eCH_Ecirc,
+  eCH_icirc,
+  eCH_Icirc,
+  eCH_ocirc,
+  eCH_Ocirc,
+  eCH_ucirc,
+  eCH_Ucirc,
+  eCH_ccedil,
+  eCH_Ccedil,
+  eCH_ntilde,
+  eCH_Ntilde,
+  eCH_aring,
+  eCH_Aring,
+  eCH_aelig,
+  eCH_Aelig,
+  eCH_oslash,
+  eCH_Oslash,
+  eCH_iquest,
+  eCH_iexcl,
+  eCH_cnt
+} tNLSCharacter;
+
+#ifdef __cplusplus
+# include "cppops.h"
+DefCPPOps_Enum(tNLSCharacter)
+#endif
+
+typedef char tNLSCharacterTab[eCH_cnt][2];
+
+typedef enum
+{
+  eCodepageASCII,
+  eCodepageISO8859_1,
+  eCodepageISO8859_15,
+  eCodepageKOI8_R,
+  eCodepage437,
+  eCodepage850,
+  eCodepage866,
+  eCodepage1251,
+  eCodepage1252,
+  eCodepageUTF8,
+  eCodepageCnt
+} tCodepage;
+
+#ifdef __cplusplus
+# include "cppops.h"
+DefCPPOps_Enum(tCodepage)
+#endif
+
+#include "datatypes.h"
+
+extern const tNLSCharacterTab *GetCharacterTab(tCodepage Codepage);
+
+extern const char NLS_HtmlCharacterTab[eCH_cnt][9];
+
+extern int CharTab_GetLength(const tNLSCharacterTab *pTab, tNLSCharacter Character);
+
+extern const char *CharTab_GetNULTermString(const tNLSCharacterTab *pTab, tNLSCharacter Character, char *pBuffer);
+
+extern LongWord UTF8ToUnicode(const char* *ppChr);
+
+extern void UnicodeToUTF8(char* *ppChr, LongWord Unicode);
+
+#endif /* _CHARDEFS_H */
diff --git a/aslshim/chunks.h b/aslshim/chunks.h
new file mode 100644 (file)
index 0000000..0b2e8ff
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef _CHUNKS_H
+#define _CHUNKS_H
+/* chunks.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Verwaltung von Adressbereichslisten                                       */
+/*                                                                           */
+/* Historie: 16. 5.1996 Grundsteinlegung                                     */
+/*           16. 8.1998 Min/Max-Ausgabe                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+typedef struct
+{
+  LargeWord Start, Length;
+} OneChunk;
+
+typedef struct
+{
+  Word RealLen,AllocLen;
+  OneChunk *Chunks;
+} ChunkList;
+
+
+extern Boolean AddChunk(ChunkList *NChunk, LargeWord NewStart, LargeWord NewLen, Boolean Warn);
+
+extern void DeleteChunk(ChunkList *NChunk, LargeWord DelStart, LargeWord DelLen);
+
+extern Boolean AddressInChunk(ChunkList *NChunk, LargeWord Address);
+
+extern void SortChunks(ChunkList *NChunk);
+
+extern void InitChunk(ChunkList *NChunk);
+
+extern void ClearChunk(ChunkList *NChunk);
+
+extern LargeWord ChunkMin(ChunkList *NChunk);
+
+extern LargeWord ChunkMax(ChunkList *NChunk);
+
+extern LargeWord ChunkSum(ChunkList *NChunk);
+
+
+extern void chunks_init(void);
+#endif /* _CHUNKS_H */
diff --git a/aslshim/codepseudo.h b/aslshim/codepseudo.h
new file mode 100644 (file)
index 0000000..48fcda9
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _CODEPSEUDO_H
+#define _CODEPSEUDO_H
+/* codepseudo.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Haeufiger benutzte Pseudo-Befehle                                         */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "addrspace.h"
+
+struct _ASSUMERec;
+
+extern int FindInst(void *Field, int Size, int Count);
+
+extern Boolean IsIndirectGen(const char *Asc, const char *pBeginEnd);
+extern Boolean IsIndirect(const char *Asc);
+
+typedef int (*tDispBaseSplitQualifier)(const char *pArg, int StartPos, int SplitPos);
+extern int FindDispBaseSplitWithQualifier(const char *pArg, int *pArgLen, tDispBaseSplitQualifier Qualifier);
+#define FindDispBaseSplit(pArg, pArgLen) FindDispBaseSplitWithQualifier(pArg, pArgLen, NULL)
+
+extern void CodeEquate(as_addrspace_t DestSeg, LargeInt Min, LargeInt Max);
+
+extern Boolean QualifyQuote_SingleQuoteConstant(const char *pStart, const char *pQuotePos);
+
+#endif /* _CODEPSEUDO_H */
diff --git a/aslshim/codevars.c b/aslshim/codevars.c
new file mode 100644 (file)
index 0000000..b0740e2
--- /dev/null
@@ -0,0 +1,19 @@
+/* codevars.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Gemeinsame Variablen aller Codegeneratoren                                */
+/*                                                                           */
+/* Historie: 26.5.1997 Grundsteinlegung                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include "asmitree.h"
+
+int InstrZ;
+int AdrCnt;
+PInstTable InstTable;
diff --git a/aslshim/codevars.h b/aslshim/codevars.h
new file mode 100644 (file)
index 0000000..2ddbc08
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _CODEVARS_H
+#define _CODEVARS_H
+/* codevars.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Gemeinsame Variablen aller Codegeneratoren                                */
+/*                                                                           */
+/* Historie: 26.5.1997 Grundsteinlegung                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+extern int InstrZ;
+extern int AdrCnt;
+
+extern PInstTable InstTable;
+
+#endif /* _CODEVARS_H */
diff --git a/aslshim/console.h b/aslshim/console.h
new file mode 100644 (file)
index 0000000..c161dad
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _CONSOLE_H
+#define _CONSOLE_H
+/* console.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS Port                                                                   */
+/*                                                                           */
+/* Console Output Handling                                                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "datatypes.h"
+
+extern void WrConsoleLine(const char *pLine, Boolean NewLine);
+
+#endif /* _CONSOLE_H */
diff --git a/aslshim/cppops.h b/aslshim/cppops.h
new file mode 100644 (file)
index 0000000..66ed31e
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef _CPPOPS_H
+#define _CPPOPS_H
+
+#define DefCPPOps_Mask(datatype)\
+\
+static inline datatype operator|=(datatype &lhs, datatype rhs)\
+{\
+  lhs = (datatype)(((int)lhs) | ((int)rhs));\
+  return lhs;\
+}\
+\
+static inline datatype operator&=(datatype &lhs, datatype rhs)\
+{\
+  lhs = (datatype)(((int)lhs) & ((int)rhs));\
+  return lhs;\
+}\
+\
+static inline datatype operator|(datatype lhs, datatype rhs)\
+{\
+  return (datatype)(((int)lhs) | ((int)rhs));\
+}\
+\
+static inline datatype operator&(datatype lhs, datatype rhs)\
+{\
+  return (datatype)(((int)lhs) & ((int)rhs));\
+}\
+\
+static inline datatype operator~(datatype rhs)\
+{\
+  return (datatype)(~((int)rhs));\
+}\
+
+#define DefCPPOps_Enum(datatype)\
+\
+static inline datatype operator++(datatype &rhs, int)\
+{\
+  datatype old = rhs;\
+  rhs = (datatype)((int)rhs + 1);\
+  return old;\
+}\
+\
+static inline datatype operator--(datatype &rhs, int)\
+{\
+  datatype old = rhs;\
+  rhs = (datatype)((int)rhs - 1);\
+  return old;\
+}\
+\
+static inline datatype operator+(datatype lhs, int rhs)\
+{\
+  return (datatype)((int)lhs + rhs);\
+}\
+\
+static inline datatype operator-(datatype lhs, int rhs)\
+{\
+  return (datatype)((int)lhs - rhs);\
+}\
+
+#endif /* _CPPOPS_H */
diff --git a/aslshim/cpulist.c b/aslshim/cpulist.c
new file mode 100644 (file)
index 0000000..9f5d170
--- /dev/null
@@ -0,0 +1,215 @@
+/* cpulist.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Port                                                                   */
+/*                                                                           */
+/* Manages CPU List                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+#include "strutil.h"
+
+#include "cpulist.h"
+
+static tpCPUDef FirstCPUDef;                   /* Liste mit Prozessordefinitionen */
+static CPUVar CPUCnt;                         /* Gesamtzahl Prozessoren */
+static int MaxNameLen = 0;
+
+/****************************************************************************/
+/* neuen Prozessor definieren */
+
+CPUVar AddCPUUserWithArgs(const char *NewName, tCPUSwitchUserProc Switcher, void *pUserData, tCPUFreeUserDataProc Freeer, const tCPUArg *pArgs)
+{
+  tpCPUDef Lauf, Neu;
+  char *p;
+  int l;
+
+  Neu = (tpCPUDef) malloc(sizeof(tCPUDef));
+  Neu->Name = as_strdup(NewName);
+  Neu->pArgs = pArgs;
+  /* kein UpString, weil noch nicht initialisiert ! */
+  for (p = Neu->Name; *p != '\0'; p++)
+    *p = as_toupper(*p);
+  Neu->SwitchProc = Switcher;
+  Neu->FreeProc = Freeer;
+  Neu->pUserData = pUserData;
+  Neu->Next = NULL;
+  Neu->Number = Neu->Orig = CPUCnt;
+
+  l = strlen(NewName);
+  if (l > MaxNameLen)
+    MaxNameLen = l;
+
+  Lauf = FirstCPUDef;
+  if (!Lauf)
+    FirstCPUDef = Neu;
+  else
+  {
+    while (Lauf->Next)
+      Lauf = Lauf->Next;
+    Lauf->Next = Neu;
+  }
+
+  return CPUCnt++;
+}
+
+typedef struct
+{
+  tCPUSwitchProc Switcher;
+} tNoUserData;
+
+static void SwitchNoUserProc(void *pUserData)
+{
+  ((tNoUserData*)pUserData)->Switcher();
+}
+
+static void FreeNoUserProc(void *pUserData)
+{
+  free(pUserData);
+}
+
+CPUVar AddCPUWithArgs(const char *NewName, tCPUSwitchProc Switcher, const tCPUArg *pArgs)
+{
+  tNoUserData *pData = (tNoUserData*)malloc(sizeof(*pData));
+
+  pData->Switcher = Switcher;
+  return AddCPUUserWithArgs(NewName, SwitchNoUserProc, pData, FreeNoUserProc, pArgs);
+}
+
+Boolean AddCPUAlias(char *OrigName, char *AliasName)
+{
+  tpCPUDef Lauf = FirstCPUDef, Neu;
+
+  while ((Lauf) && (strcmp(Lauf->Name, OrigName)))
+    Lauf = Lauf->Next;
+
+  if (!Lauf)
+    return False;
+  else
+  {
+    Neu = (tpCPUDef) malloc(sizeof(tCPUDef));
+    Neu->Next = NULL;
+    Neu->Name = as_strdup(AliasName);
+    Neu->Number = CPUCnt++;
+    Neu->Orig = Lauf->Orig;
+    Neu->SwitchProc = Lauf->SwitchProc;
+    Neu->FreeProc = Lauf->FreeProc;
+    Neu->pUserData = Lauf->pUserData;
+    Neu->pArgs = Lauf->pArgs;
+    while (Lauf->Next)
+      Lauf = Lauf->Next;
+    Lauf->Next = Neu;
+    return True;
+  }
+}
+
+void IterateCPUList(tCPUListIterator Iterator, void *pUser)
+{
+  tpCPUDef pRun;
+
+  for (pRun= FirstCPUDef; pRun; pRun = pRun->Next)
+    Iterator(pRun, pUser);
+}
+
+typedef struct
+{
+  int cnt, perline;
+  tCPUSwitchUserProc Proc;
+  tCPUSwitchProc NoUserProc;
+  tPrintNextCPUProc NxtProc;
+} tPrintContext;
+
+static void PrintIterator(const tCPUDef *pCPUDef, void *pUser)
+{
+  tPrintContext *pContext = (tPrintContext*)pUser;
+
+  /* ignore aliases */
+
+  if (pCPUDef->Number == pCPUDef->Orig)
+  {
+    tCPUSwitchProc ThisNoUserProc = (pCPUDef->SwitchProc == SwitchNoUserProc) ? ((tNoUserData*)pCPUDef->pUserData)->Switcher : NULL;
+    Boolean Unequal;
+
+    if (pCPUDef->SwitchProc != pContext->Proc)
+      Unequal = True;
+    else if (pCPUDef->SwitchProc == SwitchNoUserProc)
+      Unequal = (pContext->NoUserProc != ThisNoUserProc);
+    else
+      Unequal = False;
+    if (Unequal || (pContext->cnt == pContext->perline))
+    {
+      pContext->Proc = pCPUDef->SwitchProc;
+      pContext->NoUserProc = ThisNoUserProc;
+      printf("\n");
+      pContext->NxtProc();
+      pContext->cnt = 0;
+    }
+    printf("%-*s", MaxNameLen + 1, pCPUDef->Name);
+    pContext->cnt++;
+  }
+}
+
+void PrintCPUList(tPrintNextCPUProc NxtProc)
+{
+  tPrintContext Context;
+
+  Context.Proc = NULL;
+  Context.NoUserProc = NULL;
+  Context.cnt = 0;
+  Context.NxtProc = NxtProc;
+  Context.perline = 79 / (MaxNameLen + 1);
+  IterateCPUList(PrintIterator, &Context);
+  printf("\n");
+  NxtProc();
+}
+
+void ClearCPUList(void)
+{
+  tpCPUDef Save;
+
+  while (FirstCPUDef)
+  {
+    Save = FirstCPUDef;
+    FirstCPUDef = Save->Next;
+    free(Save->Name);
+    if (Save->FreeProc)
+      Save->FreeProc(Save->pUserData);
+    free(Save);
+  }
+}
+
+const tCPUDef *LookupCPUDefByVar(CPUVar Var)
+{
+  tpCPUDef pRun;
+
+  for (pRun = FirstCPUDef; pRun; pRun = pRun->Next)
+    if (pRun->Number == Var)
+      break;
+  return pRun;
+}
+
+const tCPUDef *LookupCPUDefByName(const char *pName)
+{
+  tpCPUDef pRun;
+
+  for (pRun = FirstCPUDef; pRun; pRun = pRun->Next)
+  {
+    int l = strlen(pRun->Name);
+
+    if (strncmp(pRun->Name, pName, l))
+      continue;
+    if ((pName[l] == '\0') || (pName[l] == ':'))
+      break;
+  }
+  return pRun;
+}
+
+void cpulist_init(void)
+{
+  FirstCPUDef = NULL;
+  CPUCnt = 0;
+}
diff --git a/aslshim/cpulist.h b/aslshim/cpulist.h
new file mode 100644 (file)
index 0000000..5556ab7
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef _CPULIST_H
+#define _CPULIST_H
+/* cpulist.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Port                                                                   */
+/*                                                                           */
+/* Manages CPU List                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+typedef void (*tCPUSwitchProc)(
+#ifdef __PROTOS__
+void
+#endif
+);
+
+typedef void (*tCPUSwitchUserProc)(
+#ifdef __PROTOS__
+void *pUserData
+#endif
+);
+
+typedef void (*tPrintNextCPUProc)(
+#ifdef __PROTOS__
+void
+#endif
+);
+
+typedef void (*tCPUFreeUserDataProc)(void *pUserData);
+
+typedef unsigned CPUVar;
+#define CPUNone ((CPUVar)-1)
+
+typedef struct sCPUArg
+{
+  const char *pName;
+  const LongInt Min, Max, DefValue;
+  LongInt *pValue;
+} tCPUArg;
+
+typedef struct sCPUDef
+{
+  struct sCPUDef *Next;
+  char *Name;
+  CPUVar Number, Orig;
+  tCPUSwitchUserProc SwitchProc;
+  tCPUFreeUserDataProc FreeProc;
+  void *pUserData;
+  const tCPUArg *pArgs;
+} tCPUDef, *tpCPUDef;
+
+typedef void (*tCPUListIterator)(const tCPUDef *pRun, void *pUser);
+
+extern CPUVar AddCPUWithArgs(const char *NewName, tCPUSwitchProc Switcher, const tCPUArg *pArgs);
+#define AddCPU(NewName, Switcher) AddCPUWithArgs(NewName, Switcher, NULL)
+extern CPUVar AddCPUUserWithArgs(const char *NewName, tCPUSwitchUserProc Switcher, void *pUserData, tCPUFreeUserDataProc Freeer, const tCPUArg *pArgs);
+#define AddCPUUser(NewName, Switcher, pUserData, Freeer) AddCPUUserWithArgs(NewName, Switcher, pUserData, Freeer, NULL)
+
+extern Boolean AddCPUAlias(char *OrigName, char *AliasName);
+
+extern const tCPUDef *LookupCPUDefByVar(CPUVar Var);
+
+extern const tCPUDef *LookupCPUDefByName(const char *pName);
+
+extern void IterateCPUList(tCPUListIterator Iterator, void *pUser);
+
+extern void PrintCPUList(tPrintNextCPUProc NxtProc);
+
+extern void ClearCPUList(void);
+
+extern void cpulist_init(void);
+
+#endif /* _CPULIST_H */
diff --git a/aslshim/datatypes.h b/aslshim/datatypes.h
new file mode 100644 (file)
index 0000000..8db3cab
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef _DATATYPES_H
+#define _DATATYPES_H
+/* datatypes.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Port                                                                   */
+/*                                                                           */
+/* define some handy types & constants                                       */
+/*                                                                           */
+/* History:  2001-10-13 /AArnold - created this comment                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "sysdefs.h"
+
+typedef Card8 Byte;       /* Integertypen */
+typedef Integ8 ShortInt;
+
+#ifdef HAS16
+typedef Card16 Word;
+typedef Integ16 Integer;
+#endif
+
+typedef Card32 LongWord;
+typedef Integ32 LongInt;
+#define PRILongInt PRIInteg32
+
+#ifdef HAS64
+typedef Card64 QuadWord;
+typedef Integ64 QuadInt;
+#endif
+
+#ifdef HAS64
+typedef QuadInt LargeInt;
+typedef QuadWord LargeWord;
+#define LARGEBITS 64
+#else
+typedef LongInt LargeInt;
+typedef LongWord LargeWord;
+#define LARGEBITS 32
+#endif
+
+typedef signed int sint;
+typedef unsigned int usint;
+
+typedef char Char;
+
+typedef double Double;
+typedef float Single;
+
+typedef Byte Boolean;
+
+#ifndef STRINGSIZE
+# define STRINGSIZE 256
+#endif
+#define SHORTSTRINGSIZE 65
+
+typedef char String[STRINGSIZE];
+typedef char ShortString[SHORTSTRINGSIZE];
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef True
+#define True 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef False
+#define False 0
+#endif
+
+#endif /* _DATATYPES_H */
diff --git a/aslshim/dynstr.c b/aslshim/dynstr.c
new file mode 100644 (file)
index 0000000..239f823
--- /dev/null
@@ -0,0 +1,206 @@
+/* dynstr.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Port                                                                   */
+/*                                                                           */
+/* Handling of strings with dynamic allocation                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "dynstr.h"
+
+static void check_dynamic(const as_dynstr_t *p_str)
+{
+  if (!p_str->dynamic)
+  {
+    fprintf(stderr, "attemt to resize non-dynamic string\n");
+    abort();
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_dynstr_ini(as_dynstr_t *p_str, size_t AllocLen)
+ * \brief  initialize empty string with given capacity
+ * \param  p_str string to initialize
+ * \param  AllocLen initial alloc length
+ * ------------------------------------------------------------------------ */
+
+void as_dynstr_ini(as_dynstr_t *p_str, size_t ini_capacity)
+{
+  p_str->p_str = (char*)malloc(ini_capacity);
+  p_str->capacity = p_str->p_str ? ini_capacity : 0;
+  p_str->dynamic = !!p_str->p_str;
+  memset(p_str->p_str, 0, p_str->capacity);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_dynstr_ini_clone(as_dynstr_t *p_str, const as_dynstr_t *p_src)
+ * \brief  initialize empty string from other string
+ * \param  p_str string to initialize
+ * \param  p_src string to clone
+ * ------------------------------------------------------------------------ */
+
+void as_dynstr_ini_clone(as_dynstr_t *p_str, const as_dynstr_t *p_src)
+{
+  p_str->p_str = (char*)malloc(p_src->capacity);
+  if (p_str->p_str)
+  {
+    strcpy(p_str->p_str, p_src->p_str);
+    p_str->capacity = p_src->capacity;
+    p_str->dynamic = 1;
+  }
+  else
+  {
+    p_str->capacity = 0;
+    p_str->dynamic = 0;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_dynstr_ini_c_str(as_dynstr_t *p_str, const char *p_src)
+ * \brief  initialize string from C string
+ * \param  p_str string to initialize
+ * \param  p_src init source
+ * ------------------------------------------------------------------------ */
+
+void as_dynstr_ini_c_str(as_dynstr_t *p_str, const char *p_src)
+{
+  size_t capacity = as_dynstr_roundup_len(strlen(p_src));
+
+  p_str->p_str = (char*)malloc(capacity);
+  if (p_str->p_str)
+  {
+    strcpy(p_str->p_str, p_src);
+    p_str->capacity = capacity;
+    p_str->dynamic = 1;
+  }
+  else
+  {
+    p_str->capacity = 0;
+    p_str->dynamic = 0;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_dynstr_realloc(as_dynstr_t *p_str, size_t new_capacity)
+ * \brief  shrink/grow string's capacity
+ * \param  p_str string to adapt
+ * \param  new_capacity new capacity
+ * \return 0 if success or error code
+ * ------------------------------------------------------------------------ */
+
+int as_dynstr_realloc(as_dynstr_t *p_str, size_t new_capacity)
+{
+  char *p_new;
+  size_t old_capacity;
+
+  check_dynamic(p_str);
+  p_new = (char*)realloc(p_str->p_str, new_capacity);
+  old_capacity = p_str->capacity;
+  if (p_new)
+  {
+    p_str->p_str = p_new;
+    p_str->capacity = new_capacity;
+    if (new_capacity > old_capacity)
+      memset(p_str->p_str + old_capacity, 0, new_capacity - old_capacity);
+    else if (new_capacity > 0)
+      p_str->p_str[new_capacity - 1] = '\0';
+    return 0;
+  }
+  else
+    return ENOMEM;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_dynstr_free(as_dynstr_t *p_str)
+ * \brief  free/destroy string
+ * \param  p_str string to handle
+ * ------------------------------------------------------------------------ */
+
+void as_dynstr_free(as_dynstr_t *p_str)
+{
+  if (p_str->dynamic && p_str->p_str)
+    free(p_str->p_str);
+  p_str->p_str = NULL;
+  p_str->capacity = 0;
+  p_str->dynamic = 0;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_dynstr_copy(as_dynstr_t *p_dest, const as_dynstr_t *p_src)
+ * \brief  set string from other string
+ * \param  p_str string to set
+ * \param  p_src init source
+ * \return actual # of characters copied
+ * ------------------------------------------------------------------------ */
+
+size_t as_dynstr_copy(as_dynstr_t *p_dest, const as_dynstr_t *p_src)
+{
+  return as_dynstr_copy_c_str(p_dest, p_src->p_str);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_dynstr_copy_c_str(as_dynstr_t *p_dest, const char *p_src)
+ * \brief  set string from C string
+ * \param  p_str string to set
+ * \param  p_src init source
+ * \return actual # of characters copied
+ * ------------------------------------------------------------------------ */
+
+size_t as_dynstr_copy_c_str(as_dynstr_t *p_dest, const char *p_src)
+{
+  size_t len = strlen(p_src);
+
+  if ((len >= p_dest->capacity) && p_dest->dynamic)
+    as_dynstr_realloc(p_dest, as_dynstr_roundup_len(len));
+
+  if (len >= p_dest->capacity)
+    len = p_dest->capacity - 1;
+  memcpy(p_dest->p_str, p_src, len);
+  p_dest->p_str[len] = '\0';
+  return len;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_dynstr_append_c_str(as_dynstr_t *p_dest, const char *p_src)
+ * \brief  extend string
+ * \param  p_dest string to extend
+ * \param  p_src what to append
+ * \return actual # of bytes transferred
+ * ------------------------------------------------------------------------ */
+
+size_t as_dynstr_append_c_str(as_dynstr_t *p_dest, const char *p_src)
+{
+  size_t src_len = strlen(p_src),
+         dest_len = strlen(p_dest->p_str);
+
+  if (dest_len + src_len + 1 > p_dest->capacity)
+    as_dynstr_realloc(p_dest, as_dynstr_roundup_len(dest_len + src_len));
+  if (src_len >= p_dest->capacity - dest_len)
+    src_len = p_dest->capacity - dest_len - 1;
+  memcpy(p_dest->p_str + dest_len, p_src, src_len);
+  p_dest->p_str[dest_len + src_len] = '\0';
+  return src_len;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_dynstr_dump_hex(FILE *p_file, const as_dynstr_t *p_str)
+ * \brief  debug helper
+ * \param  p_file where to dump
+ * \param  p_str string to dump
+ * ------------------------------------------------------------------------ */
+
+void as_dynstr_dump_hex(FILE *p_file, const as_dynstr_t *p_str)
+{
+  const char *p_run;
+
+  fprintf(p_file, "[%u]", (unsigned)p_str->capacity);
+  for (p_run = p_str->p_str; *p_run; p_run++) fprintf(p_file, " %02x", *p_run & 0xff);
+  fprintf(p_file, "\n");
+}
diff --git a/aslshim/dynstr.h b/aslshim/dynstr.h
new file mode 100644 (file)
index 0000000..a267f96
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _DYNSTR_H
+#define _DYNSTR_H
+/* dynstr.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Port                                                                   */
+/*                                                                           */
+/* Handling of strings with dynamic allocation                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <stddef.h>
+
+typedef struct as_dynstr
+{
+  size_t capacity;
+  char *p_str;
+  int dynamic;
+} as_dynstr_t;
+
+/* add one character more for terminating NUL */
+
+#define as_dynstr_roundup_len(len)  \
+        (((len) + 128) & ~127)
+
+extern void as_dynstr_ini(as_dynstr_t *p_str, size_t ini_alloc_len);
+
+extern void as_dynstr_ini_clone(as_dynstr_t *p_str, const as_dynstr_t *p_src);
+
+extern void as_dynstr_ini_c_str(as_dynstr_t *p_str, const char *p_src);
+
+extern int as_dynstr_realloc(as_dynstr_t *p_str, size_t new_alloc_len);
+
+extern void as_dynstr_free(as_dynstr_t *p_str);
+
+extern size_t as_dynstr_copy(as_dynstr_t *p_dest, const as_dynstr_t *p_src);
+
+extern size_t as_dynstr_copy_c_str(as_dynstr_t *p_dest, const char *p_src);
+
+extern size_t as_dynstr_append_c_str(as_dynstr_t *p_dest, const char *p_src);
+
+extern void as_dynstr_dump_hex(FILE *p_file, const as_dynstr_t *p_str);
+
+#endif /* _DYNSTR_H */
diff --git a/aslshim/endian.h b/aslshim/endian.h
new file mode 100644 (file)
index 0000000..a4e6a61
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef _MYENDIAN_H
+#define _MYENDIAN_H
+/* endian.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Little/Big-Endian-Routinen                                                */
+/*                                                                           */
+/* Historie: 30. 5.1996 Grundsteinlegung                                     */
+/*            6. 7.1997 Dec32BlankString dazu                                */
+/*            1. 6.2000 added LargeHIntFormat                                */
+/*            7. 7.2000 added memory read/write functions                    */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stdio.h> // Nick
+#include "datatypes.h"
+
+extern Boolean HostBigEndian;
+
+extern const char *Integ16Format, *Integ32Format, *Integ64Format;
+extern const char *IntegerFormat, *LongIntFormat, *QuadIntFormat;
+extern const char *LargeIntFormat, *LargeHIntFormat;
+
+
+extern void WSwap(void *Field, int Cnt);
+
+extern void DSwap(void *Field, int Cnt);
+
+extern void QSwap(void *Field, int Cnt);
+
+extern void TSwap(void *Field, int Cnt);
+
+extern void DWSwap(void *Field, int Cnt);
+
+extern void QWSwap(void *Field, int Cnt);
+
+extern void TWSwap(void *Field, int Cnt);
+
+
+extern Boolean Read2(FILE *file, void *Ptr);
+
+extern Boolean Read4(FILE *file, void *Ptr);
+
+extern Boolean Read8(FILE *file, void *Ptr);
+
+
+extern Boolean Write2(FILE *file, void *Ptr);
+
+extern Boolean Write4(FILE *file, void *Ptr);
+
+extern Boolean Write8(FILE *file, void *Ptr);
+
+#define MRead1L(Buffer) (*((Byte *)(Buffer)))
+
+#define MRead1B(Buffer) (*((Byte *)(Buffer)))
+
+extern Word MRead2L(Byte *Buffer);
+
+extern Word MRead2B(Byte *Buffer);
+
+#define MWrite1L(Buffer, Value) (*((Byte*) (Buffer))) = Value;
+
+#define MWrite1B(Buffer, Value) (*((Byte*) (Buffer))) = Value;
+
+extern void MWrite2L(Byte *Buffer, Word Value);
+
+extern void MWrite2B(Byte *Buffer, Word Value);
+
+extern LongWord MRead4L(Byte *Buffer);
+
+extern LongWord MRead4B(Byte *Buffer);
+
+extern void MWrite4L(Byte *Buffer, LongWord Value);
+
+extern void MWrite4B(Byte *Buffer, LongWord Value);
+
+#ifdef HAS64
+extern QuadWord MRead8L(Byte *Buffer);
+
+extern QuadWord MRead8B(Byte *Buffer);
+
+extern void MWrite8L(Byte *Buffer, QuadWord Value);
+
+extern void MWrite8B(Byte *Buffer, QuadWord Value);
+#endif
+
+extern void endian_init(void);
+#endif /* _MYENDIAN_H */
diff --git a/aslshim/errmsg.c b/aslshim/errmsg.c
new file mode 100644 (file)
index 0000000..57f4965
--- /dev/null
@@ -0,0 +1,550 @@
+/* errmsg.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* Cross Assembler                                                           */
+/*                                                                           */
+/* Error message definition & associated checking                            */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <string.h>
+#include <stdarg.h>
+#include "strutil.h"
+
+#include "datatypes.h"
+#include "asmdef.h"
+#include "asmpars.h"
+#include "strutil.h"
+#include "asmsub.h"
+#include "nlmessages.h"
+#include "cpulist.h"
+#include "as.rsc"
+#include "errmsg.h"
+
+static tErrorNum GetDefaultCPUErrorNum(tErrorNum ThisNum)
+{
+  return ThisNum ? ThisNum : ErrNum_InstructionNotSupported;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     report_error_range(LargeInt value, LargeInt ref, char comp_op, tErrorNum error_num, const tStrComp *p_comp)
+ * \brief  core routine to emit range error message
+ * \param  value offending value
+ * \param  ref reference value was checked against
+ * \param  comp_op comparison op that failed
+ * \param  error_num error message to emit
+ * \param  p_comp source argument (may be NULL)
+ * \return constant False
+ * ------------------------------------------------------------------------ */
+
+static Boolean report_error_range(LargeInt value, LargeInt ref, char comp_op, tErrorNum error_num, const tStrComp *p_comp)
+{
+  char s[100];
+
+  as_snprintf(s, sizeof(s), "%llld %c %llld", value, comp_op, ref);
+  if (p_comp)
+    WrXErrorPos(error_num, s, &p_comp->Pos);
+  else
+    WrXError(error_num, s);
+  return False;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkRangePos(LargeInt Value, LargeInt Min, LargeInt Max, const tStrComp *p_comp)
+ * \brief  check whether integer is in range and issue error if not
+ * \param  Value value to check
+ * \param  Min minimum of range
+ * \param  Max maximum of range
+ * \param  p_comp corresponding source argument (may be NULL)
+ * \return TRUE if in-range and no error
+ * ------------------------------------------------------------------------ */
+
+Boolean ChkRangePos(LargeInt Value, LargeInt Min, LargeInt Max, const tStrComp *p_comp)
+{
+  if (Value < Min)
+    return report_error_range(Value, Min, '<', ErrNum_UnderRange, p_comp);
+  else if (Value > Max)
+    return report_error_range(Value, Max, '>', ErrNum_OverRange, p_comp);
+  else
+    return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkRangeWarnPos(LargeInt Value, LargeInt Min, LargeInt Max, const tStrComp *p_comp)
+ * \brief  check whether integer is in range and issue error if not
+ * \param  Value value to check
+ * \param  Min minimum of range
+ * \param  Max maximum of range
+ * \param  p_comp corresponding source argument (may be NULL)
+ * \return TRUE if in-range and no error
+ * ------------------------------------------------------------------------ */
+
+Boolean ChkRangeWarnPos(LargeInt Value, LargeInt Min, LargeInt Max, const tStrComp *p_comp)
+{
+  if (Value < Min)
+    return report_error_range(Value, Min, '<', ErrNum_WUnderRange, p_comp);
+  else if (Value > Max)
+    return report_error_range(Value, Max, '>', ErrNum_WOverRange, p_comp);
+  else
+    return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkArgCntExtPos(int ThisCnt, int MinCnt, int MaxCnt, const struct sLineComp *pComp)
+ * \brief  check whether argument count is within given range and issue error if not
+ * \param  ThisCnt count to check
+ * \param  MinCnt minimum allowed count
+ * \param  MaxCnt maximum allowed count
+ * \param  pComp position in source line (optional)
+ * \return TRUE if in-range and no error
+ * ------------------------------------------------------------------------ */
+
+Boolean ChkArgCntExtPos(int ThisCnt, int MinCnt, int MaxCnt, const struct sLineComp *pComp)
+{
+  if ((ThisCnt < MinCnt) || (ThisCnt > MaxCnt))
+  {
+    char Str[100];
+
+    if (MinCnt != MaxCnt)
+      as_snprintf(Str, sizeof(Str), getmessage(Num_ErrMsgArgCntFromTo), MinCnt, MaxCnt, ThisCnt);
+    else switch (MinCnt)
+    {
+      case 0:
+        as_snprintf(Str, sizeof(Str), getmessage(Num_ErrMsgArgCntZero), ThisCnt);
+        break;
+      case 1:
+        as_snprintf(Str, sizeof(Str), getmessage(Num_ErrMsgArgCntOne), ThisCnt);
+        break;
+      default:
+        as_snprintf(Str, sizeof(Str), getmessage(Num_ErrMsgArgCntMulti), MinCnt, ThisCnt);
+    }
+    if (pComp)
+      WrXErrorPos(ErrNum_WrongArgCnt, Str, pComp);
+    else
+      WrXError(ErrNum_WrongArgCnt, Str);
+    return False;
+  }
+  else
+    return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkArgCntExtEitherOr(int ThisCnt, int EitherCnt, int OrCnt)
+ * \brief  check whether argument count is according to given values and issue error if not
+ * \param  ThisCnt count to check
+ * \param  EitherCnt allowed count
+ * \param  OrCnt other allowed count
+ * \return TRUE if count OK and no error
+ * ------------------------------------------------------------------------ */
+
+Boolean ChkArgCntExtEitherOr(int ThisCnt, int EitherCnt, int OrCnt)
+{
+  if ((ThisCnt != EitherCnt) && (ThisCnt != OrCnt))
+  {
+    char Str[100];
+
+    as_snprintf(Str, sizeof(Str), getmessage(Num_ErrMsgArgCntEitherOr), EitherCnt, OrCnt, ThisCnt);
+    WrXError(ErrNum_WrongArgCnt, Str);
+    return False;
+  }
+  else
+    return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkMinCPUExt(CPUVar MinCPU, tErrorNum ErrorNum)
+ * \brief  check whether currently selected CPU is at least given one and issue error if not
+ * \param  MinCPU minimum required CPU
+ * \param  ErrorNum error to issue if not OK (0 = default message)
+ * \return TRUE if currently selected CPU is OK and no error
+ * ------------------------------------------------------------------------ */
+
+extern Boolean ChkMinCPUExt(CPUVar MinCPU, tErrorNum ErrorNum)
+{
+  if (MomCPU < MinCPU)
+  {
+    const tCPUDef *pCPUDef;
+    ErrorNum = GetDefaultCPUErrorNum(ErrorNum);
+
+    pCPUDef = LookupCPUDefByVar(MinCPU);
+    if (pCPUDef)
+    {
+      char Str[100];
+
+      as_snprintf(Str, sizeof(Str), getmessage(Num_ErrMsgMinCPUSupported), pCPUDef->Name);
+      WrXError(ErrorNum, Str);
+    }
+    else
+      WrError(ErrorNum);
+    return False;
+  }
+  return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     AChkMinCPUExtPos(CPUVar MinCPU, tErrorNum ErrorNum, const struct sStrComp *pComp)
+ * \brief  check for minimum CPU of this addressing mode
+ * \param  MinCPU min. CPU required
+ * \param  ErrorNum error message to print
+ * \param  pComp argument to complain about
+ * \return True if CPU is OK
+ * ------------------------------------------------------------------------ */
+
+Boolean AChkMinCPUExtPos(CPUVar MinCPU, tErrorNum ErrorNum, const struct sStrComp *pComp)
+{
+  if (MomCPU < MinCPU)
+  {
+    WrStrErrorPos(ErrorNum, pComp);
+    return False;
+  }
+  return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkMaxCPUExt(CPUVar MaxCPU, tErrorNum ErrorNum)
+ * \brief  check whether currently selected CPU is at most given one and issue error if not
+ * \param  MaxCPU maximum required CPU
+ * \param  ErrorNum error to issue if not OK (0 = default message)
+ * \return TRUE if currently selected CPU is OK and no error
+ * ------------------------------------------------------------------------ */
+
+extern Boolean ChkMaxCPUExt(CPUVar MaxCPU, tErrorNum ErrorNum)
+{
+  if (MomCPU > MaxCPU)
+  {
+    const tCPUDef *pCPUDef;
+    ErrorNum = GetDefaultCPUErrorNum(ErrorNum);
+
+    pCPUDef = LookupCPUDefByVar(MaxCPU);
+    if (pCPUDef)
+    {
+      char Str[100];
+
+      as_snprintf(Str, sizeof(Str), getmessage(Num_ErrMsgMaxCPUSupported), pCPUDef->Name);
+      WrXError(ErrorNum, Str);
+    }
+    else
+      WrError(ErrorNum);
+    return False;
+  }
+  return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkRangeCPUExt(CPUVar MinCPU, CPUVar MaxCPU, tErrorNum ErrorNum)
+ * \brief  check whether currently selected CPU is within given range
+ * \param  MinCPU minimum required CPU
+ * \param  MaxCPU maximum required CPU
+ * \param  ErrorNum error to issue if not OK (0 = default message)
+ * \return TRUE if currently selected CPU is OK and no error
+ * ------------------------------------------------------------------------ */
+
+extern Boolean ChkRangeCPUExt(CPUVar MinCPU, CPUVar MaxCPU, tErrorNum ErrorNum)
+{
+  if ((MomCPU < MinCPU) || (MomCPU > MaxCPU))
+  {
+    const tCPUDef *pCPUDefMin, *pCPUDefMax;
+    ErrorNum = GetDefaultCPUErrorNum(ErrorNum);
+
+    pCPUDefMin = LookupCPUDefByVar(MinCPU);
+    pCPUDefMax = LookupCPUDefByVar(MaxCPU);
+    if (pCPUDefMin && pCPUDefMax)
+    {
+      char Str[100];
+
+      as_snprintf(Str, sizeof(Str), getmessage(Num_ErrMsgRangeCPUSupported), pCPUDefMin->Name, pCPUDefMax->Name);
+      WrXError(ErrorNum, Str);
+    }
+    else
+      WrError(ErrorNum);
+    return False;
+  }
+  return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkMinCPUExt(CPUVar MatchCPU, tErrorNum ErrorNum)
+ * \brief  check whether currently selected CPU is given one and issue error if not
+ * \param  MatchCPU required CPU
+ * \param  ErrorNum error to issue if not OK (0 = default message)
+ * \return TRUE if currently selected CPU is OK and no error
+ * ------------------------------------------------------------------------ */
+
+extern Boolean ChkExactCPUExt(CPUVar MatchCPU, tErrorNum ErrorNum)
+{
+  if (MomCPU != MatchCPU)
+  {
+    const tCPUDef *pCPUDef;
+    ErrorNum = GetDefaultCPUErrorNum(ErrorNum);
+
+    pCPUDef = LookupCPUDefByVar(MatchCPU);
+    if (pCPUDef)
+    {
+      char Str[100];
+
+      as_snprintf(Str, sizeof(Str), "%s%s%s", getmessage(Num_ErrMsgOnlyCPUSupported1), pCPUDef->Name, getmessage(Num_ErrMsgOnlyCPUSupported2));
+      WrXError(ErrorNum, Str);
+    }
+    else
+      WrError(ErrorNum);
+    return False;
+  }
+  return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkExcludeCPUExt(CPUVar MatchCPU, tErrorNum ErrorNum)
+ * \brief  check whether currently selected CPU is NOT given one and issue error if not
+ * \param  MatchCPU disallowed CPU
+ * \param  ErrorNum error to issue if not OK (0 = default message)
+ * \return TRUE if currently selected CPU is OK and no error
+ * ------------------------------------------------------------------------ */
+
+typedef struct
+{
+  const tCPUDef *pExcludeCPUDef;
+  const tCPUDef *pLastCPUDef;
+  String Str;
+  Boolean First;
+  Word ExcludeMask;
+  CPUVar ExcludeCPUFirst;
+} tExcludeContext;
+
+static void IterateExclude(const tCPUDef *pThisCPUDef, void *pUser)
+{
+  tExcludeContext *pContext = (tExcludeContext*)pUser;
+
+  /* ignore other families or aliases */
+
+  if (pThisCPUDef)
+  {
+    if ((pThisCPUDef->SwitchProc != pContext->pExcludeCPUDef->SwitchProc)
+     || ((1 << (pThisCPUDef->Number - pContext->ExcludeCPUFirst)) & pContext->ExcludeMask)
+     || (pThisCPUDef->Number != pThisCPUDef->Orig))
+      return;
+  }
+
+  if (pContext->pLastCPUDef)
+  {
+    if (!pContext->First)
+      strmaxcat(pContext->Str, pThisCPUDef ? ", " : getmessage(Num_ErrMsgOnlyCPUSupportedOr), sizeof(pContext->Str));
+    strmaxcat(pContext->Str, pContext->pLastCPUDef->Name, sizeof(pContext->Str));
+    pContext->First = False;
+  }
+  pContext->pLastCPUDef = pThisCPUDef;
+}
+
+extern Boolean ChkExcludeCPUExt(CPUVar MatchCPU, tErrorNum ErrorNum)
+{
+  tExcludeContext Context;
+
+  if (MomCPU != MatchCPU)
+    return True;
+
+  Context.pExcludeCPUDef = LookupCPUDefByVar(MatchCPU);
+
+  if (Context.pExcludeCPUDef)
+  {
+    *Context.Str = '\0';
+    Context.First = True;
+    Context.pLastCPUDef = NULL;
+    Context.ExcludeMask = 1;
+    Context.ExcludeCPUFirst = MatchCPU;
+    strmaxcat(Context.Str, getmessage(Num_ErrMsgOnlyCPUSupported1), sizeof(Context.Str));
+    IterateCPUList(IterateExclude, &Context);
+    IterateExclude(NULL, &Context);
+    WrXError(GetDefaultCPUErrorNum(ErrorNum), Context.Str);
+  }
+  else
+    WrError(GetDefaultCPUErrorNum(ErrorNum));
+  return False;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkExcludeCPUList(int ErrorNum, ...)
+ * \brief  check whether currently selected CPU is one of the given ones and issue error if it is
+ * \param  ErrorNum error to issue if not OK (0 = default message)
+ * \param  ... List of CPUs terminated by CPUNone
+ * \return Index (-1...-n) of matching CPU or 0 if current CPU does not match any
+ * ------------------------------------------------------------------------ */
+
+int ChkExcludeCPUList(int ErrorNum, ...)
+{
+  va_list ap;
+  int Index = -1, FoundIndex = 0;
+  CPUVar ThisCPU;
+
+  va_start(ap, ErrorNum);
+  while (True)
+  {
+    ThisCPU = va_arg(ap, CPUVar);
+    if (ThisCPU == CPUNone)
+      break;
+    if (MomCPU == ThisCPU)
+    {
+      FoundIndex = Index;
+      break;
+    }
+  }
+  va_end(ap);
+
+  if (FoundIndex < 0)
+  {
+    tExcludeContext Context;
+
+    *Context.Str = '\0';
+    Context.First = True;
+    Context.pExcludeCPUDef =
+    Context.pLastCPUDef = NULL;
+    strmaxcat(Context.Str, getmessage(Num_ErrMsgOnlyCPUSupported1), sizeof(Context.Str));
+
+    /* convert vararg list to bitmap */
+
+    Context.ExcludeMask = 0;
+    Context.ExcludeCPUFirst = CPUNone;
+    va_start(ap, ErrorNum);
+    while (TRUE)
+    {
+      ThisCPU = va_arg(ap, CPUVar);
+      if (ThisCPU == CPUNone)
+        break;
+      if (!Context.pExcludeCPUDef)
+        Context.pExcludeCPUDef = LookupCPUDefByVar(ThisCPU);
+      if (Context.ExcludeCPUFirst == CPUNone)
+      {
+        Context.ExcludeCPUFirst = ThisCPU;
+        Context.ExcludeMask = 1;
+      }
+      else if (ThisCPU > Context.ExcludeCPUFirst)
+        Context.ExcludeMask |= 1 << (ThisCPU - Context.ExcludeCPUFirst);
+      else if (ThisCPU < Context.ExcludeCPUFirst)
+      {
+        Context.ExcludeMask <<= Context.ExcludeCPUFirst - ThisCPU;
+        Context.ExcludeMask |= 1;
+        Context.ExcludeCPUFirst = ThisCPU;
+      }
+    }
+    va_end(ap);
+    IterateCPUList(IterateExclude, &Context);
+    IterateExclude(NULL, &Context);
+    WrXError(GetDefaultCPUErrorNum((tErrorNum)ErrorNum), Context.Str);
+  }
+
+  return FoundIndex;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkExactCPUList(int ErrorNum)
+ * \brief  check whether currently selected CPU is one of the given ones and issue error if not
+ * \param  ErrorNum error to issue if not OK (0 = default message)
+ * \param  ... List of CPUs terminated by CPUNone
+ * \return Index (0...) of matching CPU or -1 if current CPU does not match
+ * ------------------------------------------------------------------------ */
+
+extern int ChkExactCPUList(int ErrorNum, ...)
+{
+  va_list ap;
+  String Str;
+  CPUVar ThisCPU, NextCPU;
+  const tCPUDef *pCPUDef;
+  Boolean First = True;
+  int FoundIndex = 0;
+
+  va_start(ap, ErrorNum);
+  while (True)
+  {
+    ThisCPU = va_arg(ap, CPUVar);
+    if ((ThisCPU == CPUNone) || (MomCPU == ThisCPU))
+      break;
+    FoundIndex++;
+  }
+  va_end(ap);
+  if (ThisCPU != CPUNone)
+    return FoundIndex;
+
+  va_start(ap, ErrorNum);
+  *Str = '\0';
+  strmaxcat(Str, getmessage(Num_ErrMsgOnlyCPUSupported1), sizeof(Str));
+  ThisCPU = CPUNone;
+  while (True)
+  {
+    NextCPU = va_arg(ap, CPUVar);
+    pCPUDef = (ThisCPU != CPUNone) ? LookupCPUDefByVar(ThisCPU) : NULL;
+    if (pCPUDef)
+    {
+      if (!First)
+        strmaxcat(Str, (NextCPU == CPUNone) ? getmessage(Num_ErrMsgOnlyCPUSupportedOr) : ", ", sizeof(Str));
+      strmaxcat(Str, pCPUDef->Name, sizeof(Str));
+      First = False;
+    }
+    if (NextCPU == CPUNone)
+      break;
+    ThisCPU = NextCPU;
+  }
+  va_end(ap);
+  strmaxcat(Str, getmessage(Num_ErrMsgOnlyCPUSupported2), sizeof(Str));
+  WrXError(GetDefaultCPUErrorNum((tErrorNum)ErrorNum), Str);
+  return -1;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkExactCPUMaskExt(Word CPUMask, CPUVar FirstCPU, tErrorNum ErrorNum)
+ * \brief  check whether currently selected CPU is one of the given ones and issue error if not
+ * \param  CPUMask bit mask of allowed CPUs
+ * \param  CPUVar CPU corresponding to bit 0 in mask
+ * \param  ErrorNum error to issue if not OK (0 = default message)
+ * \param  ... List of CPUs terminated by CPUNone
+ * \return Index (0...) of matching CPU or -1 if current CPU does not match
+ * ------------------------------------------------------------------------ */
+
+int ChkExactCPUMaskExt(Word CPUMask, CPUVar FirstCPU, tErrorNum ErrorNum)
+{
+  int Bit = MomCPU - FirstCPU;
+  String Str;
+  const tCPUDef *pCPUDef;
+  Boolean First = True;
+  CPUVar ThisCPU;
+
+  if (CPUMask & (1 << Bit))
+    return Bit;
+
+  *Str = '\0';
+  strmaxcat(Str, getmessage(Num_ErrMsgOnlyCPUSupported1), sizeof(Str));
+  for (Bit = 0, ThisCPU = FirstCPU; Bit < 16; Bit++, ThisCPU++)
+  {
+    if (!(CPUMask & (1 << Bit)))
+      continue;
+    CPUMask &= ~(1 << Bit);
+    pCPUDef = LookupCPUDefByVar(ThisCPU);
+    if (pCPUDef)
+    {
+      if (!First)
+        strmaxcat(Str, CPUMask ? ", " : getmessage(Num_ErrMsgOnlyCPUSupportedOr), sizeof(Str));
+      strmaxcat(Str, pCPUDef->Name, sizeof(Str));
+      First = False;
+    }
+  }
+  strmaxcat(Str, getmessage(Num_ErrMsgOnlyCPUSupported2), sizeof(Str));
+  WrXError(ErrorNum ? ErrorNum : ErrNum_InstructionNotSupported, Str);
+  return -1;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkSamePage(LargeWord Addr1, LargeWord Addr2, unsigned PageBits)
+ * \brief  check whether two addresses are of same page
+ * \param  CurrAddr, DestAddr addresses to check
+ * \param  PageBits page size in bits
+ * \param  DestFlags symbol flags of DestAddr
+ * \return TRUE if OK
+ * ------------------------------------------------------------------------ */
+
+Boolean ChkSamePage(LargeWord CurrAddr, LargeWord DestAddr, unsigned PageBits, tSymbolFlags DestFlags)
+{
+  LargeWord Mask = ~((1ul << PageBits) - 1);
+  Boolean Result = ((CurrAddr & Mask) == (DestAddr & Mask))
+                || mFirstPassUnknownOrQuestionable(DestFlags);
+  if (!Result)
+    WrError(ErrNum_TargOnDiffPage);
+  return Result;
+}
diff --git a/aslshim/errmsg.h b/aslshim/errmsg.h
new file mode 100644 (file)
index 0000000..79994e0
--- /dev/null
@@ -0,0 +1,311 @@
+#ifndef _ERRMSG_H
+#define _ERRMSG_H
+/* errmsg.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* Cross Assembler                                                           */
+/*                                                                           */
+/* Error message definition & associated checking                            */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "cpulist.h"
+#include "symflags.h"
+#include "datatypes.h"
+
+typedef enum
+{
+  ErrNum_None = 0,
+  ErrNum_UselessDisp = 5,
+  ErrNum_ShortAddrPossible = 10,
+  ErrNum_ShortJumpPossible = 20,
+  ErrNum_NoShareFile = 30,
+  ErrNum_BigDecFloat = 40,
+  ErrNum_PrivOrder = 50,
+  ErrNum_DistNull = 60,
+  ErrNum_WrongSegment = 70,
+  ErrNum_InAccSegment = 75,
+  ErrNum_PhaseErr = 80,
+  ErrNum_Overlap = 90,
+  ErrNum_OverlapReg = 95,
+  ErrNum_NoCaseHit = 100,
+  ErrNum_InAccPage = 110,
+  ErrNum_RMustBeEven = 120,
+  ErrNum_Obsolete = 130,
+  ErrNum_Unpredictable = 140,
+  ErrNum_AlphaNoSense = 150,
+  ErrNum_Senseless = 160,
+  ErrNum_RepassUnknown = 170,
+  ErrNum_AddrNotAligned = 180,
+  ErrNum_IOAddrNotAllowed = 190,
+  ErrNum_Pipeline = 200,
+  ErrNum_DoubleAdrRegUse = 210,
+  ErrNum_NotBitAddressable = 220,
+  ErrNum_StackNotEmpty = 230,
+  ErrNum_NULCharacter = 240,
+  ErrNum_PageCrossing = 250,
+  ErrNum_WUnderRange = 255,
+  ErrNum_WOverRange = 260,
+  ErrNum_NegDUP = 270,
+  ErrNum_ConvIndX = 280,
+  ErrNum_NullResMem = 290,
+  ErrNum_BitNumberTruncated = 300,
+  ErrNum_InvRegisterPointer = 310,
+  ErrNum_MacArgRedef = 320,
+  ErrNum_Deprecated = 330,
+  ErrNum_SrcLEThanDest = 340,
+  ErrNum_TrapValidInstruction = 350,
+  ErrNum_PaddingAdded = 360,
+  ErrNum_RegNumWraparound = 370,
+  ErrNum_IndexedForIndirect = 380,
+  ErrNum_DoubleDef = 1000,
+  ErrNum_SymbolUndef = 1010,
+  ErrNum_InvSymName = 1020,
+  ErrNum_InvFormat = 1090,
+  ErrNum_UseLessAttr = 1100,
+  ErrNum_TooLongAttr = 1105,
+  ErrNum_UndefAttr = 1107,
+  ErrNum_WrongArgCnt = 1110,
+  ErrNum_CannotSplitArg = 1112,
+  ErrNum_WrongOptCnt = 1115,
+  ErrNum_OnlyImmAddr = 1120,
+  ErrNum_InvOpSize = 1130,
+  ErrNum_ConfOpSizes = 1131,
+  ErrNum_UndefOpSizes = 1132,
+  ErrNum_StringOrIntButFloat = 1133,
+  ErrNum_IntButFloat = 1134,
+  /* ErrNum_InvOpType = 1135, */
+  ErrNum_FloatButString = 1136,
+  ErrNum_OpTypeMismatch = 1137,
+  ErrNum_StringButInt = 1138,
+  ErrNum_StringButFloat = 1139,
+  ErrNum_TooManyArgs = 1140,
+  ErrNum_IntButString = 1141,
+  ErrNum_IntOrFloatButString = 1142,
+  ErrNum_ExpectString = 1143,
+  ErrNum_ExpectInt = 1144,
+  ErrNum_StringOrIntOrFloatButReg = 1145,
+  ErrNum_ExpectIntOrString = 1146,
+  ErrNum_ExpectReg = 1147,
+  ErrNum_RegWrongTarget = 1148,
+  ErrNum_NoRelocs = 1150,
+  ErrNum_UnresRelocs = 1155,
+  ErrNum_Unexportable = 1156,
+  ErrNum_UnknownInstruction = 1200,
+  ErrNum_BrackErr = 1300,
+  ErrNum_DivByZero = 1310,
+  ErrNum_UnderRange = 1315,
+  ErrNum_OverRange = 1320,
+  ErrNum_NotPwr2 = 1322,
+  ErrNum_NotAligned = 1325,
+  ErrNum_DistTooBig = 1330,
+  ErrNum_InAccReg = 1335,
+  ErrNum_NoShortAddr = 1340,
+  ErrNum_InvAddrMode = 1350,
+  ErrNum_AddrMustBeEven = 1351,
+  ErrNum_AddrMustBeAligned = 1352,
+  ErrNum_InvParAddrMode = 1355,
+  ErrNum_UndefCond = 1360,
+  ErrNum_IncompCond = 1365,
+  ErrNum_UnknownFlag = 1366,
+  ErrNum_DuplicateFlag = 1367,
+  ErrNum_UnknownInt = 1368,
+  ErrNum_DuplicateInt = 1369,
+  ErrNum_JmpDistTooBig = 1370,
+  ErrNum_DistIsOdd = 1375,
+  ErrNum_SkipTargetMismatch = 1376,
+  ErrNum_InvShiftArg = 1380,
+  ErrNum_Range18 = 1390,
+  ErrNum_Only1 = 1391,
+  ErrNum_ShiftCntTooBig = 1400,
+  ErrNum_InvRegList = 1410,
+  ErrNum_InvCmpMode = 1420,
+  ErrNum_InvCPUType = 1430,
+  ErrNum_InvFPUType = 1431,
+  ErrNum_InvPMMUType = 1432,
+  ErrNum_InvCtrlReg = 1440,
+  ErrNum_InvPMMUReg = 1444,
+  ErrNum_InvReg = 1445,
+  ErrNum_DoubleReg = 1446,
+  ErrNum_RegBankMismatch = 1447,
+  ErrNum_UndefRegSize = 1448,
+  ErrNum_InvOpOnReg = 1449,
+  ErrNum_NoSaveFrame = 1450,
+  ErrNum_NoRestoreFrame = 1460,
+  ErrNum_UnknownMacArg = 1465,
+  ErrNum_MissEndif = 1470,
+  ErrNum_InvIfConst = 1480,
+  ErrNum_DoubleSection = 1483,
+  ErrNum_InvSection = 1484,
+  ErrNum_MissingEndSect = 1485,
+  ErrNum_WrongEndSect = 1486,
+  ErrNum_NotInSection = 1487,
+  ErrNum_UndefdForward = 1488,
+  ErrNum_ContForward = 1489,
+  ErrNum_InvFuncArgCnt = 1490,
+  ErrNum_MsgMissingLTORG = 1495,
+  ErrNum_InstructionNotSupported = 1500,
+  ErrNum_FPUNotEnabled = 1501,
+  ErrNum_PMMUNotEnabled = 1502,
+  ErrNum_FullPMMUNotEnabled = 1503,
+  ErrNum_Z80SyntaxNotEnabled = 1504,
+  ErrNum_AddrModeNotSupported = 1505,
+  ErrNum_Z80SyntaxExclusive = 1506,
+  ErrNum_FPUInstructionNotSupported = 1507,
+  ErrNum_CustomNotEnabled = 1508,
+  ErrNum_InvBitPos = 1510,
+  ErrNum_OnlyOnOff = 1520,
+  ErrNum_StackEmpty = 1530,
+  ErrNum_NotOneBit = 1540,
+  ErrNum_MissingStruct = 1550,
+  ErrNum_OpenStruct = 1551,
+  ErrNum_WrongStruct = 1552,
+  ErrNum_PhaseDisallowed = 1553,
+  ErrNum_InvStructDir = 1554,
+  ErrNum_DoubleStruct = 1555,
+  ErrNum_UnresolvedStructRef = 1556,
+  ErrNum_DuplicateStructElem = 1557,
+  ErrNum_NotRepeatable = 1560,
+  ErrNum_ShortRead = 1600,
+  ErrNum_UnknownCodepage = 1610,
+  ErrNum_RomOffs063 = 1700,
+  ErrNum_InvFCode = 1710,
+  ErrNum_InvFMask = 1720,
+  ErrNum_InvMMUReg = 1730,
+  ErrNum_Level07 = 1740,
+  ErrNum_InvBitMask = 1750,
+  ErrNum_InvRegPair = 1760,
+  ErrNum_OpenMacro = 1800,
+  ErrNum_OpenIRP = 1801,
+  ErrNum_OpenIRPC = 1802,
+  ErrNum_OpenREPT = 1803,
+  ErrNum_OpenWHILE = 1804,
+  ErrNum_EXITMOutsideMacro = 1805,
+  ErrNum_TooManyMacParams = 1810,
+  ErrNum_UndefKeyArg = 1811,
+  ErrNum_NoPosArg = 1812,
+  ErrNum_DoubleMacro = 1815,
+  ErrNum_FirstPassCalc = 1820,
+  ErrNum_TooManyNestedIfs = 1830,
+  ErrNum_MissingIf = 1840,
+  ErrNum_RekMacro = 1850,
+  ErrNum_UnknownFunc = 1860,
+  ErrNum_InvFuncArg = 1870,
+  ErrNum_FloatOverflow = 1880,
+  ErrNum_InvArgPair = 1890,
+  ErrNum_NotOnThisAddress = 1900,
+  ErrNum_NotFromThisAddress = 1905,
+  ErrNum_TargOnDiffPage = 1910,
+  ErrNum_TargOnDiffSection = 1911,
+  ErrNum_CodeOverflow = 1920,
+  ErrNum_AdrOverflow = 1925,
+  ErrNum_MixDBDS = 1930,
+  ErrNum_NotInStruct = 1940,
+  ErrNum_ParNotPossible = 1950,
+  ErrNum_InvSegment = 1960,
+  ErrNum_UnknownSegment = 1961,
+  ErrNum_UnknownSegReg = 1962,
+  ErrNum_InvString = 1970,
+  ErrNum_InvRegName = 1980,
+  ErrNum_InvArg = 1985,
+  ErrNum_NoIndir = 1990,
+  ErrNum_NotInThisSegment = 1995,
+  ErrNum_NotInMaxmode = 1996,
+  ErrNum_OnlyInMaxmode = 1997,
+  ErrNum_PackCrossBoundary = 2000,
+  ErrNum_UnitMultipleUsed = 2001,
+  ErrNum_MultipleLongRead = 2002,
+  ErrNum_MultipleLongWrite = 2003,
+  ErrNum_LongReadWithStore = 2004,
+  ErrNum_TooManyRegisterReads = 2005,
+  ErrNum_OverlapDests = 2006,
+  ErrNum_TooManyBranchesInExPacket = 2008,
+  ErrNum_CannotUseUnit = 2009,
+  ErrNum_InvEscSequence = 2010,
+  ErrNum_InvPrefixCombination = 2020,
+  ErrNum_ConstantRedefinedAsVariable = 2030,
+  ErrNum_VariableRedefinedAsConstant = 2035,
+  ErrNum_StructNameMissing = 2040,
+  ErrNum_EmptyArgument = 2050,
+  ErrNum_Unimplemented = 2060,
+  ErrNum_FreestandingUnnamedStruct = 2070,
+  ErrNum_STRUCTEndedByENDUNION = 2080,
+  ErrNum_AddrOnDifferentPage = 2090,
+  ErrNum_UnknownMacExpMod = 2100,
+  ErrNum_TooManyMacExpMod = 2105,
+  ErrNum_ConflictingMacExpMod = 2110,
+  ErrNum_InvalidPrepDir = 2120,
+  ErrNum_ExpectedError = 2130,
+  ErrNum_NoNestExpect = 2140,
+  ErrNum_MissingENDEXPECT = 2150,
+  ErrNum_MissingEXPECT = 2160,
+  ErrNum_NoDefCkptReg = 2170,
+  ErrNum_InvBitField = 2180,
+  ErrNum_ArgValueMissing = 2190,
+  ErrNum_UnknownArg = 2200,
+  ErrNum_IndexRegMustBe16Bit = 2210,
+  ErrNum_IOAddrRegMustBe16Bit = 2211,
+  ErrNum_SegAddrRegMustBe32Bit = 2212,
+  ErrNum_NonSegAddrRegMustBe16Bit = 2213,
+  ErrNum_InvStructArgument = 2220,
+  ErrNum_TooManyArrayDimensions = 2221,
+  ErrNum_InvIntFormat = 2230,
+  ErrNum_InvIntFormatList = 2231,
+  ErrNum_InvScale = 2240,
+  ErrNum_ConfStringOpt = 2250,
+  ErrNum_UnknownStringOpt = 2251,
+  ErrNum_InvCacheInvMode = 2252,
+  ErrNum_InvCfgList = 2253,
+  ErrNum_ConfBitBltOpt = 2254,
+  ErrNum_UnknownBitBltOpt = 2255,
+  ErrNum_InternalError = 10000,
+  ErrNum_OpeningFile = 10001,
+  ErrNum_ListWrError = 10002,
+  ErrNum_FileReadError = 10003,
+  ErrNum_FileWriteError = 10004,
+  ErrNum_HeapOvfl = 10006,
+  ErrNum_StackOvfl = 10007,
+  ErrNum_MaxIncLevelExceeded = 10008
+} tErrorNum;
+
+struct sLineComp;
+struct sStrComp;
+
+extern Boolean ChkRangePos(LargeInt Value, LargeInt Min, LargeInt Max, const struct sStrComp *p_comp);
+#define ChkRange(Value, Min, Max) ChkRangePos(Value, Min, Max, NULL)
+extern Boolean ChkRangeWarnPos(LargeInt Value, LargeInt Min, LargeInt Max, const struct sStrComp *p_comp);
+#define ChkRangeWarn(Value, Min, Max) ChkRangeWarnPos(Value, Min, Max, NULL)
+
+extern Boolean ChkArgCntExtPos(int ThisCnt, int MinCnt, int MaxCnt, const struct sLineComp *pComp);
+#define ChkArgCnt(MinCnt, MaxCnt) ChkArgCntExtPos(ArgCnt, MinCnt, MaxCnt, NULL)
+#define ChkArgCntExt(ThisCnt, MinCnt, MaxCnt) ChkArgCntExtPos(ThisCnt, MinCnt, MaxCnt, NULL)
+extern Boolean ChkArgCntExtEitherOr(int ThisCnt, int EitherCnt, int OrCnt);
+
+extern Boolean ChkMinCPUExt(CPUVar MinCPU, tErrorNum ErrorNum);
+#define ChkMinCPU(MinCPU) ChkMinCPUExt(MinCPU, ErrNum_InstructionNotSupported)
+
+extern Boolean AChkMinCPUExtPos(CPUVar MinCPU, tErrorNum ErrorNum, const struct sStrComp *pComp);
+#define AChkMinCPUPos(MinCPU, pComp) AChkMinCPUExtPos(MinCPU, ErrNum_AddrModeNotSupported, pComp)
+
+extern Boolean ChkMaxCPUExt(CPUVar MaxCPU, tErrorNum ErrorNum);
+#define ChkMaxCPU(MaxCPU) ChkMaxCPUExt(MaxCPU, ErrNum_InstructionNotSupported)
+
+extern Boolean ChkExactCPUExt(CPUVar CheckCPU, tErrorNum ErrorNum);
+#define ChkExactCPU(CheckCPU) ChkExactCPUExt(CheckCPU, ErrNum_InstructionNotSupported)
+
+extern Boolean ChkRangeCPUExt(CPUVar MinCPU, CPUVar MaxCPU, tErrorNum ErrorNum);
+#define ChkRangeCPU(MinCPU, MaxCPU) ChkRangeCPUExt(MinCPU, MaxCPU, ErrNum_InstructionNotSupported)
+
+extern Boolean ChkExcludeCPUExt(CPUVar CheckCPU, tErrorNum ErrorNum);
+#define ChkExcludeCPU(CheckCPU) ChkExcludeCPUExt(CheckCPU, ErrNum_InstructionNotSupported)
+
+extern int ChkExactCPUList(int ErrorNum, ...);
+extern int ChkExcludeCPUList(int ErrorNum, ...);
+
+extern int ChkExactCPUMaskExt(Word CPUMask, CPUVar FirstCPU, tErrorNum ErrorNum);
+#define ChkExactCPUMask(CPUMask, FirstCPU) ChkExactCPUMaskExt(CPUMask, FirstCPU, ErrNum_InstructionNotSupported)
+
+extern Boolean ChkSamePage(LargeWord CurrAddr, LargeWord DestAddr, unsigned PageBits, tSymbolFlags DestFlags);
+
+#endif /* _ERRMSG_H */
diff --git a/aslshim/fileformat.h b/aslshim/fileformat.h
new file mode 100644 (file)
index 0000000..fc194cf
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _FILEFORMAT_H
+#define _FILEFORMAT_H
+/* fileformat.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Definition von Konstanten fuer das P-Format                               */
+/*                                                                           */
+/* Historie: 3.12.1996 Grundsteinlegung                                      */
+/*           11. 9.1998 ROMDATA-Segment hinzugenommen                        */
+/*           12. 7.1999 RelocRec-Typ hinzugenommen                           */
+/*           19. 1.2000 Patch-Typen definiert                                */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "addrspace.h"
+
+#define FileMagic 0x1489
+
+#define FileHeaderEnd       0x00   /* Dateiende */
+#define FileHeaderStartAdr  0x80   /* Einsprungadresse absolut */
+#define FileHeaderDataRec   0x81   /* normaler Datenrecord */
+#define FileHeaderRDataRec  0x82   /* Datenrecord mit Symbolen */
+#define FileHeaderRelocRec  0x83   /* relokatibler Datenrecord */
+#define FileHeaderRRelocRec 0x84   /* relokatibler Datenrecord mit Symbolen */
+#define FileHeaderRelocInfo 0x85   /* Relokationsinformationen */
+
+/* Definition der im Code liegenden, zu patchenden Typen:
+
+   Dazu wird ein 32-Bit-Wert verwendet.  Das oberste Byte gibt den Basistyp
+   an, hier ist momentan nur 0 fuer binaere Integers definiert.  Fuer diesen
+   Fall steht in Bit 0..7 die Laenge des Integers in Bits, in Bit 20 die
+   Information, ob es sich um einen Big(1)- oder Little-Endian(0)-Typ handelt.
+   Bits 8..11 geben die Startposition bzw. Bits 12..15 die Laenge der ersten
+   Komponente im ersten Byte an, danach folgen so viele ganze Bytes wie
+   moeglich.  Bits 16 bis 19 geben die Lage der verbleibenden Bits im letzten
+   Byte an.  Bit 21 zeigt an, ob bei der Relokation addiert oder subtrahiert
+   werden soll.  Bit 22 spezifiziert 'Seitenintegers', d.h. die Adresse,
+   die an einer bestimmten Stelle eingepatcht wird, muss in den oberen (nicht
+   gespeicherten) Bits identisch zur Adresse der Patchstelle selber sein.
+   Ist Bit22=0, ist es ein normaler vorzeichenloser Int von 0...(2^n)-1
+
+   Daraus ergeben sich z. B. folgende einfachen Typen: */
+
+#define RelocTypeL8  0x00008008l
+#define RelocTypeB8  RelocTypeL8          /* :-) was wunder */
+#define RelocTypeL16 0x00008010l
+#define RelocTypeB16 0x00108010l
+#define RelocTypeL24 0x00008018l
+#define RelocTypeB24 0x00108018l
+#define RelocTypeL32 0x00008020l
+#define RelocTypeB32 0x00108020l
+#define RelocTypeL64 0x00008040l
+#define RelocTypeB64 0x00108040l
+
+#define RelocFlagBig  0x00100000l
+#define RelocFlagSUB  0x00200000l
+#define RelocBitCnt(Type) (Type & 0xff)
+#define RelocFlagPage 0x00400000l
+
+/* this is an internal symbol name used to signify the start address
+   of a segment */
+
+#define RelName_SegStart "$$$"
+
+#define RelFlag_Relative 1
+
+#endif /* _FILEFORMAT_H */
diff --git a/aslshim/function.h b/aslshim/function.h
new file mode 100644 (file)
index 0000000..6b59d17
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _FUNCTION_H
+#define _FUNCTION_H
+/* function.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* internal holder for int/float/string                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "datatypes.h"
+#include "tempresult.h"
+
+typedef struct
+{
+  const char *pName;
+  Byte MinNumArgs, MaxNumArgs;
+  Byte ArgTypes[3];
+  void (*pFunc)(TempResult *pErg, const TempResult *pArgs, unsigned ArgCnt);
+} tFunction;
+
+extern const tFunction Functions[];
+
+#endif /* _FUNCTION_H */
diff --git a/aslshim/ieeefloat.h b/aslshim/ieeefloat.h
new file mode 100644 (file)
index 0000000..ffd7844
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _IEEEFLOAT_H
+#define _IEEEFLOAT_H
+/* ieeefloat.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS                                                                        */
+/*                                                                           */
+/* IEEE Floating Point Handling                                              */
+/*                                                                           */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "datatypes.h"
+
+enum
+{
+  AS_FP_NORMAL,
+  AS_FP_SUBNORMAL,
+  AS_FP_NAN,
+  AS_FP_INFINITE
+};
+
+extern int as_fpclassify(Double inp);
+
+extern Boolean Double_2_ieee2(Double inp, Byte *pDest, Boolean NeedsBig);
+
+extern void Double_2_ieee4(Double inp, Byte *pDest, Boolean NeedsBig);
+
+extern void Double_2_ieee8(Double inp, Byte *pDest, Boolean NeedsBig);
+
+extern void Double_2_ieee10(Double inp, Byte *pDest, Boolean NeedsBig);
+
+#endif /* _IEEEFLOAT_H */
diff --git a/aslshim/intformat.c b/aslshim/intformat.c
new file mode 100644 (file)
index 0000000..61bfd08
--- /dev/null
@@ -0,0 +1,398 @@
+/* intformat.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS                                                                        */
+/*                                                                           */
+/* enums regarding integer constant notations                                */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "strutil.h"
+#include "datatypes.h"
+#include <stdlib.h>
+#include <string.h>
+
+#include "intformat.h"
+
+static const Byte BaseVals[3] =
+{
+  2, 8, 16
+};
+
+LongWord NativeIntConstModeMask, OtherIntConstModeMask;
+tIntFormatList *IntFormatList = NULL;
+tIntConstMode IntConstMode;
+Boolean IntConstModeIBMNoTerm, RelaxedMode;
+int RadixBase;
+
+static Boolean ChkIntFormatCHex(tIntCheckCtx *pCtx, char Ch)
+{
+  if ((pCtx->ExprLen > 2)
+   && (*pCtx->pExpr == '0')
+   && (RadixBase <= Ch - 'A' + 10)
+   && (as_toupper(pCtx->pExpr[1]) == Ch))
+  {
+    pCtx->pExpr += 2;
+    pCtx->ExprLen -= 2;
+    return True;
+  }
+  return False;
+}
+
+static Boolean ChkIntFormatCBin(tIntCheckCtx *pCtx, char Ch)
+{
+  if ((pCtx->ExprLen > 2)
+   && (*pCtx->pExpr == '0')
+   && (RadixBase <= Ch - 'A' + 10)
+   && (as_toupper(pCtx->pExpr[1]) == Ch))
+  {
+    const char *pRun;
+
+    for (pRun = pCtx->pExpr + 2; pRun < pCtx->pExpr + pCtx->ExprLen; pRun++)
+      if (DigitVal(*pRun, 2) < 0)
+        return False;
+    pCtx->pExpr += 2;
+    pCtx->ExprLen -= 2;
+    return True;
+  }
+  return False;
+}
+
+static Boolean ChkIntFormatMot(tIntCheckCtx *pCtx, char Ch)
+{
+  if ((pCtx->ExprLen > 1)
+   && (*pCtx->pExpr == Ch))
+  {
+    pCtx->pExpr++;
+    pCtx->ExprLen--;
+    return True;
+  }
+  return False;
+}
+
+static Boolean ChkIntFormatInt(tIntCheckCtx *pCtx, char Ch)
+{
+  if ((pCtx->ExprLen < 2) || !as_isdigit(*pCtx->pExpr))
+    return False;
+  if ((RadixBase <= Ch - 'A' + 10)
+   && (as_toupper(pCtx->pExpr[pCtx->ExprLen - 1]) == Ch))
+  {
+    pCtx->ExprLen--;
+    return True;
+  }
+  return False;
+}
+
+static Boolean ChkIntFormatIBM(tIntCheckCtx *pCtx, char Ch)
+{
+  if ((pCtx->ExprLen < 3)
+   || (as_toupper(*pCtx->pExpr) != Ch)
+   || (pCtx->pExpr[1] != '\''))
+    return False;
+  if ((pCtx->ExprLen > 3) && (pCtx->pExpr[pCtx->ExprLen - 1] == '\''))
+  {
+    pCtx->pExpr += 2;
+    pCtx->ExprLen -= 3;
+    return True;
+  }
+  else if (IntConstModeIBMNoTerm)
+  {
+    pCtx->pExpr += 2;
+    pCtx->ExprLen -= 2;
+    return True;
+  }
+  return False;
+}
+
+static Boolean ChkIntFormatCOct(tIntCheckCtx *pCtx, char Ch)
+{
+  const char *pRun;
+  UNUSED(Ch);
+
+  if ((pCtx->ExprLen < 2)
+   || (*pCtx->pExpr != '0'))
+    return False;
+  for (pRun = pCtx->pExpr + 1; pRun < pCtx->pExpr + pCtx->ExprLen; pRun++)
+    if (DigitVal(*pRun, 8) < 0)
+      return False;
+  return True;
+}
+
+static Boolean ChkIntFormatNatHex(tIntCheckCtx *pCtx, char Ch)
+{
+  const char *pRun;
+  UNUSED(Ch);
+
+  if ((pCtx->ExprLen < 2)
+   || (*pCtx->pExpr != '0'))
+    return False;
+  for (pRun = pCtx->pExpr + 1; pRun < pCtx->pExpr + pCtx->ExprLen; pRun++)
+    if (!as_isxdigit(*pRun))
+      return False;
+  return True;
+}
+
+static Boolean ChkIntFormatDef(tIntCheckCtx *pCtx, char Ch)
+{
+  UNUSED(pCtx);
+  UNUSED(Ch);
+  return True;
+}
+
+static const tIntFormatList IntFormatList_All[] =
+{
+  { ChkIntFormatCHex  , eIntFormatCHex,    16, 'X', "0xhex"  },
+  { ChkIntFormatCBin  , eIntFormatCBin,     2, 'B', "0bbin"  },
+  { ChkIntFormatMot   , eIntFormatMotHex,  16, '$', "$hex"   },
+  { ChkIntFormatMot   , eIntFormatMotBin,   2, '%', "%bin"   },
+  { ChkIntFormatMot   , eIntFormatMotOct,   8, '@', "@oct"   },
+  { ChkIntFormatInt   , eIntFormatIntHex,  16, 'H', "hexh"   },
+  { ChkIntFormatInt   , eIntFormatIntBin,   2, 'B', "binb"   },
+  { ChkIntFormatInt   , eIntFormatIntOOct,  8, 'O', "octo"   },
+  { ChkIntFormatInt   , eIntFormatIntQOct,  8, 'Q', "octq"   },
+  { ChkIntFormatIBM   , eIntFormatIBMHHex, 16, 'H', "h'hex'" },
+  { ChkIntFormatIBM   , eIntFormatIBMXHex, 16, 'X', "x'hex'" },
+  { ChkIntFormatIBM   , eIntFormatIBMBin,   2, 'B', "b'bin'" },
+  { ChkIntFormatIBM   , eIntFormatIBMOct,   8, 'O', "o'oct'" },
+  { ChkIntFormatCOct  , eIntFormatCOct,     8, '0', "0oct"   },
+  { ChkIntFormatNatHex, eIntFormatNatHex,  16, '0', "0hex"   },
+  { ChkIntFormatDef   , eIntFormatDefRadix,-1, '\0', "dec"   }, /* -1 -> RadixBase */
+  { NULL              , (tIntFormatId)0,    0, '\0', ""      }
+};
+
+/*!------------------------------------------------------------------------
+ * \fn     GetIntConstIntelSuffix(unsigned Radix)
+ * \brief  return Intel-style suffix letter fitting to number system
+ * \param  Radix req'd number system
+ * \return * to suffix string (may be empty)
+ * ------------------------------------------------------------------------ */
+
+const char *GetIntConstIntelSuffix(unsigned Radix)
+{
+  static const char BaseLetters[3] =
+  {
+    'B', 'O', 'H'
+  };
+  unsigned BaseIdx;
+
+  for (BaseIdx = 0; BaseIdx < sizeof(BaseVals) / sizeof(*BaseVals); BaseIdx++)
+    if (Radix == BaseVals[BaseIdx])
+    {
+      static char Result[2] = { '\0', '\0' };
+
+      Result[0] = BaseLetters[BaseIdx] + (HexStartCharacter - 'A');
+      return Result;
+    }
+  return "";
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     GetIntConstMotoPrefix(unsigned Radix)
+ * \brief  return Motorola-style prefix letter fitting to number system
+ * \param  Radix req'd number system
+ * \return * to prefix string (may be empty)
+ * ------------------------------------------------------------------------ */
+
+const char *GetIntConstMotoPrefix(unsigned Radix)
+{
+  static const char BaseIds[3] =
+  {
+    '%', '@', '$'
+  };
+  unsigned BaseIdx;
+
+  for (BaseIdx = 0; BaseIdx < sizeof(BaseVals) / sizeof(*BaseVals); BaseIdx++)
+    if (Radix == BaseVals[BaseIdx])
+    {
+      static char Result[2] = { '\0', '\0' };
+
+      Result[0] = BaseIds[BaseIdx];
+      return Result;
+    }
+  return "";
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     GetIntConstCPrefix(unsigned Radix)
+ * \brief  return C-style prefix letter fitting to number system
+ * \param  Radix req'd number system
+ * \return * to prefix string (may be empty)
+ * ------------------------------------------------------------------------ */
+
+const char *GetIntConstCPrefix(unsigned Radix)
+{
+  static const char BaseIds[3][3] =
+  {
+    "0b", "0", "0x"
+  };
+  unsigned BaseIdx;
+
+  for (BaseIdx = 0; BaseIdx < sizeof(BaseVals) / sizeof(*BaseVals); BaseIdx++)
+    if (Radix == BaseVals[BaseIdx])
+      return BaseIds[BaseIdx];;
+  return "";
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     GetIntConstIBMPrefix(unsigned Radix)
+ * \brief  return IBM-style prefix letter fitting to number system
+ * \param  Radix req'd number system
+ * \return * to prefix string (may be empty)
+ * ------------------------------------------------------------------------ */
+
+const char *GetIntConstIBMPrefix(unsigned Radix)
+{
+  static const char BaseIds[3] =
+  {
+    'B', 'O', 'X'
+  };
+  unsigned BaseIdx;
+
+  for (BaseIdx = 0; BaseIdx < sizeof(BaseVals) / sizeof(*BaseVals); BaseIdx++)
+    if (Radix == BaseVals[BaseIdx])
+    {
+      static char Result[3] = { '\0', '\'', '\0' };
+
+      Result[0] = BaseIds[BaseIdx] + (HexStartCharacter - 'A');
+      return Result;
+    }
+  return "";
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     GetIntConstIBMSuffix(unsigned Radix)
+ * \brief  return IBM-style suffix fitting to number system
+ * \param  Radix req'd number system
+ * \return * to prefix string (may be empty)
+ * ------------------------------------------------------------------------ */
+
+const char *GetIntConstIBMSuffix(unsigned Radix)
+{
+  unsigned BaseIdx;
+
+  for (BaseIdx = 0; BaseIdx < sizeof(BaseVals) / sizeof(*BaseVals); BaseIdx++)
+    if (Radix == BaseVals[BaseIdx])
+      return "\'";
+  return "";
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     SetIntConstModeByMask(LongWord Mask)
+ * \brief  set new (non-relaxed) integer constant mode by bit mask
+ * \param  Mask modes to set
+ * ------------------------------------------------------------------------ */
+
+void SetIntConstModeByMask(LongWord Mask)
+{
+  const tIntFormatList *pSrc;
+  tIntFormatList *pDest;
+
+  if (!IntFormatList)
+    IntFormatList = (tIntFormatList*)malloc(sizeof(IntFormatList_All));
+  for (pDest = IntFormatList, pSrc = IntFormatList_All; pSrc->Check; pSrc++)
+  {
+    if (!((Mask >> pSrc->Id) & 1))
+      continue;
+    *pDest++ = *pSrc;
+  }
+  memset(pDest, 0, sizeof(*pDest));
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ModifyIntConstModeByMask(LongWord ANDMask, LongWord ORMask)
+ * \brief  add or remove integer notations to/from native list
+ * \param  ANDMask notations to remove
+ * \param  ORMask notations to add
+ * \return True if mask was set up successfully
+ * ------------------------------------------------------------------------ */
+
+#define BadMask ((1ul << eIntFormatCOct) | (1ul << eIntFormatNatHex))
+
+Boolean ModifyIntConstModeByMask(LongWord ANDMask, LongWord ORMask)
+{
+  LongWord NewMask = (NativeIntConstModeMask & ~ANDMask) | ORMask;
+
+  if ((NewMask & BadMask) == BadMask)
+    return False;
+  else
+  {
+    NativeIntConstModeMask = NewMask;
+    SetIntConstModeByMask(NativeIntConstModeMask | (RelaxedMode ? OtherIntConstModeMask : 0));
+    return True;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     SetIntConstMode(tIntConstMode Mode)
+ * \brief  set new (non-relaxed) integer constant mode
+ * \param  Mode mode to set
+ * ------------------------------------------------------------------------ */
+
+void SetIntConstMode(tIntConstMode Mode)
+{
+  IntConstMode = Mode;
+  switch (Mode)
+  {
+    case eIntConstModeC:
+      NativeIntConstModeMask = eIntFormatMaskC;
+      OtherIntConstModeMask = eIntFormatMaskIntel | eIntFormatMaskMoto | eIntFormatMaskIBM;
+      break;
+    case eIntConstModeIntel:
+      NativeIntConstModeMask = eIntFormatMaskIntel;
+      OtherIntConstModeMask = eIntFormatMaskC | eIntFormatMaskMoto | eIntFormatMaskIBM;
+      break;
+    case eIntConstModeMoto:
+      NativeIntConstModeMask = eIntFormatMaskMoto;
+      OtherIntConstModeMask = eIntFormatMaskC | eIntFormatMaskIntel | eIntFormatMaskIBM;
+      break;
+    case eIntConstModeIBM:
+      NativeIntConstModeMask = eIntFormatMaskIBM;
+      OtherIntConstModeMask = eIntFormatMaskC | eIntFormatMaskIntel | eIntFormatMaskMoto;
+      break;
+    default:
+      NativeIntConstModeMask = 0;
+  }
+  NativeIntConstModeMask |= (1ul << eIntFormatDefRadix);
+  SetIntConstModeByMask(NativeIntConstModeMask | (RelaxedMode ? OtherIntConstModeMask : 0));
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     SetIntConstRelaxedMode(Boolean NewRelaxedMode)
+ * \brief  update relaxed mode - parser list
+ * \param  NewRelaxedMode mode to set
+ * ------------------------------------------------------------------------ */
+
+void SetIntConstRelaxedMode(Boolean NewRelaxedMode)
+{
+  SetIntConstModeByMask(NativeIntConstModeMask | (NewRelaxedMode ? OtherIntConstModeMask : 0));
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     GetIntFormatId(const char *pIdent)
+ * \brief  transform identifier to id
+ * \param  pIdent textual identifier
+ * \return resulting Id or None if not found
+ * ------------------------------------------------------------------------ */
+
+tIntFormatId GetIntFormatId(const char *pIdent)
+{
+  const tIntFormatList *pList;
+  for (pList = IntFormatList_All; pList->Check; pList++)
+   if (!as_strcasecmp(pIdent, pList->Ident))
+     return (tIntFormatId)pList->Id;
+  return eIntFormatNone;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     intformat_init(void)
+ * \brief  module initialization
+ * ------------------------------------------------------------------------ */
+
+void intformat_init(void)
+{
+  /* Allow all int const modes for handling possible -D options: */
+
+  RelaxedMode = True;
+  SetIntConstMode(eIntConstModeC);
+}
diff --git a/aslshim/intformat.h b/aslshim/intformat.h
new file mode 100644 (file)
index 0000000..9bb5c85
--- /dev/null
@@ -0,0 +1,88 @@
+/* intformat.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS                                                                        */
+/*                                                                           */
+/* enums regarding integer constant notations                                */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef _INTFORMAT_H
+#define _INTFORMAT_H
+
+typedef enum
+{
+  eIntFormatNone,
+  eIntFormatDefRadix, /* ... */
+  eIntFormatMotBin,   /* %... */
+  eIntFormatMotOct,   /* @... */
+  eIntFormatMotHex,   /* $... */
+  eIntFormatIntBin,   /* ...b */
+  eIntFormatIntOOct,  /* ...o */
+  eIntFormatIntQOct,  /* ...q */
+  eIntFormatIntHex,   /* ...h */
+  eIntFormatIBMBin,   /* b'...' */
+  eIntFormatIBMOct,   /* o'...' */
+  eIntFormatIBMXHex,  /* x'...' */
+  eIntFormatIBMHHex,  /* h'...' */
+  eIntFormatCBin,     /* 0b... */
+  eIntFormatCOct,     /* 0... */
+  eIntFormatCHex,     /* 0x... */
+  eIntFormatNatHex    /* 0..., incompatible with eIntFormatCOct */
+} tIntFormatId;
+
+#define eIntFormatMaskC     ((1ul << eIntFormatCHex)   | (1ul << eIntFormatCBin)   | (1ul << eIntFormatCOct))
+#define eIntFormatMaskIntel ((1ul << eIntFormatIntHex) | (1ul << eIntFormatIntBin) | (1ul << eIntFormatIntOOct) | (1ul << eIntFormatIntQOct))
+#define eIntFormatMaskMoto  ((1ul << eIntFormatMotHex) | (1ul << eIntFormatMotBin) | (1ul << eIntFormatMotOct))
+#define eIntFormatMaskIBM   ((1ul << eIntFormatIBMXHex) | (1ul << eIntFormatIBMHHex) | (1ul << eIntFormatIBMBin) | (1ul << eIntFormatIBMOct))
+
+typedef enum eIntConstMode
+{
+  eIntConstModeIntel,     /* Hex xxxxh, Oct xxxxo, Bin xxxxb */
+  eIntConstModeMoto,      /* Hex $xxxx, Oct @xxxx, Bin %xxxx */
+  eIntConstModeC,         /* Hex 0x..., Oct 0...., Bin 0b... */
+  eIntConstModeIBM        /* Hex 'xxxx['], Oct o'xxxx['], Bin b'xxxx['] */
+} tIntConstMode;
+
+typedef struct
+{
+  const char *pExpr;
+  size_t ExprLen;
+  int Base;
+} tIntCheckCtx;
+
+typedef Boolean (*tIntFormatCheck)(tIntCheckCtx *pCtx, char Ch);
+
+typedef struct
+{
+  tIntFormatCheck Check;
+  Byte Id;
+  ShortInt Base;
+  char Ch;
+  char Ident[7];
+} tIntFormatList;
+
+extern LongWord NativeIntConstModeMask, OtherIntConstModeMask;
+extern tIntFormatList *IntFormatList;
+extern Boolean RelaxedMode;
+extern int RadixBase;
+
+extern const char *GetIntConstMotoPrefix(unsigned Radix);
+extern const char *GetIntConstIntelSuffix(unsigned Radix);
+extern const char *GetIntConstIBMPrefix(unsigned Radix);
+extern const char *GetIntConstIBMSuffix(unsigned Radix);
+extern const char *GetIntConstCPrefix(unsigned Radix);
+
+extern void SetIntConstModeByMask(LongWord Mask);
+extern Boolean ModifyIntConstModeByMask(LongWord ANDMask, LongWord ORMask);
+
+extern void SetIntConstMode(tIntConstMode Mode);
+
+extern void SetIntConstRelaxedMode(Boolean NewRelaxedMode);
+
+extern tIntFormatId GetIntFormatId(const char *pIdent);
+
+extern void intformat_init(void);
+
+#endif /* _INTFORMAT_H */
diff --git a/aslshim/intpseudo.c b/aslshim/intpseudo.c
new file mode 100644 (file)
index 0000000..697b18c
--- /dev/null
@@ -0,0 +1,1543 @@
+/* intpseudo.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS                                                                        */
+/*                                                                           */
+/* Commonly Used Intel-Style Pseudo Instructions                             */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************
+ * Includes
+ *****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+
+#include "bpemu.h"
+#include "endian.h"
+#include "strutil.h"
+#include "nls.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmitree.h"
+#include "onoff_common.h"
+#include "errmsg.h"
+#include "ieeefloat.h"
+
+#include "intpseudo.h"
+
+#define LEAVE goto func_exit
+
+/*****************************************************************************
+ * Local Types
+ *****************************************************************************/
+
+struct sLayoutCtx;
+
+typedef Boolean (*TLayoutFunc)(
+#ifdef __PROTOS__
+                               const tStrComp *pArg, struct sLayoutCtx *pCtx
+#endif
+                               );
+
+typedef enum
+{
+  DSNone, DSConstant, DSSpace
+} tDSFlag;
+
+struct sCurrCodeFill
+{
+  LongInt FullWordCnt;
+  int LastWordFill;
+};
+typedef struct sCurrCodeFill tCurrCodeFill;
+
+struct sLayoutCtx
+{
+  tDSFlag DSFlag;
+  TLayoutFunc LayoutFunc;
+  int BaseElemLenBits, FullWordSize, ElemsPerFullWord;
+  Boolean (*Put4I)(Byte b, struct sLayoutCtx *pCtx);
+  Boolean (*Put8I)(Byte b, struct sLayoutCtx *pCtx);
+  Boolean (*Put16I)(Word w, struct sLayoutCtx *pCtx);
+  Boolean (*Put16F)(Double f, struct sLayoutCtx *pCtx);
+  Boolean (*Put32I)(LongWord l, struct sLayoutCtx *pCtx);
+  Boolean (*Put32F)(Double f, struct sLayoutCtx *pCtx);
+  Boolean (*Put64I)(LargeWord q, struct sLayoutCtx *pCtx);
+  Boolean (*Put64F)(Double f, struct sLayoutCtx *pCtx);
+  Boolean (*Put80F)(Double t, struct sLayoutCtx *pCtx);
+  Boolean (*Replicate)(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx);
+  tCurrCodeFill CurrCodeFill, FillIncPerElem;
+  const tStrComp *pCurrComp;
+  int LoHiMap;
+};
+typedef struct sLayoutCtx tLayoutCtx;
+
+/*****************************************************************************
+ * Global Variables
+ *****************************************************************************/
+
+static char Z80SyntaxName[] = "Z80SYNTAX";
+tZ80Syntax CurrZ80Syntax;
+
+/*****************************************************************************
+ * Local Functions
+ *****************************************************************************/
+
+void _DumpCodeFill(const char *pTitle, const tCurrCodeFill *pFill)
+{
+  fprintf(stderr, "%s %u %d\n", pTitle, (unsigned)pFill->FullWordCnt, pFill->LastWordFill);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     Boolean SetDSFlag(struct sLayoutCtx *pCtx, tDSFlag Flag)
+ * \brief  check set data disposition/reservation flag in context
+ * \param  pCtx context
+ * \param  Flag operation to be set
+ * \return True if operation could be set or was alreday set
+ * ------------------------------------------------------------------------ */
+
+static Boolean SetDSFlag(struct sLayoutCtx *pCtx, tDSFlag Flag)
+{
+  if ((pCtx->DSFlag != DSNone) && (pCtx->DSFlag != Flag))
+  {
+    WrStrErrorPos(ErrNum_MixDBDS, pCtx->pCurrComp);
+    return False;
+  }
+  pCtx->DSFlag = Flag;
+  return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     IncMaxCodeLen(struct sLayoutCtx *pCtx, LongWord NumFullWords)
+ * \brief  assure xAsmCode has space for at moleast n more full words
+ * \param  pCtxcontext
+ * \param  NumFullWords # of additional words intended to write
+ * \return True if success
+ * ------------------------------------------------------------------------ */
+
+static Boolean IncMaxCodeLen(struct sLayoutCtx *pCtx, LongWord NumFullWords)
+{
+  if (SetMaxCodeLen((pCtx->CurrCodeFill.FullWordCnt + NumFullWords) * pCtx->FullWordSize))
+  {
+    WrStrErrorPos(ErrNum_CodeOverflow, pCtx->pCurrComp);
+    return False;
+  }
+  else
+    return True;
+}
+
+static LargeWord ByteInWord(Byte b, int Pos)
+{
+  return ((LargeWord)b) << (Pos << 3);
+}
+
+static Byte NibbleInByte(Byte n, int Pos)
+{
+  return (n & 15) << (Pos << 2);
+}
+
+static Word NibbleInWord(Byte n, int Pos)
+{
+  return ((Word)(n & 15)) << (Pos << 2);
+}
+
+static Byte ByteFromWord(LargeWord w, int Pos)
+{
+  return (w >> (Pos << 3)) & 0xff;
+}
+
+static Byte NibbleFromByte(Byte b, int Pos)
+{
+  return (b >> (Pos << 2)) & 0x0f;
+}
+
+static Byte NibbleFromWord(Word w, int Pos)
+{
+  return (w >> (Pos << 2)) & 0x0f;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     SubCodeFill
+ * \brief  perform 'c = a - b' on tCurrCodeFill structures
+ * \param  c result
+ * \param  b, c arguments
+ * ------------------------------------------------------------------------ */
+
+static void SubCodeFill(tCurrCodeFill *c, const tCurrCodeFill *a, const tCurrCodeFill *b, struct sLayoutCtx *pCtx)
+{
+  c->FullWordCnt = a->FullWordCnt - b->FullWordCnt;
+  if ((c->LastWordFill = a->LastWordFill - b->LastWordFill) < 0)
+  {
+    c->LastWordFill += pCtx->ElemsPerFullWord;
+    c->FullWordCnt--;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     MultCodeFill(tCurrCodeFill *b, LongWord a, struct sLayoutCtx *pCtx)
+ * \brief  perform 'b *= a' on tCurrCodeFill structures
+ * \param  b what to multiply
+ * \param  a scaling factor
+ * ------------------------------------------------------------------------ */
+
+static void MultCodeFill(tCurrCodeFill *b, LongWord a, struct sLayoutCtx *pCtx)
+{
+  b->FullWordCnt *= a;
+  b->LastWordFill *= a;
+  if (pCtx->ElemsPerFullWord > 1)
+  {
+    LongWord div = b->LastWordFill / pCtx->ElemsPerFullWord,
+             mod = b->LastWordFill % pCtx->ElemsPerFullWord;
+    b->FullWordCnt += div;
+    b->LastWordFill = mod;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     IncCodeFill(tCurrCodeFill *a, struct sLayoutCtx *pCtx)
+ * \brief  advance tCurrCodeFill pointer by one base element
+ * \param  a pointer to increment
+ * \param  pCtx context
+ * ------------------------------------------------------------------------ */
+
+static void IncCodeFill(tCurrCodeFill *a, struct sLayoutCtx *pCtx)
+{
+  if (++a->LastWordFill >= pCtx->ElemsPerFullWord)
+  {
+    a->LastWordFill -= pCtx->ElemsPerFullWord;
+    a->FullWordCnt++;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     IncCurrCodeFill(struct sLayoutCtx *pCtx)
+ * \brief  advance CodeFill pointer in context and reserve memory
+ * \param  pCtx context
+ * \return True if success
+ * ------------------------------------------------------------------------ */
+
+static Boolean IncCurrCodeFill(struct sLayoutCtx *pCtx)
+{
+  LongInt OldFullWordCnt = pCtx->CurrCodeFill.FullWordCnt;
+
+  IncCodeFill(&pCtx->CurrCodeFill, pCtx);
+  if (OldFullWordCnt == pCtx->CurrCodeFill.FullWordCnt)
+    return True;
+  else if (!IncMaxCodeLen(pCtx, 1))
+    return False;
+  else
+  {
+    WAsmCode[pCtx->CurrCodeFill.FullWordCnt] = 0;
+    return True;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     IncCodeFillBy(tCurrCodeFill *a, const tCurrCodeFill *inc, struct sLayoutCtx *pCtx)
+ * \brief  perform 'a += inc' on tCurrCodeFill structures
+ * \param  a what to advance
+ * \param  inc by what to advance
+ * \param  pCtx context
+ * ------------------------------------------------------------------------ */
+
+static void IncCodeFillBy(tCurrCodeFill *a, const tCurrCodeFill *inc, struct sLayoutCtx *pCtx)
+{
+  a->LastWordFill += inc->LastWordFill;
+  if ((pCtx->ElemsPerFullWord > 1) && (a->LastWordFill >= pCtx->ElemsPerFullWord))
+  {
+    a->LastWordFill -= pCtx->ElemsPerFullWord;
+    a->FullWordCnt++;
+  }
+  a->FullWordCnt += inc->FullWordCnt;
+}
+
+/*****************************************************************************
+ * Function:    LayoutNibble
+ * Purpose:     parse argument, interprete as nibble,
+ *              and put into result buffer
+ * Result:      TRUE if no errors occured
+ *****************************************************************************/
+
+static Boolean Put4I_To_8(Byte b, struct sLayoutCtx *pCtx)
+{
+  tCurrCodeFill Pos = pCtx->CurrCodeFill;
+  if (!IncCurrCodeFill(pCtx))
+    return False;
+  if (!Pos.LastWordFill)
+    BAsmCode[Pos.FullWordCnt] = NibbleInByte(b, Pos.LastWordFill ^ pCtx->LoHiMap);
+  else
+    BAsmCode[Pos.FullWordCnt] |= NibbleInByte(b, Pos.LastWordFill ^ pCtx->LoHiMap);
+  return True;
+}
+
+static Boolean Replicate4_To_8(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx)
+{
+  Byte b;
+  tCurrCodeFill CurrPos;
+
+  CurrPos = *pStartPos;
+  while ((CurrPos.FullWordCnt != pEndPos->FullWordCnt) || (CurrPos.LastWordFill != pEndPos->LastWordFill))
+  {
+    b = NibbleFromByte(BAsmCode[CurrPos.FullWordCnt], CurrPos.LastWordFill ^ pCtx->LoHiMap);
+    if (!Put4I_To_8(b, pCtx))
+      return False;
+    IncCodeFill(&CurrPos, pCtx);
+  }
+
+  return True;
+}
+
+static Boolean Put4I_To_16(Byte b, struct sLayoutCtx *pCtx)
+{
+  tCurrCodeFill Pos = pCtx->CurrCodeFill;
+  if (!IncCurrCodeFill(pCtx))
+    return False;
+  if (!Pos.LastWordFill)
+    WAsmCode[Pos.FullWordCnt] = NibbleInWord(b, Pos.LastWordFill ^ pCtx->LoHiMap);
+  else
+    WAsmCode[Pos.FullWordCnt] |= NibbleInWord(b, Pos.LastWordFill ^ pCtx->LoHiMap);
+  return True;
+}
+
+static Boolean Replicate4_To_16(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx)
+{
+  Byte b;
+  tCurrCodeFill CurrPos;
+
+  CurrPos = *pStartPos;
+  while ((CurrPos.FullWordCnt != pEndPos->FullWordCnt) || (CurrPos.LastWordFill != pEndPos->LastWordFill))
+  {
+    b = NibbleFromWord(WAsmCode[CurrPos.FullWordCnt], CurrPos.LastWordFill ^ pCtx->LoHiMap);
+    if (!Put4I_To_16(b, pCtx))
+      return False;
+    IncCodeFill(&CurrPos, pCtx);
+  }
+
+  return True;
+}
+
+static Boolean LayoutNibble(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
+{
+  Boolean Result = False;
+  TempResult t;
+
+  as_tempres_ini(&t);
+  EvalStrExpression(pExpr, &t);
+  switch (t.Typ)
+  {
+    case TempInt:
+      if (mFirstPassUnknown(t.Flags)) t.Contents.Int &= 0xf;
+      if (!mSymbolQuestionable(t.Flags) && !RangeCheck(t.Contents.Int, Int4)) WrStrErrorPos(ErrNum_OverRange, pExpr);
+      else
+      {
+        if (!pCtx->Put4I(t.Contents.Int, pCtx))
+          LEAVE;
+        Result = True;
+      }
+      break;
+    case TempFloat:
+      WrStrErrorPos(ErrNum_IntButFloat, pExpr);
+      break;
+    case TempString:
+      WrStrErrorPos(ErrNum_IntButString, pExpr);
+      break;
+    default:
+      break;
+  }
+
+func_exit:
+  as_tempres_free(&t);
+  return Result;
+}
+
+/*****************************************************************************
+ * Function:    LayoutByte
+ * Purpose:     parse argument, interprete as byte,
+ *              and put into result buffer
+ * Result:      TRUE if no errors occured
+ *****************************************************************************/
+
+static Boolean Put8I_To_8(Byte b, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 1))
+    return False;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt++] = b;
+  return True;
+}
+
+static Boolean Put8I_To_16(Byte b, struct sLayoutCtx *pCtx)
+{
+  tCurrCodeFill Pos = pCtx->CurrCodeFill;
+  if (!IncCurrCodeFill(pCtx))
+    return False;
+  if (!Pos.LastWordFill)
+    WAsmCode[Pos.FullWordCnt] = ByteInWord(b, Pos.LastWordFill ^ pCtx->LoHiMap);
+  else
+    WAsmCode[Pos.FullWordCnt] |= ByteInWord(b, Pos.LastWordFill ^ pCtx->LoHiMap);
+  return True;
+}
+
+static Boolean Replicate8ToN_To_8(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx)
+{
+  tCurrCodeFill Pos;
+
+  if (!IncMaxCodeLen(pCtx, pEndPos->FullWordCnt - pStartPos->FullWordCnt))
+    return False;
+
+  for (Pos = *pStartPos; Pos.FullWordCnt < pEndPos->FullWordCnt; Pos.FullWordCnt += pCtx->BaseElemLenBits / 8)
+  {
+    memcpy(&BAsmCode[pCtx->CurrCodeFill.FullWordCnt], &BAsmCode[Pos.FullWordCnt], pCtx->BaseElemLenBits / 8);
+    pCtx->CurrCodeFill.FullWordCnt += pCtx->BaseElemLenBits / 8;
+  }
+  if (Pos.FullWordCnt != pEndPos->FullWordCnt)
+  {
+    WrXError(ErrNum_InternalError, "DUP replication inconsistency");
+    return False;
+  }
+
+  return True;
+}
+
+static Boolean Replicate8_To_16(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx)
+{
+  Byte b;
+  tCurrCodeFill CurrPos;
+
+  CurrPos = *pStartPos;
+  while ((CurrPos.FullWordCnt != pEndPos->FullWordCnt) || (CurrPos.LastWordFill != pEndPos->LastWordFill))
+  {
+    b = ByteFromWord(WAsmCode[CurrPos.FullWordCnt], CurrPos.LastWordFill ^ pCtx->LoHiMap);
+    if (!Put8I_To_16(b, pCtx))
+      return False;
+    IncCodeFill(&CurrPos, pCtx);
+  }
+
+  return True;
+}
+
+static Boolean LayoutByte(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
+{
+  Boolean Result = False;
+  TempResult t;
+
+  as_tempres_ini(&t);
+  EvalStrExpression(pExpr, &t);
+  switch (t.Typ)
+  {
+    case TempInt:
+    ToInt:
+      if (mFirstPassUnknown(t.Flags)) t.Contents.Int &= 0xff;
+      if (!mSymbolQuestionable(t.Flags) && !RangeCheck(t.Contents.Int, Int8)) WrStrErrorPos(ErrNum_OverRange, pExpr);
+      else
+      {
+        if (!pCtx->Put8I(t.Contents.Int, pCtx))
+          LEAVE;
+        Result = True;
+      }
+      break;
+    case TempFloat:
+      WrStrErrorPos(ErrNum_StringOrIntButFloat, pExpr);
+      break;
+    case TempString:
+    {
+      unsigned z;
+
+      if (MultiCharToInt(&t, 1))
+        goto ToInt;
+
+      TranslateString(t.Contents.str.p_str, t.Contents.str.len);
+
+      for (z = 0; z < t.Contents.str.len; z++)
+        if (!pCtx->Put8I(t.Contents.str.p_str[z], pCtx))
+          LEAVE;
+
+      Result = True;
+      break;
+    }
+    default:
+      break;
+  }
+
+func_exit:
+  as_tempres_free(&t);
+  return Result;
+}
+
+/*****************************************************************************
+ * Function:    LayoutWord
+ * Purpose:     parse argument, interprete as 16-bit word,
+ *              and put into result buffer
+ * Result:      TRUE if no errors occured
+ *****************************************************************************/
+
+static Boolean Put16I_To_8(Word w, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 2))
+    return False;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap)] = Lo(w);
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap)] = Hi(w);
+  pCtx->CurrCodeFill.FullWordCnt += 2;
+  return True;
+}
+
+static Boolean Put16F_To_8(Double t, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 2))
+    return False;
+  if (!Double_2_ieee2(t, BAsmCode + pCtx->CurrCodeFill.FullWordCnt, !!pCtx->LoHiMap))
+  {
+    WrError(ErrNum_OverRange);
+    return False;
+  }
+  pCtx->CurrCodeFill.FullWordCnt += 2;
+  return True;
+}
+
+static Boolean Put16I_To_16(Word w, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 1))
+    return False;
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt++] = w;
+  return True;
+}
+
+static Boolean Put16F_To_16(Double t, struct sLayoutCtx *pCtx)
+{
+  Byte Tmp[2];
+
+  if (!IncMaxCodeLen(pCtx, 1))
+    return False;
+
+  Double_2_ieee2(t, Tmp, !!pCtx->LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 0] = ByteInWord(Tmp[0], 0 ^ pCtx->LoHiMap) | ByteInWord(Tmp[1], 1 ^ pCtx->LoHiMap);
+  pCtx->CurrCodeFill.FullWordCnt += 1;
+  return True;
+}
+
+static Boolean Replicate16ToN_To_16(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx)
+{
+  tCurrCodeFill Pos;
+
+  if (!IncMaxCodeLen(pCtx, pEndPos->FullWordCnt - pStartPos->FullWordCnt))
+    return False;
+
+  for (Pos = *pStartPos; Pos.FullWordCnt < pEndPos->FullWordCnt; Pos.FullWordCnt += pCtx->BaseElemLenBits / 16)
+  {
+    memcpy(&WAsmCode[pCtx->CurrCodeFill.FullWordCnt], &WAsmCode[Pos.FullWordCnt], pCtx->BaseElemLenBits / 8);
+    pCtx->CurrCodeFill.FullWordCnt += pCtx->BaseElemLenBits / 16;
+  }
+  if (Pos.FullWordCnt != pEndPos->FullWordCnt)
+  {
+    WrXError(ErrNum_InternalError, "DUP replication inconsistency");
+    return False;
+  }
+
+  return True;
+}
+
+static Boolean LayoutWord(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
+{
+  Boolean Result = False;
+  TempResult t;
+
+  as_tempres_ini(&t);
+  EvalStrExpression(pExpr, &t);
+  Result = True;
+  switch (t.Typ)
+  {
+    case TempInt:
+    ToInt:
+      if (pCtx->Put16I)
+      {
+        if (mFirstPassUnknown(t.Flags)) t.Contents.Int &= 0xffff;
+        if (!mSymbolQuestionable(t.Flags) && !RangeCheck(t.Contents.Int, Int16)) WrStrErrorPos(ErrNum_OverRange, pExpr);
+        else
+        {
+          if (!pCtx->Put16I(t.Contents.Int, pCtx))
+            LEAVE;
+          Result = True;
+        }
+        break;
+      }
+      else
+        TempResultToFloat(&t);
+      /* fall-through */
+    case TempFloat:
+      if (!pCtx->Put16F) WrStrErrorPos(ErrNum_StringOrIntButFloat, pExpr);
+      else if (!FloatRangeCheck(t.Contents.Float, Float16)) WrStrErrorPos(ErrNum_OverRange, pExpr);
+      else
+      {
+        if (!pCtx->Put16F(t.Contents.Float, pCtx))
+          LEAVE;
+        Result = True;
+      }
+      break;
+    case TempString:
+    {
+      unsigned z;
+
+      if (MultiCharToInt(&t, 2))
+        goto ToInt;
+
+      TranslateString(t.Contents.str.p_str, t.Contents.str.len);
+
+      for (z = 0; z < t.Contents.str.len; z++)
+        if (!pCtx->Put16I(t.Contents.str.p_str[z], pCtx))
+          LEAVE;
+
+      Result = True;
+      break;
+    }
+    default:
+      break;
+  }
+
+func_exit:
+  as_tempres_free(&t);
+  return Result;
+}
+
+/*****************************************************************************
+ * Function:    LayoutDoubleWord
+ * Purpose:     parse argument, interprete as 32-bit word or
+                single precision float, and put into result buffer
+ * Result:      TRUE if no errors occured
+ *****************************************************************************/
+
+static Boolean Put32I_To_8(LongWord l, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 4))
+    return False;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap)] = (l      ) & 0xff;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap)] = (l >>  8) & 0xff;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ pCtx->LoHiMap)] = (l >> 16) & 0xff;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (3 ^ pCtx->LoHiMap)] = (l >> 24) & 0xff;
+  pCtx->CurrCodeFill.FullWordCnt += 4;
+  return True;
+}
+
+static Boolean Put32F_To_8(Double t, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 4))
+    return False;
+  Double_2_ieee4(t, BAsmCode + pCtx->CurrCodeFill.FullWordCnt, !!pCtx->LoHiMap);
+  pCtx->CurrCodeFill.FullWordCnt += 4;
+  return True;
+}
+
+static Boolean Put32I_To_16(LongWord l, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 2))
+    return False;
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap)] = LoWord(l);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap)] = HiWord(l);
+  pCtx->CurrCodeFill.FullWordCnt += 2;
+  return True;
+}
+
+static Boolean Put32F_To_16(Double t, struct sLayoutCtx *pCtx)
+{
+  Byte Tmp[4];
+
+  if (!IncMaxCodeLen(pCtx, 2))
+    return False;
+  Double_2_ieee4(t, Tmp, !!pCtx->LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 0] = ByteInWord(Tmp[0], 0 ^ pCtx->LoHiMap) | ByteInWord(Tmp[1], 1 ^ pCtx->LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 1] = ByteInWord(Tmp[2], 0 ^ pCtx->LoHiMap) | ByteInWord(Tmp[3], 1 ^ pCtx->LoHiMap);
+  pCtx->CurrCodeFill.FullWordCnt += 2;
+  return True;
+}
+
+static Boolean LayoutDoubleWord(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
+{
+  TempResult erg;
+  Boolean Result = False;
+  Word Cnt = 0;
+
+  as_tempres_ini(&erg);
+  EvalStrExpression(pExpr, &erg);
+  Result = False;
+  switch (erg.Typ)
+  {
+    case TempNone:
+      break;
+    case TempInt:
+    ToInt:
+      if (pCtx->Put32I)
+      {
+        if (mFirstPassUnknown(erg.Flags)) erg.Contents.Int &= 0xfffffffful;
+        if (!mSymbolQuestionable(erg.Flags) && !RangeCheck(erg.Contents.Int, Int32)) WrStrErrorPos(ErrNum_OverRange, pExpr);
+        else
+        {
+          if (!pCtx->Put32I(erg.Contents.Int, pCtx))
+            LEAVE;
+          Cnt = 4;
+          Result = True;
+        }
+        break;
+      }
+      else
+        TempResultToFloat(&erg);
+      /* fall-through */
+    case TempFloat:
+      if (!pCtx->Put32F) WrStrErrorPos(ErrNum_StringOrIntButFloat, pExpr);
+      else if (!FloatRangeCheck(erg.Contents.Float, Float32)) WrStrErrorPos(ErrNum_OverRange, pExpr);
+      else
+      {
+        if (!pCtx->Put32F(erg.Contents.Float, pCtx))
+          LEAVE;
+        Cnt = 4;
+        Result = True;
+      }
+      break;
+    case TempString:
+    {
+      unsigned z;
+
+      if (MultiCharToInt(&erg, 4))
+        goto ToInt;
+
+      TranslateString(erg.Contents.str.p_str, erg.Contents.str.len);
+
+      for (z = 0; z < erg.Contents.str.len; z++)
+        if (!pCtx->Put32I(erg.Contents.str.p_str[z], pCtx))
+          LEAVE;
+
+      Cnt = erg.Contents.str.len * 4;
+      Result = True;
+      break;
+    }
+    case TempReg:
+      WrStrErrorPos(ErrNum_StringOrIntOrFloatButReg, pExpr);
+      break;
+    case TempAll:
+      assert(0);
+  }
+  (void)Cnt;
+
+func_exit:
+  as_tempres_free(&erg);
+  return Result;
+}
+
+
+/*****************************************************************************
+ * Function:    LayoutQuadWord
+ * Purpose:     parse argument, interprete as 64-bit word or
+                double precision float, and put into result buffer
+ * Result:      TRUE if no errors occured
+ *****************************************************************************/
+
+static Boolean Put64I_To_8(LargeWord l, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 8))
+    return False;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap)] = (l      ) & 0xff;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap)] = (l >>  8) & 0xff;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ pCtx->LoHiMap)] = (l >> 16) & 0xff;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (3 ^ pCtx->LoHiMap)] = (l >> 24) & 0xff;
+#ifdef HAS64
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (4 ^ pCtx->LoHiMap)] = (l >> 32) & 0xff;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (5 ^ pCtx->LoHiMap)] = (l >> 40) & 0xff;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (6 ^ pCtx->LoHiMap)] = (l >> 48) & 0xff;
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (7 ^ pCtx->LoHiMap)] = (l >> 56) & 0xff;
+#else
+  /* TempResult is TempInt, so sign-extend */
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (4 ^ pCtx->LoHiMap)] =
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (5 ^ pCtx->LoHiMap)] =
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (6 ^ pCtx->LoHiMap)] =
+  BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (7 ^ pCtx->LoHiMap)] = (l & 0x80000000ul) ? 0xff : 0x00;
+#endif
+  pCtx->CurrCodeFill.FullWordCnt += 8;
+  return True;
+}
+
+static Boolean Put64F_To_8(Double t, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 8))
+    return False;
+  Double_2_ieee8(t, BAsmCode + pCtx->CurrCodeFill.FullWordCnt, !!pCtx->LoHiMap);
+  pCtx->CurrCodeFill.FullWordCnt += 8;
+  return True;
+}
+
+static Boolean Put64I_To_16(LargeWord l, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 4))
+    return False;
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap)] = (l      ) & 0xffff;
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap)] = (l >> 16) & 0xffff;
+#ifdef HAS64
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ pCtx->LoHiMap)] = (l >> 32) & 0xffff;
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (3 ^ pCtx->LoHiMap)] = (l >> 48) & 0xffff;
+#else
+  /* TempResult is TempInt, so sign-extend */
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ pCtx->LoHiMap)] =
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (3 ^ pCtx->LoHiMap)] = (l & 0x80000000ul) ? 0xffff : 0x0000;
+#endif
+  pCtx->CurrCodeFill.FullWordCnt += 4;
+  return True;
+}
+
+static Boolean Put64F_To_16(Double t, struct sLayoutCtx *pCtx)
+{
+  Byte Tmp[8];
+  int LoHiMap = pCtx->LoHiMap & 1;
+
+  if (!IncMaxCodeLen(pCtx, 4))
+    return False;
+  Double_2_ieee8(t, Tmp, !!pCtx->LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 0] = ByteInWord(Tmp[0], 0 ^ LoHiMap) | ByteInWord(Tmp[1], 1 ^ LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 1] = ByteInWord(Tmp[2], 0 ^ LoHiMap) | ByteInWord(Tmp[3], 1 ^ LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 2] = ByteInWord(Tmp[4], 0 ^ LoHiMap) | ByteInWord(Tmp[5], 1 ^ LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 3] = ByteInWord(Tmp[6], 0 ^ LoHiMap) | ByteInWord(Tmp[7], 1 ^ LoHiMap);
+  pCtx->CurrCodeFill.FullWordCnt += 4;
+  return True;
+}
+
+static Boolean LayoutQuadWord(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
+{
+  Boolean Result = False;
+  TempResult erg;
+  Word Cnt  = 0;
+
+  as_tempres_ini(&erg);
+  EvalStrExpression(pExpr, &erg);
+  Result = False;
+  switch(erg.Typ)
+  {
+    case TempNone:
+      break;
+    case TempInt:
+    ToInt:
+      if (pCtx->Put64I)
+      {
+        if (!pCtx->Put64I(erg.Contents.Int, pCtx))
+          LEAVE;
+        Cnt = 8;
+        Result = True;
+        break;
+      }
+      else
+        TempResultToFloat(&erg);
+      /* fall-through */
+    case TempFloat:
+      if (!pCtx->Put64F) WrStrErrorPos(ErrNum_StringOrIntButFloat, pExpr);
+      else if (!pCtx->Put64F(erg.Contents.Float, pCtx))
+        LEAVE;
+      Cnt = 8;
+      Result = True;
+      break;
+    case TempString:
+    {
+      unsigned z;
+
+      if (MultiCharToInt(&erg, 8))
+        goto ToInt;
+
+      TranslateString(erg.Contents.str.p_str, erg.Contents.str.len);
+
+      for (z = 0; z < erg.Contents.str.len; z++)
+        if (!pCtx->Put64I(erg.Contents.str.p_str[z], pCtx))
+          LEAVE;
+
+      Cnt = erg.Contents.str.len * 8;
+      Result = True;
+      break;
+    }
+    case TempReg:
+      WrStrErrorPos(ErrNum_StringOrIntOrFloatButReg, pExpr);
+      break;
+    case TempAll:
+      assert(0);
+  }
+  (void)Cnt;
+
+func_exit:
+  as_tempres_free(&erg);
+  return Result;
+}
+
+/*****************************************************************************
+ * Function:    LayoutTenBytes
+ * Purpose:     parse argument, interprete extended precision float,
+ *              and put into result buffer
+ * Result:      TRUE if no errors occured
+ *****************************************************************************/
+
+static Boolean Put80F_To_8(Double t, struct sLayoutCtx *pCtx)
+{
+  if (!IncMaxCodeLen(pCtx, 10))
+    return False;
+  Double_2_ieee10(t, BAsmCode + pCtx->CurrCodeFill.FullWordCnt, !!pCtx->LoHiMap);
+  pCtx->CurrCodeFill.FullWordCnt += 10;
+  return True;
+}
+
+static Boolean Put80F_To_16(Double t, struct sLayoutCtx *pCtx)
+{
+  Byte Tmp[10];
+  int LoHiMap = pCtx->LoHiMap & 1;
+
+  if (!IncMaxCodeLen(pCtx, 5))
+    return False;
+  Double_2_ieee10(t, Tmp, !!pCtx->LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 0] = ByteInWord(Tmp[0], 0 ^ LoHiMap) | ByteInWord(Tmp[1], 1 ^ LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 1] = ByteInWord(Tmp[2], 0 ^ LoHiMap) | ByteInWord(Tmp[3], 1 ^ LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 2] = ByteInWord(Tmp[4], 0 ^ LoHiMap) | ByteInWord(Tmp[5], 1 ^ LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 3] = ByteInWord(Tmp[6], 0 ^ LoHiMap) | ByteInWord(Tmp[7], 1 ^ LoHiMap);
+  WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 4] = ByteInWord(Tmp[8], 0 ^ LoHiMap) | ByteInWord(Tmp[9], 1 ^ LoHiMap);
+  pCtx->CurrCodeFill.FullWordCnt += 5;
+  return True;
+}
+
+static Boolean LayoutTenBytes(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
+{
+  Boolean Result = False;
+  TempResult erg;
+  Word Cnt;
+
+  as_tempres_ini(&erg);
+  EvalStrExpression(pExpr, &erg);
+  Result = False;
+  switch(erg.Typ)
+  {
+    case TempNone:
+      break;
+    case TempInt:
+    ToInt:
+      TempResultToFloat(&erg);
+      /* fall-through */
+    case TempFloat:
+      if (!pCtx->Put80F(erg.Contents.Float, pCtx))
+        LEAVE;
+      Cnt = 10;
+      Result = True;
+      break;
+    case TempString:
+    {
+      unsigned z;
+
+      if (MultiCharToInt(&erg, 4))
+        goto ToInt;
+
+      TranslateString(erg.Contents.str.p_str, erg.Contents.str.len);
+
+      for (z = 0; z < erg.Contents.str.len; z++)
+        if (!pCtx->Put80F(erg.Contents.str.p_str[z], pCtx))
+          LEAVE;
+
+      Cnt = erg.Contents.str.len * 10;
+      Result = True;
+      break;
+    }
+    case TempReg:
+      WrStrErrorPos(ErrNum_StringOrIntOrFloatButReg, pExpr);
+      break;
+    case TempAll:
+      assert(0);
+  }
+  (void)Cnt;
+
+func_exit:
+  as_tempres_free(&erg);
+  return Result;
+}
+
+/*****************************************************************************
+ * Global Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Function:    DecodeIntelPseudo
+ * Purpose:     handle Intel-style pseudo instructions
+ * Result:      TRUE if mnemonic was handled
+ *****************************************************************************/
+
+static Boolean DecodeIntelPseudo_ValidSymChar(char ch)
+{
+  ch = as_toupper(ch);
+
+  return (((ch >= 'A') && (ch <= 'Z'))
+       || ((ch >= '0') && (ch <= '9'))
+       || (ch == '_')
+       || (ch == '.'));
+}
+
+static void DecodeIntelPseudo_HandleQuote(int *pDepth, Byte *pQuote, char Ch)
+{
+  switch (Ch)
+  {
+    case '(':
+      if (!(*pQuote))
+        (*pDepth)++;
+      break;
+    case ')':
+      if (!(*pQuote))
+        (*pDepth)--;
+      break;
+    case '\'':
+      if (!((*pQuote) & 2))
+        (*pQuote) ^= 1;
+      break;
+    case '"':
+      if (!((*pQuote) & 1))
+        (*pQuote) ^= 2;
+      break;
+  }
+}
+
+static Boolean DecodeIntelPseudo_LayoutMult(const tStrComp *pArg, struct sLayoutCtx *pCtx)
+{
+  int z, Depth, Len, LastNonBlank;
+  Boolean OK, LastValid, Result;
+  Byte Quote;
+  const char *pDupFnd, *pRun;
+  const tStrComp *pSaveComp;
+
+  pSaveComp = pCtx->pCurrComp;
+  pCtx->pCurrComp = pArg;
+
+  /* search for DUP:
+     - Exclude parts in parentheses, and parts in quotation marks.
+     - Assure there is some (non-blank) token before DUP, so if there
+       is e.g. a plain DUP as argument, it will not be interpreted as
+       DUP operator. */
+
+  Depth = Quote = 0;
+  LastValid = FALSE;
+  LastNonBlank = -1;
+  pDupFnd = NULL; Len = strlen(pArg->str.p_str);
+  for (pRun = pArg->str.p_str; pRun < pArg->str.p_str + Len - 2; pRun++)
+  {
+    DecodeIntelPseudo_HandleQuote(&Depth, &Quote, *pRun);
+    if (!Depth && !Quote)
+    {
+      if (!LastValid
+       && (LastNonBlank >= 0)
+       && !DecodeIntelPseudo_ValidSymChar(pRun[3])
+       && !as_strncasecmp(pRun, "DUP", 3))
+      {
+        pDupFnd = pRun;
+        break;
+      }
+      if (!as_isspace(*pRun))
+        LastNonBlank = pRun - pArg->str.p_str;
+    }
+    LastValid = DecodeIntelPseudo_ValidSymChar(*pRun);
+  }
+
+  /* found DUP: */
+
+  if (pDupFnd)
+  {
+    LongInt DupCnt;
+    char *pSep, *pRun;
+    String CopyStr;
+    tStrComp Copy, DupArg, RemArg, ThisRemArg;
+    tCurrCodeFill DUPStartFill, DUPEndFill;
+    tSymbolFlags Flags;
+
+    /* operate on copy */
+
+    StrCompMkTemp(&Copy, CopyStr, sizeof(CopyStr));
+    StrCompCopy(&Copy, pArg);
+    pSep = Copy.str.p_str + (pDupFnd - pArg->str.p_str);
+
+    /* evaluate count */
+
+    StrCompSplitRef(&DupArg, &RemArg, &Copy, pSep);
+    DupCnt = EvalStrIntExpressionWithFlags(&DupArg, Int32, &OK, &Flags);
+    if (mFirstPassUnknown(Flags))
+    {
+      WrStrErrorPos(ErrNum_FirstPassCalc, &DupArg); return False;
+    }
+    if (!OK)
+    {
+      Result = False;
+      goto func_exit;
+    }
+
+    /* catch invalid counts */
+
+    if (DupCnt <= 0)
+    {
+      if (DupCnt < 0)
+        WrStrErrorPos(ErrNum_NegDUP, &DupArg);
+      Result = True;
+      goto func_exit;
+    }
+
+    /* split into parts and evaluate */
+
+    StrCompIncRefLeft(&RemArg, 2);
+    KillPrefBlanksStrCompRef(&RemArg);
+    Len = strlen(RemArg.str.p_str);
+    if ((Len >= 2) && (*RemArg.str.p_str == '(') && (RemArg.str.p_str[Len - 1] == ')'))
+    {
+      StrCompIncRefLeft(&RemArg, 1);
+      StrCompShorten(&RemArg, 1);
+      Len -= 2;
+    }
+    DUPStartFill = pCtx->CurrCodeFill;
+    do
+    {
+      pSep = NULL; Quote = Depth = 0;
+      for (pRun = RemArg.str.p_str; *pRun; pRun++)
+      {
+        DecodeIntelPseudo_HandleQuote(&Depth, &Quote, *pRun);
+        if ((!Depth) && (!Quote) && (*pRun == ','))
+        {
+          pSep = pRun;
+          break;
+        }
+      }
+      if (pSep)
+        StrCompSplitRef(&RemArg, &ThisRemArg, &RemArg, pSep);
+      KillPrefBlanksStrCompRef(&RemArg);
+      KillPostBlanksStrComp(&RemArg);
+      if (!DecodeIntelPseudo_LayoutMult(&RemArg, pCtx))
+      {
+        Result = False;
+        goto func_exit;
+      }
+      if (pSep)
+        RemArg = ThisRemArg;
+    }
+    while (pSep);
+    DUPEndFill = pCtx->CurrCodeFill;
+
+    /* replicate result (data or reserve) */
+
+    switch (pCtx->DSFlag)
+    {
+      case DSConstant:
+        for (z = 1; z <= DupCnt - 1; z++)
+          if (!pCtx->Replicate(&DUPStartFill, &DUPEndFill, pCtx))
+          {
+            Result = False;
+            goto func_exit;
+          }
+        break;
+      case DSSpace:
+      {
+        tCurrCodeFill Diff;
+
+        SubCodeFill(&Diff, &DUPEndFill, &DUPStartFill, pCtx);
+        MultCodeFill(&Diff, DupCnt - 1, pCtx);
+        IncCodeFillBy(&pCtx->CurrCodeFill, &Diff, pCtx);
+        break;
+      }
+      default:
+        Result = False;
+        goto func_exit;
+    }
+
+    Result = True;
+  }
+
+  /* no DUP: simple expression.  Differentiate space reservation & data disposition */
+
+  else if (!strcmp(pArg->str.p_str, "?"))
+  {
+    Result = SetDSFlag(pCtx, DSSpace);
+    if (Result)
+      IncCodeFillBy(&pCtx->CurrCodeFill, &pCtx->FillIncPerElem, pCtx);
+  }
+
+  else
+    Result = SetDSFlag(pCtx, DSConstant) && pCtx->LayoutFunc(pArg, pCtx);
+
+func_exit:
+  pCtx->pCurrComp = pSaveComp;
+  return Result;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DecodeIntelDx(tLayoutCtx *pLayoutCtx)
+ * \brief  Intel-style constant disposition
+ * \param  pLayoutCtx layout infos & context
+ * ------------------------------------------------------------------------ */
+
+static void DecodeIntelDx(tLayoutCtx *pLayoutCtx)
+{
+  tStrComp *pArg;
+  Boolean OK;
+
+  pLayoutCtx->DSFlag = DSNone;
+  pLayoutCtx->FullWordSize = Grans[ActPC];
+  pLayoutCtx->ElemsPerFullWord = (8 * pLayoutCtx->FullWordSize) / pLayoutCtx->BaseElemLenBits;
+  if (pLayoutCtx->ElemsPerFullWord > 1)
+  {
+    pLayoutCtx->FillIncPerElem.FullWordCnt = 0;
+    pLayoutCtx->FillIncPerElem.LastWordFill = 1;
+  }
+  else
+  {
+    pLayoutCtx->FillIncPerElem.FullWordCnt = pLayoutCtx->BaseElemLenBits / (8 * pLayoutCtx->FullWordSize);
+    pLayoutCtx->FillIncPerElem.LastWordFill = 0;
+  }
+
+  OK = True;
+  forallargs(pArg, OK)
+  {
+    if (!*pArg->str.p_str)
+    {
+      OK = FALSE;
+      WrStrErrorPos(ErrNum_EmptyArgument, pArg);
+    }
+    else
+      OK = DecodeIntelPseudo_LayoutMult(pArg, pLayoutCtx);
+  }
+
+  /* Finalize: add optional padding if fractions of full words
+     remain unused & set code length */
+
+  if (OK)
+  {
+    if (pLayoutCtx->CurrCodeFill.LastWordFill)
+    {
+      WrError(ErrNum_PaddingAdded);
+      pLayoutCtx->CurrCodeFill.LastWordFill = 0;
+      pLayoutCtx->CurrCodeFill.FullWordCnt++;
+    }
+    CodeLen = pLayoutCtx->CurrCodeFill.FullWordCnt;
+  }
+
+  DontPrint = (pLayoutCtx->DSFlag == DSSpace);
+  if (DontPrint)
+  {
+    BookKeeping();
+    if (!CodeLen && OK) WrError(ErrNum_NullResMem);
+  }
+  if (OK && (pLayoutCtx->FullWordSize == 1))
+    ActListGran = 1;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DecodeIntelDN(Word Flags)
+ * \brief  Intel-style constant disposition - nibbles
+ * \param  Flags Data Type & Endianess Flags
+ * ------------------------------------------------------------------------ */
+
+void DecodeIntelDN(Word Flags)
+{
+  tLayoutCtx LayoutCtx;
+
+  memset(&LayoutCtx, 0, sizeof(LayoutCtx));
+  LayoutCtx.LayoutFunc = LayoutNibble;
+  LayoutCtx.BaseElemLenBits = 4;
+  switch (Grans[ActPC])
+  {
+    case 1:
+      LayoutCtx.Put4I = Put4I_To_8;
+      LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
+      LayoutCtx.Replicate = Replicate4_To_8;
+      break;
+    case 2:
+      LayoutCtx.Put4I = Put4I_To_16;
+      LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 3 : 0;
+      LayoutCtx.Replicate = Replicate4_To_16;
+      break;
+  }
+  DecodeIntelDx(&LayoutCtx);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DecodeIntelDB(Word BigEndian)
+ * \brief  Intel-style constant disposition - bytes
+ * \param  Flags Data Type & Endianess Flags
+ * ------------------------------------------------------------------------ */
+
+void DecodeIntelDB(Word Flags)
+{
+  tLayoutCtx LayoutCtx;
+
+  memset(&LayoutCtx, 0, sizeof(LayoutCtx));
+  LayoutCtx.LayoutFunc = LayoutByte;
+  LayoutCtx.BaseElemLenBits = 8;
+  switch (Grans[ActPC])
+  {
+    case 1:
+      LayoutCtx.Put8I = Put8I_To_8;
+      LayoutCtx.Replicate = Replicate8ToN_To_8;
+      break;
+    case 2:
+      LayoutCtx.Put8I = Put8I_To_16;
+      LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
+      LayoutCtx.Replicate = Replicate8_To_16;
+      break;
+  }
+  if (*LabPart.str.p_str)
+    SetSymbolOrStructElemSize(&LabPart, eSymbolSize8Bit);
+  DecodeIntelDx(&LayoutCtx);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DecodeIntelDW(Word Flags)
+ * \brief  Intel-style constant disposition - words
+ * \param  Flags Data Type & Endianess Flags
+ * ------------------------------------------------------------------------ */
+
+void DecodeIntelDW(Word Flags)
+{
+  tLayoutCtx LayoutCtx;
+
+  memset(&LayoutCtx, 0, sizeof(LayoutCtx));
+  LayoutCtx.LayoutFunc = LayoutWord;
+  LayoutCtx.BaseElemLenBits = 16;
+  switch (Grans[ActPC])
+  {
+    case 1:
+      LayoutCtx.Put16I = (Flags & eIntPseudoFlag_AllowInt) ? Put16I_To_8 : NULL;
+      LayoutCtx.Put16F = (Flags & eIntPseudoFlag_AllowFloat) ? Put16F_To_8 : NULL;
+      LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
+      LayoutCtx.Replicate = Replicate8ToN_To_8;
+      break;
+    case 2:
+      LayoutCtx.Put16I = (Flags & eIntPseudoFlag_AllowInt) ? Put16I_To_16 : NULL;
+      LayoutCtx.Put16F = (Flags & eIntPseudoFlag_AllowFloat) ? Put16F_To_16 : NULL;
+      LayoutCtx.Replicate = Replicate16ToN_To_16;
+      break;
+  }
+  if (*LabPart.str.p_str)
+    SetSymbolOrStructElemSize(&LabPart, eSymbolSize16Bit);
+  DecodeIntelDx(&LayoutCtx);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DecodeIntelDD(Word Flags)
+ * \brief  Intel-style constant disposition - 32-bit words
+ * \param  Flags Data Type & Endianess Flags
+ * ------------------------------------------------------------------------ */
+
+void DecodeIntelDD(Word Flags)
+{
+  tLayoutCtx LayoutCtx;
+
+  memset(&LayoutCtx, 0, sizeof(LayoutCtx));
+  LayoutCtx.LayoutFunc = LayoutDoubleWord;
+  LayoutCtx.BaseElemLenBits = 32;
+  switch (Grans[ActPC])
+  {
+    case 1:
+      LayoutCtx.Put32I = (Flags & eIntPseudoFlag_AllowInt) ? Put32I_To_8 : NULL;
+      LayoutCtx.Put32F = (Flags & eIntPseudoFlag_AllowFloat) ? Put32F_To_8 : NULL;
+      LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 3 : 0;
+      LayoutCtx.Replicate = Replicate8ToN_To_8;
+      break;
+    case 2:
+      LayoutCtx.Put32I = (Flags & eIntPseudoFlag_AllowInt) ? Put32I_To_16 : NULL;
+      LayoutCtx.Put32F = (Flags & eIntPseudoFlag_AllowFloat) ? Put32F_To_16 : NULL;
+      LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
+      LayoutCtx.Replicate = Replicate16ToN_To_16;
+      break;
+  }
+  if (*LabPart.str.p_str)
+    SetSymbolOrStructElemSize(&LabPart, eSymbolSize32Bit);
+  DecodeIntelDx(&LayoutCtx);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DecodeIntelDQ(Word Flags)
+ * \brief  Intel-style constant disposition - 64-bit words
+ * \param  Flags Data Type & Endianess Flags
+ * ------------------------------------------------------------------------ */
+
+void DecodeIntelDQ(Word Flags)
+{
+  tLayoutCtx LayoutCtx;
+
+  memset(&LayoutCtx, 0, sizeof(LayoutCtx));
+  LayoutCtx.LayoutFunc = LayoutQuadWord;
+  LayoutCtx.BaseElemLenBits = 64;
+  switch (Grans[ActPC])
+  {
+    case 1:
+      LayoutCtx.Put64I = (Flags & eIntPseudoFlag_AllowInt) ? Put64I_To_8 : NULL;
+      LayoutCtx.Put64F = (Flags & eIntPseudoFlag_AllowFloat) ? Put64F_To_8 : NULL;
+      LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 7 : 0;
+      LayoutCtx.Replicate = Replicate8ToN_To_8;
+      break;
+    case 2:
+      LayoutCtx.Put64I = (Flags & eIntPseudoFlag_AllowInt) ? Put64I_To_16 : NULL;
+      LayoutCtx.Put64F = (Flags & eIntPseudoFlag_AllowFloat) ? Put64F_To_16 : NULL;
+      LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 3 : 0;
+      LayoutCtx.Replicate = Replicate16ToN_To_16;
+      break;
+  }
+  if (*LabPart.str.p_str)
+    SetSymbolOrStructElemSize(&LabPart, eSymbolSize64Bit);
+  DecodeIntelDx(&LayoutCtx);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DecodeIntelDT(Word Flags)
+ * \brief  Intel-style constant disposition - 80-bit words
+ * \param  Flags Data Type & Endianess Flags
+ * ------------------------------------------------------------------------ */
+
+void DecodeIntelDT(Word Flags)
+{
+  tLayoutCtx LayoutCtx;
+
+  memset(&LayoutCtx, 0, sizeof(LayoutCtx));
+  LayoutCtx.LayoutFunc = LayoutTenBytes;
+  LayoutCtx.BaseElemLenBits = 80;
+  switch (Grans[ActPC])
+  {
+    case 1:
+      LayoutCtx.Put80F = Put80F_To_8;
+      LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
+      LayoutCtx.Replicate = Replicate8ToN_To_8;
+      break;
+    case 2:
+      LayoutCtx.Put80F = Put80F_To_16;
+      LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
+      LayoutCtx.Replicate = Replicate16ToN_To_16;
+      break;
+  }
+  if (*LabPart.str.p_str)
+    SetSymbolOrStructElemSize(&LabPart, eSymbolSize80Bit);
+  DecodeIntelDx(&LayoutCtx);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DecodeIntelDS(Word Code)
+ * \brief  Intel-style memory reservation
+ * ------------------------------------------------------------------------ */
+
+void DecodeIntelDS(Word Code)
+{
+  UNUSED(Code);
+
+  if (ChkArgCnt(1, 1))
+  {
+    tSymbolFlags Flags;
+    Boolean OK;
+    LongInt HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags);
+
+    if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
+    else if (OK)
+    {
+      DontPrint = True;
+      CodeLen = HVal;
+      if (!HVal)
+        WrError(ErrNum_NullResMem);
+      BookKeeping();
+    }
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DecodeIntelPseudo(Boolean BigEndian)
+ * \brief  decode Intel-style pseudo instructions
+ * \param  BigEndian target endianess
+ * \return True if instruction found
+ * ------------------------------------------------------------------------ */
+
+Boolean DecodeIntelPseudo(Boolean BigEndian)
+{
+  static PInstTable InstTables[2] = { NULL, NULL };
+  int Idx = !!BigEndian;
+
+  if (!InstTables[Idx])
+  {
+    PInstTable InstTable = CreateInstTable(17);
+    Word Flag = BigEndian ? eIntPseudoFlag_BigEndian : eIntPseudoFlag_None;
+
+    AddInstTable(InstTable, "DN", Flag | eIntPseudoFlag_AllowInt, DecodeIntelDN);
+    AddInstTable(InstTable, "DB", Flag | eIntPseudoFlag_AllowInt, DecodeIntelDB);
+    AddInstTable(InstTable, "DW", Flag | eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowFloat, DecodeIntelDW);
+    AddInstTable(InstTable, "DD", Flag | eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowFloat, DecodeIntelDD);
+    AddInstTable(InstTable, "DQ", Flag | eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowFloat, DecodeIntelDQ);
+    AddInstTable(InstTable, "DT", Flag | eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowFloat, DecodeIntelDT);
+    AddInstTable(InstTable, "DS", 0, DecodeIntelDS);
+    InstTables[Idx] = InstTable;
+  }
+  return LookupInstTable(InstTables[Idx], OpPart.str.p_str);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DecodeZ80SYNTAX(Word Code)
+ * \brief  change Z80 syntax support for target
+ * ------------------------------------------------------------------------ */
+
+static void DecodeZ80SYNTAX(Word Code)
+{
+  UNUSED(Code);
+
+  if (ChkArgCnt(1, 1))
+  {
+    tStrComp TmpComp;
+
+    StrCompMkTemp(&TmpComp, Z80SyntaxName, 0);
+    NLS_UpString(ArgStr[1].str.p_str);
+    if (!as_strcasecmp(ArgStr[1].str.p_str, "OFF"))
+    {
+      CurrZ80Syntax = eSyntax808x;
+      EnterIntSymbol(&TmpComp, 0, SegNone, True);
+    }
+    else if (!as_strcasecmp(ArgStr[1].str.p_str, "ON"))
+    {
+      CurrZ80Syntax = eSyntaxBoth;
+      EnterIntSymbol(&TmpComp, 1, SegNone, True);
+    }
+    else if (!as_strcasecmp(ArgStr[1].str.p_str, "EXCLUSIVE"))
+    {
+      CurrZ80Syntax = eSyntaxZ80;
+      EnterIntSymbol(&TmpComp, 2, SegNone, True);
+    }
+    else
+      WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     ChkZ80Syntax(tZ80Syntax InstrSyntax)
+ * \brief  check whether instruction's syntax (808x/Z80) fits to selected one
+ * \param  InstrSyntax instruction syntax
+ * \return True if all fine
+ * ------------------------------------------------------------------------ */
+
+Boolean ChkZ80Syntax(tZ80Syntax InstrSyntax)
+{
+  if ((InstrSyntax == eSyntax808x) && (!(CurrZ80Syntax & eSyntax808x)))
+  {
+    WrStrErrorPos(ErrNum_Z80SyntaxExclusive, &OpPart);
+    return False;
+  }
+  else if ((InstrSyntax == eSyntaxZ80) && (!(CurrZ80Syntax & eSyntaxZ80)))
+  {
+    WrStrErrorPos(ErrNum_Z80SyntaxNotEnabled, &OpPart);
+    return False;
+  }
+  else
+    return True;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     AddZ80Syntax(struct sInstTable *InstTable)
+ * \brief  add Z80SYNTAX instruction to list & possibly set default
+ * \param  InstTable table to add to
+ * ------------------------------------------------------------------------ */
+
+void AddZ80Syntax(struct sInstTable *InstTable)
+{
+  if (!onoff_test_and_set(e_onoff_reg_z80syntax))
+  {
+    tStrComp TmpComp;
+
+    CurrZ80Syntax = eSyntax808x;
+    StrCompMkTemp(&TmpComp, Z80SyntaxName, 0);
+    EnterIntSymbol(&TmpComp, 0, SegNone, True);
+  }
+  AddInstTable(InstTable, "Z80SYNTAX", 0, DecodeZ80SYNTAX);
+}
diff --git a/aslshim/intpseudo.h b/aslshim/intpseudo.h
new file mode 100644 (file)
index 0000000..f86eaf7
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef _INTPSEUDO_H
+#define _INTPSEUDO_H
+/* intpseudo.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Commonly used 'Intel Style' Pseudo Instructions                           */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "datatypes.h"
+
+typedef enum
+{
+  eSyntaxNeither = 0,
+  eSyntax808x = 1,
+  eSyntaxZ80 = 2,
+  eSyntaxBoth = 3
+} tZ80Syntax;
+
+extern tZ80Syntax CurrZ80Syntax;
+
+/*****************************************************************************
+ * Global Functions
+ *****************************************************************************/
+
+enum
+{
+  eIntPseudoFlag_None = 0,
+  eIntPseudoFlag_BigEndian = 1 << 0,
+  eIntPseudoFlag_AllowInt = 1 << 1,
+  eIntPseudoFlag_AllowFloat = 1 << 2
+};
+
+extern void DecodeIntelDN(Word Flags);
+extern void DecodeIntelDB(Word Flags);
+extern void DecodeIntelDW(Word Flags);
+extern void DecodeIntelDD(Word Flags);
+extern void DecodeIntelDQ(Word Flags);
+extern void DecodeIntelDT(Word Flags);
+
+extern Boolean DecodeIntelPseudo(Boolean BigEndian);
+
+struct sInstTable;
+extern void AddZ80Syntax(struct sInstTable *InstTable);
+
+extern Boolean ChkZ80Syntax(tZ80Syntax InstrSyntax);
+
+#endif /* _INTPSEUDO_H */
diff --git a/aslshim/ioerrs.h b/aslshim/ioerrs.h
new file mode 100644 (file)
index 0000000..7835ee2
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _IOERRS_H
+#define _IOERRS_H
+/* ioerrs.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Abliefern der I/O-Fehlermeldungen                                         */
+/*                                                                           */
+/* Historie: 11.10.1996 Grundsteinlegung                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+extern char *GetErrorMsg(int number);
+
+extern void ioerrs_init(char *ProgPath);
+#endif /* _IOERRS_H */
diff --git a/aslshim/lstmacroexp.h b/aslshim/lstmacroexp.h
new file mode 100644 (file)
index 0000000..2b8e275
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef LSTMACROEXP_H
+#define LSTMACROEXP_H
+/* lstmacroexp.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Functions & variables regarding macro expansion in listing                */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "datatypes.h"
+
+typedef enum
+{
+  eLstMacroExpNone = 0,
+  eLstMacroExpRest = 1,
+  eLstMacroExpIf = 2,
+  eLstMacroExpMacro = 4,
+  eLstMacroExpAll = eLstMacroExpRest | eLstMacroExpIf | eLstMacroExpMacro
+} tLstMacroExp;
+
+#ifdef __cplusplus
+#include "cppops.h"
+DefCPPOps_Mask(tLstMacroExp)
+#endif
+
+#define LSTMACROEXPMOD_MAX 8
+
+typedef struct
+{
+  unsigned Count;
+  Byte Modifiers[LSTMACROEXPMOD_MAX];
+} tLstMacroExpMod;
+
+extern void SetLstMacroExp(tLstMacroExp NewMacroExp);
+extern tLstMacroExp GetLstMacroExp(void);
+
+extern void InitLstMacroExpMod(tLstMacroExpMod *pLstMacroExpMod);
+
+extern Boolean AddLstMacroExpMod(tLstMacroExpMod *pLstMacroExpMod, Boolean Set, tLstMacroExp Mod);
+
+extern Boolean ChkLstMacroExpMod(const tLstMacroExpMod *pLstMacroExpMod);
+
+extern void DumpLstMacroExpMod(const tLstMacroExpMod *pLstMacroExpMod, char *pDest, int DestLen);
+
+extern tLstMacroExp ApplyLstMacroExpMod(tLstMacroExp Src, const tLstMacroExpMod *pLstMacroExpMod);
+
+#endif /* LSTMACROEXP_H */
diff --git a/aslshim/math64.h b/aslshim/math64.h
new file mode 100644 (file)
index 0000000..0c17a54
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _MATH64_H
+#define _MATH64_H
+/* math64.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* 64 bit arithmetic for platforms not having a 64 bit integer               */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "datatypes.h"
+
+typedef struct
+{
+  LongWord low;
+  LongWord high;
+} t64;
+
+extern void add64(t64 *pRes, const t64 *pA, const t64 *pB);
+
+extern void sub64(t64 *pRes, const t64 *pA, const t64 *pB);
+
+extern void mul64(t64 *pRes, const t64 *pA, const t64 *pB);
+
+extern void div64(t64 *pRes, const t64 *pA, const t64 *pB);
+
+#endif /* _MATH64_H */
diff --git a/aslshim/natpseudo.c b/aslshim/natpseudo.c
new file mode 100644 (file)
index 0000000..39a58b1
--- /dev/null
@@ -0,0 +1,110 @@
+/* natpseudo.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Port                                                                   */
+/*                                                                           */
+/* Pseudo Instructions used for National Semiconductor CPUs                  */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************
+ * Includes
+ *****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include "bpemu.h"
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmitree.h"
+#include "codepseudo.h"
+#include "intpseudo.h"
+#include "errmsg.h"
+
+#include "natpseudo.h"
+
+/*****************************************************************************
+ * Global Functions
+ *****************************************************************************/
+
+static void DecodeSFR(Word Code)
+{
+  UNUSED(Code);
+  CodeEquate(SegData, 0, 0xff);
+}
+
+static void DecodeDSx(Word Shift)
+{
+  if (ChkArgCnt(1, 1))
+  {
+    tSymbolFlags Flags;
+    Boolean ValOK;
+    Word Size = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt16, &ValOK, &Flags) << Shift;
+
+    if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
+    else if (ValOK)
+    {
+      DontPrint = True;
+      if (!Size) WrError(ErrNum_NullResMem);
+      CodeLen = Size;
+      BookKeeping();
+    }
+  }
+}
+
+static void DecodeFx(Word Shift)
+{
+  if (ChkArgCnt(2, 2))
+  {
+    tSymbolFlags Flags;
+    Boolean ValOK;
+    Word Size = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt16, &ValOK, &Flags);
+
+    if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
+    else if (ValOK)
+    {
+      if (SetMaxCodeLen(Size << Shift)) WrError(ErrNum_CodeOverflow);
+      else
+      {
+        Word Value = EvalStrIntExpression(&ArgStr[2], Shift ? Int16 : Int8, &ValOK);
+
+        if (ValOK)
+        {
+          Word z;
+
+          for (z = 0; z < Size; z++)
+          {
+            BAsmCode[CodeLen++] = Lo(Value);
+            if (Shift)
+              BAsmCode[CodeLen++] = Hi(Value);
+          }
+        }
+      }
+    }
+  }
+}
+
+Boolean DecodeNatPseudo(void)
+{
+  static PInstTable InstTable = NULL;
+
+  if (!InstTable)
+  {
+    InstTable = CreateInstTable(31);
+
+    AddInstTable(InstTable, "SFR"  , 0     , DecodeSFR);
+    AddInstTable(InstTable, "ADDR" , eIntPseudoFlag_BigEndian | eIntPseudoFlag_AllowInt , DecodeIntelDB);
+    AddInstTable(InstTable, "ADDRW", eIntPseudoFlag_BigEndian | eIntPseudoFlag_AllowInt , DecodeIntelDW);
+    AddInstTable(InstTable, "BYTE" , eIntPseudoFlag_AllowInt , DecodeIntelDB);
+    AddInstTable(InstTable, "WORD" , eIntPseudoFlag_AllowInt , DecodeIntelDW);
+    AddInstTable(InstTable, "DSB"  , 0     , DecodeDSx);
+    AddInstTable(InstTable, "DSW"  , 1     , DecodeDSx);
+    AddInstTable(InstTable, "FB"   , 0     , DecodeFx);
+    AddInstTable(InstTable, "FW"   , 1     , DecodeFx);
+  }
+
+  return LookupInstTable(InstTable, OpPart.str.p_str);
+}
diff --git a/aslshim/natpseudo.h b/aslshim/natpseudo.h
new file mode 100644 (file)
index 0000000..26dd1b7
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _NATPSEUDO_H
+#define _NATPSEUDO_H
+/* natpseudo.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Port                                                                   */
+/*                                                                           */
+/* Pseudo Instructions commonly used on National targets                     */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************
+ * Global Functions
+ *****************************************************************************/
+
+extern Boolean DecodeNatPseudo(void);
+
+#endif /* _NATPSEUDO_H */
diff --git a/aslshim/nlmessages.h b/aslshim/nlmessages.h
new file mode 100644 (file)
index 0000000..8c05718
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _NLMESSAGES_H
+#define _NLMESSAGES_H
+/* nlmessages.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Einlesen und Verwalten von Meldungs-Strings                               */
+/*                                                                           */
+/* Historie: 13. 8.1997 Grundsteinlegung                                     */
+/*           17. 8.1997 Verallgemeinerung auf mehrere Kataloge               */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "datatypes.h"
+
+typedef struct
+{
+  char *MsgBlock;
+  LongInt *StrPosis, MsgCount;
+} TMsgCat, *PMsgCat;
+
+extern char *catgetmessage(PMsgCat Catalog, int Num);
+
+extern void opencatalog(PMsgCat Catalog, const char *File, const char *Path, LongInt File_MsgId1, LongInt File_MsgId2);
+
+extern char *getmessage(int Num);
+
+extern void nlmessages_init(const char *File, char *Path, LongInt File_MsgId1, LongInt File_MsgId2);
+#endif /* _NLMESSAGES_H */
diff --git a/aslshim/nls.h b/aslshim/nls.h
new file mode 100644 (file)
index 0000000..3754774
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _NLS_H
+#define _NLS_H
+/* nls.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Abhandlung landesspezifischer Unterschiede                                */
+/*                                                                           */
+/* Historie: 16. 5.1996 Grundsteinlegung                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stddef.h>
+
+#include "chardefs.h"
+
+typedef enum
+{
+  TimeFormatUSA,
+  TimeFormatEurope,
+  TimeFormatJapan
+} TimeFormat;
+
+typedef enum
+{
+  DateFormatMTY,
+  DateFormatTMY,
+  DateFormatYMT
+} DateFormat;
+
+typedef enum
+{
+  CurrFormatPreNoBlank,
+  CurrFormatPostNoBlank,
+  CurrFormatPreBlank,
+  CurrFormatPostBlank
+} CurrFormat;
+
+typedef char CharTable[256];
+
+extern CharTable UpCaseTable, LowCaseTable;
+
+
+extern Boolean NLS_Initialize(int *argc, char **argv);
+
+extern Word NLS_GetCountryCode(void);
+
+extern tCodepage NLS_GetCodepage(void);
+
+extern void NLS_DateString(Word Year, Word Month, Word Day, char *Dest, size_t DestSize);
+
+extern void NLS_CurrDateString(char *Dest, size_t DestSize);
+
+extern void NLS_TimeString(Word Hour, Word Minute, Word Second, Word Sec100, char *Dest, size_t DestSize);
+
+extern void NLS_CurrTimeString(Boolean Use100, char *Dest, size_t DestSize);
+
+extern void NLS_CurrencyString(double inp, char *erg, size_t DestSize);
+
+extern char Upcase(char inp);
+
+extern void NLS_UpString(char *s);
+
+extern void NLS_LowString(char *s);
+
+extern int NLS_StrCmp(const char *s1, const char *s2);
+
+
+extern void nls_init(void);
+#endif /* _NLS_H */
diff --git a/aslshim/nonzstring.h b/aslshim/nonzstring.h
new file mode 100644 (file)
index 0000000..c958a9e
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef _NONZSTRING_H
+#define _NONZSTRING_H
+/* nonzstring.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Port                                                                   */
+/*                                                                           */
+/* Handling of strings without NUL termination                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stddef.h>
+
+struct as_nonz_dynstr
+{
+  size_t len, capacity;
+  char *p_str;
+};
+typedef struct as_nonz_dynstr as_nonz_dynstr_t;
+
+#define as_nonz_dynstr_roundup_len(len)  \
+        (((len) + 127) & ~127)
+
+extern void as_nonz_dynstr_ini(as_nonz_dynstr_t *p_str, size_t ini_capacity);
+
+extern void as_nonz_dynstr_ini_c_str(as_nonz_dynstr_t *p_str, const char *p_src);
+
+extern void as_nonz_dynstr_realloc(as_nonz_dynstr_t *p_str, size_t new_capacity);
+
+extern void as_nonz_dynstr_free(as_nonz_dynstr_t *p_str);
+
+extern size_t as_nonz_dynstr_to_c_str(char *p_dest, const as_nonz_dynstr_t *p_src, size_t dest_len);
+
+extern size_t as_nonz_dynstr_copy(as_nonz_dynstr_t *p_dest, const as_nonz_dynstr_t *p_src);
+
+extern size_t as_nonz_dynstr_append_raw(as_nonz_dynstr_t *p_dest, const char *p_src, int src_len); /* -1 -> strlen */
+
+extern size_t as_nonz_dynstr_copy_c_str(as_nonz_dynstr_t *p_dest, const char *p_src);
+
+extern size_t as_nonz_dynstr_append(as_nonz_dynstr_t *p_dest, const as_nonz_dynstr_t *p_src);
+
+extern int as_nonz_dynstr_cmp(const as_nonz_dynstr_t *p_str1, const as_nonz_dynstr_t *p_str2);
+
+extern int as_nonz_dynstr_find(const as_nonz_dynstr_t *p_haystack, const as_nonz_dynstr_t *p_needle);
+
+extern void as_nonz_dynstr_dump_hex(FILE *p_file, const as_nonz_dynstr_t *p_str);
+
+#endif /* _NONZSTRING_H */
diff --git a/aslshim/onoff_common.h b/aslshim/onoff_common.h
new file mode 100644 (file)
index 0000000..98914b9
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _ONOFF_COMMON_H
+#define _ONOFF_COMMON_H
+/* onoff_common.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Port                                                                   */
+/*                                                                           */
+/* ON/OFF flags used by several targets                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#define FPUAvailName     "HASFPU"     /* FPU-Befehle erlaubt */
+#define PMMUAvailName    "HASPMMU"    /* PMMU-Befehle erlaubt */
+#define FullPMMUName     "FULLPMMU"
+#define SupAllowedCmdName "SUPMODE"   /* Privileged instructions allowed */
+#define SupAllowedSymName "INSUPMODE"
+#define MaxModeSymName    "INMAXMODE"  /* CPU in maximum mode */
+#define MaxModeCmdName    "MAXMODE"
+#define SrcModeCmdName    "SRCMODE"
+#define SrcModeSymName    "INSRCMODE"  /* CPU im Quellcode-kompatiblen Modus */
+#define ExtModeCmdName    "EXTMODE"
+#define ExtModeSymName    "INEXTMODE"
+#define LWordModeCmdName  "LWORDMODE"
+#define LWordModeSymName  "INLWORDMODE"
+#define DSPCmdName        "DSP"
+#define DSPSymName        "HASDSP"
+#define CustomAvailCmdName "CUSTOM"
+#define CustomAvailSymName "CUSTOM"
+#define PackingCmdName    "PACKING"
+#define PackingSymName    "PACKING"
+#define BigEndianCmdName  "BIGENDIAN"
+#define BigEndianSymName  "BIGENDIAN"  /* Data storage MSB first */
+#define BranchExtCmdName  "BRANCHEXT"
+#define BranchExtSymName  "BRANCHEXT"
+
+extern Boolean FPUAvail,
+               PMMUAvail,
+               SupAllowed,
+               MaxMode,
+               TargetBigEndian,
+               DoPadding;
+
+/* NOTE: will have to switch this to #define as soon as
+   everything up to 2**15 is used up - 16 bit compilers
+   silently limit enums to int range */
+
+enum
+{
+  e_onoff_reg_fpu = 1 << 0,
+  e_onoff_reg_pmmu = 1 << 1,
+  e_onoff_reg_custom = 1 << 2,
+  e_onoff_reg_supmode = 1 << 3,
+  e_onoff_reg_maxmode = 1 << 4,
+  e_onoff_reg_extmode = 1 << 5,
+  e_onoff_reg_srcmode = 1 << 6,
+  e_onoff_reg_compmode = 1 << 7,
+  e_onoff_reg_lwordmode = 1 << 8,
+  e_onoff_reg_fullpmmu = 1 << 9,
+  e_onoff_reg_dsp = 1 << 10,
+  e_onoff_reg_packing = 1 << 11,
+  e_onoff_reg_bigendian = 1 << 12,
+  e_onoff_reg_branchext = 1 << 13,
+  e_onoff_reg_z80syntax = 1 << 14
+};
+
+extern unsigned onoff_test_and_set(unsigned mask);
+
+extern void onoff_fpu_add(void);
+extern void onoff_pmmu_add(void);
+extern void onoff_supmode_add(void);
+extern void onoff_maxmode_add(void);
+extern void onoff_bigendian_add(void);
+
+extern void onoff_common_init(void);
+
+#endif /* _ONOFF_COMMON_H */
diff --git a/aslshim/operator.h b/aslshim/operator.h
new file mode 100644 (file)
index 0000000..130bab6
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _OPERATOR_H
+#define _OPERATOR_H
+/* operator.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* defintion of operators                                                    */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "datatypes.h"
+#include "tempresult.h"
+
+#define OPERATOR_MAXCNT 30
+#define OPERATOR_MAXCOMB 5
+
+typedef struct
+{
+  const char *Id;
+  int IdLen;
+  Boolean Dyadic;
+  Byte Priority;
+  Byte TypeCombinations[OPERATOR_MAXCOMB];
+  void (*pFunc)(TempResult *pErg, TempResult *pLVal, TempResult *pRVal);
+} Operator;
+
+extern const Operator Operators[], MinusMonadicOperator, *pPotMonadicOperator;
+
+#endif /* _OPERATOR_H */
diff --git a/aslshim/pascstyle.h b/aslshim/pascstyle.h
new file mode 100644 (file)
index 0000000..c27809a
--- /dev/null
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+#ifndef _PASCSTYLE_H
+#define _PASCSTYLE_H
+
+#ifndef False
+#define False 0
+#define True 1
+#endif
+
+#define Ord(b) ((b) ? 1L : 0L)
+
+#define MaxLongInt 2147483647
+#endif /* _PASCSTYLE_H */
diff --git a/aslshim/stdhandl.h b/aslshim/stdhandl.h
new file mode 100644 (file)
index 0000000..2a22e29
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _STDHANDL_H
+#define _STDHANDL_H
+/* stdhandl.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Bereitstellung von fuer AS benoetigten Handle-Funktionen                  */
+/*                                                                           */
+/* Historie:  5. 4.1996 Grundsteinlegung                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+typedef enum {NoRedir,RedirToDevice,RedirToFile} TRedirected;  /* Umleitung von Handles */
+
+#define NumStdIn 0
+#define NumStdOut 1
+#define NumStdErr 2
+
+extern TRedirected Redirected;
+
+extern void OpenWithStandard(FILE **ppFile, char *Path);
+
+extern void CloseIfOpen(FILE **ppFile);
+
+extern void stdhandl_init(void);
+#endif /* _STDHANDL_H */
diff --git a/aslshim/stdinc.h b/aslshim/stdinc.h
new file mode 100644 (file)
index 0000000..92a9652
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef _STDINC_H
+#define _STDINC_H
+/* stdinc.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* globaler Einzug immer benoetigter includes                                */
+/*                                                                           */
+/* Historie: 21. 5.1996 min/max                                              */
+/*           11. 5.1997 DOS-Anpassungen                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stddef.h>
+#include <stdio.h>
+#ifndef __MUNIX__
+#include <stdlib.h>
+#endif
+#if !defined ( __MSDOS__ ) && !defined( __IBMC__ )
+#include <unistd.h>
+#endif
+#include <math.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifdef __MSDOS__
+#include <alloc.h>
+#else
+#include <memory.h>
+#if !defined (__FreeBSD__) && !defined(__APPLE__)
+#include <malloc.h>
+#endif
+#endif
+
+#include "pascstyle.h"
+#include "datatypes.h"
+#include "chardefs.h"
+
+#ifndef min
+#define min(a,b) ((a<b)?(a):(b))
+#endif
+#ifndef max
+#define max(a,b) ((a>b)?(a):(b))
+#endif
+
+#ifndef M_PI
+#define M_PI 3.1415926535897932385E0
+#endif
+
+#endif /* _STDINC_H */
diff --git a/aslshim/strcomp.c b/aslshim/strcomp.c
new file mode 100644 (file)
index 0000000..397e8fd
--- /dev/null
@@ -0,0 +1,379 @@
+/* strcomp.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* Macro Assembler AS                                                        */
+/*                                                                           */
+/* Definition of a source line's component present after parsing             */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+#include "datatypes.h"
+#include "strutil.h"
+#include "strcomp.h"
+
+static void check_capacity(const tStrComp *pComp)
+{
+  if (!pComp->str.capacity)
+  {
+    fprintf(stderr, "copy to zero-capacity StrComp\n");
+    abort();
+  }
+}
+
+static void check_no_capacity(const tStrComp *pComp)
+{
+  if (pComp->str.capacity)
+  {
+    fprintf(stderr, "ptr move on non-zero-capacity StrComp\n");
+    abort();
+  }
+}
+
+static size_t check_realloc(as_dynstr_t *p_str, size_t req_count)
+{
+  if ((req_count >= p_str->capacity) && p_str->dynamic)
+    as_dynstr_realloc(p_str, as_dynstr_roundup_len(req_count));
+  if (req_count >= p_str->capacity)
+    req_count = p_str->capacity - 1;
+  return req_count;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompAlloc(tStrComp *pComp, size_t capacity)
+ * \brief  initialize string component with dynamic buffer
+ * \param  pComp component to fill
+ * \param  capacity requested capacity of buffer
+ * ------------------------------------------------------------------------ */
+
+void StrCompAlloc(tStrComp *pComp, size_t capacity)
+{
+  as_dynstr_ini(&pComp->str, capacity);
+  StrCompReset(pComp);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompReset(tStrComp *pComp)
+ * \brief  reset string component to "empty" state
+ * \param  pComp component to set
+ * ------------------------------------------------------------------------ */
+
+void StrCompReset(tStrComp *pComp)
+{
+  LineCompReset(&pComp->Pos);
+  *pComp->str.p_str = '\0';
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     LineCompReset(tLineComp *pComp)
+ * \brief  reset line position to "empty" state
+ * \param  pComp component to set
+ * ------------------------------------------------------------------------ */
+
+void LineCompReset(tLineComp *pComp)
+{
+  pComp->StartCol = -1;
+  pComp->Len = 0;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompFree(tStrComp *pComp)
+ * \brief  free/clean string component
+ * \param  pComp string component to be cleared
+ * ------------------------------------------------------------------------ */
+
+void StrCompFree(tStrComp *pComp)
+{
+  LineCompReset(&pComp->Pos);
+  as_dynstr_free(&pComp->str);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompMkTemp(tStrComp *pComp, char *pStr, size_t capacity)
+ * \brief  create a dummy StrComp from plain string
+ * \param  pComp comp to create
+ * \param  pStr string to use
+ * \param  capacity string's capacity
+ * ------------------------------------------------------------------------ */
+
+void StrCompMkTemp(tStrComp *pComp, char *pStr, size_t capacity)
+{
+  LineCompReset(&pComp->Pos);
+  pComp->str.p_str = pStr;
+  pComp->str.capacity = capacity;
+  pComp->str.dynamic = 0;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompRefRight(tStrComp *pDest, const tStrComp *pSrc, size_t StartOffs)
+ * \brief  create a right-aligned substring component of string component (no copy)
+ * \param  pDest destination component
+ * \param  pSrc source component
+ * \param  StartOffs how many characters to omit at the left
+ * ------------------------------------------------------------------------ */
+
+void StrCompRefRight(tStrComp *pDest, const tStrComp *pSrc, size_t StartOffs)
+{
+  pDest->str.p_str = pSrc->str.p_str + StartOffs;
+  pDest->str.capacity = 0;
+  pDest->str.dynamic = 0;
+  pDest->Pos.StartCol = pSrc->Pos.StartCol + StartOffs;
+  pDest->Pos.Len = pSrc->Pos.Len - StartOffs;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompCopy(tStrComp *pDest, tStrComp *pSrc)
+ * \brief  copy string component
+ * \param  pDest destination component
+ * \param  pSrc source component
+ * ------------------------------------------------------------------------ */
+
+void StrCompCopy(tStrComp *pDest, const tStrComp *pSrc)
+{
+  pDest->Pos = pSrc->Pos;
+  pDest->Pos.Len = as_dynstr_copy(&pDest->str, &pSrc->str);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompCopySub(tStrComp *pDest, const tStrComp *pSrc, size_t Start, size_t Count)
+ * \brief  copy substring
+ * \param  pDest destination
+ * \param  pSrc source
+ * \param  Start start index to copy from
+ * \param  Count # of characters to copy
+ * ------------------------------------------------------------------------ */
+
+void StrCompCopySub(tStrComp *pDest, const tStrComp *pSrc, size_t Start, size_t Count)
+{
+  unsigned l = strlen(pSrc->str.p_str);
+
+  if (Start >= l)
+    Count = 0;
+  else if (Start + Count > l)
+    Count = l - Start;
+  check_capacity(pDest);
+  Count = check_realloc(&pDest->str, Count);
+  memcpy(pDest->str.p_str, pSrc->str.p_str + Start, Count);
+  pDest->str.p_str[Count] = '\0';
+  pDest->Pos.StartCol = pSrc->Pos.StartCol + Start;
+  pDest->Pos.Len = Count;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompSplitRight(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
+ * \brief  split off another component at the right of the source
+ * \param  pSrc source to split off
+ * \param  pDest where to put part splitted off
+ * \param  pSrcSplitPos split position (not included in source or dest any more)
+ * ------------------------------------------------------------------------ */
+
+void StrCompSplitRight(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
+{
+  size_t SrcLen = strlen(pSrcSplitPos + 1);
+
+  check_capacity(pDest);
+  SrcLen = check_realloc(&pDest->str, SrcLen);
+  memcpy(pDest->str.p_str, pSrcSplitPos + 1, SrcLen);
+  pDest->str.p_str[SrcLen] = '\0';
+  pDest->Pos.StartCol = pSrc->Pos.StartCol + pSrcSplitPos + 1 - pSrc->str.p_str;
+  pDest->Pos.Len = SrcLen;
+  *pSrcSplitPos = '\0';
+  pSrc->Pos.Len = pSrcSplitPos - pSrc->str.p_str;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompSplitLeft(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
+ * \brief  split off another component at the left of the source
+ * \param  pSrc source to split off
+ * \param  pDest where to put part splitted off
+ * \param  pSrcSplitPos split position (not included in source or dest any more)
+ * ------------------------------------------------------------------------ */
+
+void StrCompSplitLeft(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
+{
+  size_t SrcLen;
+
+  *pSrcSplitPos = '\0';
+  SrcLen = strlen(pSrc->str.p_str);
+  check_capacity(pDest);
+  SrcLen = check_realloc(&pDest->str, SrcLen);
+
+  memcpy(pDest->str.p_str, pSrc->str.p_str, SrcLen);
+  pDest->str.p_str[SrcLen] = '\0';
+  pDest->Pos.StartCol = pSrc->Pos.StartCol;
+  pDest->Pos.Len = pSrcSplitPos - pSrc->str.p_str;
+
+  strmov(pSrc->str.p_str, pSrcSplitPos + 1);
+  pSrc->Pos.StartCol += pSrcSplitPos - pSrc->str.p_str + 1;
+  pSrc->Pos.Len -= pSrcSplitPos - pSrc->str.p_str + 1;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompSplitCopy(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
+ * \brief  copy left & right part of string to new components
+ * \param  pLeft dest for left part
+ * \param  pRight dest for right part
+ * \param  pSrc character source
+ * \param  pSplitPos split position in source
+ * ------------------------------------------------------------------------ */
+
+void StrCompSplitCopy(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
+{
+  /* pLeft may be equal to pSrc, use memmove() and save SrcLen */
+
+  size_t SrcLen = pSrc->Pos.Len;
+
+  check_capacity(pLeft);
+  pLeft->Pos.StartCol = pSrc->Pos.StartCol;
+  pLeft->Pos.Len = check_realloc(&pLeft->str, pSplitPos - pSrc->str.p_str);
+  memmove(pLeft->str.p_str, pSrc->str.p_str, pLeft->Pos.Len);
+  pLeft->str.p_str[pLeft->Pos.Len] = '\0';
+
+  check_capacity(pRight);
+  pRight->Pos.StartCol = pSrc->Pos.StartCol + (pLeft->Pos.Len + 1);
+  pRight->Pos.Len = check_realloc(&pRight->str, SrcLen - (pLeft->Pos.Len + 1));
+  memcpy(pRight->str.p_str, pSplitPos + 1, pRight->Pos.Len);
+  pRight->str.p_str[pRight->Pos.Len] = '\0';
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompSplitRef(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
+ * \brief  split string into left & right and form references
+ * \param  pLeft dest for left part
+ * \param  pRight dest for right part
+ * \param  pSrc character source
+ * \param  pSplitPos split position in source
+ * ------------------------------------------------------------------------ */
+
+char StrCompSplitRef(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
+{
+  char Old = *pSplitPos;
+  /* save because pLeft and pSrc might be equal */
+  tLineComp SrcPos = pSrc->Pos;
+
+  *pSplitPos = '\0';
+  pLeft->str.p_str = pSrc->str.p_str;
+  if (pLeft != pSrc)
+  {
+    pLeft->str.capacity = 0;
+    pLeft->str.dynamic = 0;
+  }
+  pLeft->Pos.StartCol = SrcPos.StartCol;
+  pLeft->Pos.Len = pSplitPos - pLeft->str.p_str;
+  pRight->str.p_str = pSrc->str.p_str + (pLeft->Pos.Len + 1);
+  pRight->str.capacity = 0;
+  pRight->str.dynamic = 0;
+  pRight->Pos.StartCol = SrcPos.StartCol + (pLeft->Pos.Len + 1);
+  pRight->Pos.Len = SrcPos.Len - (pLeft->Pos.Len + 1);
+
+  return Old;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     KillPrefBlanksStrComp(struct sStrComp *pComp)
+ * \brief  remove leading spaces on string component
+ * \param  pComp component to handle
+ * ------------------------------------------------------------------------ */
+
+void KillPrefBlanksStrComp(struct sStrComp *pComp)
+{
+  int Delta = KillPrefBlanks(pComp->str.p_str);
+  pComp->Pos.StartCol += Delta;
+  pComp->Pos.Len -= Delta;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     KillPrefBlanksStrCompRef(struct sStrComp *pComp)
+ * \brief  remove leading spaces on string component by inc'ing pointer
+ * \param  pComp component to handle
+ * ------------------------------------------------------------------------ */
+
+void KillPrefBlanksStrCompRef(struct sStrComp *pComp)
+{
+  check_no_capacity(pComp);
+  while (isspace(*pComp->str.p_str))
+  {
+    pComp->str.p_str++;
+    if (pComp->str.capacity > 0)
+      pComp->str.capacity--;
+    pComp->Pos.StartCol++;
+    pComp->Pos.Len--;
+  }
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     KillPostBlanksStrComp(struct sStrComp *pComp)
+ * \brief  remove trailing spaces on string component
+ * \param  pComp component to handle
+ * ------------------------------------------------------------------------ */
+
+void KillPostBlanksStrComp(struct sStrComp *pComp)
+{
+  pComp->Pos.Len -= KillPostBlanks(pComp->str.p_str);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompShorten(struct sStrComp *pComp, size_t Delta)
+ * \brief  shorten string component by n characters
+ * \param  pComp component to shorten
+ * \param  Delta # of characters to chop off (no checks!)
+ * ------------------------------------------------------------------------ */
+
+void StrCompShorten(struct sStrComp *pComp, size_t Delta)
+{
+  pComp->str.p_str[strlen(pComp->str.p_str) - Delta] = '\0';
+  pComp->Pos.Len -= Delta;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompCutLeft(struct sStrComp *pComp, size_t Delta)
+ * \brief  remove n characters at start of component
+ * \param  pComp component to shorten
+ * \param  Delta # of characters to cut off
+ * \return actual # of characters cut off
+ * ------------------------------------------------------------------------ */
+
+size_t StrCompCutLeft(struct sStrComp *pComp, size_t Delta)
+{
+  size_t len = strlen(pComp->str.p_str);
+
+  if (Delta > len)
+    Delta = len;
+  if (Delta > pComp->Pos.Len)
+    Delta = pComp->Pos.Len;
+  strmov(pComp->str.p_str, pComp->str.p_str + Delta);
+  pComp->Pos.StartCol += Delta;
+  pComp->Pos.Len -= Delta;
+  return Delta;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     StrCompIncRefLeft(struct sStrComp *pComp, size_t Delta)
+ * \brief  move start of component by n characters
+ * \param  pComp component to shorten
+ * \param  Delta # of characters to move by (no checks!)
+ * ------------------------------------------------------------------------ */
+
+void StrCompIncRefLeft(struct sStrComp *pComp, size_t Delta)
+{
+  check_no_capacity(pComp);
+  pComp->str.p_str += Delta;
+  pComp->str.capacity = (pComp->str.capacity > Delta) ? pComp->str.capacity - Delta : 0;
+  pComp->Pos.StartCol += Delta;
+  pComp->Pos.Len -= Delta;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DumpStrComp(const char *pTitle, const struct sStrComp *pComp)
+ * \brief  debug dump of component
+ * \param  pTitle description of component
+ * \param  pComp component to dump
+ * ------------------------------------------------------------------------ */
+
+void DumpStrComp(const char *pTitle, const struct sStrComp *pComp)
+{
+  fprintf(stderr, "%s: @ col %u len %u '%s'\n", pTitle, pComp->Pos.StartCol, pComp->Pos.Len, pComp->str.p_str);
+}
diff --git a/aslshim/strcomp.h b/aslshim/strcomp.h
new file mode 100644 (file)
index 0000000..507eb7c
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef _STRCOMP_H
+#define _STRCOMP_H
+/* strcomp.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* Macro Assembler AS                                                        */
+/*                                                                           */
+/* Definition of a source line's component present after parsing             */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stddef.h>
+#include "dynstr.h"
+
+typedef char *StringPtr;
+
+struct sLineComp
+{
+  int StartCol;
+  unsigned Len;
+};
+typedef struct sLineComp tLineComp;
+
+struct sStrComp
+{
+  tLineComp Pos;
+  as_dynstr_t str;
+};
+typedef struct sStrComp tStrComp;
+
+extern void StrCompAlloc(tStrComp *pComp, size_t Capacity);
+extern void StrCompFree(tStrComp *pComp);
+
+extern void StrCompReset(tStrComp *pComp);
+extern void LineCompReset(tLineComp *pComp);
+
+extern void StrCompMkTemp(tStrComp *pComp, char *pStr, size_t Capacity);
+
+extern void StrCompRefRight(tStrComp *pDest, const tStrComp *pSrc, size_t StartOffs);
+
+extern void StrCompCopy(tStrComp *pDest, const tStrComp *pSrc);
+
+extern void StrCompCopySub(tStrComp *pDest, const tStrComp *pSrc, size_t Start, size_t Count);
+
+extern void StrCompSplitRight(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos);
+
+extern void StrCompSplitLeft(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos);
+
+extern void StrCompSplitCopy(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos);
+extern char StrCompSplitRef(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos);
+
+extern void StrCompShorten(struct sStrComp *pComp, size_t Delta);
+
+extern size_t StrCompCutLeft(struct sStrComp *pComp, size_t Delta);
+extern void StrCompIncRefLeft(struct sStrComp *pComp, size_t Delta);
+
+extern void KillPrefBlanksStrComp(struct sStrComp *pComp);
+extern void KillPrefBlanksStrCompRef(struct sStrComp *pComp);
+
+extern void KillPostBlanksStrComp(struct sStrComp *pComp);
+
+extern void DumpStrComp(const char *pTitle, const struct sStrComp *pComp);
+
+#endif /* _STRCOMP_H */
diff --git a/aslshim/stringlists.h b/aslshim/stringlists.h
new file mode 100644 (file)
index 0000000..4ab60a3
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef _STRINGLISTS_H
+#define _STRINGLISTS_H
+/* stringlists.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Verwaltung von String-Listen                                              */
+/*                                                                           */
+/* Historie:  4. 5.1996 Grundsteinlegung                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "datatypes.h"
+
+typedef struct sStringRec
+{
+  struct sStringRec *Next;
+  char *Content;
+} StringRec, *StringRecPtr;
+typedef StringRecPtr StringList;
+
+extern void InitStringList(StringList *List);
+
+extern void ClearStringEntry(StringRecPtr *Elem);
+
+extern void ClearStringList(StringList *List);
+
+extern void AddStringListFirst(StringList *List, const char *NewStr);
+
+extern void AddStringListLast(StringList *List, const char *NewStr);
+
+extern void RemoveStringList(StringList *List, const char *OldStr);
+
+extern const char *GetStringListFirst(StringList List, StringRecPtr *Lauf);
+
+extern const char *GetStringListNext(StringRecPtr *Lauf);
+
+extern char *GetAndCutStringList(StringList *List);
+
+extern Boolean StringListEmpty(StringList List);
+
+extern StringList DuplicateStringList(StringList Src);
+
+extern Boolean StringListPresent(StringList List, char *Search);
+
+extern void DumpStringList(StringList List);
+#endif /* _STRINGLISTS_H */
diff --git a/aslshim/strutil.c b/aslshim/strutil.c
new file mode 100644 (file)
index 0000000..3cafd68
--- /dev/null
@@ -0,0 +1,1462 @@
+/* strutil.c */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* haeufig benoetigte String-Funktionen                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#include "dynstr.h"
+#include "strutil.h"
+#undef strlen   /* VORSICHT, Rekursion!!! */
+
+char HexStartCharacter;            /* characters to use for 10,11,...35 */
+char SplitByteCharacter;    /* output large numbers per-byte with given split char */
+
+/*--------------------------------------------------------------------------*/
+/* eine bestimmte Anzahl Leerzeichen liefern */
+
+const char *Blanks(int cnt)
+{
+  static const char *BlkStr = "                                                                                                           ";
+  static int BlkStrLen = 0;
+
+  if (!BlkStrLen)
+    BlkStrLen = strlen(BlkStr);
+
+  if (cnt < 0)
+    cnt = 0;
+  if (cnt > BlkStrLen)
+    cnt = BlkStrLen;
+
+  return BlkStr + (BlkStrLen - cnt);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     SysString(char *pDest, size_t DestSize, LargeWord i, int System, int Stellen, Boolean ForceLeadZero, char StartCharacter, char SplitCharacter)
+ * \brief  convert number to string in given number system, leading zeros
+ * \param  pDest where to write
+ * \param  DestSize size of dest buffer
+ * \param  i number to convert
+ * \param  Stellen minimum length of output
+ * \param  ForceLeadZero prepend zero if first character is no number
+ * \param  System number system
+ * \param  StartCharacter 'a' or 'A' for hex digits
+ * \param  SplitCharacter split bytes if not NUL
+ * ------------------------------------------------------------------------ */
+
+char *SysStringCore(char *pDest, char *pDestCurr, LargeWord Num, int System, int Stellen, char StartCharacter)
+{
+  LargeWord Digit;
+
+  do
+  {
+    if (pDestCurr <= pDest)
+      break;
+    Digit = Num % System;
+    if (Digit < 10)
+      *(--pDestCurr) = Digit + '0';
+    else
+      *(--pDestCurr) = Digit - 10 + StartCharacter;
+    Num /= System;
+    Stellen--;
+  }
+  while ((Stellen > 0) || Num);
+  return pDestCurr;
+}
+
+int SysString(char *pDest, size_t DestSize, LargeWord Num, int System, int Stellen, Boolean ForceLeadZero, char StartCharacter, char SplitCharacter)
+{
+  int Len = 0;
+  char *pDestCurr, *pDestNext;
+
+  if (DestSize < 1)
+    return 0;
+
+  if (Stellen > (int)DestSize - 1)
+    Stellen = DestSize - 1;
+
+  pDestCurr = pDest + DestSize - 1;
+  *pDestCurr = '\0';
+  if (SplitCharacter)
+  {
+    LargeWord Part;
+    int ThisLen;
+    static int SystemByteLen[37];
+
+    if (!SystemByteLen[System])
+    {
+      char Dummy[50];
+
+      SystemByteLen[System] = SysString(Dummy, sizeof(Dummy), 0xff, System, 0, False, StartCharacter, False);
+    }
+
+    do
+    {
+      Part = Num % 256;
+      Num = Num / 256;
+      pDestNext = SysStringCore(pDest, pDestCurr, Part, System, Num ? SystemByteLen[System] : Stellen, StartCharacter);
+      ThisLen = pDestCurr - pDestNext;
+      Len += ThisLen;
+      pDestCurr = pDestNext;
+      Stellen -= ThisLen;
+      if (Num)
+      {
+        if (pDestCurr <= pDest)
+          break;
+        *(--pDestCurr) = SplitCharacter;
+        Len++;
+      }
+    }
+    while ((Stellen > 0) || Num);
+  }
+  else
+  {
+    pDestNext = SysStringCore(pDest, pDestCurr, Num, System, Stellen, StartCharacter);
+    Len += pDestCurr - pDestNext;
+    pDestCurr = pDestNext;
+  }
+
+  if (ForceLeadZero && !isdigit(*pDestCurr) && (pDestCurr > pDest))
+  {
+    *(--pDestCurr) = '0';
+    Len++;
+  }
+
+  if (pDestCurr != pDest)
+    strmov(pDest, pDestCurr);
+  return Len;
+}
+
+/*---------------------------------------------------------------------------*/
+/* strdup() is not part of ANSI C89 */
+
+char *as_strdup(const char *s)
+{
+  char *ptr;
+
+  if (!s)
+    return NULL;
+  ptr = (char *) malloc(strlen(s) + 1);
+#ifdef CKMALLOC
+  if (!ptr)
+  {
+    fprintf(stderr, "strdup: out of memory?\n");
+    exit(255);
+  }
+#endif
+  if (ptr != 0)
+    strcpy(ptr, s);
+  return ptr;
+}
+/*---------------------------------------------------------------------------*/
+/* ...so is snprintf... */
+
+typedef enum { eNotSet, eSet, eFinished } tArgState;
+
+typedef struct
+{
+  tArgState ArgState[3];
+  Boolean InFormat, LeadZero, Signed, LeftAlign, AddPlus, ForceLeadZero, ForceUpper;
+  int Arg[3], CurrArg, IntSize;
+} tFormatContext;
+
+typedef struct
+{
+  char *p_dest;
+  size_t dest_remlen;
+  as_dynstr_t *p_dynstr;
+} dest_format_context_t;
+
+static void ResetFormatContext(tFormatContext *pContext)
+{
+  int z;
+
+  for (z = 0; z < 3; z++)
+  {
+    pContext->Arg[z] = 0;
+    pContext->ArgState[z] = eNotSet;
+  }
+  pContext->CurrArg = 0;
+  pContext->IntSize = 0;
+  pContext->InFormat =
+  pContext->LeadZero =
+  pContext->ForceLeadZero =
+  pContext->Signed =
+  pContext->LeftAlign =
+  pContext->AddPlus =
+  pContext->ForceUpper = False;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     limit_minus_one(dest_format_context_t *p_dest_ctx, size_t cnt)
+ * \brief  check if space is left to append given # of characters, plus trailing NUL
+ * \param  p_dest_ctx destination context
+ * \param  cnt requested # of characters to append
+ * \return actual # that can be appended
+ * ------------------------------------------------------------------------ */
+
+static size_t limit_minus_one(dest_format_context_t *p_dest_ctx, size_t cnt)
+{
+  /* anyway still enough space? */
+
+  if (p_dest_ctx->dest_remlen > cnt)
+    return cnt;
+
+  /* not enough space: try to realloc dynamic string dest */
+
+  if (p_dest_ctx->p_dynstr)
+  {
+    size_t curr_len = p_dest_ctx->p_dest - p_dest_ctx->p_dynstr->p_str;
+    size_t new_capacity = as_dynstr_roundup_len(curr_len + cnt + 1);
+
+    /* if realloc successful, pointer into string buffer must be adapted: */
+
+    if (!as_dynstr_realloc(p_dest_ctx->p_dynstr, new_capacity))
+    {
+      p_dest_ctx->p_dest = p_dest_ctx->p_dynstr->p_str + curr_len;
+      p_dest_ctx->dest_remlen = p_dest_ctx->p_dynstr->capacity - curr_len;
+    }
+  }
+
+  /* pathological case... */
+
+  if (!p_dest_ctx->dest_remlen)
+    return 0;
+
+  /* truncation */
+
+  else
+    return (cnt >= p_dest_ctx->dest_remlen) ? p_dest_ctx->dest_remlen - 1 : cnt;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     append_pad(dest_format_context_t *p_dest_ctx, char src, size_t cnt)
+ * \brief  append given character n times
+ * \param  p_dest_ctx destination context
+ * \param  src character to append
+ * \param  cnt # of times to append
+ * \return actual # of characters appended
+ * ------------------------------------------------------------------------ */
+
+static size_t append_pad(dest_format_context_t *p_dest_ctx, char src, size_t cnt)
+{
+  cnt = limit_minus_one(p_dest_ctx, cnt);
+
+  if (cnt > 0)
+  {
+    memset(p_dest_ctx->p_dest, src, cnt);
+    p_dest_ctx->p_dest += cnt;
+    p_dest_ctx->dest_remlen -= cnt;
+  }
+  return cnt;
+}
+
+#if 0
+static int FloatConvert(char *pDest, size_t DestSize, double Src, int Digits, Boolean TruncateTrailingZeros, char FormatType)
+{
+  int DecPt;
+  int Sign, Result = 0;
+  char *pBuf, *pEnd, *pRun;
+
+  (void)FormatType;
+
+  if (DestSize < Digits + 6)
+  {
+    *pDest = '\0';
+    return Result;
+  }
+
+  if (Digits < 0)
+    Digits = 6;
+
+  pBuf = ecvt(Src, Digits + 1, &DecPt, &Sign);
+  puts(pBuf);
+  pEnd = pBuf + strlen(pBuf) - 1;
+  if (TruncateTrailingZeros)
+  {
+    for (; pEnd > pBuf + 1; pEnd--)
+      if (*pEnd != '0')
+        break;
+  }
+
+  pRun = pDest;
+  if (Sign)
+    *pRun++ = '-';
+  *pRun++ = *pBuf;
+  *pRun++ = '.';
+  memcpy(pRun, pBuf + 1, pEnd - pBuf); pRun += pEnd - pBuf;
+  *pRun = '\0';
+  Result = pRun - pDest;
+  Result += as_snprintf(pRun, DestSize - Result, "e%+02d", DecPt - 1);
+  return Result;
+}
+#else
+static int FloatConvert(char *pDest, size_t DestSize, double Src, int Digits, Boolean TruncateTrailingZeros, char FormatType)
+{
+  char Format[10];
+
+  (void)DestSize;
+  (void)TruncateTrailingZeros;
+  strcpy(Format, "%0.*e");
+  Format[4] = (HexStartCharacter == 'a') ? FormatType : toupper(FormatType);
+  sprintf(pDest, Format, Digits, Src);
+  return strlen(pDest);
+}
+#endif
+
+/*!------------------------------------------------------------------------
+ * \fn     append(dest_format_context_t *p_dest_ctx, const char *p_src, size_t cnt, tFormatContext *pFormatContext)
+ * \brief  append given data, with possible left/right padding
+ * \param  p_dest_ctx destination context
+ * \param  p_src data to append
+ * \param  cnt length of data to append
+ * \param  pFormatContext formatting context
+ * \return actual # of characters appended
+ * ------------------------------------------------------------------------ */
+
+static size_t append(dest_format_context_t *p_dest_ctx, const char *p_src, size_t cnt, tFormatContext *pFormatContext)
+{
+  size_t pad_len, result = 0;
+
+  pad_len = (pFormatContext->Arg[0] > (int)cnt) ? pFormatContext->Arg[0] - cnt : 0;
+
+  if ((pad_len > 0) && !pFormatContext->LeftAlign)
+    result += append_pad(p_dest_ctx, ' ', pad_len);
+
+  cnt = limit_minus_one(p_dest_ctx, cnt);
+  if (cnt > 0)
+  {
+    memcpy(p_dest_ctx->p_dest, p_src, cnt);
+    p_dest_ctx->p_dest += cnt;
+    p_dest_ctx->dest_remlen -= cnt;
+  }
+
+  if ((pad_len > 0) && pFormatContext->LeftAlign)
+    result += append_pad(p_dest_ctx, ' ', pad_len);
+
+  if (pFormatContext->InFormat)
+    ResetFormatContext(pFormatContext);
+
+  return result + cnt;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     vsprcatf_core(dest_format_context_t *p_dest_ctx, const char *pFormat, va_list ap)
+ * \brief  The actual core routine to process the format string
+ * \param  p_dest_ctx context describing destination
+ * \param  pFormat format specifier
+ * \param  ap format arguments
+ * \return # of characters appended
+ * ------------------------------------------------------------------------ */
+
+static int vsprcatf_core(dest_format_context_t *p_dest_ctx, const char *pFormat, va_list ap)
+{
+  const char *pFormatStart = pFormat;
+  int Result = 0;
+  size_t OrigLen = strlen(p_dest_ctx->p_dest);
+  tFormatContext FormatContext;
+  LargeInt IntArg;
+
+  if (p_dest_ctx->dest_remlen > OrigLen)
+    p_dest_ctx->dest_remlen -= OrigLen;
+  else
+    p_dest_ctx->dest_remlen = 0;
+  p_dest_ctx->p_dest += OrigLen;
+
+  ResetFormatContext(&FormatContext);
+  for (; *pFormat; pFormat++)
+    if (FormatContext.InFormat)
+      switch (*pFormat)
+      {
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+        {
+          if (!FormatContext.CurrArg && !FormatContext.ArgState[FormatContext.CurrArg] && (*pFormat == '0'))
+            FormatContext.LeadZero = True;
+          FormatContext.Arg[FormatContext.CurrArg] = (FormatContext.Arg[FormatContext.CurrArg] * 10) + (*pFormat - '0');
+          FormatContext.ArgState[FormatContext.CurrArg] = eSet;
+          break;
+        }
+        case '-':
+          if (!FormatContext.CurrArg && !FormatContext.ArgState[FormatContext.CurrArg])
+            FormatContext.LeftAlign = True;
+          break;
+        case '+':
+          FormatContext.AddPlus = True;
+          break;
+        case '~':
+          FormatContext.ForceLeadZero = True;
+          break;
+        case '*':
+          FormatContext.Arg[FormatContext.CurrArg] = va_arg(ap, int);
+          FormatContext.ArgState[FormatContext.CurrArg] = eFinished;
+          break;
+        case '.':
+          if (FormatContext.CurrArg < 3)
+            FormatContext.CurrArg++;
+          break;
+        case 'c':
+        {
+          char ch = va_arg(ap, int);
+
+          Result += append(p_dest_ctx, &ch, 1, &FormatContext);
+          break;
+        }
+        case '%':
+          Result += append(p_dest_ctx, "%", 1, &FormatContext);
+          break;
+        case 'l':
+        {
+          FormatContext.IntSize++;
+          FormatContext.CurrArg = 2;
+          break;
+        }
+        case 'd':
+        {
+          if (FormatContext.IntSize >= 3)
+            IntArg = va_arg(ap, LargeInt);
+          else
+#ifndef NOLONGLONG
+          if (FormatContext.IntSize >= 2)
+            IntArg = va_arg(ap, long long);
+          else
+#endif
+          if (FormatContext.IntSize >= 1)
+            IntArg = va_arg(ap, long);
+          else
+            IntArg = va_arg(ap, int);
+          FormatContext.Arg[1] = 10;
+          FormatContext.Signed = True;
+          goto IntCommon;
+        }
+        case 'u':
+        {
+          if (FormatContext.IntSize >= 3)
+            IntArg = va_arg(ap, LargeWord);
+          else
+#ifndef NOLONGLONG
+          if (FormatContext.IntSize >= 2)
+            IntArg = va_arg(ap, unsigned long long);
+          else
+#endif
+          if (FormatContext.IntSize >= 1)
+            IntArg = va_arg(ap, unsigned long);
+          else
+            IntArg = va_arg(ap, unsigned);
+          goto IntCommon;
+        }
+        case 'x':
+        case 'X':
+        {
+          if (FormatContext.IntSize >= 3)
+            IntArg = va_arg(ap, LargeWord);
+          else
+#ifndef NOLONGLONG
+          if (FormatContext.IntSize >= 2)
+            IntArg = va_arg(ap, unsigned long long);
+          else
+#endif
+          if (FormatContext.IntSize)
+            IntArg = va_arg(ap, unsigned long);
+          else
+            IntArg = va_arg(ap, unsigned);
+          FormatContext.Arg[1] = 16;
+          FormatContext.ForceUpper = as_isupper(*pFormat);
+          goto IntCommon;
+        }
+        IntCommon:
+        {
+          char Str[100], *pStr = Str;
+          int Cnt;
+          int NumPadZeros = 0;
+
+          if (FormatContext.Signed)
+          {
+            if (IntArg < 0)
+            {
+              *pStr++ = '-';
+              IntArg = 0 - IntArg;
+            }
+            else if (FormatContext.AddPlus)
+              *pStr++ = '+';
+          }
+          if (FormatContext.LeadZero)
+          {
+            NumPadZeros = FormatContext.Arg[0];
+            FormatContext.Arg[0] = 0;
+          }
+          Cnt = (pStr - Str)
+              + SysString(pStr, sizeof(Str) - (pStr - Str), IntArg,
+                          FormatContext.Arg[1] ? FormatContext.Arg[1] : 10,
+                          NumPadZeros, FormatContext.ForceLeadZero,
+                          FormatContext.ForceUpper ? 'A' : HexStartCharacter,
+                          SplitByteCharacter);
+          if (Cnt > (int)sizeof(Str))
+            Cnt = sizeof(Str);
+          Result += append(p_dest_ctx, Str, Cnt, &FormatContext);
+          break;
+        }
+        case 'e':
+        case 'f':
+        case 'g':
+        {
+          char Str[100];
+          int Cnt;
+
+          Cnt = FloatConvert(Str, sizeof(Str), va_arg(ap, double), FormatContext.Arg[1], False, *pFormat);
+          if (Cnt > (int)sizeof(Str))
+            Cnt = sizeof(Str);
+          Result += append(p_dest_ctx, Str, Cnt, &FormatContext);
+          break;
+        }
+        case 's':
+        {
+          const char *pStr = va_arg(ap, char*);
+
+          Result += append(p_dest_ctx, pStr, strlen(pStr), &FormatContext);
+          break;
+        }
+        default:
+          fprintf(stderr, "invalid format: '%c' in '%s'\n", *pFormat, pFormatStart);
+          exit(255);
+      }
+    else if (*pFormat == '%')
+      FormatContext.InFormat = True;
+    else
+      Result += append(p_dest_ctx, pFormat, 1, &FormatContext);
+
+  if (p_dest_ctx->dest_remlen > 0)
+    *(p_dest_ctx->p_dest++) = '\0';
+  return Result;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_vsdprcatf(as_dynstr_t *p_dest, const char *pFormat, va_list ap)
+ * \brief  append to dynamic string by format
+ * \param  p_dest string to be appended to
+ * \param  pFormat format specifier
+ * \param  ap format arguments
+ * \return # of characters appended
+ * ------------------------------------------------------------------------ */
+
+int as_vsdprcatf(as_dynstr_t *p_dest, const char *pFormat, va_list ap)
+{
+  dest_format_context_t ctx;
+
+  ctx.p_dest = p_dest->p_str;
+  ctx.dest_remlen = p_dest->capacity;
+  ctx.p_dynstr = p_dest;
+  return vsprcatf_core(&ctx, pFormat, ap);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_vsdprintf(as_dynstr_t *p_dest, const char *pFormat, va_list ap)
+ * \brief  print to dynamic string by format
+ * \param  p_dest string to be appended to
+ * \param  pFormat format specifier
+ * \param  ap format arguments
+ * \return # of characters written
+ * ------------------------------------------------------------------------ */
+
+int as_vsdprintf(as_dynstr_t *p_dest, const char *pFormat, va_list ap)
+{
+  if (p_dest->capacity > 0)
+    p_dest->p_str[0] = '\0';
+  return as_vsdprcatf(p_dest, pFormat, ap);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_sdprcatf(as_dynstr_t *p_dest, const char *pFormat, ...)
+ * \brief  append to dynamic string by format
+ * \param  p_dest string to be appended to
+ * \param  pFormat format specifier
+ * \param  ... format arguments
+ * \return # of characters written
+ * ------------------------------------------------------------------------ */
+
+int as_sdprcatf(as_dynstr_t *p_dest, const char *pFormat, ...)
+{
+  va_list ap;
+  int ret;
+
+  va_start(ap, pFormat);
+  ret = as_vsdprcatf(p_dest, pFormat, ap);
+  va_end(ap);
+  return ret;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_sdprintf(as_dynstr_t *p_dest, const char *pFormat, ...)
+ * \brief  print to dynamic string by format
+ * \param  p_dest string to be appended to
+ * \param  pFormat format specifier
+ * \param  ... format arguments
+ * \return # of characters written
+ * ------------------------------------------------------------------------ */
+
+int as_sdprintf(as_dynstr_t *p_dest, const char *pFormat, ...)
+{
+  va_list ap;
+  int ret;
+
+  va_start(ap, pFormat);
+  ret = as_vsdprintf(p_dest, pFormat, ap);
+  va_end(ap);
+  return ret;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_vsnprcatf(char *pDest, size_t DestSize, const char *pFormat, va_list ap)
+ * \brief  append to string by format
+ * \param  pDest string to be appended to
+ * \param  DestSize capacity of string
+ * \param  pFormat format specifier
+ * \param  ap format arguments
+ * \return # of characters appended
+ * ------------------------------------------------------------------------ */
+
+int as_vsnprcatf(char *pDest, size_t DestSize, const char *pFormat, va_list ap)
+{
+  dest_format_context_t ctx;
+
+  if (DestSize == sizeof(char*))
+  {
+    fprintf(stderr, "pointer size passed to as_vsnprcatf\n");
+    exit(2);
+  }
+
+  ctx.p_dest = pDest;
+  ctx.dest_remlen = DestSize;
+  ctx.p_dynstr = NULL;
+  return vsprcatf_core(&ctx, pFormat, ap);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_vsnprintf(char *pDest, size_t DestSize, const char *pFormat, va_list ap)
+ * \brief  print to string by format
+ * \param  pDest string to be appended to
+ * \param  DestSize capacity of string
+ * \param  pFormat format specifier
+ * \param  ap format arguments
+ * \return # of characters written
+ * ------------------------------------------------------------------------ */
+
+int as_vsnprintf(char *pDest, size_t DestSize, const char *pFormat, va_list ap)
+{
+  if (DestSize > 0)
+    *pDest = '\0';
+  return as_vsnprcatf(pDest, DestSize, pFormat, ap);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_snprintf(char *pDest, size_t DestSize, const char *pFormat, ...)
+ * \brief  print to string by format
+ * \param  pDest string to be appended to
+ * \param  DestSize capacity of string
+ * \param  pFormat format specifier
+ * \param  ... format arguments
+ * \return # of characters written
+ * ------------------------------------------------------------------------ */
+
+int as_snprintf(char *pDest, size_t DestSize, const char *pFormat, ...)
+{
+  va_list ap;
+  int Result;
+
+  va_start(ap, pFormat);
+  if (DestSize > 0)
+    *pDest = '\0';
+  Result = as_vsnprcatf(pDest, DestSize, pFormat, ap);
+  va_end(ap);
+  return Result;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     as_snprcatf(char *pDest, size_t DestSize, const char *pFormat, ...)
+ * \brief  append to string by format
+ * \param  pDest string to be appended to
+ * \param  DestSize capacity of string
+ * \param  pFormat format specifier
+ * \param  ... format arguments
+ * \return # of characters appended
+ * ------------------------------------------------------------------------ */
+
+int as_snprcatf(char *pDest, size_t DestSize, const char *pFormat, ...)
+{
+  va_list ap;
+  int Result;
+
+  va_start(ap, pFormat);
+  Result = as_vsnprcatf(pDest, DestSize, pFormat, ap);
+  va_end(ap);
+  return Result;
+}
+
+int as_strcasecmp(const char *src1, const char *src2)
+{
+  if (!src1)
+    src1 = "";
+  if (!src2)
+    src2 = "";
+  while (tolower(*src1) == tolower(*src2))
+  {
+    if ((!*src1) && (!*src2))
+      return 0;
+    src1++;
+    src2++;
+  }
+  return ((int) tolower(*src1)) - ((int) tolower(*src2));
+}      
+
+int as_strncasecmp(const char *src1, const char *src2, size_t len)
+{
+  if (!src1)
+    src1 = "";
+  if (!src2)
+    src2 = "";
+  while (tolower(*src1) == tolower(*src2))
+  {
+    if (--len == 0)
+      return 0;
+    if ((!*src1) && (!*src2))
+      return 0;
+    src1++;
+    src2++;
+  }
+  return ((int) tolower(*src1)) - ((int) tolower(*src2));
+}      
+
+#ifdef NEEDS_STRSTR
+char *strstr(const char *haystack, const char *needle)
+{
+  int lh = strlen(haystack), ln = strlen(needle);
+  int z;
+  char *p;
+
+  for (z = 0; z <= lh - ln; z++)
+    if (strncmp(p = haystack + z, needle, ln) == 0)
+      return p;
+  return NULL;
+}
+#endif
+
+/*!------------------------------------------------------------------------
+ * \fn     strrmultchr(const char *haystack, const char *needles)
+ * \brief  find the last occurence of either character in string
+ * \param  haystack string to search in
+ * \param  needles characters to search for
+ * \return last occurence or NULL
+ * ------------------------------------------------------------------------ */
+
+char *strrmultchr(const char *haystack, const char *needles)
+{
+  const char *pPos;
+
+  for (pPos = haystack + strlen(haystack) - 1; pPos >= haystack; pPos--)
+    if (strchr(needles, *pPos))
+      return (char*)pPos;
+  return NULL;
+}
+
+/*---------------------------------------------------------------------------*/
+/* das originale strncpy plaettet alle ueberstehenden Zeichen mit Nullen */
+
+size_t strmaxcpy(char *dest, const char *src, size_t Max)
+{
+  size_t cnt = strlen(src);
+
+  /* leave room for terminating NUL */
+
+  if (!Max)
+    return 0;
+  if (cnt + 1 > Max)
+    cnt = Max - 1;
+  memcpy(dest, src, cnt);
+  dest[cnt] = '\0';
+  return cnt;
+}
+
+/*---------------------------------------------------------------------------*/
+/* einfuegen, mit Begrenzung */
+
+size_t strmaxcat(char *Dest, const char *Src, size_t MaxLen)
+{
+  int TLen = strlen(Src);
+  size_t DLen = strlen(Dest);
+
+  if (TLen > (int)MaxLen - 1 - (int)DLen)
+    TLen = MaxLen - DLen - 1;
+  if (TLen > 0)
+  {
+    memcpy(Dest + DLen, Src, TLen);
+    Dest[DLen + TLen] = '\0';
+    return DLen + TLen;
+  }
+  else
+    return DLen;
+}
+
+void strprep(char *Dest, const char *Src)
+{
+  memmove(Dest + strlen(Src), Dest, strlen(Dest) + 1);
+  memmove(Dest, Src, strlen(Src));
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     strmaxprep(char *p_dest, const char *p_src, size_t max_len)
+ * \brief  prepend as much as possible from src to dest
+ * \param  p_dest string to be prepended
+ * \param  p_src string to prepend
+ * \param  max_len capacity of p_dest
+ * ------------------------------------------------------------------------ */
+
+void strmaxprep(char *p_dest, const char *p_src, size_t max_len)
+{
+  size_t src_len = strlen(p_src),
+         dest_len = strlen(p_dest);
+
+  assert(dest_len + 1 <= max_len);
+  if (src_len > max_len - dest_len - 1)
+    src_len = max_len - dest_len - 1;
+  memmove(p_dest + src_len, p_dest, dest_len + 1);
+  memmove(p_dest, p_src, src_len);
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     strmaxprep2(char *p_dest, const char *p_src, size_t max_len)
+ * \brief  prepend as much as possible from src to dest, and possibly truncate dest by that
+ * \param  p_dest string to be prepended
+ * \param  p_src string to prepend
+ * \param  max_len capacity of p_dest
+ * ------------------------------------------------------------------------ */
+
+void strmaxprep2(char *p_dest, const char *p_src, size_t max_len)
+{
+  size_t src_len = strlen(p_src),
+         dest_len = strlen(p_dest);
+
+  assert(max_len > 0);
+  if (src_len >= max_len)
+    src_len = max_len - 1;
+  max_len -= src_len;
+  if (dest_len >= max_len)
+    dest_len = max_len - 1;
+  memmove(p_dest + src_len, p_dest, dest_len + 1);
+  memmove(p_dest, p_src, src_len);
+}
+
+void strins(char *Dest, const char *Src, int Pos)
+{
+  memmove(Dest + Pos + strlen(Src), Dest + Pos, strlen(Dest) + 1 - Pos);
+  memmove(Dest + Pos, Src, strlen(Src));
+}
+
+void strmaxins(char *Dest, const char *Src, int Pos, size_t MaxLen)
+{
+  size_t RLen;
+
+  RLen = strlen(Src);
+  if (RLen > MaxLen - strlen(Dest))
+    RLen = MaxLen - strlen(Dest);
+  memmove(Dest + Pos + RLen, Dest + Pos, strlen(Dest) + 1 - Pos);
+  memmove(Dest + Pos, Src, RLen);
+}
+
+int strlencmp(const char *pStr1, unsigned Str1Len,
+              const char *pStr2, unsigned Str2Len)
+{
+  const char *p1, *p2, *p1End, *p2End;
+  int Diff;
+
+  for (p1 = pStr1, p1End = p1 + Str1Len,
+       p2 = pStr2, p2End = p2 + Str2Len;
+       p1 < p1End && p2 < p2End; p1++, p2++)
+  {
+    Diff = ((int)*p1) - ((int)*p2);
+    if (Diff)
+      return Diff;
+  }
+  return ((int)Str1Len) - ((int)Str2Len);
+}
+
+unsigned fstrlenprint(FILE *pFile, const char *pStr, unsigned StrLen)
+{
+  unsigned Result = 0;
+  const char *pRun, *pEnd;
+
+  for (pRun = pStr, pEnd = pStr + StrLen; pRun < pEnd; pRun++)
+    if ((*pRun == '\\') || (*pRun == '"') || (*pRun == ' ') || (!isprint(*pRun)))
+    {
+      fprintf(pFile, "\\%03d", *pRun);
+      Result += 4;
+    }
+    else
+    {
+      fputc(*pRun, pFile);
+      Result++;
+    }
+
+  return Result;
+}
+
+size_t as_strnlen(const char *pStr, size_t MaxLen)
+{
+  size_t Res = 0;
+
+  for (; (MaxLen > 0); MaxLen--, pStr++, Res++)
+    if (!*pStr)
+      break;
+  return Res;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     strreplace(char *pHaystack, const char *pFrom, const char *pTo, size_t ToMaxLen, size_t HaystackSize)
+ * \brief  replaces all occurences of From to To in Haystack
+ * \param  pHaystack string to search in
+ * \param  pFrom what to find
+ * \param  pFrom what to find
+ * \param  pTo what to replace it with
+ * \param  ToMaxLen if not -1, max. length of pTo (not NUL-terminated)
+ * \param  HaystackSize buffer capacity
+ * \return # of occurences
+ * ------------------------------------------------------------------------ */
+
+int strreplace(char *pHaystack, const char *pFrom, const char *pTo, size_t ToMaxLen, size_t HaystackSize)
+{
+  int HaystackLen = -1, FromLen = -1, ToLen = -1, Count = 0;
+  int HeadLen, TailLen;
+  char *pSearch, *pPos;
+
+  pSearch = pHaystack;
+  while (True)
+  {
+    /* find an occurence */
+
+    pPos = strstr(pSearch, pFrom);
+    if (!pPos)
+      return Count;
+
+    /* compute some stuff upon first occurence when needed */
+
+    if (FromLen < 0)
+    {
+      HaystackLen = strlen(pHaystack);
+      FromLen = strlen(pFrom);
+    }
+    ToLen = (ToMaxLen > 0) ? as_strnlen(pTo, ToMaxLen) : strlen(pTo);
+
+    /* See how much of the remainder behind 'To' still fits into buffer after replacement,
+       and move accordingly: */
+
+    HeadLen = pPos - pHaystack;
+    TailLen = HaystackLen - HeadLen - FromLen;
+    if (HeadLen + ToLen + TailLen >= (int)HaystackSize)
+    {
+      TailLen = HaystackSize - 1 - HeadLen - ToLen;
+      if (TailLen < 0)
+        TailLen = 0;
+    }
+    if (TailLen > 0)
+      memmove(pPos + ToLen, pPos + FromLen, TailLen);
+
+    /* See how much of 'To' still fits into buffer, and set accordingly: */
+
+    if (HeadLen + ToLen >= (int)HaystackSize)
+    {
+      ToLen = HaystackSize - 1 - ToLen;
+      if (ToLen < 0)
+        ToLen = 0;
+    }
+    if (ToLen > 0)
+      memcpy(pPos, pTo, ToLen);
+
+    /* Update length & terminate new string */
+
+    HaystackLen = HeadLen + ToLen + TailLen;
+    pHaystack[HaystackLen] = '\0';
+
+    /* continue searching behind replacement: */
+
+    pSearch = &pHaystack[HeadLen + ToLen];
+
+    Count++;
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Bis Zeilenende lesen */
+
+void ReadLn(FILE *Datei, char *Zeile)
+{
+  char *ptr;
+  int l;
+
+  *Zeile = '\0';
+  ptr = fgets(Zeile, 256, Datei);
+  if ((!ptr) && (ferror(Datei) != 0))
+    *Zeile = '\0';
+  l = strlen(Zeile);
+  if ((l > 0) && (Zeile[l - 1] == '\n'))
+    Zeile[--l] = '\0';
+  if ((l > 0) && (Zeile[l - 1] == '\r'))
+    Zeile[--l] = '\0';
+  if ((l > 0) && (Zeile[l - 1] == 26))
+    Zeile[--l] = '\0';
+}
+
+#if 0
+
+static void dump(const char *pLine, unsigned Cnt)
+{
+  unsigned z;
+
+  fputc('\n', stderr);
+  for (z = 0; z < Cnt; z++)
+  {
+    fprintf(stderr, " %02x", pLine[z]);
+    if ((z & 15) == 15)
+      fputc('\n', stderr);
+  }
+  fputc('\n', stderr);
+}
+
+#endif
+
+/*!------------------------------------------------------------------------
+ * \fn     ReadLnCont(FILE *Datei, as_dynstr_t *p_line)
+ * \brief  read line, regarding \ continuation characters
+ * \param  Datei where to read from
+ * \param  pLine dest buffer
+ * \return # of lines read
+ * ------------------------------------------------------------------------ */
+
+size_t ReadLnCont(FILE *Datei, as_dynstr_t *p_line)
+{
+  char *ptr, *pDest;
+  size_t l, Count, LineCount;
+  Boolean Terminated;
+
+  /* read from input until no continuation is present */
+
+  pDest = p_line->p_str;
+  LineCount = Count = 0;
+  while (1)
+  {
+    /* get a line from file, possibly reallocating until everything up to \n fits */
+
+    while (1)
+    {
+      if (p_line->capacity - Count < 128)
+        as_dynstr_realloc(p_line, p_line->capacity + 128);
+
+      pDest = p_line->p_str + Count;
+      *pDest = '\0';
+      ptr = fgets(pDest, p_line->capacity - Count, Datei);
+      if (!ptr)
+      {
+        if (ferror(Datei) != 0)
+          *pDest = '\0';
+        break;
+      }
+
+      /* If we have a trailing \n, we read up to end of line: */
+
+      l = strlen(pDest);
+      Terminated = ((l > 0) && (pDest[l - 1] == '\n'));
+
+      /* srtrip possible CR preceding LF: */
+
+      if (Terminated)
+      {
+        /* strip LF, and possible CR, and bail out: */
+
+        pDest[--l] = '\0';
+        if ((l > 0) && (pDest[l - 1] == '\r'))
+          pDest[--l] = '\0';
+      }
+
+      Count += l;
+      pDest += l;
+
+      if (Terminated)
+        break;
+    }
+
+    LineCount++;
+    if ((Count > 0) && (p_line->p_str[Count - 1] == 26))
+      p_line->p_str[--Count] = '\0';
+
+    /* optional line continuation */
+
+    if ((Count > 0) && (p_line->p_str[Count - 1] == '\\'))
+      p_line->p_str[--Count] = '\0';
+    else
+      break;
+  }
+
+  return LineCount;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     DigitVal(char ch, int Base)
+ * \brief  get value of hex digit
+ * \param  ch digit
+ * \param  Base Number System
+ * \return 0..Base-1 or -1 if no valid digit
+ * ------------------------------------------------------------------------ */
+
+int DigitVal(char ch, int Base)
+{
+  int Result;
+
+  /* Ziffern 0..9 ergeben selbiges */
+
+  if ((ch >= '0') && (ch <= '9'))
+    Result = ch - '0';
+
+  /* Grossbuchstaben fuer Hexziffern */
+
+  else if ((ch >= 'A') && (ch <= 'Z'))
+    Result = ch - 'A' + 10;
+
+  /* Kleinbuchstaben nicht vergessen...! */
+
+  else if ((ch >= 'a') && (ch <= 'z'))
+    Result = ch - 'a' + 10;
+
+  /* alles andere ist Schrott */
+
+  else
+    Result = -1;
+
+  return (Result >= Base) ? -1 : Result;
+}
+
+/*--------------------------------------------------------------------*/
+/* Zahlenkonstante umsetzen: $ hex, % binaer, @ oktal */
+/* inp: Eingabezeichenkette */
+/* erg: Zeiger auf Ergebnis-Longint */
+/* liefert TRUE, falls fehlerfrei, sonst FALSE */
+
+LargeInt ConstLongInt(const char *inp, Boolean *pErr, LongInt Base)
+{
+  static const char Prefixes[4] = { '$', '@', '%', '\0' }; /* die moeglichen Zahlensysteme */
+  static const char Postfixes[4] = { 'H', 'O', '\0', '\0' };
+  static const LongInt Bases[3] = { 16, 8, 2 };            /* die dazugehoerigen Basen */
+  LargeInt erg, val;
+  int z, vorz = 1;  /* Vermischtes */
+  int InpLen = strlen(inp);
+
+  /* eventuelles Vorzeichen abspalten */
+
+  if (*inp == '-')
+  {
+    vorz = -1;
+    inp++;
+    InpLen--;
+  }
+
+  /* Sonderbehandlung 0x --> $ */
+
+  if ((InpLen >= 2)
+   && (*inp == '0')
+   && (as_toupper(inp[1]) == 'X'))
+  {
+    inp += 2;
+    InpLen -= 2;
+    Base = 16;
+  }
+
+  /* Jetzt das Zahlensystem feststellen.  Vorgabe ist dezimal, was
+     sich aber durch den Initialwert von Base jederzeit aendern
+     laesst.  Der break-Befehl verhindert, dass mehrere Basenzeichen
+     hintereinander eingegeben werden koennen */
+
+  else if (InpLen > 0)
+  {
+    for (z = 0; z < 3; z++)
+      if (*inp == Prefixes[z])
+      {
+        Base = Bases[z];
+        inp++;
+        InpLen--;
+        break;
+      }
+      else if (as_toupper(inp[InpLen - 1]) == Postfixes[z])
+      {
+        Base = Bases[z];
+        InpLen--;
+        break;
+      }
+  }
+
+  /* jetzt die Zahlenzeichen der Reihe nach durchverwursten */
+
+  erg = 0;
+  *pErr = False;
+  for(; InpLen > 0; inp++, InpLen--)
+  {
+    val = DigitVal(*inp, 16);
+    if (val < -0)
+      break;
+
+    /* entsprechend der Basis zulaessige Ziffer ? */
+
+    if (val >= Base)
+      break;
+
+    /* Zahl linksschieben, zusammenfassen, naechster bitte */
+
+    erg = erg * Base + val;
+  }
+
+  /* bis zum Ende durchgelaufen ? */
+
+  if (!InpLen)
+  {
+    /* Vorzeichen beruecksichtigen */
+
+    erg *= vorz;
+    *pErr = True;
+  }
+
+  return erg;
+}
+
+/*--------------------------------------------------------------------------*/
+/* alle Leerzeichen aus einem String loeschen */
+
+void KillBlanks(char *s)
+{
+  char *z, *dest;
+  Boolean InSgl = False, InDbl = False, ThisEscaped = False, NextEscaped = False;
+
+  dest = s;
+  for (z = s; *z != '\0'; z++, ThisEscaped = NextEscaped)
+  {
+    NextEscaped = False;
+    switch (*z)
+    {
+      case '\'':
+        if (!InDbl && !ThisEscaped)
+          InSgl = !InSgl;
+        break;
+      case '"':
+        if (!InSgl && !ThisEscaped)
+          InDbl = !InDbl;
+        break;
+      case '\\':
+        if ((InSgl || InDbl) && !ThisEscaped)
+          NextEscaped = True;
+        break;
+    }
+    if (!as_isspace(*z) || InSgl || InDbl)
+      *dest++ = *z;
+  }
+  *dest = '\0';
+}
+
+int CopyNoBlanks(char *pDest, const char *pSrc, size_t MaxLen)
+{
+  const char *pSrcRun;
+  char *pDestRun = pDest;
+  size_t Cnt = 0;
+  Byte Flags = 0;
+  char ch;
+  Boolean ThisEscaped, PrevEscaped;
+
+  /* leave space for NUL */
+
+  MaxLen--;
+
+  PrevEscaped = False;
+  for (pSrcRun = pSrc; *pSrcRun; pSrcRun++)
+  {
+    ch = *pSrcRun;
+    ThisEscaped = False;
+    switch (ch)
+    {
+      case '\'':
+        if (!(Flags & 2) && !PrevEscaped)
+          Flags ^= 1;
+        break;
+      case '"':
+        if (!(Flags & 1) && !PrevEscaped)
+          Flags ^= 2;
+        break;
+      case '\\':
+        if (!PrevEscaped)
+          ThisEscaped = True;
+        break;
+    }
+    if (!as_isspace(ch) || Flags)
+      *(pDestRun++) = ch;
+    if (++Cnt >= MaxLen)
+      break;
+    PrevEscaped = ThisEscaped;
+  }
+  *pDestRun = '\0';
+
+  return Cnt;
+}
+
+/*--------------------------------------------------------------------------*/
+/* fuehrende Leerzeichen loeschen */
+
+int KillPrefBlanks(char *s)
+{
+  char *z = s;
+
+  while ((*z != '\0') && as_isspace(*z))
+    z++;
+  if (z != s)
+    strmov(s, z);
+  return z - s;
+}
+
+/*--------------------------------------------------------------------------*/
+/* anhaengende Leerzeichen loeschen */
+
+int KillPostBlanks(char *s)
+{
+  char *z = s + strlen(s) - 1;
+  int count = 0;
+
+  while ((z >= s) && as_isspace(*z))
+  {
+    *(z--) = '\0';
+    count++;
+  }
+  return count;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int strqcmp(const char *s1, const char *s2)
+{
+  int erg = (*s1) - (*s2);
+
+  return (erg != 0) ? erg : strcmp(s1, s2);
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* we need a strcpy() with a defined behaviour in case of overlapping source
+   and destination: */
+
+char *strmov(char *pDest, const char *pSrc)
+{
+  memmove(pDest, pSrc, strlen(pSrc) + 1);
+  return pDest;
+}
+
+#ifdef __GNUC__
+
+#ifdef strcpy
+# undef strcpy
+#endif
+char *strcpy(char *pDest, const char *pSrc)
+{
+  int l = strlen(pSrc) + 1;
+  int Overlap = 0;
+
+  if (pSrc < pDest)
+  {
+    if (pSrc + l > pDest)
+      Overlap = 1;
+  }
+  else if (pSrc > pDest)
+  {
+    if (pDest + l > pSrc)
+      Overlap = 1;
+  }
+  else if (l > 0)
+  {
+    Overlap = 1;
+  }
+
+  if (Overlap)
+  {
+    fprintf(stderr, "overlapping strcpy() called from address %p, resolve this address with addr2line and report to author\n",
+            __builtin_return_address(0));
+    abort();
+  }
+
+  return strmov(pDest, pSrc);
+}
+
+#endif
+
+/*!------------------------------------------------------------------------
+ * \fn     strmemcpy(char *pDest, size_t DestSize, const char *pSrc, size_t SrcLen)
+ * \brief  copy string with length limitation
+ * \param  pDest where to write
+ * \param  DestSize destination capacity
+ * \param  pSrc copy source
+ * \param  SrcLen # of characters to copy at most
+ * \return actual, possibly limited length
+ * ------------------------------------------------------------------------ */
+
+int strmemcpy(char *pDest, size_t DestSize, const char *pSrc, size_t SrcLen)
+{
+  if (DestSize < SrcLen + 1)
+    SrcLen = DestSize - 1;
+  memmove(pDest, pSrc, SrcLen);
+  pDest[SrcLen] = '\0';
+  return SrcLen;
+}
+
+/*--------------------------------------------------------------------------*/
+
+char *ParenthPos(char *pHaystack, char Needle)
+{
+  char *pRun;
+  int Level = 0;
+
+  for (pRun = pHaystack; *pRun; pRun++)
+  {
+    switch (*pRun)
+    {
+      case '(':
+        Level++;
+        break;
+      case ')':
+        if (Level < 1)
+          return NULL;
+        Level--;
+        break;
+      default:
+        if (*pRun == Needle && !Level)
+          return pRun;
+    }
+  }
+  return NULL;
+}
+
+/*!------------------------------------------------------------------------
+ * \fn     TabCompressed(char in)
+ * \brief  replace TABs with spaces for error display
+ * \param  in character to compress
+ * \return compressed result
+ * ------------------------------------------------------------------------ */
+
+char TabCompressed(char in)
+{
+  return (in == '\t') ? ' ' : (as_isprint(in) ? in : '*');
+}
+
+/*--------------------------------------------------------------------------*/
+
+void strutil_init(void)
+{
+  HexStartCharacter = 'A';
+}
diff --git a/aslshim/strutil.h b/aslshim/strutil.h
new file mode 100644 (file)
index 0000000..364f9ec
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef _STRUTIL_H
+#define _STRUTIL_H
+/* strutil.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* haeufig benoetigte String-Funktionen                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+
+#include "datatypes.h"
+
+struct as_dynstr;
+
+extern char HexStartCharacter;
+extern char SplitByteCharacter;
+
+extern const char *Blanks(int cnt);
+
+#define HexString(pDest, DestSize, i, Stellen) SysString(pDest, DestSize, i, 16, Stellen, False, HexStartCharacter, SplitByteCharacter)
+#define DecString(pDest, DestSize, i, Digits) SysString(pDest, DestSize, i, 10, Digits, False, HexStartCharacter, '\0')
+
+extern int SysString(char *pDest, size_t DestSize, LargeWord i, int System, int Stellen, Boolean ForceLeadZero, char StartCharacter, char SplitCharacter);
+
+extern char *as_strdup(const char *s);
+
+extern int as_vsnprcatf(char *pDest, size_t DestSize, const char *pFormat, va_list ap);
+extern int as_snprcatf(char *pDest, size_t DestSize, const char *pFormat, ...);
+extern int as_vsnprintf(char *pDest, size_t DestSize, const char *pFormat, va_list ap);
+extern int as_snprintf(char *pDest, size_t DestSize, const char *pFormat, ...);
+
+extern int as_vsdprcatf(struct as_dynstr *p_dest, const char *pFormat, va_list ap);
+extern int as_sdprcatf(struct as_dynstr *p_dest, const char *pFormat, ...);
+extern int as_vsdprintf(struct as_dynstr *p_dest, const char *pFormat, va_list ap);
+extern int as_sdprintf(struct as_dynstr *p_dest, const char *pFormat, ...);
+
+extern int as_strcasecmp(const char *src1, const char *src2);
+extern int as_strncasecmp(const char *src1, const char *src2, size_t maxlen);
+
+#ifdef NEEDS_STRSTR
+extern char *strstr(const char *haystack, const char *needle);
+#endif
+
+extern char *strrmultchr(const char *haystack, const char *needles);
+
+extern size_t strmaxcpy(char *dest, const char *src, size_t Max);
+extern size_t strmaxcat(char *Dest, const char *Src, size_t MaxLen);
+extern void strprep(char *Dest, const char *Src);
+extern void strmaxprep(char *p_dest, const char *p_src, size_t max_len);
+extern void strmaxprep2(char *p_dest, const char *p_src, size_t max_len);
+extern void strins(char *Dest, const char *Src, int Pos);
+extern void strmaxins(char *Dest, const char *Src, int Pos, size_t MaxLen);
+
+extern size_t as_strnlen(const char *pStr, size_t MaxLen);
+
+extern int strreplace(char *pHaystack, const char *pFrom, const char *pTo, size_t ToMaxLen, size_t HaystackSize);
+
+extern int strlencmp(const char *pStr1, unsigned Str1Len,
+                     const char *pStr2, unsigned Str2Len);
+
+extern unsigned fstrlenprint(FILE *pFile, const char *pStr, unsigned StrLen);
+
+extern void ReadLn(FILE *Datei, char *Zeile);
+
+extern size_t ReadLnCont(FILE *Datei, struct as_dynstr *p_line);
+
+extern int DigitVal(char ch, int Base);
+
+extern LargeInt ConstLongInt(const char *inp, Boolean *pErr, LongInt Base);
+
+extern char *ParenthPos(char *pHaystack, char Needle);
+
+extern void KillBlanks(char *s);
+
+extern int CopyNoBlanks(char *pDest, const char *pSrc, size_t MaxLen);
+
+extern int KillPrefBlanks(char *s);
+
+extern int KillPostBlanks(char *s);
+
+extern char TabCompressed(char in);
+
+extern int strqcmp(const char *s1, const char *s2);
+
+extern char *strmov(char *pDest, const char *pSrc);
+
+extern int strmemcpy(char *pDest, size_t DestSize, const char *pSrc, size_t SrcLen);
+
+extern void strutil_init(void);
+
+/* avoid nasty "subscript has type char..." messages on some platforms */
+
+#include <ctype.h>
+
+#define __chartouint(c) (((unsigned int)(c)) & 0xff)
+#define as_toupper(c) (toupper(__chartouint(c)))
+#define as_tolower(c) (tolower(__chartouint(c)))
+#define as_isspace(c) (!!isspace(__chartouint(c)))
+#define as_isdigit(c) (!!isdigit(__chartouint(c)))
+#define as_isxdigit(c) (!!isxdigit(__chartouint(c)))
+#define as_isprint(c) (!!isprint(__chartouint(c)))
+#define as_isalpha(c) (!!isalpha(__chartouint(c)))
+#define as_isupper(c) (!!isupper(__chartouint(c)))
+#define as_islower(c) (!!islower(__chartouint(c)))
+#define as_isalnum(c) (!!isalnum(__chartouint(c)))
+
+#endif /* _STRUTIL_H */
diff --git a/aslshim/symbolsize.h b/aslshim/symbolsize.h
new file mode 100644 (file)
index 0000000..d969be5
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _SYMBOLSIZE_H
+#define _SYMBOLSIZE_H
+/* symbolsize.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* Macro Assembler AS                                                        */
+/*                                                                           */
+/* Definition of a symbol's/instruction's operand type & size                */
+/*                                                                           */
+/*****************************************************************************/
+
+typedef enum
+{
+  eSymbolSizeUnknown = -1,
+  eSymbolSize8Bit = 0,
+  eSymbolSize16Bit = 1,
+  eSymbolSize32Bit = 2,
+  eSymbolSize64Bit = 3,
+  eSymbolSize80Bit = 4, /* Intel 80 Bit extended float */
+  eSymbolSizeFloat32Bit = 5,
+  eSymbolSizeFloat64Bit = 6,
+  eSymbolSizeFloat96Bit = 7,
+  eSymbolSize24Bit = 8,
+  eSymbolSizeFloatDec96Bit = 9,
+  eSymbolSizeFloat16Bit = 10
+} tSymbolSize;
+
+#ifdef __cplusplus
+#include "cppops.h"
+DefCPPOps_Enum(tSymbolSize)
+#endif
+
+extern const char *GetSymbolSizeName(tSymbolSize Size);
+
+extern unsigned GetSymbolSizeBytes(tSymbolSize Size);
+
+#endif /* _SYMBOLSIZE_H */
diff --git a/aslshim/symflags.h b/aslshim/symflags.h
new file mode 100644 (file)
index 0000000..fdce199
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef _SYMFLAGS_H
+#define _SYMFLAGS_H
+/* symflags.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS                                                                        */
+/*                                                                           */
+/* Symbol Flags Used in Symbol Table and TempResult                          */
+/*                                                                           */
+/*****************************************************************************/
+
+typedef enum eSymbolFlags
+{
+  eSymbolFlag_None = 0,
+  eSymbolFlag_NextLabelAfterBSR = 1 << 0,
+  eSymbolFlag_StringSingleQuoted = 1 << 1,
+
+  /* Hinweisflag: evtl. im ersten Pass unbe-
+     kanntes Symbol, Ausdruck nicht ausgewertet */
+
+  eSymbolFlag_FirstPassUnknown = 1 << 2,
+
+  /* Hinweisflag:  Dadurch, dass Phasenfehler
+     aufgetreten sind, ist dieser Symbolwert evtl.
+     nicht mehr aktuell */
+
+  eSymbolFlag_Questionable = 1 << 3,
+
+  /* Hinweisflag: benutzt Vorwaertsdefinitionen */
+
+  eSymbolFlag_UsesForwards = 1 << 4,
+
+  eSymbolFlag_Label = 1 << 5,
+
+  eSymbolFlags_Promotable = eSymbolFlag_FirstPassUnknown | eSymbolFlag_Questionable | eSymbolFlag_UsesForwards
+} tSymbolFlags;
+
+#ifdef __cplusplus
+#include "cppops.h"
+DefCPPOps_Mask(tSymbolFlags)
+#endif
+
+#define mFirstPassUnknown(Flags) (!!((Flags) & eSymbolFlag_FirstPassUnknown))
+
+#define mSymbolQuestionable(Flags) (!!((Flags) & eSymbolFlag_Questionable))
+
+#define mFirstPassUnknownOrQuestionable(Flags) (!!((Flags) & (eSymbolFlag_FirstPassUnknown | eSymbolFlag_Questionable)))
+
+#define mUsesForwards(Flags) (!!((Flags) & eSymbolFlag_UsesForwards))
+
+#endif /* _SYMFLAGS_H */
diff --git a/aslshim/sysdefs.h b/aslshim/sysdefs.h
new file mode 100644 (file)
index 0000000..5d6c6b6
--- /dev/null
@@ -0,0 +1,1370 @@
+#ifndef _SYSDEFS_H
+#define _SYSDEFS_H
+/* sysdefs.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS Port                                                                   */
+/*                                                                           */
+/* system-specific definitions                                               */
+/*                                                                           */
+/* History:  2001-04-13 activated DRSEP for Win32 platform                   */
+/*           2001-09-11 added MacOSX                                         */
+/*           2001-10-13 added ARM/Linux                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+/* NOTE:
+ *
+ * when adding new platforms, " gcc -dM -E - <<<'' " might be helpful to
+ * find out about predefined symbols
+ *
+ */
+
+/*---------------------------------------------------------------------------*/
+/* unify 68K platforms */
+
+#ifdef __mc68020
+#ifndef __m68k
+#define __m68k
+#endif
+#endif
+
+#ifdef m68000
+#ifndef __m68k
+#define __m68k
+#endif
+#endif
+
+#ifdef __mc68000
+# ifndef __m68k
+#  define __m68k
+# endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* ditto for i386 platforms */
+
+/* MSDOS only runs on x86s... */
+
+#ifdef __MSDOS__
+#define __i386
+#endif
+
+/* For IBMC... */
+
+#ifdef _M_I386
+#define __i386
+#endif
+
+#ifdef __i386__
+#ifndef __i386
+#define __i386
+#endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* ditto for VAX platforms */
+
+#ifdef vax
+#define __vax__
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* ditto for PPC platforms */
+
+#ifdef __PPC
+#ifndef _POWER
+#define _POWER
+#endif
+#endif
+
+#ifdef __ppc__
+#ifndef _POWER
+#define _POWER
+#endif
+#endif
+
+#ifdef __PPC__
+# ifndef _POWER
+#  define _POWER
+# endif
+#endif
+
+#ifdef __PPC64__
+# ifndef _POWER4
+#  define _POWER4
+# endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* ditto for ARM platforms */
+
+#ifdef __arm__
+#ifndef __arm
+#define __arm
+#endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* If the compiler claims to be ANSI, we surely can use prototypes */
+
+#ifdef __STDC__
+#define __PROTOS__
+#define UNUSED(x) (void)x
+#else
+#define UNUSED(x) {}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* just a hack to allow distinguishing SunOS from Solaris on Sparcs... */
+
+#ifdef sparc
+#ifndef __sparc
+#define __sparc
+#endif
+#endif
+
+#ifdef __sparc
+# ifndef __NetBSD__
+#  ifndef __FreeBSD__
+#   ifndef __linux__
+#    ifndef __SVR4
+#     define __sunos__
+#    else /* __SVR4 */
+#     define __solaris__
+#    endif /* __SVR4 */
+#   endif /* __linux__ */
+#  endif /* __FreeBSD__ */
+# endif /* __NetBSD */
+#endif /* __sparc */
+
+#ifdef __sparc__
+#ifndef __sparc
+#define __sparc
+#endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* similar on Sun 3's... */
+
+#ifdef __m68k
+#ifndef __NetBSD__
+#ifndef __MUNIX__
+#ifndef __amiga
+#define __sunos__
+#endif
+#endif
+#endif
+#endif
+
+/*===========================================================================*/
+/* 68K platforms */
+
+#ifdef __m68k
+
+#define ARCHPRNAME "m68k"
+
+/*---------------------------------------------------------------------------*/
+/* SUN/3 with SunOS 4.x:
+
+   see my SunOS quarrels in the Sparc section... */
+
+#ifdef __sunos__
+#define ARCHSYSNAME "sun-sunos"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+#ifdef __GNUC__
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#else
+#define NOLONGLONG
+#endif
+#define memmove(s1,s2,len) bcopy(s2,s1,len)
+extern void bcopy();
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* SUN/3 with NetBSD 1.x:
+
+   quite a normal 32-Bit-UNIX system */
+
+#ifdef __NetBSD__
+#define ARCHSYSNAME "sun-netbsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* PCS/Cadmus:
+
+   quite a bare system, lots of work required... */
+
+#ifdef __MUNIX__
+#define ARCHSYSNAME "pcs-munix"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+#define NEEDS_STRSTR
+typedef char Integ8;
+typedef unsigned char Card8;
+typedef short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+#define NOLONGLONG
+#define memmove(s1,s2,len) bcopy(s2,s1,len)
+extern double strtod();
+extern char *getenv();
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Linux/68K:
+
+   quite a normal 32-Bit-UNIX system */
+
+#ifdef __linux__
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define NO_NLS
+#endif
+
+#endif /* __m68k */
+
+/*===========================================================================*/
+/* SPARC platforms */
+
+#ifdef __sparc
+
+#define ARCHPRNAME "sparc"
+
+/*---------------------------------------------------------------------------*/
+/* SUN Sparc with SunOS 4.1.x:
+
+   don't try cc, use gcc, it's hopeless without an ANSI-compliant compiler...
+   SunOS does have NLS support, but it does not have D_FMT and T_FMT
+   I should change this ...
+   Though the manual pages claim that memmove and atexit exist, I could not
+   find them in any library :-(  Fortunately, bcopy claims to be safe for
+   overlapping arrays, we just have to reverse source and destination pointers.
+   The sources themselves contain a switch to use on_exit instead of atexit
+   (it uses a different callback scheme, so we cannot just make a #define here...)
+   To get rid of most of the messages about missing prototypes, add
+   -D__USE_FIXED_PROTOTYPES__ to your compiler flags!
+   Apart from these few points, one could claim SunOS to be quite a normal
+   32-bit-UNIX... */
+
+#ifdef __sunos__
+#define ARCHSYSNAME "sun-sunos"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+#ifdef __GNUC__
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#else
+#define NOLONGLONG
+#endif
+#define fpos_t long
+#ifdef __STDC__
+extern void bcopy();
+#endif
+#define memmove(s1,s2,len) bcopy(s2,s1,len)
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* SUN Sparc with Solaris 2.x:
+
+   quite a normal 32-Bit-UNIX system */
+
+#ifdef __solaris__
+#define ARCHSYSNAME "sun-solaris"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Sparc with NetBSD 1.x:
+
+   quite a normal 32-Bit-UNIX system */
+
+#ifdef __NetBSD__
+#define ARCHSYSNAME "sun-netbsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Sparc with Linux                                                          */
+
+#ifdef __linux__
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#endif /* __sparc */
+
+/*===========================================================================*/
+/* Mips platforms */
+
+#ifdef __mips
+
+#define ARCHPRNAME "mips"
+
+/*---------------------------------------------------------------------------*/
+/* R3000 with Ultrix 4.3:
+
+   nl_langinfo prototype is there, but no function in library ?!
+   use long long only if you have gcc, c89 doesn't like them !
+   cc isn't worth trying, believe me! */
+
+#ifdef __ultrix
+#define ARCHSYSNAME "dec-ultrix"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+#define NEEDS_STRDUP
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+#ifdef __GNUC__
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#else
+#define NOLONGLONG
+#endif
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* R2000/3000 with NetBSD 1.2:
+
+   quite a normal 32-Bit-UNIX system */
+
+#ifdef __NetBSD__
+#define ARCHSYSNAME "dec-netbsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* R3000/4x00 with Irix 5.x:
+
+  quite a normal 32-Bit-UNIX system
+  seems also to work with 6.2... */
+
+#ifdef __sgi
+#define ARCHSYSNAME "sgi-irix"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#ifdef __linux__
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#endif /* __mips */
+
+/*===========================================================================*/
+/* HP-PA platforms */
+
+#ifdef __hppa
+
+#define ARCHPRNAME "parisc"
+
+/*---------------------------------------------------------------------------*/
+/* HP-PA 1.x with HP-UX: */
+
+#ifdef __hpux
+#define ARCHSYSNAME "hp-hpux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#endif /* __hppa */
+
+/*===========================================================================*/
+/* POWER 64 bit platforms */
+
+#ifdef _POWER64
+
+#define ARCHPRNAME "ppc64"
+
+/*---------------------------------------------------------------------------*/
+/* POWER64 with Linux (Macintosh) */
+
+#ifdef __linux__
+
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long Integ64;
+typedef unsigned long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*===========================================================================*/
+/* POWER(32) platforms */
+
+#elif defined _POWER
+
+#define ARCHPRNAME "ppc"
+
+/*---------------------------------------------------------------------------*/
+/* POWER with AIX 4.1: rs6000 */
+
+#ifdef _AIX
+#define ARCHSYSNAME "ibm-aix"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* POWER with Linux (Macintosh) */
+
+#ifdef __linux__
+
+/* no long long data type if C89 is used */
+
+#if (defined __STDC__) && (!defined __STDC_VERSION__)
+# define NOLONGLONG
+#endif
+
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+#ifndef NOLONGLONG
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+# define HAS64
+#endif /* !NOLONGLONG */
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* POWER with OSX (Macintosh) */
+
+#ifdef __APPLE__
+#define ARCHSYSNAME "apple-macosx"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define NO_NLS
+#endif
+
+#endif /* _POWER */
+
+/*===========================================================================*/
+/* VAX platforms */
+
+#ifdef __vax__
+
+#define ARCHPRNAME "vax"
+
+/*---------------------------------------------------------------------------*/
+/* VAX with Ultrix: */
+
+#ifdef ultrix
+#define ARCHSYSNAME "dec-ultrix"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define VAXFLOAT
+#define NEEDS_STRDUP
+#define BKOKEN_SPRINTF
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+#define NOLONGLONG
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* VAX with NetBSD 1.x:
+
+   quite a normal 32-Bit-UNIX system - apart from the float format... */
+
+#ifdef __NetBSD__
+#define ARCHSYSNAME "vax-netbsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define VAXFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#endif /* vax */
+
+#ifdef __aarch64__
+
+#define ARCHPRNAME "aarch64"
+
+/*---------------------------------------------------------------------------*/
+/* AArch64 with Linux and GCC: */
+
+#ifdef __linux__
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long Integ64;
+typedef unsigned long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#endif /* __aarch64__ */
+
+/*===========================================================================*/
+/* DEC Alpha platforms */
+
+#ifdef __alpha
+
+#define ARCHPRNAME "alpha"
+
+/*---------------------------------------------------------------------------*/
+/* DEC Alpha with Digital UNIX and DEC C / GCC:
+
+   Alpha is a 64 bit machine, so we do not need to use extra longs
+   OSF has full NLS support */
+
+#ifdef __osf__
+#define ARCHSYSNAME "dec-osf"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long Integ64;
+typedef unsigned long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* DEC Alpha with Linux and GCC:
+
+   see OSF... */
+
+#ifdef __linux__
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long Integ64;
+typedef unsigned long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* DEC Alpha with NetBSD and GCC:
+
+   see OSF... */
+
+#ifdef __NetBSD__
+#define ARCHSYSNAME "unknown-netbsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long Integ64;
+typedef unsigned long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#ifdef __FreeBSD__
+#define ARCHSYSNAME "unknown-freebsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long Integ64;
+typedef unsigned long Card64;
+#define HAS64
+#define NO_NLS
+#endif
+
+#endif /* __alpha */
+
+/*===========================================================================*/
+/* Intel i386 platforms */
+
+#ifdef __i386
+
+#define ARCHPRNAME "i386"
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with NetBSD 1. and GCC: (tested on 1.5.3)
+
+   principally, a normal 32-bit UNIX */
+
+#ifdef __NetBSD__
+#define ARCHSYSNAME "i386-netbsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with Linux and GCC:
+
+   principally, a normal 32-bit *NIX */
+
+#ifdef __linux__
+
+/* no long long data type if C89 is used */
+
+#if (defined __STDC__) && (!defined __STDC_VERSION__)
+# define NOLONGLONG
+#endif
+
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+#ifndef NOLONGLONG
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#endif /* !NOLONGLONG */
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with FreeBSD and GCC:
+
+   principally, a normal 32-bit *NIX */
+
+#ifdef __FreeBSD__
+#define ARCHSYSNAME "unknown-freebsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with Darwin and GCC:
+   principally, a normal 32-bit *NIX */
+
+#ifdef __APPLE__
+#define ARCHSYSNAME "apple-osx"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with WIN32 and Cygnus GCC:
+
+   well, not really a UNIX... */
+
+#ifdef _WIN32
+
+/* no long long data type if C89 is used */
+
+#if (defined __STDC__) && (!defined __STDC_VERSION__)
+# define NOLONGLONG
+#endif
+
+#define ARCHSYSNAME "unknown-win32"
+#define DEFSMADE
+#define OPENRDMODE "rb"
+#define OPENWRMODE "wb"
+#define OPENUPMODE "rb+"
+#define IEEEFLOAT
+#define SLASHARGS
+#define PATHSEP '\\'
+#define SPATHSEP "\\"
+#define DIRSEP ';'
+#define SDIRSEP ";"
+#define DRSEP ':'
+#define SDRSEP ":"
+#define NULLDEV "NUL"
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+#ifndef NOLONGLONG
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+# define HAS64
+#endif
+#define W32_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with OS/2 and emx-GCC:
+
+   well, not really a UNIX... */
+
+#ifdef __EMX__
+#define ARCHSYSNAME "unknown-os2"
+#define DEFSMADE
+#define OPENRDMODE "rb"
+#define OPENWRMODE "wb"
+#define OPENUPMODE "rb+"
+#define IEEEFLOAT
+#define SLASHARGS
+#define PATHSEP '\\'
+#define SPATHSEP "\\"
+#define DIRSEP ';'
+#define SDIRSEP ";"
+#define DRSEP ':'
+#define SDRSEP ":"
+#define NULLDEV "NUL"
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define OS2_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with OS/2 and IBMC:
+
+well, not really a UNIX... */
+
+#ifdef __IBMC__
+#define DEFSMADE
+#define NODUP
+#define OPENRDMODE "rb"
+#define OPENWRMODE "wb"
+#define OPENUPMODE "rb+"
+#define IEEEFLOAT
+#define SLASHARGS
+#define PATHSEP '\\'
+#define SPATHSEP "\\"
+#define DRSEP ':'
+#define SDRSEP ":"
+#define NULLDEV "NUL"
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+#define NOLONGLONG
+#define OS2_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel x86 with MS-DOS and Borland-C:
+
+   well, not really a UNIX...
+   assure we get a usable memory model */
+
+#ifdef __MSDOS__
+#ifdef __TURBOC__
+#ifndef __LARGE__
+#error Wrong memory model - use large!
+#endif
+#undef ARCHPRNAME
+#ifdef __DPMI16__
+#define ARCHPRNAME "i286"
+#define ARCHSYSNAME "unknown-dpmi"
+#else
+#define ARCHPRNAME "i86"
+#define ARCHSYSNAME "unknown-msdos"
+#endif
+#define CKMALLOC
+#define HEAPRESERVE 4096
+#define DEFSMADE
+#define OPENRDMODE "rb"
+#define OPENWRMODE "wb"
+#define OPENUPMODE "rb+"
+#define IEEEFLOAT
+#define SLASHARGS
+#define PATHSEP '\\'
+#define SPATHSEP "\\"
+#define DIRSEP ';'
+#define SDIRSEP ";"
+#define DRSEP ':'
+#define SDRSEP ":"
+#define NULLDEV "NUL"
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed long Integ32;
+#define PRIInteg32 "ld"
+typedef unsigned long Card32;
+#define NOLONGLONG
+#define DOS_NLS
+#define __PROTOS__
+#undef UNUSED
+#define UNUSED(x) (void)x
+#endif
+#endif
+
+#endif /* __i386 */
+
+
+/*===========================================================================*/
+/* Intel x86_64 platforms */
+
+#if  (defined __k8__) || (defined __x86_64) || (defined __x86_64__)
+
+#define ARCHPRNAME "x86_64"
+
+/*---------------------------------------------------------------------------*/
+/* x86-64/amd64 with Linux/FreeBSD, OSX and GCC:
+
+   Principally, a normal *NIX. */
+
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
+
+/* no long long data type if C89 is used */
+
+#if (defined __STDC__) && (!defined __STDC_VERSION__)
+# define NOLONGLONG
+#endif
+
+#ifdef __linux__
+#define ARCHSYSNAME "unknown-linux"
+#elif defined __FreeBSD__
+#define ARCHSYSNAME "unknown-freebsd"
+#else
+#define ARCHSYSNAME "apple-osx"
+#endif
+
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long Integ64;
+typedef unsigned long Card64;
+#define HAS64
+#define LOCALE_NLS
+
+#endif /* __linux__ || __FreeBSD__ || __APPLE__ */
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with WIN32 and MinGW:
+
+   Well, not really a UNIX...note that in contrast to Unix-like systems,
+   the size of 'long' remains 32 bit.  One still has to use 'long long' to
+   get 64 bits. */
+
+#ifdef _WIN32
+
+/* no long long data type if C89 is used */
+
+#if (defined __STDC__) && (!defined __STDC_VERSION__)
+# define NOLONGLONG
+#endif
+
+#define ARCHSYSNAME "unknown-win64"
+#define DEFSMADE
+#define OPENRDMODE "rb"
+#define OPENWRMODE "wb"
+#define OPENUPMODE "rb+"
+#define IEEEFLOAT
+#define SLASHARGS
+#define PATHSEP '\\'
+#define SPATHSEP "\\"
+#define DIRSEP ';'
+#define SDIRSEP ";"
+#define DRSEP ':'
+#define SDRSEP ":"
+#define NULLDEV "NUL"
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+#ifndef NOLONGLONG
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+# define HAS64
+#endif
+#define NO_NLS
+
+#endif /* _WIN32 */
+
+#endif /* __k8__ || __x86_64 || __x86_64__ */
+
+/*===========================================================================*/
+/* ARM platform */
+
+#ifdef __arm
+
+#define ARCHPRNAME "arm"
+
+/*---------------------------------------------------------------------------*/
+/* ARM linux with GCC */
+
+#ifdef __linux__
+#define ARCHSYSNAME "unknown-linux-arm"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif /* __linux__ */
+
+/*---------------------------------------------------------------------------*/
+/* Psion PDA (ARM cpu) with SymbianOS Epoc32 rel.5 and installed epocemx-GCC:
+
+   well, not really a UNIX... */
+
+#ifdef __EPOC32__
+
+#ifdef __EPOCEMX__
+#define ARCHSYSNAME "psion-epoc32-epocemx"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+#define PRIInteg32 "d"
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define NO_NLS
+#endif /* __EPOCEMX__ */
+
+
+#endif /* __EPOC32__ */
+
+#endif /* __arm */
+
+/*===========================================================================*/
+/* Misc... */
+
+/*---------------------------------------------------------------------------*/
+/* Just for curiosity, it won't work without 16 bit int's... */
+
+#ifdef _CRAYMPP
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ32;
+#define PRIInteg32 "d"
+typedef unsigned short Card32;
+typedef signed int Integ64;
+typedef unsigned int Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*===========================================================================*/
+/* Post-Processing: check for definition, add defaults */
+
+
+#ifdef DEFSMADE
+#ifndef PATHSEP
+#define PATHSEP '/'
+#define SPATHSEP "/"
+#define DIRSEP ':'
+#define SDIRSEP ":"
+#endif
+#ifndef NULLDEV
+#define NULLDEV "/dev/null"
+#endif
+#else
+#error "your platform so far is not included in AS's header files!"
+#error "please edit sysdefs.h!"
+#endif
+
+#ifdef CKMALLOC
+#define malloc(s) ckmalloc(s)
+#define realloc(p,s) ckrealloc(p,s)
+
+extern void *ckmalloc(size_t s);
+
+extern void *ckrealloc(void *p, size_t s);
+#endif
+#endif /* _SYSDEFS_H */
diff --git a/aslshim/tempresult.h b/aslshim/tempresult.h
new file mode 100644 (file)
index 0000000..20468f7
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef _TEMPRESULT_H
+#define _TEMPRESULT_H
+/* tempresult.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* internal holder for int/float/string                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <stddef.h>
+
+#include "datatypes.h"
+#include "nonzstring.h"
+#include "symflags.h"
+#include "symbolsize.h"
+
+typedef enum
+{
+  TempNone = 0,
+  TempInt = 1,
+  TempFloat = 2,
+  TempString = 4,
+  TempReg = 8,
+  TempAll = 15
+} TempType;
+
+struct sRelocEntry;
+struct as_dynstr;
+
+typedef unsigned tRegInt;
+
+typedef void (*DissectRegProc)(
+#ifdef __PROTOS__
+char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize
+#endif
+);
+
+typedef struct sRegDescr
+{
+  DissectRegProc Dissect;
+  tRegInt Reg;
+} tRegDescr;
+
+struct sTempResult
+{
+  TempType Typ;
+  tSymbolFlags Flags;
+  unsigned AddrSpaceMask;
+  tSymbolSize DataSize;
+  struct sRelocEntry *Relocs;
+  union
+  {
+    LargeInt Int;
+    Double Float;
+    as_nonz_dynstr_t str;
+    tRegDescr RegDescr;
+  } Contents;
+};
+typedef struct sTempResult TempResult;
+
+extern void as_tempres_ini(TempResult *p_res);
+
+extern void as_tempres_free(TempResult *p_res);
+
+extern void as_tempres_set_none(TempResult *p_res);
+
+extern void as_tempres_set_int(TempResult *p_res, LargeInt value);
+
+extern void as_tempres_set_float(TempResult *p_res, Double value);
+
+extern void as_tempres_set_str(TempResult *p_res, const as_nonz_dynstr_t *p_value);
+
+extern void as_tempres_set_str_raw(TempResult *p_res, const char *p_value, size_t len);
+
+extern void as_tempres_set_c_str(TempResult *p_res, const char *p_value);
+
+extern void as_tempres_set_reg(TempResult *p_res, const tRegDescr *p_value);
+
+void as_tempres_copy_value(TempResult *p_dest, const TempResult *p_src);
+
+extern void as_tempres_copy(TempResult *p_dest, const TempResult *p_src);
+
+extern int as_tempres_cmp(const TempResult *p_res1, const TempResult *p_res2);
+
+extern int TempResultToFloat(TempResult *pResult);
+
+extern int as_tempres_append_dynstr(struct as_dynstr *p_dest, const TempResult *pResult);
+
+#endif /* _TEMPRESULT_H */
diff --git a/aslshim/trees.h b/aslshim/trees.h
new file mode 100644 (file)
index 0000000..8c38328
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _TREES_H
+#define _TREES_H
+/* trees.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Tree management                                                           */
+/*                                                                           */
+/*****************************************************************************/
+
+extern Boolean BalanceTrees;
+
+typedef struct _TTree
+{
+  struct _TTree *Left, *Right;
+  ShortInt Balance;
+  char *Name;
+  LongInt Attribute;
+} TTree, *PTree;
+
+typedef void (*TTreeCallback)(PTree Node, void *pData);
+
+typedef Boolean (*TTreeAdder)(PTree *PDest, PTree Neu, void *pData);
+
+extern void IterTree(PTree Tree, TTreeCallback Callback, void *pData);
+
+extern void GetTreeDepth(PTree Tree, LongInt *pMin, LongInt *pMax);
+
+extern void DestroyTree(PTree *Tree, TTreeCallback Callback, void *pData);
+
+extern void DumpTree(PTree Tree);
+
+extern PTree SearchTree(PTree Tree, char *Name, LongInt Attribute);
+
+extern Boolean EnterTree(PTree *PDest, PTree Neu, TTreeAdder Adder, void *pData);
+
+#endif /* _TREES_H */
diff --git a/aslshim/version.h b/aslshim/version.h
new file mode 100644 (file)
index 0000000..4575163
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _VERSION_H
+#define _VERSION_H
+/* version.h */
+/*****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
+/*                                                                           */
+/* AS-Portierung                                                             */
+/*                                                                           */
+/* Lagert die Versionsnummer                                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+extern const char *Version;
+extern LongInt VerNo;
+
+extern const char *InfoMessCopyright;
+
+extern LongInt Magic;
+
+extern void version_init(void);
+
+#endif /* _VERSION_H */
index e08d545..e17504d 100644 (file)
@@ -62,6 +62,7 @@ clean:
        rm -f $(SRCASX)*.o\r
        rm -f $(SRCLNK)*.o\r
        rm -f $(SRCMISC)*.o\r
+       rm -f $(SRCLSHIM)*.o\r
        rm -f $(S19OS9)*.o\r
        rm -f $(SRC1802)*.o\r
        rm -f $(SRC2650)*.o\r
@@ -160,6 +161,7 @@ prep:
        rm -f $(SRCASX)*.o\r
        rm -f $(SRCLNK)*.o\r
        rm -f $(SRCMISC)*.o\r
+       rm -f $(SRCLSHIM)*.o\r
        rm -f $(S19OS9)*.o\r
        rm -f $(SRC1802)*.o\r
        rm -f $(SRC2650)*.o\r
@@ -271,6 +273,7 @@ ASXEXE:=    ../
 SRCASX:=       $(ASXBAS)asxxsrc/\r
 SRCLNK:=       $(ASXBAS)linksrc/\r
 SRCMISC:=      $(ASXBAS)asxxmisc/\r
+SRCLSHIM:=     $(ASXBAS)aslshim/\r
 SRCS19OS9:=    $(ASXBAS)s19os9/\r
 DSTEXE:=       $(ASXBAS)asxmak/linux/exe/\r
 \r
@@ -322,7 +325,7 @@ SRCZ280=    $(ASXBAS)asz280/
 .SUFFIXES:     .c .o\r
 \r
 %.o: %.c\r
-       $(CC) $(CCFLAGS) -I$(SRCMISC) -I$(SRCASX) -c $< -o $@\r
+       $(CC) $(CCFLAGS) -I$(SRCLSHIM) -I$(SRCMISC) -I$(SRCASX) -c $< -o $@\r
 \r
 \r
 ASXX = asdata.o asexpr.o aslex.o aslist.o      \\r
@@ -334,6 +337,37 @@ ASXXSRC =  $(addprefix $(SRCASX),$(ASXX))
 $(ASXXSRC):    $(SRCMISC)alloc.h $(SRCASX)asxxxx.h\r
 \r
 \r
+LSHIM =        asmdef.c asmerr.c asmitree.c asmpars.c asmsub.c bpemu.c codevars.c \\r
+       cpulist.c dynstr.c errmsg.c intformat.c intpseudo.c natpseudo.c \\r
+       strcomp.c strutil.c\r
+\r
+LSHIMSRC =     $(addprefix $(SRCLSHIM),$(LSHIM))\r
+\r
+$(LSHIMSRC):   $(SRCLSHIM)addrspace.h $(SRCLSHIM)as.h $(SRCLSHIM)asmdebug.h \\r
+               $(SRCLSHIM)asmdef.h $(SRCLSHIM)asmerr.h $(SRCLSHIM)asmfnums.h \\r
+               $(SRCLSHIM)asmitree.h $(SRCLSHIM)asmpars.h \\r
+               $(SRCLSHIM)asmrelocs.h $(SRCLSHIM)asmstructs.h \\r
+               $(SRCLSHIM)asmsub.h $(SRCLSHIM)bpemu.h $(SRCLSHIM)chardefs.h \\r
+               $(SRCLSHIM)chunks.h $(SRCLSHIM)codepseudo.h \\r
+               $(SRCLSHIM)codevars.h $(SRCLSHIM)console.h \\r
+               $(SRCLSHIM)cppops.h $(SRCLSHIM)cpulist.h \\r
+               $(SRCLSHIM)datatypes.h $(SRCLSHIM)dynstr.h \\r
+               $(SRCLSHIM)endian.h $(SRCLSHIM)errmsg.h \\r
+               $(SRCLSHIM)fileformat.h $(SRCLSHIM)function.h \\r
+               $(SRCLSHIM)ieeefloat.h $(SRCLSHIM)intformat.h \\r
+               $(SRCLSHIM)intpseudo.h $(SRCLSHIM)ioerrs.h \\r
+               $(SRCLSHIM)lstmacroexp.h $(SRCLSHIM)math64.h \\r
+               $(SRCLSHIM)natpseudo.h $(SRCLSHIM)nlmessages.h \\r
+               $(SRCLSHIM)nls.h $(SRCLSHIM)nonzstring.h \\r
+               $(SRCLSHIM)onoff_common.h $(SRCLSHIM)operator.h \\r
+               $(SRCLSHIM)pascstyle.h $(SRCLSHIM)stdhandl.h \\r
+               $(SRCLSHIM)stdinc.h $(SRCLSHIM)strcomp.h \\r
+               $(SRCLSHIM)stringlists.h $(SRCLSHIM)strutil.h \\r
+               $(SRCLSHIM)symbolsize.h $(SRCLSHIM)symflags.h \\r
+               $(SRCLSHIM)sysdefs.h $(SRCLSHIM)tempresult.h \\r
+               $(SRCLSHIM)trees.h $(SRCLSHIM)version.h \r
+\r
+\r
 ####################################################################\r
 # AS1802\r
 ####################################################################\r
@@ -880,14 +914,15 @@ ash8:     $(ASXXSRC) $(ASH8SRC)
 # ASLCOP8\r
 ####################################################################\r
 \r
-ASLCOP8 =      lcop8mch.o lcop8pst.o\r
+ASLCOP8 =      codecop8.o lcop8mch.o lcop8pst.o\r
 \r
 ASLCOP8SRC =   $(addprefix $(SRCLCOP8),$(ASLCOP8))\r
 \r
-$(ASLCOP8SRC): $(SRCMISC)alloc.h $(SRCASX)asxxxx.h $(SRCLCOP8)lcop8.h\r
+$(ASLCOP8SRC): $(SRCMISC)alloc.h $(SRCASX)asxxxx.h $(SRCLCOP8)lcop8.h \\r
+               $(SRCLCOP8)codecop8.h\r
 \r
-aslcop8:       $(ASXXSRC) $(ASLCOP8SRC)\r
-       $(LD) $(LDFLAGS) $(ASXXSRC) $(ASLCOP8SRC) -o aslcop8\r
+aslcop8:       $(ASXXSRC) $(LSHIMSRC) $(ASLCOP8SRC)\r
+       $(LD) $(LDFLAGS) $(ASXXSRC) $(LSHIMSRC) $(ASLCOP8SRC) -o aslcop8\r
        cp aslcop8 $(DSTEXE)aslcop8\r
        strip $(DSTEXE)aslcop8\r
        chmod 755 $(DSTEXE)aslcop8\r