/* asmsub.c */
/*****************************************************************************/
/* AS-Portierung                                                             */
/*                                                                           */
/* Unterfunktionen, vermischtes                                              */
/*                                                                           */
/* Historie:  4. 5.1996 Grundsteinlegung                                     */
/*           13. 8.1997 KillBlanks-Funktionen nach stringutil.c geschoben    */
/*           26. 6.1998 Fehlermeldung Codepage nicht gefunden                */
/*            7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars     */
/*           17. 8.1998 Unterfunktion zur Buchhaltung Adressbereiche         */
/*            1. 9.1998 FloatString behandelte Sonderwerte nicht korrekt     */
/*           13. 9.1998 Prozessorliste macht Zeilenvorschub nach 6 Namen     */
/*           14.10.1998 Fehlerzeilen mit > > >                               */
/*           30. 1.1999 Formatstrings maschinenunabhaengig gemacht           */
/*           18. 4.1999 Ausgabeliste Sharefiles                              */
/*           13. 7.1999 Fehlermeldungen relokatible Symbole                  */
/*           13. 9.1999 I/O-Fehler 25 ignorieren                             */
/*            5.11.1999 ExtendErrors ist jetzt ShortInt                      */
/*                                                                           */
/*****************************************************************************/

#include "stdinc.h"
#include <string.h>
#include <ctype.h>

#include "version.h"
#include "endian.h"
#include "stdhandl.h"
#include "nls.h"
#include "nlmessages.h"
#include "as.rsc"
#include "strutil.h"
#include "stringlists.h"
#include "chunks.h"
#include "ioerrs.h"
#include "asmdef.h"
#include "asmpars.h"
#include "asmdebug.h"
#include "as.h"

#include "asmsub.h"


#ifdef __TURBOC__
#ifdef __DPMI16__
#define STKSIZE 40960
#else
#define STKSIZE 49152
#endif
#endif


Word ErrorCount,WarnCount;
static StringList CopyrightList, OutList, ShareOutList;

static LongWord StartStack,MinStack,LowStack;

/****************************************************************************/
/* Modulinitialisierung */

        void AsmSubInit(void)
BEGIN
   PageLength=60; PageWidth=0;
   ErrorCount=0; WarnCount=0;
END

/****************************************************************************/
/* neuen Prozessor definieren */

        CPUVar AddCPU(char *NewName, TSwitchProc Switcher)
BEGIN
   PCPUDef Lauf,Neu;
   char *p;

   Neu=(PCPUDef) malloc(sizeof(TCPUDef));
   Neu->Name=strdup(NewName); 
   /* kein UpString, weil noch nicht initialisiert ! */
   for (p=Neu->Name; *p!='\0'; p++) *p=toupper(*p);
   Neu->SwitchProc=Switcher;
   Neu->Next=Nil;
   Neu->Number=Neu->Orig=CPUCnt;

   Lauf=FirstCPUDef;
   if (Lauf==Nil) FirstCPUDef=Neu;
   else
    BEGIN
     while (Lauf->Next!=Nil) Lauf=Lauf->Next;
     Lauf->Next=Neu;
    END

   return CPUCnt++;
END

        Boolean AddCPUAlias(char *OrigName, char *AliasName)
BEGIN
   PCPUDef Lauf=FirstCPUDef,Neu;

   while ((Lauf!=Nil) AND (strcmp(Lauf->Name,OrigName)!=0)) Lauf=Lauf->Next;

   if (Lauf==Nil) return False;
   else
    BEGIN
     Neu=(PCPUDef) malloc(sizeof(TCPUDef));
     Neu->Next=Nil; 
     Neu->Name=strdup(AliasName);
     Neu->Number=CPUCnt++;
     Neu->Orig=Lauf->Orig;
     Neu->SwitchProc=Lauf->SwitchProc;
     while (Lauf->Next!=Nil) Lauf=Lauf->Next;
     Lauf->Next=Neu;
     return True;
    END
END

	void PrintCPUList(TSwitchProc NxtProc)
BEGIN
   PCPUDef Lauf;
   TSwitchProc Proc;
   int cnt;

   Lauf=FirstCPUDef; Proc=NullProc; cnt=0;
   while (Lauf!=Nil)
    BEGIN
     if (Lauf->Number==Lauf->Orig)
      BEGIN
       if ((Lauf->SwitchProc!=Proc) OR (cnt==7))
        BEGIN
         Proc=Lauf->SwitchProc; printf("\n"); NxtProc(); cnt=0;
        END
       printf("%-10s",Lauf->Name); cnt++;
      END
     Lauf=Lauf->Next;
    END
   printf("\n"); NxtProc();
END

	void ClearCPUList(void)
BEGIN
   PCPUDef Save;
   
   while (FirstCPUDef!=Nil)
    BEGIN
     Save=FirstCPUDef; FirstCPUDef=Save->Next;
     free(Save->Name); free(Save);
    END
END	

/****************************************************************************/
/* Copyrightlistenverwaltung */

        void AddCopyright(char *NewLine)
BEGIN
   AddStringListLast(&CopyrightList,NewLine);
END

        void WriteCopyrights(TSwitchProc NxtProc)
BEGIN
   StringRecPtr Lauf;

   if (NOT StringListEmpty(CopyrightList)) 
    BEGIN
     printf("%s\n",GetStringListFirst(CopyrightList,&Lauf)); NxtProc();
     while (Lauf!=Nil) 
      BEGIN
       printf("%s\n",GetStringListNext(&Lauf)); NxtProc();
      END
    END
END

/*--------------------------------------------------------------------------*/
/* ermittelt das erste/letzte Auftauchen eines Zeichens ausserhalb */
/* "geschuetzten" Bereichen */

#if 0
	char *QuotPos(char *s, char Zeichen)
BEGIN
   register int Cnt=0;
   register char *i;
   register char ch,Cmp2,Cmp3;

   for (i=s; (ch=*i)!='\0'; i++)
    if (Cnt==0)
     BEGIN
      if (ch==Zeichen) return i;
      else switch (ch)
       BEGIN
        case '"':
        case '\'': Cmp2='\0'; Cmp3=ch; Cnt=1; break;
        case '(': Cmp2='('; Cmp3=')'; Cnt=1; break;
        case '[': Cmp2='['; Cmp3=']'; Cnt=1; break;
       END
     END
    else
     BEGIN
      if (ch==Cmp2) Cnt++;
      else if (ch==Cmp3) Cnt--;
     END

   return Nil;
END
#else
        char *QuotPos(char *s, char Zeichen)
BEGIN
   register ShortInt Brack=0,AngBrack=0;
   register char *i;
   register LongWord Flag=0;
   static Boolean First=True,Imp[256],Save;

   if (First)
    BEGIN
     memset(Imp,False,256);
     Imp['"']=Imp['\'']=Imp['(']=Imp[')']=Imp['[']=Imp[']']=True;
     First=False;
    END
   
   Save=Imp[(unsigned char)Zeichen]; Imp[(unsigned char)Zeichen]=True;
   for (i=s; *i!='\0'; i++)
    if (Imp[(unsigned char)*i])
     BEGIN
      if (*i==Zeichen)
       BEGIN
        if ((AngBrack|Brack|Flag)==0)
         { Imp[(unsigned char)Zeichen]=Save; return i;}
       END
      else switch(*i)
       BEGIN
        case '"': if (((Brack|AngBrack)==0) AND ((Flag&2)==0)) Flag^=1; break;
        case '\'':if (((Brack|AngBrack)==0) AND ((Flag&1)==0)) Flag^=2; break;
        case '(': if ((AngBrack|Flag)==0) Brack++; break;
        case ')': if ((AngBrack|Flag)==0) Brack--; break;
        case '[': if ((Brack|Flag)==0) AngBrack++; break;
        case ']': if ((Brack|Flag)==0) AngBrack--; break;
       END
     END

   Imp[(unsigned char)Zeichen]=Save; return Nil;    
END
#endif
        char *RQuotPos(char *s, char Zeichen)
BEGIN
   ShortInt Brack=0,AngBrack=0;
   char *i;
   Boolean Quot=False,Paren=False;

   for (i=s+strlen(s)-1; i>=s; i--)
    if (*i==Zeichen)
     BEGIN
      if ((AngBrack==0) AND (Brack==0) AND (NOT Paren) AND (NOT Quot)) return i;
     END
    else switch (*i)
     BEGIN
      case '"': if ((Brack==0) AND (AngBrack==0) AND (NOT Quot)) Paren=NOT Paren; break;
      case '\'':if ((Brack==0) AND (AngBrack==0) AND (NOT Paren)) Quot=NOT Quot; break;
      case ')': if ((AngBrack==0) AND (NOT Paren) AND (NOT Quot)) Brack++; break;
      case '(': if ((AngBrack==0) AND (NOT Paren) AND (NOT Quot)) Brack--; break;
      case ']': if ((Brack==0) AND (NOT Paren) AND (NOT Quot)) AngBrack++; break;
      case '[': if ((Brack==0) AND (NOT Paren) AND (NOT Quot)) AngBrack--; break;
     END

   return Nil;
END

/*--------------------------------------------------------------------------*/
/* ermittelt das erste Leerzeichen in einem String */

        char *FirstBlank(char *s)
BEGIN
   char *h,*Min=Nil;

   h=strchr(s,' ');  
   if (h!=Nil) if ((Min==Nil) OR (h<Min)) Min=h;
   h=strchr(s,Char_HT);
   if (h!=Nil) if ((Min==Nil) OR (h<Min)) Min=h;
   return Min;
END

/*--------------------------------------------------------------------------*/
/* einen String in zwei Teile zerlegen */

	void SplitString(char *Source, char *Left, char *Right, char *Trenner)
BEGIN
   char Save;
   LongInt slen=strlen(Source);

   if ((Trenner==Nil) OR (Trenner>=Source+slen))
    Trenner=Source+slen;
   Save=(*Trenner); *Trenner='\0';
   strcpy(Left,Source); *Trenner=Save;
   if (Trenner>=Source+slen) *Right='\0';
   else strcpy(Right,Trenner+1);
END

/*--------------------------------------------------------------------------*/
/* verbesserte Grossbuchstabenfunktion */

/* einen String in Grossbuchstaben umwandeln.  Dabei Stringkonstanten in Ruhe */
/* lassen */

	void UpString(char *s)
BEGIN
   char *z;
   int hypquot=0;

   for (z=s; *z!='\0'; z++)
    BEGIN
     if ((*z=='\'') AND ((hypquot&2)==0)) hypquot^=1;
     else if ((*z=='"') AND ((hypquot&1)==0)) hypquot^=2;
     else if (hypquot==0) *z=UpCaseTable[(int)*z];
    END
END

/****************************************************************************/

        void TranslateString(char *s)
BEGIN
   char *z;

   for (z=s; *z!='\0'; z++) *z=CharTransTable[((usint)(*z))&0xff];
END

	ShortInt StrCmp(char *s1, char *s2, LongInt Hand1, LongInt Hand2)
BEGIN
   int tmp;

   tmp=(*s1)-(*s2);
   if (tmp==0) tmp=strcmp(s1,s2);
   if (tmp==0) tmp=Hand1-Hand2;
   if (tmp<0) return -1;
   if (tmp>0) return 1;
   return 0;
END

/****************************************************************************/
/* an einen Dateinamen eine Endung anhaengen */

        void AddSuffix(char *s, char *Suff)
BEGIN
   char *p,*z,*Part;

   p=Nil;
   for (z=s; *z!='\0'; z++) if (*z=='\\') p=z;
   Part=(p!=Nil)?(p):(s);
   if (strchr(Part,'.')==Nil) strmaxcat(s,Suff,255);
END


/*--------------------------------------------------------------------------*/
/* von einem Dateinamen die Endung loeschen */

        void KillSuffix(char *s)
BEGIN
   char *p,*z,*Part;

   p=Nil;
   for (z=s; *z!='\0'; z++) if (*z=='\\') p=z;
   Part=(p!=Nil)?(p):(s); Part=strchr(Part,'.');
   if (Part!=Nil) *Part='\0';
END

/*--------------------------------------------------------------------------*/
/* Pfadanteil (Laufwerk+Verzeichnis) von einem Dateinamen abspalten */

        char *PathPart(char *Name)
BEGIN
   static String s;
   char *p;

   strmaxcpy(s,Name,255);

   p=strrchr(Name,PATHSEP);
#ifdef DRSEP
   if (p==Nil) p=strrchr(Name,DRSEP);
#endif

   if (p==Nil) *s='\0'; else s[1]='\0';

   return s;
END

/*--------------------------------------------------------------------------*/
/* Namensanteil von einem Dateinamen abspalten */

        char *NamePart(char *Name)
BEGIN
   char *p=strrchr(Name,PATHSEP);

#ifdef DRSEP
   if (p==Nil) p=strrchr(Name,DRSEP);
#endif

   return (p==Nil)?(Name):(p+1);
END

/****************************************************************************/
/* eine Gleitkommazahl in einen String umwandeln */

        char *FloatString(Double f)
BEGIN
#define MaxLen 18
   static String s;
   char *p,*d;
   sint n,ExpVal,nzeroes;
   Boolean WithE,OK;

   /* 1. mit Maximallaenge wandeln, fuehrendes Vorzeichen weg */

   sprintf(s,"%27.15e",f); 
   for (p=s; (*p==' ') OR (*p=='+'); p++);
   if (p!=s) strcpy(s,p);

   /* 2. Exponenten soweit als moeglich kuerzen, evtl. ganz streichen */

   p=strchr(s,'e'); 
   if (p==Nil) return s;
   switch (*(++p))
    BEGIN
     case '+': strcpy(p,p+1); break;
     case '-': p++; break;
    END

   while (*p=='0') strcpy(p,p+1);
   WithE=(*p!='\0');
   if (NOT WithE) s[strlen(s)-1]='\0';

   /* 3. Nullen am Ende der Mantisse entfernen, Komma bleibt noch */

   if (WithE) p=strchr(s,'e'); else p=s+strlen(s); p--;
   while (*p=='0') 
    BEGIN
     strcpy(p,p+1); p--;
    END

   /* 4. auf die gewuenschte Maximalstellenzahl begrenzen */

   if (WithE) p=strchr(s,'e'); else p=s+strlen(s);
   d=strchr(s,'.');
   n=p-d-1;

   /* 5. Maximallaenge ueberschritten ? */

   if (strlen(s)>MaxLen) strcpy(d+(n-(strlen(s)-MaxLen)),d+n);

   /* 6. Exponentenwert berechnen */

   if (WithE)
    BEGIN
     p=strchr(s,'e');
     ExpVal=ConstLongInt(p+1,&OK);
    END
   else
    BEGIN
     p=s+strlen(s);
     ExpVal=0;
    END

   /* 7. soviel Platz, dass wir den Exponenten weglassen und evtl. Nullen
        anhaengen koennen ? */

   if (ExpVal>0)
    BEGIN
     nzeroes=ExpVal-(p-strchr(s,'.')-1); /* = Zahl von Nullen, die anzuhaengen waere */

     /* 7a. nur Kommaverschiebung erforderlich. Exponenten loeschen und
           evtl. auch Komma */

     if (nzeroes<=0)
      BEGIN
       *p='\0';
       d=strchr(s,'.'); strcpy(d,d+1);
       if (nzeroes!=0) 
        BEGIN
         memmove(s+strlen(s)+nzeroes+1,s+strlen(s)+nzeroes,-nzeroes);
         s[strlen(s)-1+nzeroes]='.';
        END
      END

     /* 7b. Es muessen Nullen angehaengt werden. Schauen, ob nach Loeschen von
           Punkt und E-Teil genuegend Platz ist */

     else
      BEGIN
       n=strlen(p)+1+(MaxLen-strlen(s)); /* = Anzahl freizubekommender Zeichen+Gutschrift */ 
       if (n>=nzeroes)
        BEGIN
         *p='\0'; d=strchr(s,'.'); strcpy(d,d+1);
         d=s+strlen(s); 
         for (n=0; n<nzeroes; n++) *(d++)='0'; *d='\0';
        END
      END
    END

   /* 8. soviel Platz, dass Exponent wegkann und die Zahl mit vielen Nullen
        vorne geschrieben werden kann ? */

   else if (ExpVal<0)
    BEGIN
     n=(-ExpVal)-(strlen(p)); /* = Verlaengerung nach Operation */
     if (strlen(s)+n<=MaxLen)
      BEGIN
       *p='\0'; d=strchr(s,'.'); strcpy(d,d+1);
       if (s[0]=='-') d=s+1; else d=s;
       memmove(d-ExpVal+1,d,strlen(s)+1);
       *(d++)='0'; *(d++)='.';
       for (n=0; n<-ExpVal-1; n++) *(d++)='0';
      END
    END


   /* 9. Ueberfluessiges Komma entfernen */

   if (WithE) 
    BEGIN
     p=strchr(s,'e'); if (p!=Nil) *p='E';
    END
   else p=s+strlen(s);
   if ((p!=Nil) AND (*(p-1)=='.')) strcpy(p-1,p);

   return s;
END

/****************************************************************************/
/* Symbol in String wandeln */

        void StrSym(TempResult *t, Boolean WithSystem, char *Dest)
BEGIN
   switch (t->Typ)
    BEGIN
     case TempInt:
      strcpy(Dest,HexString(t->Contents.Int,1));
      if (WithSystem)
       switch (ConstMode)
        BEGIN
         case ConstModeIntel : strcat(Dest,"H"); break;
         case ConstModeMoto  : strprep(Dest,"$"); break;
         case ConstModeC     : strprep(Dest,"0x"); break;
        END
      break;
     case TempFloat:
      strcpy(Dest,FloatString(t->Contents.Float)); break;
     case TempString:
      strcpy(Dest,t->Contents.Ascii); break;
     default: strcpy(Dest,"???");
    END
END

/****************************************************************************/
/* Listingzaehler zuruecksetzen */

        void ResetPageCounter(void)
BEGIN
   int z;

   for (z=0; z<=ChapMax; z++) PageCounter[z]=0;
   LstCounter=0; ChapDepth=0;
END

/*--------------------------------------------------------------------------*/
/* eine neue Seite im Listing beginnen */

        void NewPage(ShortInt Level, Boolean WithFF)
BEGIN
   ShortInt z;
   String Header,s;
   char Save;

   if (ListOn==0) return;

   LstCounter=0;

   if (ChapDepth<(Byte) Level)
    BEGIN
     memmove(PageCounter+(Level-ChapDepth),PageCounter,(ChapDepth+1)*sizeof(Word));
     for (z=0; z<=Level-ChapDepth; PageCounter[z++]=1);
     ChapDepth=Level;
    END
   for (z=0; z<=Level-1; PageCounter[z++]=1);
   PageCounter[Level]++;

   if (WithFF)
    BEGIN
     errno=0; fprintf(LstFile,"%c",Char_FF); ChkIO(10002);
    END

   sprintf(Header," AS V%s%s%s",Version,getmessage(Num_HeadingFileNameLab),NamePart(SourceFile));
   if ((strcmp(CurrFileName,"INTERNAL")!=0) AND (strcmp(NamePart(CurrFileName),NamePart(SourceFile))!=0))
    BEGIN
     strmaxcat(Header,"(",255);
     strmaxcat(Header,NamePart(CurrFileName),255);
     strmaxcat(Header,")",255);
    END
   strmaxcat(Header,getmessage(Num_HeadingPageLab),255);

   for (z=ChapDepth; z>=0; z--)
    BEGIN
     sprintf(s, IntegerFormat, PageCounter[z]);
     strmaxcat(Header,s,255);
     if (z!=0) strmaxcat(Header,".",255);
    END

   strmaxcat(Header," - ",255);
   NLS_CurrDateString(s); strmaxcat(Header,s,255);
   strmaxcat(Header," ",255);
   NLS_CurrTimeString(False,s); strmaxcat(Header,s,255);

   if (PageWidth!=0)
    while (strlen(Header)>PageWidth)
     BEGIN
      Save=Header[PageWidth]; Header[PageWidth]='\0';
      errno=0; fprintf(LstFile,"%s\n",Header); ChkIO(10002); 
      Header[PageWidth]=Save; strcpy(Header,Header+PageWidth);
     END
   errno=0; fprintf(LstFile,"%s\n",Header); ChkIO(10002);

   if (PrtTitleString[0]!='\0')
    BEGIN
     errno=0; fprintf(LstFile,"%s\n",PrtTitleString); ChkIO(10002);
    END

   errno=0; fprintf(LstFile,"\n\n"); ChkIO(10002);
END


/*--------------------------------------------------------------------------*/
/* eine Zeile ins Listing schieben */

        void WrLstLine(char *Line)
BEGIN
   int LLength;
   char bbuf[2500];
   String LLine;
   int blen=0,hlen,z,Start;

   if (ListOn==0) return;

   if (PageLength==0)
    BEGIN
     errno=0; fprintf(LstFile,"%s\n",Line); ChkIO(10002);
    END
   else
    BEGIN
     if ((PageWidth==0) OR ((strlen(Line)<<3)<PageWidth)) LLength=1;
     else
      BEGIN
       blen=0;
       for (z=0; z<strlen(Line);  z++)
        if (Line[z]==Char_HT)
         BEGIN
          memset(bbuf+blen,8-(blen&7),' ');
          blen+=8-(blen&7);
         END
        else bbuf[blen++]=Line[z];
       LLength=blen/PageWidth; if (blen%PageWidth!=0) LLength++;
      END
     if (LLength==1)
      BEGIN
       errno=0; fprintf(LstFile,"%s\n",Line); ChkIO(10002);
       if ((++LstCounter)==PageLength) NewPage(0,True);
      END
     else
      BEGIN
       Start=0;
       for (z=1; z<=LLength; z++)
        BEGIN
         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;
        END
      END
    END
END

/*****************************************************************************/
/* Ausdruck in Spalte vor Listing */


        void SetListLineVal(TempResult *t)
BEGIN
   StrSym(t,True,ListLine); strmaxprep(ListLine,"=",255);
   if (strlen(ListLine)>14)
    BEGIN
     ListLine[12]='\0'; strmaxcat(ListLine,"..",255);
    END
END

/****************************************************************************/
/* einen Symbolnamen auf Gueltigkeit ueberpruefen */

        Boolean ChkSymbName(char *sym)
BEGIN
   char *z;

   if (*sym=='\0') return False;
   if (NOT (isalpha((unsigned int) *sym) OR (*sym=='_') OR (*sym=='.'))) return False;
   for (z=sym; *z!='\0'; z++)
    if (NOT (isalnum((unsigned int) *z) OR (*z=='_') OR (*z=='.'))) return False;
   return True;
END

        Boolean ChkMacSymbName(char *sym)
BEGIN
   char *z;

   if (*sym=='\0') return False;
   if (NOT isalpha((unsigned int) *sym)) return False;
   for (z=sym; *z!='\0'; z++)
    if (NOT isalnum((unsigned int) *z)) return False;
   return True;
END

/****************************************************************************/
/* Fehlerkanal offen ? */

        static void ForceErrorOpen(void)
BEGIN
   if (NOT IsErrorOpen)
    BEGIN
     RewriteStandard(&ErrorFile,ErrorName); IsErrorOpen=True;
     if (ErrorFile==Nil) ChkIO(10001);
    END
END

/*--------------------------------------------------------------------------*/
/* eine Fehlermeldung  mit Klartext ausgeben */

	static void EmergencyStop(void)
BEGIN
   if ((IsErrorOpen) AND (ErrorFile!=Nil)) fclose(ErrorFile);
   fclose(LstFile);
   if (ShareMode!=0)
    BEGIN
     fclose(ShareFile); unlink(ShareName);
    END
   if (MacProOutput)
    BEGIN
     fclose(MacProFile); unlink(MacProName);
    END
   if (MacroOutput)
    BEGIN
     fclose(MacroFile); unlink(MacroName);
    END
   if (MakeDebug) fclose(Debug);
   if (CodeOutput)
    BEGIN
     fclose(PrgFile); unlink(OutName);
    END
END

        void WrErrorString(char *Message, char *Add, Boolean Warning, Boolean Fatal)
BEGIN
   String h,h2;
   char *p;
   FILE *errfile;

   strcpy(h,"> > >");
   strmaxcat(h,p=GetErrorPos(),255); free(p);
   if (NOT Warning)
    BEGIN
     strmaxcat(h,getmessage(Num_ErrName),255);
     strmaxcat(h,Add,255);
     strmaxcat(h,": ",255);
     ErrorCount++;
    END
   else
    BEGIN
     strmaxcat(h,getmessage(Num_WarnName),255);
     strmaxcat(h,Add,255);
     strmaxcat(h,": ",255);
     WarnCount++;
    END

   if ((strcmp(LstName, "/dev/null") != 0) AND (NOT Fatal))
    BEGIN
     strmaxcpy(h2, h, 255); strmaxcat(h2, Message, 255); WrLstLine(h2);
     if ((ExtendErrors > 0) AND (*ExtendError != '\0'))
      BEGIN
       sprintf(h2, "> > > %s", ExtendError); WrLstLine(h2);
      END
     if (ExtendErrors > 1)
      BEGIN
       sprintf(h2, "> > > %s", OneLine); WrLstLine(h2);
      END
    END

   ForceErrorOpen();
   if ((strcmp(LstName, "!1")!=0) OR (Fatal))
    BEGIN
     errfile = (ErrorFile == Nil) ? stdout : ErrorFile;
     fprintf(errfile, "%s%s%s\n", h, Message, ClrEol);
     if ((ExtendErrors > 0) AND (*ExtendError != '\0'))
      fprintf(errfile, "> > > %s%s\n", ExtendError, ClrEol);
     if (ExtendErrors > 1)
      fprintf(errfile, "> > > %s%s\n", OneLine, ClrEol);
    END
   *ExtendError = '\0';

   if (Fatal)
    BEGIN
     fprintf((ErrorFile==Nil)?stdout:ErrorFile,"%s\n",getmessage(Num_ErrMsgIsFatal));
     EmergencyStop();
     exit(3);
    END
END

/*--------------------------------------------------------------------------*/
/* eine Fehlermeldung ueber Code ausgeben */

        static void WrErrorNum(Word Num)
BEGIN
   String h;
   char Add[11];
   int msgno;
   
   if ((NOT CodeOutput) AND (Num==1200)) return;

   if ((SuppWarns) AND (Num<1000)) return;

   switch (Num)
    BEGIN
     case    0: msgno=Num_ErrMsgUselessDisp; break;
     case   10: msgno=Num_ErrMsgShortAddrPossible; break;
     case   20: msgno=Num_ErrMsgShortJumpPossible; break;
     case   30: msgno=Num_ErrMsgNoShareFile; break;
     case   40: msgno=Num_ErrMsgBigDecFloat; break;
     case   50: msgno=Num_ErrMsgPrivOrder; break;
     case   60: msgno=Num_ErrMsgDistNull; break;
     case   70: msgno=Num_ErrMsgWrongSegment; break;
     case   75: msgno=Num_ErrMsgInAccSegment; break;
     case   80: msgno=Num_ErrMsgPhaseErr; break;
     case   90: msgno=Num_ErrMsgOverlap; break;
     case  100: msgno=Num_ErrMsgNoCaseHit; break;
     case  110: msgno=Num_ErrMsgInAccPage; break;
     case  120: msgno=Num_ErrMsgRMustBeEven; break;
     case  130: msgno=Num_ErrMsgObsolete; break;
     case  140: msgno=Num_ErrMsgUnpredictable; break;
     case  150: msgno=Num_ErrMsgAlphaNoSense; break;
     case  160: msgno=Num_ErrMsgSenseless; break;
     case  170: msgno=Num_ErrMsgRepassUnknown; break;
     case  180: msgno=Num_ErrMsgAddrNotAligned; break;
     case  190: msgno=Num_ErrMsgIOAddrNotAllowed; break;
     case  200: msgno=Num_ErrMsgPipeline; break;
     case  210: msgno=Num_ErrMsgDoubleAdrRegUse; break;
     case  220: msgno=Num_ErrMsgNotBitAddressable; break;
     case  230: msgno=Num_ErrMsgStackNotEmpty; break;
     case  240: msgno=Num_ErrMsgNULCharacter; break;
     case  250: msgno=Num_ErrMsgPageCrossing; break;
     case  260: msgno=Num_ErrMsgWOverRange; break;
     case  270: msgno=Num_ErrMsgNegDUP; break;
     case 1000: msgno=Num_ErrMsgDoubleDef; break;
     case 1010: msgno=Num_ErrMsgSymbolUndef; break;
     case 1020: msgno=Num_ErrMsgInvSymName; break;
     case 1090: msgno=Num_ErrMsgInvFormat; break;
     case 1100: msgno=Num_ErrMsgUseLessAttr; break;
     case 1105: msgno=Num_ErrMsgTooLongAttr; break;
     case 1107: msgno=Num_ErrMsgUndefAttr; break;
     case 1110: msgno=Num_ErrMsgWrongArgCnt; break;
     case 1115: msgno=Num_ErrMsgWrongOptCnt; break;
     case 1120: msgno=Num_ErrMsgOnlyImmAddr; break;
     case 1130: msgno=Num_ErrMsgInvOpsize; break;
     case 1131: msgno=Num_ErrMsgConfOpSizes; break;
     case 1132: msgno=Num_ErrMsgUndefOpSizes; break;
     case 1135: msgno=Num_ErrMsgInvOpType; break;
     case 1140: msgno=Num_ErrMsgTooMuchArgs; break;
     case 1150: msgno=Num_ErrMsgNoRelocs; break;
     case 1155: msgno=Num_ErrMsgUnresRelocs; break;
     case 1200: msgno=Num_ErrMsgUnknownOpcode; break;
     case 1300: msgno=Num_ErrMsgBrackErr; break;
     case 1310: msgno=Num_ErrMsgDivByZero; break;
     case 1315: msgno=Num_ErrMsgUnderRange; break;
     case 1320: msgno=Num_ErrMsgOverRange; break;
     case 1325: msgno=Num_ErrMsgNotAligned; break;
     case 1330: msgno=Num_ErrMsgDistTooBig; break;
     case 1335: msgno=Num_ErrMsgInAccReg; break;
     case 1340: msgno=Num_ErrMsgNoShortAddr; break;
     case 1350: msgno=Num_ErrMsgInvAddrMode; break;
     case 1351: msgno=Num_ErrMsgMustBeEven; break;
     case 1355: msgno=Num_ErrMsgInvParAddrMode; break;
     case 1360: msgno=Num_ErrMsgUndefCond; break;
     case 1370: msgno=Num_ErrMsgJmpDistTooBig; break;
     case 1375: msgno=Num_ErrMsgDistIsOdd; break;
     case 1380: msgno=Num_ErrMsgInvShiftArg; break;
     case 1390: msgno=Num_ErrMsgRange18; break;
     case 1400: msgno=Num_ErrMsgShiftCntTooBig; break;
     case 1410: msgno=Num_ErrMsgInvRegList; break;
     case 1420: msgno=Num_ErrMsgInvCmpMode; break;
     case 1430: msgno=Num_ErrMsgInvCPUType; break;
     case 1440: msgno=Num_ErrMsgInvCtrlReg; break;
     case 1445: msgno=Num_ErrMsgInvReg; break;
     case 1450: msgno=Num_ErrMsgNoSaveFrame; break;
     case 1460: msgno=Num_ErrMsgNoRestoreFrame; break;
     case 1465: msgno=Num_ErrMsgUnknownMacArg; break;
     case 1470: msgno=Num_ErrMsgMissEndif; break;
     case 1480: msgno=Num_ErrMsgInvIfConst; break;
     case 1483: msgno=Num_ErrMsgDoubleSection; break;
     case 1484: msgno=Num_ErrMsgInvSection; break;
     case 1485: msgno=Num_ErrMsgMissingEndSect; break;
     case 1486: msgno=Num_ErrMsgWrongEndSect; break;
     case 1487: msgno=Num_ErrMsgNotInSection; break;
     case 1488: msgno=Num_ErrMsgUndefdForward; break;
     case 1489: msgno=Num_ErrMsgContForward; break;
     case 1490: msgno=Num_ErrMsgInvFuncArgCnt; break;
     case 1495: msgno=Num_ErrMsgMissingLTORG; break;
     case 1500: msgno= -1;
                sprintf(h,"%s%s%s",getmessage(Num_ErrMsgNotOnThisCPU1), 
                        MomCPUIdent,getmessage(Num_ErrMsgNotOnThisCPU2));
                break;
     case 1505: msgno= -1;
                sprintf(h,"%s%s%s",getmessage(Num_ErrMsgNotOnThisCPU3),
                        MomCPUIdent,getmessage(Num_ErrMsgNotOnThisCPU2));
                break;
     case 1510: msgno=Num_ErrMsgInvBitPos; break;
     case 1520: msgno=Num_ErrMsgOnlyOnOff; break;
     case 1530: msgno=Num_ErrMsgStackEmpty; break;
     case 1540: msgno=Num_ErrMsgNotOneBit; break;
     case 1550: msgno=Num_ErrMsgMissingStruct; break;
     case 1551: msgno=Num_ErrMsgOpenStruct; break;
     case 1552: msgno=Num_ErrMsgWrongStruct; break;
     case 1553: msgno=Num_ErrMsgPhaseDisallowed; break;
     case 1554: msgno=Num_ErrMsgInvStructDir; break;
     case 1600: msgno=Num_ErrMsgShortRead; break;
     case 1610: msgno=Num_ErrMsgUnknownCodepage; break;
     case 1700: msgno=Num_ErrMsgRomOffs063; break;
     case 1710: msgno=Num_ErrMsgInvFCode; break;
     case 1720: msgno=Num_ErrMsgInvFMask; break;
     case 1730: msgno=Num_ErrMsgInvMMUReg; break;
     case 1740: msgno=Num_ErrMsgLevel07; break;
     case 1750: msgno=Num_ErrMsgInvBitMask; break;
     case 1760: msgno=Num_ErrMsgInvRegPair; break;
     case 1800: msgno=Num_ErrMsgOpenMacro; break;
     case 1805: msgno=Num_ErrMsgEXITMOutsideMacro; break;
     case 1810: msgno=Num_ErrMsgTooManyMacParams; break;
     case 1815: msgno=Num_ErrMsgDoubleMacro; break;
     case 1820: msgno=Num_ErrMsgFirstPassCalc; break;
     case 1830: msgno=Num_ErrMsgTooManyNestedIfs; break;
     case 1840: msgno=Num_ErrMsgMissingIf; break;
     case 1850: msgno=Num_ErrMsgRekMacro; break;
     case 1860: msgno=Num_ErrMsgUnknownFunc; break;
     case 1870: msgno=Num_ErrMsgInvFuncArg; break;
     case 1880: msgno=Num_ErrMsgFloatOverflow; break;
     case 1890: msgno=Num_ErrMsgInvArgPair; break;
     case 1900: msgno=Num_ErrMsgNotOnThisAddress; break;
     case 1905: msgno=Num_ErrMsgNotFromThisAddress; break;
     case 1910: msgno=Num_ErrMsgTargOnDiffPage; break;
     case 1920: msgno=Num_ErrMsgCodeOverflow; break;
     case 1925: msgno=Num_ErrMsgAdrOverflow; break;
     case 1930: msgno=Num_ErrMsgMixDBDS; break;
     case 1940: msgno=Num_ErrMsgNotInStruct; break;
     case 1950: msgno=Num_ErrMsgParNotPossible; break;
     case 1960: msgno=Num_ErrMsgInvSegment; break;
     case 1961: msgno=Num_ErrMsgUnknownSegment; break;
     case 1962: msgno=Num_ErrMsgUnknownSegReg; break;
     case 1970: msgno=Num_ErrMsgInvString; break;
     case 1980: msgno=Num_ErrMsgInvRegName; break;
     case 1985: msgno=Num_ErrMsgInvArg; break;
     case 1990: msgno=Num_ErrMsgNoIndir; break;
     case 1995: msgno=Num_ErrMsgNotInThisSegment; break;
     case 1996: msgno=Num_ErrMsgNotInMaxmode; break;
     case 1997: msgno=Num_ErrMsgOnlyInMaxmode; break;
     case 10001: msgno=Num_ErrMsgOpeningFile; break;
     case 10002: msgno=Num_ErrMsgListWrError; break;
     case 10003: msgno=Num_ErrMsgFileReadError; break;
     case 10004: msgno=Num_ErrMsgFileWriteError; break;
     case 10006: msgno=Num_ErrMsgHeapOvfl; break;
     case 10007: msgno=Num_ErrMsgStackOvfl; break;
     default  : msgno= -1;
                sprintf(h,"%s %d",getmessage(Num_ErrMsgIntError),(int) Num);
    END
   if (msgno!=-1) strmaxcpy(h,getmessage(msgno),255);   

   if (((Num==1910) OR (Num==1370)) AND (NOT Repass)) JmpErrors++;

   if (NumericErrors) sprintf(Add,"#%d", (int)Num); 
   else *Add='\0';
   WrErrorString(h,Add,Num<1000,Num>=10000);
END

        void WrError(Word Num)
BEGIN
   *ExtendError='\0'; WrErrorNum(Num);
END

        void WrXError(Word Num, char *Message)
BEGIN
   strmaxcpy(ExtendError,Message,255); WrErrorNum(Num);
END

/*--------------------------------------------------------------------------*/
/* I/O-Fehler */

        void ChkIO(Word ErrNo)
BEGIN
   int io;

   io=errno; if ((io == 0) OR (io == 19) OR (io == 25)) return;

   WrXError(ErrNo,GetErrorMsg(io));
END

/*--------------------------------------------------------------------------*/
/* Bereichsfehler */

        Boolean ChkRange(LargeInt Value, LargeInt Min, LargeInt Max)
BEGIN
   char s1[100],s2[100];

   if (Value<Min)
    BEGIN
     strmaxcpy(s1,LargeString(Value),99); 
     strmaxcpy(s2,LargeString(Min),99);
     strmaxcat(s1,"<",99); strmaxcat(s1,s2,99);
     WrXError(1315,s1); return False;
    END
   else if (Value>Max)
    BEGIN
     strmaxcpy(s1,LargeString(Value),99);
     strmaxcpy(s2,LargeString(Max),99);
     strmaxcat(s1,">",99); strmaxcat(s1,s2,99);
     WrXError(1320,s1); return False;
    END
   else return True;
END

/****************************************************************************/

        LargeWord ProgCounter(void)
BEGIN
   return PCs[ActPC];
END

/*--------------------------------------------------------------------------*/
/* aktuellen Programmzaehler mit Phasenverschiebung holen */

        LargeWord EProgCounter(void)
BEGIN
   return PCs[ActPC]+Phases[ActPC];
END


/*--------------------------------------------------------------------------*/
/* Granularitaet des aktuellen Segments holen */

        Word Granularity(void)
BEGIN
   return Grans[ActPC];
END

/*--------------------------------------------------------------------------*/
/* Linstingbreite des aktuellen Segments holen */

        Word ListGran(void)
BEGIN
   return ListGrans[ActPC];
END

/*--------------------------------------------------------------------------*/
/* pruefen, ob alle Symbole einer Formel im korrekten Adressraum lagen */

        void ChkSpace(Byte Space)
BEGIN
   Byte Mask=0xff-(1<<Space);

   if ((TypeFlag&Mask)!=0) WrError(70);
END

/****************************************************************************/
/* eine Chunkliste im Listing ausgeben & Speicher loeschen */

        void PrintChunk(ChunkList *NChunk)
BEGIN
   LargeWord NewMin,FMin;
   Boolean Found;
   Word p=0,z;
   int BufferZ;
   String BufferS;

   NewMin=0; BufferZ=0; *BufferS='\0';

   do  
    BEGIN 
     /* niedrigsten Start finden, der ueberhalb des letzten Endes liegt */
     Found=False;
#ifdef __STDC__
     FMin=0xffffffffu;
#else
     FMin=0xffffffff;
#endif
     for (z=0; z<NChunk->RealLen; z++)
      if (NChunk->Chunks[z].Start>=NewMin)
       if (FMin>NChunk->Chunks[z].Start)
        BEGIN
         Found=True; FMin=NChunk->Chunks[z].Start; p=z;
        END

     if (Found)
      BEGIN
       strmaxcat(BufferS,HexString(NChunk->Chunks[p].Start,0),255);
       if (NChunk->Chunks[p].Length!=1)
        BEGIN 
         strmaxcat(BufferS,"-",255);
         strmaxcat(BufferS,HexString(NChunk->Chunks[p].Start+NChunk->Chunks[p].Length-1,0),255);
        END
       strmaxcat(BufferS,Blanks(19-strlen(BufferS)%19),255);
       if (++BufferZ==4)
        BEGIN
         WrLstLine(BufferS); *BufferS='\0'; BufferZ=0;
        END
       NewMin=NChunk->Chunks[p].Start+NChunk->Chunks[p].Length;
      END
    END
   while (Found);

   if (BufferZ!=0) WrLstLine(BufferS);
END

/*--------------------------------------------------------------------------*/
/* Listen ausgeben */

        void PrintUseList(void)
BEGIN
   int z,z2,l;
   String s;

   for (z=1; z<=PCMax; z++)
    if (SegChunks[z].Chunks!=Nil)
     BEGIN
      sprintf(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,"-",255);
      WrLstLine(s);
      WrLstLine("");
      PrintChunk(SegChunks+z);
      WrLstLine("");
     END
END

        void ClearUseList(void)
BEGIN
   int z;

   for (z=1; z<=PCMax; z++)
    ClearChunk(SegChunks+z);
END

/****************************************************************************/
/* Include-Pfadlistenverarbeitung */

        static char *GetPath(char *Acc)
BEGIN
   char *p;
   static String tmp;

   p=strchr(Acc,DIRSEP);
   if (p==Nil)
    BEGIN
     strmaxcpy(tmp,Acc,255); Acc[0]='\0';
    END
   else
    BEGIN
     *p='\0'; strmaxcpy(tmp,Acc,255); strcpy(Acc,p+1);
    END
   return tmp;
END

        void AddIncludeList(char *NewPath)
BEGIN
   String Test;

   strmaxcpy(Test,IncludeList,255);
   while (*Test!='\0')
    if (strcmp(GetPath(Test),NewPath)==0) return;
   if (*IncludeList!='\0') strmaxprep(IncludeList,SDIRSEP,255);
   strmaxprep(IncludeList,NewPath,255);
END


        void RemoveIncludeList(char *RemPath)
BEGIN
   String Save;
   char *Part;

   strmaxcpy(IncludeList,Save,255); IncludeList[0]='\0';
   while (Save[0]!='\0')
    BEGIN
     Part=GetPath(Save);
     if (strcmp(Part,RemPath)!=0)
      BEGIN
       if (IncludeList[0]!='\0') strmaxcat(IncludeList,SDIRSEP,255);
       strmaxcat(IncludeList,Part,255);
      END
    END
END

/****************************************************************************/
/* Liste mit Ausgabedateien */

        void ClearOutList(void)
BEGIN
   ClearStringList(&OutList);
END

        void AddToOutList(char *NewName)
BEGIN
   AddStringListLast(&OutList,NewName);
END

        void RemoveFromOutList(char *OldName)
BEGIN
   RemoveStringList(&OutList,OldName);
END

        char *GetFromOutList(void)
BEGIN
   return GetAndCutStringList(&OutList);
END

        void ClearShareOutList(void)
BEGIN
   ClearStringList(&ShareOutList);
END

        void AddToShareOutList(char *NewName)
BEGIN
   AddStringListLast(&ShareOutList,NewName);
END

        void RemoveFromShareOutList(char *OldName)
BEGIN
   RemoveStringList(&ShareOutList,OldName);
END

        char *GetFromShareOutList(void)
BEGIN
   return GetAndCutStringList(&ShareOutList);
END

/****************************************************************************/
/* Tokenverarbeitung */

	static Boolean CompressLine_NErl(char ch)
BEGIN
   return (((ch>='A') AND (ch<='Z')) OR ((ch>='a') AND (ch<='z')) OR ((ch>='0') AND (ch<='9')));
END

        void CompressLine(char *TokNam, Byte Num, char *Line)
BEGIN
   int z,e,tlen,llen;
   Boolean SFound;

   z=0; tlen=strlen(TokNam); llen=strlen(Line);
   while (z<=llen-tlen)
    BEGIN
     e=z+strlen(TokNam); 
     SFound=(CaseSensitive) ? (strncmp(Line+z,TokNam,tlen)==0)
                            : (strncasecmp(Line+z,TokNam,tlen)==0);
     if  ( (SFound) 
     AND   ((z==0) OR (NOT CompressLine_NErl(Line[z-1])))
     AND   ((e>=strlen(Line)) OR (NOT CompressLine_NErl(Line[e]))) )
      BEGIN
       strcpy(Line+z+1,Line+e); Line[z]=Num;
       llen=strlen(Line);
      END;
     z++; 
    END
END

        void ExpandLine(char *TokNam, Byte Num, char *Line)
BEGIN
    char *z;

    do
     BEGIN
      z=strchr(Line,Num);
      if (z!=Nil)
       BEGIN
        strcpy(z,z+1); 
        strmaxins(Line,TokNam,z-Line,255);
       END
     END
    while (z!=0);
END

        void KillCtrl(char *Line)
BEGIN
   char *z;
   
   if (*(z=Line)=='\0') return;
   do
    BEGIN
     if (*z=='\0');
     else if (*z==Char_HT)
      BEGIN
       strcpy(z,z+1);
       strprep(z,Blanks(8-((z-Line)%8)));
      END
     else if ((*z&0xe0)==0) *z=' ';
     z++;
    END
   while (*z!='\0');
END

/****************************************************************************/
/* Buchhaltung */

	void BookKeeping(void)
BEGIN
   if (MakeUseList)
    if (AddChunk(SegChunks+ActPC,ProgCounter(),CodeLen,ActPC==SegCode)) WrError(90);
   if (DebugMode!=DebugNone)
    BEGIN
     AddSectionUsage(ProgCounter(),CodeLen);
     AddLineInfo(InMacroFlag,CurrLine,CurrFileName,ActPC,PCs[ActPC],CodeLen);
    END
END

/****************************************************************************/
/* Differenz zwischen zwei Zeiten mit Jahresueberlauf berechnen */

        long DTime(long t1, long t2)
BEGIN
   LongInt d;

   d=t2-t1; if (d<0) d+=(24*360000);
   return (d>0) ? d : -d;
END

/*--------------------------------------------------------------------------*/
/* Zeit holen */

#ifdef __MSDOS__

#include <dos.h>

        long GTime(void)
BEGIN
   static unsigned long *tick=MK_FP(0x40,0x6c);
   double tmp=*tick;

   return ((long) (tmp*5.4931641));
END

#elif __IBMC__

#include <time.h>
#define INCL_DOSDATETIME
#include <os2.h>

        long GTime(void)
BEGINM
   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);
END

#else

#include <sys/time.h>

        long GTime(void)
BEGIN
   struct timeval tv;
  
   gettimeofday(&tv,Nil);
   return (tv.tv_sec*100)+(tv.tv_usec/10000);
END

#endif
/**
{****************************************************************************}
{ Heapfehler abfedern }

        FUNCTION MyHeapError(Size:Word):Integer;
        Far;
 BEGIN
   IF Size<>0 THEN WrError(10006);
   MyHeapError:=1;
END;
**/
/*-------------------------------------------------------------------------*/
/* Stackfehler abfangen - bis auf DOS nur Dummies */

#ifdef __TURBOC__
#ifdef __DPMI16__
#else
unsigned _stklen=STKSIZE;
unsigned _ovrbuffer=64*48;
#endif
#include <malloc.h>
#endif

        void ChkStack(void)
BEGIN
#ifdef __TURBOC__
   LongWord avail=stackavail();
   if (avail<MinStack) WrError(10007);   
   if (avail<LowStack) LowStack=avail;
#endif
END

        void ResetStack(void)
BEGIN
#ifdef __TURBOC__
   LowStack=stackavail();
#endif
END

        LongWord StackRes(void)
BEGIN
#ifdef __TURBOC__
   return LowStack-MinStack;
#else
   return 0;
#endif
END

#ifdef CKMALLOC
#undef malloc
#undef realloc

        void *ckmalloc(size_t s)
BEGIN
   void *tmp=malloc(s);
   if (tmp==NULL) WrError(10006);
   return tmp;
END

        void *ckrealloc(void *p, size_t s)
BEGIN
   void *tmp=realloc(p,s);
   if (tmp==NULL) WrError(10006);
   return tmp;
END
#endif

	void asmsub_init(void)
BEGIN
   char *CMess=InfoMessCopyright;
   Word z;
   LongWord XORVal;

#ifdef __TURBOC__
#ifdef __MSDOS__
#ifdef __DPMI16__
   char *MemFlag,*p;
   String MemVal,TempName;
   unsigned long FileLen;
#else
   char *envval;
   int ovrerg;
#endif
#endif
#endif

   for (z=0; z<strlen(CMess); z++)
    BEGIN
     XORVal=CMess[z];
     XORVal=XORVal << (((z+1) % 4)*8);
     Magic=Magic ^ XORVal;
    END

   InitStringList(&CopyrightList);
   InitStringList(&OutList);
   InitStringList(&ShareOutList);

#ifdef __TURBOC__
#ifdef __MSDOS__
#ifdef __DPMI16__
   /* Fuer DPMI evtl. Swapfile anlegen */

   MemFlag=getenv("ASXSWAP");
   if (MemFlag!=Nil)
    BEGIN
     strmaxcpy(MemVal,MemFlag,255);
     p=strchr(MemVal,',');
     if (p==Nil) strcpy(TempName,"ASX.TMP");
     else
      BEGIN
       *p=Nil; strcpy(TempName,MemVal);
       strcpy(MemVal,p+1);
      END;
     KillBlanks(TempName); KillBlanks(MemVal);
     FileLen=strtol(MemFlag,&p,0);
     if (*p!='\0')
      BEGIN
       fputs(getmessage(Num_ErrMsgInvSwapSize),stderr); exit(4);
      END;
     if (MEMinitSwapFile(TempName,FileLen << 20)!=RTM_OK)
      BEGIN
       fputs(getmessage(Num_ErrMsgSwapTooBig),stderr); exit(4);
      END
    END
#else
   /* Bei DOS Auslagerung Overlays in XMS/EMS versuchen */

   envval=getenv("USEXMS");
   if ((envval!=Nil) AND (toupper(*envval)=='N')) ovrerg=-1;
   else ovrerg=_OvrInitExt(0,0);
   if (ovrerg!=0)
    BEGIN
     envval=getenv("USEEMS");
     if ((envval==Nil) OR (toupper(*envval)!='N')) _OvrInitEms(0,0,0);
    END
#endif
#endif
#endif

#ifdef __TURBOC__
   StartStack=stackavail(); LowStack=stackavail();
   MinStack=StartStack-STKSIZE+0x800;
#else
   StartStack=LowStack=MinStack=0;
#endif
END

