/* 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 "be_le.h"
#include "stdhandl.h"
#include "console.h"
#include "nls.h"
#include "chardefs.h"
#include "nlmessages.h"
#include "cmdarg.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 "asmlist.h"
#include "as.h"
#include "asmsub.h"
#ifdef __TURBOC__
#ifdef __DPMI16__
#define STKSIZE 32768
#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(void(*PrintProc)(const char *))
{
StringRecPtr Lauf;
const char *p_line;
for (p_line = GetStringListFirst(CopyrightList, &Lauf);
p_line; p_line = GetStringListNext(&Lauf))
PrintProc(p_line);
}
/*--------------------------------------------------------------------------*/
/* 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)
{
return 1;
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;
if (h)
if ((!Min) || (h < Min))
Min = h;
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;
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:
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;
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:
return pResult;
}
/*!------------------------------------------------------------------------
* \fn as_iterate_str_quoted(const char *p_str, as_quoted_iterator_cb_t callback, as_quoted_iterator_cb_data_t *p_cb_data)
* \brief iterate through string, skipping quoted areas
* \param p_str string to iterate through
* \param callback is called for all characters outside quoted areas
* \param p_cb_data callback data
* ------------------------------------------------------------------------ */
void as_iterate_str_quoted(const char *p_str, as_quoted_iterator_cb_t callback, as_quoted_iterator_cb_data_t *p_cb_data)
{
const char *p_run;
Boolean this_escaped, next_escaped;
p_cb_data->p_str = p_str;
p_cb_data->in_single_quote =
p_cb_data->in_double_quote = False;
for (p_run = p_str, this_escaped = False;
*p_run;
p_run++, this_escaped = next_escaped)
{
next_escaped = False;
switch(*p_run)
{
case '\\':
if ((p_cb_data->in_single_quote || p_cb_data->in_double_quote) && !this_escaped)
next_escaped = True;
break;
case '\'':
if (p_cb_data->in_double_quote) { }
else if (!p_cb_data->in_single_quote && (!QualifyQuote || QualifyQuote(p_str, p_run)))
p_cb_data->in_single_quote = True;
else if (!this_escaped) /* skip escaped ' in '...' */
p_cb_data->in_single_quote = False;
break;
case '"':
if (p_cb_data->in_single_quote) { }
else if (!p_cb_data->in_double_quote)
p_cb_data->in_double_quote = True;
else if (!this_escaped) /* skip escaped " in "..." */
p_cb_data->in_double_quote = False;
break;
default:
if (!p_cb_data->in_single_quote && !p_cb_data->in_double_quote)
{
if (!callback(p_run, p_cb_data))
return;
}
}
}
}
/*!------------------------------------------------------------------------
* \fn FindClosingParenthese(const char *pStr)
* \brief find matching closing parenthese
* \param pStr * to string right after opening parenthese
* \return * to closing parenthese or NULL
* ------------------------------------------------------------------------ */
typedef struct
{
as_quoted_iterator_cb_data_t data;
int nest;
const char *p_ret;
} close_par_cb_data_t;
static Boolean close_par_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data)
{
close_par_cb_data_t *p_data = (close_par_cb_data_t*)p_cb_data;
switch(*p_pos)
{
case '(':
p_data->nest++;
break;
case ')':
if (!--p_data->nest)
{
p_data->p_ret = p_pos;
return False;
}
break;
}
return True;
}
char *FindClosingParenthese(const char *pStr)
{
close_par_cb_data_t data;
data.nest = 1;
data.p_ret = NULL;
as_iterate_str_quoted(pStr, close_par_cb,&data.data);
return (char*)data.p_ret;
}
/*!------------------------------------------------------------------------
* \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
* ------------------------------------------------------------------------ */
typedef struct
{
as_quoted_iterator_cb_data_t data;
int nest;
const char *p_str_end;
const char *p_ret;
const char *p_bracks;
} open_par_cb_data_t;
static Boolean open_par_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data)
{
open_par_cb_data_t *p_data = (open_par_cb_data_t*)p_cb_data;
if (*p_pos == p_data->p_bracks[0])
{
if (!p_data->nest)
p_data->p_ret = p_pos;
p_data->nest++;
}
else if (*p_pos == p_data->p_bracks[1])
p_data->nest--;
/* We are interested in the opening parenthese that is nearest to the closing
one and on same level, so continue searching: */
return ((p_pos + 1) < p_data->p_str_end);
}
char *FindOpeningParenthese(const char *pStrBegin, const char *pStrEnd, const char Bracks[2])
{
open_par_cb_data_t data;
data.nest = 0;
data.p_ret = NULL;
data.p_bracks = Bracks;
data.p_str_end = pStrEnd;
as_iterate_str_quoted(pStrBegin, open_par_cb, &data.data);
return (char*)data.p_ret;
}
/****************************************************************************/
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 == PATHSEP)
p = z;
Part = p ? p : s;
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 == PATHSEP)
p = z;
Part = p ? p : s;
if (Part)
*Part = '\0';
}
/*--------------------------------------------------------------------------*/
/* Pfadanteil (Laufwerk+Verzeichnis) von einem Dateinamen abspalten */
char *PathPart(char *Name)
{
static String s;
char *p;
strmaxcpy(s, Name, STRINGSIZE);
#ifdef DRSEP
if (!p)
#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)
#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 */
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--;
while (*p == '0')
{
strmov(p, p + 1);
p--;
}
/* 4. auf die gewuenschte Maximalstellenzahl begrenzen */
n = p - d - 1;
/* 5. Maximallaenge ueberschritten ? */
strmov
(d
+ (n
- (strlen(pDest
) - MaxLen
)), d
+ n
);
/* 6. Exponentenwert berechnen */
if (WithE)
{
ExpVal = ConstLongInt(p + 1, &OK, 10);
}
else
{
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';
strmov(d, d + 1);
if (nzeroes != 0)
{
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';
strmov(d, d + 1);
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';
strmov(d, d + 1);
d = (pDest[0] == '-') ? pDest + 1 : pDest;
*(d++) = '0';
*(d++) = '.';
for (n = 0; n < -ExpVal - 1; n++)
*(d++) = '0';
}
}
/* 9. Ueberfluessiges Komma entfernen */
if (WithE)
else
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;
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;
ChkIO(ErrNum_ListWrError);
}
Header[PageWidth] = Save;
strmov(Header, Header + PageWidth);
}
if (!ListToNull)
{
errno = 0;
ChkIO(ErrNum_ListWrError);
if (PrtTitleString[0])
{
errno = 0;
fprintf(LstFile
, "%s\n", PrtTitleString
);
ChkIO(ErrNum_ListWrError);
}
errno = 0;
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;
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;
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;
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);
as_dynstr_free(&str);
}
/*!------------------------------------------------------------------------
* \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)
{
Boolean Match;
errno = 0;
for (z = 0; z < Len; z++)
{
Match = CompMatch(z, pMuteComponent) || CompMatch(z, pMuteComponent2);
fputc(Match
? ' ' : pLine
[z
], 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;
for (pRun = pLine; *pRun; pRun++)
fputc(TabCompressed
(*pRun
), pFile
);
if (pLineComp && (pLineComp->StartCol >= 0) && (pLineComp->Len > 0))
{
if (pLineComp->StartCol > 0)
fprintf(pFile
, "%*s", pLineComp
->StartCol
, "");
for (z = 0; z < (int)pLineComp->Len; z++)
}
}
/****************************************************************************/
/* 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;
}
Boolean ChkMacSymbChar(char ch)
{
return !!(GetValidSymChar(ch) & (VALID_M1 | VALID_MN));
}
/*!------------------------------------------------------------------------
* \fn visible_strlen(const char *pSym)
* \brief retrieve 'visible' length of string, regarding multi-byte
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)
Result += as_wcwidth(UTF8ToUnicode(&pSym));
return Result;
}
else
}
/****************************************************************************/
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);
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 */
/*!------------------------------------------------------------------------
* \fn get_first_path_from_list(const char *p_path_list, char *p_first_path, size_t first_path_size)
* \brief extract first path from list of paths
* \param p_path_list path list
* \param p_first_path where to put component
* \param first_path_size buffer size
* \return p_path_list for next call of get_first_path_from_list()
* ------------------------------------------------------------------------ */
static const char *get_first_path_from_list(const char *p_path_list, char *p_first_path, size_t first_path_size)
{
const char *p;
p
= strchr(p_path_list
, DIRSEP
);
if (!p)
{
strmaxcpy(p_first_path, p_path_list, first_path_size);
return "";
}
else
{
strmemcpy(p_first_path, first_path_size, p_path_list, p - p_path_list);
return p + 1;
}
}
/*!------------------------------------------------------------------------
* \fn AddIncludeList(const char *p_new_path)
* \brief add path to include list
* \param p_new_path path to add
* ------------------------------------------------------------------------ */
void AddIncludeList(const char *p_new_path)
{
const char *p_list_run = IncludeList;
String one_path;
/* path already present in list? */
while (*p_list_run)
{
p_list_run = get_first_path_from_list(p_list_run, one_path, sizeof(one_path));
if (!strcmp(one_path
, p_new_path
))
return;
}
/* no -> prepend */
if (*IncludeList != '\0')
strmaxprep(IncludeList, SDIRSEP, STRINGSIZE);
strmaxprep(IncludeList, p_new_path, STRINGSIZE);
}
/*!------------------------------------------------------------------------
* \fn RemoveIncludeList(const char *p_rem_path)
* \brief remove one path from include list
* \param p_rem_path path to remove
* ------------------------------------------------------------------------ */
void RemoveIncludeList(const char *p_rem_path)
{
String one_path;
const char *p_list_run, *p_list_next;
p_list_run = IncludeList;
while (*p_list_run)
{
p_list_next = get_first_path_from_list(p_list_run, one_path, sizeof(one_path));
if (!strcmp(one_path
, p_rem_path
))
strmov((char*)p_list_run, p_list_next);
else
p_list_run = p_list_next;
}
}
/****************************************************************************/
/* 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 *MoveFromOutListFirst(void)
{
return MoveAndCutStringListFirst(&OutList);
}
void ClearShareOutList(void)
{
ClearStringList(&ShareOutList);
}
void AddToShareOutList(const char *NewName)
{
AddStringListLast(&ShareOutList, NewName);
}
void RemoveFromShareOutList(const char *OldName)
{
RemoveStringList(&ShareOutList, OldName);
}
char *MoveFromShareOutListFirst(void)
{
return MoveAndCutStringListFirst(&ShareOutList);
}
void ClearListOutList(void)
{
ClearStringList(&ListOutList);
}
void AddToListOutList(const char *NewName)
{
AddStringListLast(&ListOutList, NewName);
}
void RemoveFromListOutList(const char *OldName)
{
RemoveStringList(&ListOutList, OldName);
}
char *MoveFromListOutListFirst(void)
{
return MoveAndCutStringListFirst(&ListOutList);
}
/****************************************************************************/
/* Tokenverarbeitung */
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) || !ChkMacSymbChar(p_str->p_str[Pos - 1]))
&& ((End >= StrLen) || !ChkMacSymbChar(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;
}
/*!------------------------------------------------------------------------
* \fn GTime(void)
* \brief fetch time of day in units of 10 ms
* \return time of day
* ------------------------------------------------------------------------ */
#ifdef __MSDOS__
#include <dos.h>
long GTime(void)
{
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;
}
# define GTIME_DEFINED
#endif /* __MSDOS__ */
#ifdef __IBMC__
#include <time.h>
#define INCL_DOSDATETIME
#include <os2.h>
long GTime(void)
{
DATETIME dt;
struct tm ts;
DosGetDateTime(&dt);
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);
}
# define GTIME_DEFINED
#endif /* __IBMC__ */
#ifdef _WIN32
# include <windows.h>
# ifdef NOLONGLONG
# include "math64.h"
# endif
long GTime(void)
{
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
# ifdef NOLONGLONG
{
static const t64 offs = { 0xd53e8000, 0x019db1de },
mod = { 8640000, 0 };
t64 acc;
/* time since 1 Jan 1601 in 100ns units */
acc.low = ft.dwLowDateTime;
acc.high = ft.dwHighDateTime;
/* -> time since 1 Jan 1970 in 100ns units */
sub64(&acc, &acc, &offs);
/* -> time since 1 Jan 1970 in 10ms units */
/* -> time since 0:00:00.0 in 10ms units */
mod64(&acc, &acc, &mod);
return acc.low;
}
# else /* !NOLONGLONG */
# define _W32_FT_OFFSET (116444736000000000ULL)
unsigned long long time_tot;
/* time since 1 Jan 1601 in 100ns units */
time_tot = ((unsigned long long)ft.dwLowDateTime ) ;
time_tot += ((unsigned long long)ft.dwHighDateTime) << 32;
/* -> time since 1 Jan 1970 in 100ns units */
time_tot -= _W32_FT_OFFSET;
/* -> time since 1 Jan 1970 in 10ms units */
time_tot /= 100000ULL;
/* -> time since 0:00:00.0 in 10ms units */
time_tot %= 8640000ULL;
return time_tot;
# endif /* NOLONGLONG */
}
# define GTIME_DEFINED
#endif /* _WIN32 */
#ifndef GTIME_DEFINED
#include <sys/time.h>
long GTime(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
tv.tv_sec %= 86400;
return (tv.tv_sec * 100) + (tv.tv_usec/10000);
}
#endif /* GTIME_DEFINED */
/*-------------------------------------------------------------------------*/
/* 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
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
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);
}
static as_cmd_result_t cmd_underscore_macroargs(Boolean negate, const char *p_arg)
{
unsigned ch = (unsigned)'_';
UNUSED(p_arg);
if (negate)
ValidSymChar[ch] &= ~(VALID_M1 | VALID_MN);
else
ValidSymChar[ch] |= (VALID_M1 | VALID_MN);
return e_cmd_ok;
}
static const as_cmd_rec_t cmd_params[] =
{
{ "underscore-macroargs", cmd_underscore_macroargs }
};
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 */
if (MemFlag)
{
strmaxcpy(MemVal, MemFlag, STRINGSIZE);
if (!p)
else
{
*p = NULL;
strmov(MemVal, p + 1);
};
KillBlanks(TempName);
KillBlanks(MemVal);
FileLen
= strtol(MemFlag
, &p
, 0);
if (*p != '\0')
{
fputs(getmessage
(Num_ErrMsgInvSwapSize
), stderr
);
}
if (MEMinitSwapFile(TempName, FileLen << 20) != RTM_OK)
{
fputs(getmessage
(Num_ErrMsgSwapTooBig
), stderr
);
}
}
#else
/* Bei DOS Auslagerung Overlays in XMS/EMS versuchen */
if ((envval) && (as_toupper(*envval) == 'N'))
ovrerg = -1;
else
ovrerg = _OvrInitExt(0, 0);
if (ovrerg != 0)
{
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
as_cmd_register(cmd_params, as_array_size(cmd_params));
/* initialize array of valid characters */
ValidSymCharLen = (NLS_GetCodepage() == eCodepageUTF8) ? 1280 : 256;
ValidSymChar
= (Byte
*) calloc(ValidSymCharLen
, sizeof(Byte
));
/* The basic ASCII stuff: letters, dot and underscore are allowed
anywhere, 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
, " %x", ValidSymChar
[z
]);
if ((z & 15) == 15)
}
#endif
version_init();
}