#include <ctype.h>
#include "globals.h"
#include "memalloc.h"
#include "parser.h"
#include "expreval.h"
#include "equate.h"
#include "input.h"
#include "tokenize.h"
#include "macro.h"
#include "condasm.h"
#include "fastpass.h"
#include "listing.h"
#ifdef DEBUG_OUT
static uint_32 catstrcnt;
static uint_32 substrcnt;
static uint_32 sizstrcnt;
static uint_32 instrcnt;
static uint_32 equcnt;
#endif
#if defined(WINDOWSDDK)
#if defined(_WIN32)
typedef _W64 int INT_PTR, *PINT_PTR;
typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;
typedef _W64 long LONG_PTR, *PLONG_PTR;
typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
#define __int3264 __int32
#else
typedef __int64 INT_PTR, *PINT_PTR;
typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
typedef __int64 LONG_PTR, *PLONG_PTR;
typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
#define __int3264 __int64
#endif
#else
#include <inttypes.h>
#if defined(_WIN32)
typedef _W64 int INT_PTR, *PINT_PTR;
typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;
typedef _W64 long LONG_PTR, *PLONG_PTR;
typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
#define __int3264 __int32
#else
typedef int64_t INT_PTR, *PINT_PTR;
typedef uint64_t UINT_PTR, *PUINT_PTR;
typedef int64_t LONG_PTR, *PLONG_PTR;
typedef uint64_t ULONG_PTR, *PULONG_PTR;
#define __int3264 int64_t
#endif
#endif
#define MAXUINT_PTR (~((UINT_PTR)0))
UINT_PTR UTF8toWideChar(const unsigned char *pSource, UINT_PTR nSourceLen, UINT_PTR *nSourceDone, unsigned short *szTarget, UINT_PTR nTargetMax);
UINT_PTR UTF8toWideChar(const unsigned char *pSource, UINT_PTR nSourceLen, UINT_PTR *nSourceDone, unsigned short *szTarget, UINT_PTR nTargetMax)
{
static const unsigned int lpOffsetsFromUTF8[6]={0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080};
const unsigned char *pSrc=pSource;
const unsigned char *pSrcEnd=pSource + nSourceLen;
const unsigned char *pSrcDone=pSource;
unsigned short *pDst;
unsigned short *pDstEnd;
unsigned long nChar;
unsigned int nTrailing;
if (!szTarget && !nTargetMax)
{
pDst=NULL;
pDstEnd=(unsigned short *)MAXUINT_PTR;
}
else
{
pDst=szTarget;
pDstEnd=szTarget + nTargetMax;
}
while (pSrc < pSrcEnd && pDst < pDstEnd)
{
if (*pSrc < 0x80)
{
nTrailing=0;
}
else if (*pSrc < 0xC0)
{
pSrcDone=++pSrc;
continue;
}
else if (*pSrc < 0xE0)
{
if (pSrc + 1 >= pSrcEnd) break;
nTrailing=1;
}
else if (*pSrc < 0xF0)
{
if (pSrc + 2 >= pSrcEnd) break;
nTrailing=2;
}
else if (*pSrc < 0xF8)
{
if (pSrc + 3 >= pSrcEnd) break;
nTrailing=3;
}
else
{
pSrcDone=++pSrc;
continue;
}
nChar=0;
switch (nTrailing)
{
case 3:
{
nChar+=*pSrc++;
nChar=nChar << 6;
}
case 2:
{
nChar+=*pSrc++;
nChar=nChar << 6;
}
case 1:
{
nChar+=*pSrc++;
nChar=nChar << 6;
}
case 0:
{
nChar+=*pSrc++;
}
}
nChar-=lpOffsetsFromUTF8[nTrailing];
if (nChar <= 0xFFFF)
{
if (szTarget)
*pDst++=(unsigned short)nChar;
else
pDst+=1;
}
else
{
if (pDst + 1 >= pDstEnd) break;
nChar-=0x10000;
if (szTarget)
{
*pDst++=(unsigned short)((nChar >> 10) + 0xD800);
*pDst++=(unsigned short)((nChar & 0x3ff) + 0xDC00);
}
else pDst+=2;
}
pSrcDone=pSrc;
}
if (nSourceDone)
*nSourceDone=pSrcDone - pSource;
return (pDst - szTarget);
}
int TextItemError( struct asm_tok *item )
{
if ( item->token == T_STRING && *item->string_ptr == '<' ) {
return( EmitError( MISSING_ANGLE_BRACKET_OR_BRACE_IN_LITERAL ) );
}
if ( item->token == T_ID ) {
struct asym *sym = SymSearch( item->string_ptr );
if ( sym == NULL || sym->state == SYM_UNDEFINED ) {
return( EmitErr( SYMBOL_NOT_DEFINED, item->string_ptr ) );
}
}
return( EmitError( TEXT_ITEM_REQUIRED ) );
}
ret_code CatStrDir( int i, struct asm_tok tokenarray[] )
{
struct asym *sym;
int count;
char *p;
DebugMsg1(("CatStrDir(%u) enter\n", i ));
DebugCmd( catstrcnt++ );
#if 0#endif
i++;
for ( count = 0; i < Token_Count; ) {
DebugMsg1(("CatStrDir(%s): item[%u]=%s delim=0x%x\n", tokenarray[0].string_ptr, i, tokenarray[i].string_ptr, tokenarray[i].string_delim ));
if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) {
DebugMsg(("CatStrDir: error, not a <>-literal: %s\n", tokenarray[i].tokpos ));
return( TextItemError( &tokenarray[i] ) );
}
if ( ( count + tokenarray[i].stringlen ) >= MAX_LINE_LEN ) {
DebugMsg(("CatStrDir: error, literal too long: %u + %u >= %u\n", count, tokenarray[i].stringlen, MAX_LINE_LEN ));
return( EmitError( STRING_OR_TEXT_LITERAL_TOO_LONG ) );
}
count = count + tokenarray[i].stringlen;
i++;
if ( ( tokenarray[i].token != T_COMMA ) &&
( tokenarray[i].token != T_FINAL ) ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
i++;
}
sym = SymSearch( tokenarray[0].string_ptr );
if ( sym == NULL ) {
sym = SymCreate( tokenarray[0].string_ptr );
DebugMsg1(( "CatStrDir: new symbol %s created\n", sym->name));
} else if( sym->state == SYM_UNDEFINED ) {
sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym );
#if FASTPASS
SkipSavedState();
#endif
EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name );
} else if( sym->state != SYM_TMACRO ) {
DebugMsg(( "CatStrDir(%s) exit, symbol redefinition\n", sym->name));
return( EmitErr( SYMBOL_REDEFINITION, sym->name ) );
}
sym->state = SYM_TMACRO;
sym->isdefined = TRUE;
#if FASTMEM==0
if ( sym->string_ptr )
LclFree( sym->string_ptr );
sym->string_ptr = (char *)LclAlloc( count + 1 );
#else
if ( sym->total_size < ( count+1 ) ) {
LclFree( sym->string_ptr );
sym->string_ptr = (char *)LclAlloc( count + 1 );
sym->total_size = count + 1;
}
#endif
for ( i = 2, p = sym->string_ptr; i < Token_Count; i += 2 ) {
memcpy( p, tokenarray[i].string_ptr, tokenarray[i].stringlen );
p += tokenarray[i].stringlen;
}
*p = NULLC;
DebugMsg1(("CatStrDir(%s) (new) value: >%s<\n", sym->name, sym->string_ptr ));
if ( ModuleInfo.list )
LstWrite( LSTTYPE_TMACRO, 0, sym );
return( NOT_ERROR );
}
struct asym *SetTextMacro( struct asm_tok tokenarray[], struct asym *sym, const char *name, const char *value )
{
int count;
DebugCmd( equcnt++ );
if ( sym == NULL )
sym = SymCreate( name );
else if ( sym->state == SYM_UNDEFINED ) {
sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym );
#if FASTPASS
SkipSavedState();
#endif
EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name );
} else if ( sym->state != SYM_TMACRO ) {
EmitErr( SYMBOL_REDEFINITION, name );
return( NULL );
}
sym->state = SYM_TMACRO;
sym->isdefined = TRUE;
if ( tokenarray[2].token == T_STRING && tokenarray[2].string_delim == '<' ) {
if ( tokenarray[3].token != T_FINAL ) {
EmitErr( SYNTAX_ERROR_EX, tokenarray[3].tokpos );
return( NULL );
}
value = tokenarray[2].string_ptr;
count = tokenarray[2].stringlen;
} else {
count = strlen( value );
for ( ; count; count-- )
if ( isspace( *( value + count - 1 ) ) == FALSE )
break;
}
#if FASTMEM==0
if ( sym->string_ptr )
LclFree( sym->string_ptr );
sym->string_ptr = (char *)LclAlloc( count + 1 );
#else
if ( sym->total_size < ( count + 1 ) ) {
LclFree( sym->string_ptr );
sym->string_ptr = (char *)LclAlloc( count + 1 );
sym->total_size = count + 1;
}
#endif
memcpy( sym->string_ptr, value, count );
*(sym->string_ptr + count) = NULLC;
DebugMsg1(( "SetTextMacro(%s): value is >%s<, exit\n", sym->name, sym->string_ptr ));
return( sym );
}
struct asym *AddPredefinedText( const char *name, const char *value )
{
struct asym *sym;
DebugMsg1(("AddPredefinedText(%s): >%s<\n", name, value ));
if ( NULL == ( sym = SymSearch( name ) ) )
sym = SymCreate( name );
sym->state = SYM_TMACRO;
sym->isdefined = TRUE;
sym->predefined = TRUE;
sym->string_ptr = (char *)value;
sym->total_size = 0;
return( sym );
}
ret_code SubStrDir( int i, struct asm_tok tokenarray[] )
{
struct asym *sym;
char *name;
char *p;
int pos;
int size;
int cnt;
bool chksize;
struct expr opndx;
DebugMsg1(("SubStrDir enter\n"));
DebugCmd( substrcnt++ );
#if 0#endif
name = tokenarray[0].string_ptr;
i++;
if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) {
DebugMsg(("SubStrDir: error, no text item\n"));
return( TextItemError( &tokenarray[i] ) );
}
p = tokenarray[i].string_ptr;
cnt = tokenarray[i].stringlen;
i++;
DebugMsg1(("SubStrDir(%s): src=>%s<\n", name, p));
if ( tokenarray[i].token != T_COMMA ) {
return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) );
}
i++;
if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) {
DebugMsg(("SubStrDir(%s): invalid pos value\n", name));
return( ERROR );
}
if ( opndx.kind != EXPR_CONST ) {
DebugMsg(("SubStrDir(%s): pos value is not a constant\n", name));
return( EmitError( CONSTANT_EXPECTED ) );
}
pos = opndx.value;
if ( pos <= 0 ) {
return( EmitError( POSITIVE_VALUE_EXPECTED ) );
}
if ( tokenarray[i].token != T_FINAL ) {
if ( tokenarray[i].token != T_COMMA ) {
return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) );
}
i++;
if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) {
DebugMsg(("SubStrDir(%s): invalid size value\n", name));
return( ERROR );
}
if ( opndx.kind != EXPR_CONST ) {
DebugMsg(("SubStrDir(%s): size value is not a constant\n", name));
return( EmitError( CONSTANT_EXPECTED ) );
}
size = opndx.value;
if ( tokenarray[i].token != T_FINAL ) {
DebugMsg(("SubStrDir(%s): additional items found\n", name));
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
if ( size < 0 ) {
return( EmitError( COUNT_MUST_BE_POSITIVE_OR_ZERO ) );
}
chksize = TRUE;
} else {
size = -1;
chksize = FALSE;
}
#if 0#else
if ( pos > cnt ) {
return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) );
}
if ( chksize && (pos+size-1) > cnt ) {
return( EmitError( COUNT_VALUE_TOO_LARGE ) );
}
p += pos - 1;
if ( size == -1 )
size = cnt - pos + 1;
#endif
sym = SymSearch( name );
if( sym == NULL ) {
sym = SymCreate( name );
} else if( sym->state == SYM_UNDEFINED ) {
sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym );
#if FASTPASS
SkipSavedState();
EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name );
#endif
} else if( sym->state != SYM_TMACRO ) {
DebugMsg(( "SubStrDir(%s) error, incompatible type\n", sym->name));
return( EmitErr( SYMBOL_REDEFINITION, sym->name ) );
}
sym->state = SYM_TMACRO;
sym->isdefined = TRUE;
#if FASTMEM==0
if ( sym->string_ptr )
LclFree( sym->string_ptr );
sym->string_ptr = (char *)LclAlloc( size + 1 );
#else
if ( sym->total_size < ( size + 1 ) ) {
LclFree( sym->string_ptr );
sym->string_ptr = LclAlloc ( size + 1 );
sym->total_size = size + 1;
}
#endif
memcpy( sym->string_ptr, p, size );
*(sym->string_ptr + size) = NULLC;
DebugMsg1(("SubStrDir(%s): result=>%s<\n", sym->name, sym->string_ptr ));
LstWrite( LSTTYPE_TMACRO, 0, sym );
return( NOT_ERROR );
}
ret_code SizeStrDir( int i, struct asm_tok tokenarray[] )
{
struct asym *sym;
int sizestr;
DebugMsg1(("SizeStrDir entry\n"));
DebugCmd( sizstrcnt++ );
if ( i != 1 ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
#if 0#endif
if ( tokenarray[2].token != T_STRING || tokenarray[2].string_delim != '<' ) {
return( TextItemError( &tokenarray[2] ) );
}
if ( Token_Count > 3 ) {
DebugMsg(("SizeStrDir: syntax error, name=%s, Token_Count=%u\n", tokenarray[0].string_ptr, Token_Count));
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[3].string_ptr ) );
}
sizestr = tokenarray[2].stringlen;
if ( sym = CreateVariable( tokenarray[0].string_ptr, sizestr ) ) {
DebugMsg1(("SizeStrDir(%s) exit, value=%u\n", tokenarray[0].string_ptr, sizestr));
LstWrite( LSTTYPE_EQUATE, 0, sym );
return( NOT_ERROR );
}
return( ERROR );
}
ret_code InStrDir( int i, struct asm_tok tokenarray[] )
{
struct asym *sym;
int sizestr;
int j;
char *src;
char *p;
char *q;
char *string1;
struct expr opndx;
int start = 1;
int strpos;
DebugMsg1(("InStrDir entry\n"));
DebugCmd( instrcnt++ );
if ( i != 1) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
#if 0#endif
i++;
if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) {
if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR )
return( ERROR );
if ( opndx.kind != EXPR_CONST ) {
return( EmitError( CONSTANT_EXPECTED ) );
}
start = opndx.value;
if ( start <= 0 ) {
EmitWarn( 3, POSITIVE_VALUE_EXPECTED );
}
if ( tokenarray[i].token != T_COMMA ) {
return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) );
}
i++;
}
if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) {
return( TextItemError( &tokenarray[i] ) );
}
src = tokenarray[i].string_ptr;
sizestr = tokenarray[i].stringlen;
DebugMsg1(("InStrDir: first string >%s< \n", src ));
if ( start > sizestr ) {
return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, start ) );
}
p = src + start - 1;
i++;
if ( tokenarray[i].token != T_COMMA ) {
return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) );
}
i++;
if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) {
return( TextItemError( &tokenarray[i] ) );
}
q = tokenarray[i].string_ptr;
j = tokenarray[i].stringlen;
DebugMsg1(("InStrDir: second string >%s< \n", q ));
i++;
if ( tokenarray[i].token != T_FINAL ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
strpos = 0;
if ( ( start > 0 ) && ( sizestr >= j ) && j && ( string1 = strstr( p, q ) ))
strpos = string1 - src + 1;
if ( sym = CreateVariable( tokenarray[0].string_ptr, strpos ) ) {
DebugMsg1(("InStrDir(%s) exit, value=%u\n", tokenarray[0].string_ptr, strpos));
LstWrite( LSTTYPE_EQUATE, 0, sym );
return ( NOT_ERROR );
}
return( ERROR );
}
static ret_code CatStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] )
{
#ifdef DEBUG_OUT
int cnt = 0;
#endif
int i;
char *p;
DebugMsg1(("@CatStr( %s )\n", mi->parm_array[0] ? mi->parm_array[0] : "NULL" ));
for ( p = mi->parm_array[0]; mi->parmcnt; mi->parmcnt-- ) {
DebugMsg1(("@CatStr.%u: >%s<\n", cnt++, p ));
i = strlen( p );
memcpy( buffer, p, i );
p = GetAlignedPointer( p, i );
buffer += i;
}
*buffer = NULLC;
return( NOT_ERROR );
}
static ret_code GetNumber( char *string, int *pi, struct asm_tok tokenarray[] )
{
struct expr opndx;
int i;
int last;
last = Tokenize( string, Token_Count+1, tokenarray, TOK_RESCAN );
i = Token_Count+1;
if( EvalOperand( &i, tokenarray, last, &opndx, EXPF_NOUNDEF ) == ERROR ) {
return( ERROR );
}
if( opndx.kind != EXPR_CONST || tokenarray[i].token != T_FINAL ) {
return( EmitErr( SYNTAX_ERROR_EX, string ) );
}
*pi = opndx.value;
return( NOT_ERROR );
}
static ret_code InStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] )
{
int pos = 1;
char *p;
uint_32 found;
DebugMsg1(("@InStr( %s, %s, %s)\n",
mi->parm_array[0] ? mi->parm_array[0] : "",
mi->parm_array[1] ? mi->parm_array[1] : "",
mi->parm_array[2] ? mi->parm_array[2] : "" ));
*buffer = '0';
*(buffer+1) = NULLC;
if ( mi->parm_array[0] ) {
if ( GetNumber( mi->parm_array[0], &pos, tokenarray ) == ERROR )
return( ERROR );
if ( pos == 0 ) {
DebugMsg(( "@InStr(): index value is 0, changed to 1\n" ));
pos++;
}
}
if ( pos > strlen( mi->parm_array[1] ) ) {
return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) );
}
if ( *(mi->parm_array[2]) != NULLC ) {
p = strstr( mi->parm_array[1] + pos - 1, mi->parm_array[2] );
if ( p ) {
found = p - mi->parm_array[1] + 1;
myltoa( found, buffer, ModuleInfo.radix, FALSE, TRUE );
}
}
DebugMsg1(( "@InStr()=>%s<\n", buffer ));
return( NOT_ERROR );
}
static ret_code SizeStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] )
{
DebugMsg1(("@SizeStr(%s)\n", mi->parm_array[0] ? mi->parm_array[0] : "" ));
if ( mi->parm_array[0] )
myltoa( strlen( mi->parm_array[0] ), buffer, ModuleInfo. radix, FALSE, TRUE );
else {
buffer[0] = '0';
buffer[1] = NULLC;
}
return( NOT_ERROR );
}
static ret_code SubStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] )
{
int pos;
int size;
char *src = mi->parm_array[0];
DebugMsg1(("@SubStr( %s, %s, %s)\n",
src ? src : "",
mi->parm_array[1] ? mi->parm_array[1] : "",
mi->parm_array[2] ? mi->parm_array[2] : "" ));
if ( GetNumber( mi->parm_array[1], &pos, tokenarray ) == ERROR )
return( ERROR );
if ( pos <= 0 ) {
if ( pos ) {
return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) );
}
DebugMsg(( "@SubStr(): index value 0 changed to 1\n", pos ));
pos = 1;
}
size = strlen( src );
if ( pos > size ) {
return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) );
}
size = size - pos + 1;
if ( mi->parm_array[2] ) {
int sizereq;
if ( GetNumber( mi->parm_array[2], &sizereq, tokenarray ) == ERROR )
return( ERROR );
if ( sizereq < 0 ) {
return( EmitError( COUNT_MUST_BE_POSITIVE_OR_ZERO ) );
}
if ( sizereq > size ) {
return( EmitError( COUNT_VALUE_TOO_LARGE ) );
}
size = sizereq;
}
#if 1
memcpy( buffer, src + pos - 1, size );
*(buffer+size) = NULLC;
#else#endif
return( NOT_ERROR );
}
void StringInit( void )
{
int i;
struct dsym *macro;
DebugMsg(( "StringInit() enter\n" ));
#ifdef DEBUG_OUT
catstrcnt = 0;
substrcnt = 0;
sizstrcnt = 0;
instrcnt = 0;
equcnt = 0;
#endif
macro = CreateMacro( "@CatStr" );
macro->sym.isdefined = TRUE;
macro->sym.predefined = TRUE;
macro->sym.func_ptr = CatStrFunc;
macro->sym.isfunc = TRUE;
macro->sym.mac_vararg = TRUE;
macro->e.macroinfo->parmcnt = 1;
macro->e.macroinfo->parmlist = LclAlloc( sizeof( struct mparm_list ) * 1 );
macro->e.macroinfo->parmlist[0].deflt = NULL;
macro->e.macroinfo->parmlist[0].required = FALSE;
macro = CreateMacro( "@InStr" );
macro->sym.isdefined = TRUE;
macro->sym.predefined = TRUE;
macro->sym.func_ptr = InStrFunc;
macro->sym.isfunc = TRUE;
macro->e.macroinfo->parmcnt = 3;
macro->e.macroinfo->autoexp = 1;
macro->e.macroinfo->parmlist = LclAlloc(sizeof( struct mparm_list) * 3);
for (i = 0; i < 3; i++) {
macro->e.macroinfo->parmlist[i].deflt = NULL;
macro->e.macroinfo->parmlist[i].required = (i != 0);
}
macro = CreateMacro( "@SizeStr" );
macro->sym.isdefined = TRUE;
macro->sym.predefined = TRUE;
macro->sym.func_ptr = SizeStrFunc;
macro->sym.isfunc = TRUE;
macro->e.macroinfo->parmcnt = 1;
macro->e.macroinfo->parmlist = LclAlloc(sizeof( struct mparm_list));
macro->e.macroinfo->parmlist[0].deflt = NULL;
macro->e.macroinfo->parmlist[0].required = FALSE;
macro = CreateMacro( "@SubStr" );
macro->sym.isdefined = TRUE;
macro->sym.predefined = TRUE;
macro->sym.func_ptr = SubStrFunc;
macro->sym.isfunc = TRUE;
macro->e.macroinfo->parmcnt = 3;
macro->e.macroinfo->autoexp = 2 + 4;
macro->e.macroinfo->parmlist = LclAlloc(sizeof( struct mparm_list) * 3);
for (i = 0; i < 3; i++) {
macro->e.macroinfo->parmlist[i].deflt = NULL;
macro->e.macroinfo->parmlist[i].required = (i < 2);
}
return;
}
#ifdef DEBUG_OUT
void StringFini( void )
{
if ( Options.quiet == FALSE )
printf("invokation CATSTR=%u SUBSTR=%u SIZESTR=%u INSTR=%u EQU(text)=%u\n", catstrcnt, substrcnt, sizstrcnt, instrcnt, equcnt );
}
#endif