/* 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
)
{
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 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
;
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
== PATHSEP
)
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);
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
)
{
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
;
}
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
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 */
/*!------------------------------------------------------------------------
* \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)
{
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
;
}
# 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
);
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);
}
# 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 },
div = { 100000, 0 },
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 */
div64
(&acc
, &acc
, &div);
/* -> 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
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
);
}
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 */
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
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
, "%02x:", z
);
fprintf(stderr
, " %x", ValidSymChar
[z
]);
if ((z
& 15) == 15)
fprintf(stderr
, "\n");
}
#endif
version_init
();
}