static struct dsym *CreateGroup( const char *name ) /*************************************************/ { struct dsym *grp; grp = (struct dsym *)SymSearch( name ); if( grp == NULL || grp->sym.state == SYM_UNDEFINED ) { if ( grp == NULL ) grp = (struct dsym *)SymCreate( name ); else sym_remove_table( &SymTables[TAB_UNDEF], grp ); grp->sym.state = SYM_GRP; grp->e.grpinfo = LclAlloc( sizeof( struct grp_info ) ); grp->e.grpinfo->seglist = NULL; //grp->e.grpinfo->grp_idx = 0; //grp->e.grpinfo->lname_idx = 0; grp->e.grpinfo->numseg = 0; sym_add_table( &SymTables[TAB_GRP], grp ); grp->sym.list = TRUE; grp->e.grpinfo->grp_idx = ++grpdefidx; grp->e.grpinfo->lname_idx = ++LnamesIdx; AddLnameData( &grp->sym ); } else if( grp->sym.state != SYM_GRP ) { EmitErr( SYMBOL_REDEFINITION, name ); return( NULL ); } grp->sym.isdefined = TRUE; return( grp ); }
static struct dsym *CreateSegment( struct dsym *seg, const char *name, bool add_global ) /**************************************************************************************/ { if ( seg == NULL ) seg = ( add_global ? (struct dsym *)SymCreate( name ) : (struct dsym *)SymAlloc( name ) ); else if ( seg->sym.state == SYM_UNDEFINED ) sym_remove_table( &SymTables[TAB_UNDEF], seg ); if ( seg ) { seg->sym.state = SYM_SEG; seg->e.seginfo = LclAlloc( sizeof( struct seg_info ) ); memset( seg->e.seginfo, 0, sizeof( struct seg_info ) ); seg->e.seginfo->Ofssize = ModuleInfo.defOfssize; seg->e.seginfo->alignment = 4; /* this is PARA (2^4) */ seg->e.seginfo->combine = COMB_INVALID; /* null class name, in case none is mentioned */ seg->e.seginfo->class_name_idx = 1; seg->next = NULL; /* don't use sym_add_table(). Thus the "prev" member * becomes free for another use. */ if ( SymTables[TAB_SEG].head == NULL ) SymTables[TAB_SEG].head = SymTables[TAB_SEG].tail = seg; else { SymTables[TAB_SEG].tail->next = seg; SymTables[TAB_SEG].tail = seg; } } return( seg ); }
/* create external. * sym must be NULL or of state SYM_UNDEFINED! */ static struct asym *CreateExternal( struct asym *sym, const char *name, char weak ) /*********************************************************************************/ { if ( sym == NULL ) sym = SymCreate( name ); else sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym ); if ( sym ) { sym->state = SYM_EXTERNAL; sym->seg_ofssize = ModuleInfo.Ofssize; sym->iscomm = FALSE; sym->weak = weak; sym_add_table( &SymTables[TAB_EXT], (struct dsym *)sym ); /* add EXTERNAL */ } return( sym ); }
/* create a (predefined) text macro. * used to create @code, @data, ... * there are 2 more locations where predefined text macros may be defined: * - assemble.c, add_cmdline_tmacros() * - symbols.c, SymInit() * this should be changed eventually. */ struct asym *AddPredefinedText( const char *name, const char *value ) /*******************************************************************/ { struct asym *sym; DebugMsg1(("AddPredefinedText(%s): >%s<\n", name, value )); /* v2.08: ignore previous setting */ if ( NULL == ( sym = SymSearch( name ) ) ) sym = SymCreate( name ); sym->state = SYM_TMACRO; sym->isdefined = TRUE; sym->predefined = TRUE; sym->string_ptr = (char *)value; /* to ensure that a new buffer is used if the string is modified */ sym->total_size = 0; return( sym ); }
// make sure to get a predefined type so that the type system is not // exercised in the back end // static SYMBOL rtSymbolCreate( // CREATE NEW RUN-TIME SYMBOL RTS_TYPE runtime_type, // - run-time type definition NAME name ) // - name of run-time function { SYMBOL sym; // - new symbol TYPE sym_type; // - symbol's type symbol_flag flags; // - symbol's flags flags = SF_REFERENCED; if( runtime_type & RTS_FUNCTION ) { if( runtime_type & RTS_POINTER ) { sym_type = TypePtrVoidFunOfVoid(); } else if( runtime_type & RTS_HANDLER ) { sym_type = TypeVoidHandlerFunOfVoid(); } else { sym_type = TypeVoidFunOfVoid(); } if( runtime_type & RTS_INLINE ) { sym_type = AddFunctionFlag( sym_type, TF1_INTRINSIC ); } if( runtime_type & RTS_CAN_THROW ) { flags |= SF_LONGJUMP; } else if( runtime_type & RTS_NO_THROW ) { flags |= SF_NO_LONGJUMP; } else if( runtime_type & RTS_IG_THROW ) { RepoFunAdd( name, RFFLAG_IG_LONGJUMP ); } if( runtime_type & RTS_IS_THROW ) { flags |= SF_IS_THROW; } } else if( runtime_type & RTS_BASE_VOID ) { if( runtime_type & RTS_POINTER ) { sym_type = TypePtrToVoid(); } else { sym_type = GetBasicType( TYP_VOID ); } } else { sym_type = GetBasicType( TYP_SINT ); } sym = SymCreate( sym_type, SC_EXTERN, flags, name, GetInternalScope() ); LinkageSet( sym, "C" ); return sym; }
ret_code SafeSEHDirective( int i, struct asm_tok tokenarray[] ) /*************************************************************/ { struct asym *sym; struct qnode *node; if ( Options.output_format != OFORMAT_COFF ) { if ( Parse_Pass == PASS_1) EmitWarn( 2, DIRECTIVE_IGNORED_WITHOUT_X, "coff" ); return( NOT_ERROR ); } if ( Options.safeseh == FALSE ) { if ( Parse_Pass == PASS_1) EmitWarn( 2, DIRECTIVE_IGNORED_WITHOUT_X, "safeseh" ); return( NOT_ERROR ); } i++; if ( tokenarray[i].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } sym = SymSearch( tokenarray[i].string_ptr ); /* make sure the argument is a true PROC */ if ( sym == NULL || sym->state == SYM_UNDEFINED ) { if ( Parse_Pass != PASS_1 ) { return( EmitErr( SYMBOL_NOT_DEFINED, tokenarray[i].string_ptr ) ); } } else if ( sym->isproc == FALSE ) { return( EmitErr( SAFESEH_ARGUMENT_MUST_BE_A_PROC, tokenarray[i].string_ptr ) ); } if ( Parse_Pass == PASS_1 ) { if ( sym ) { for ( node = ModuleInfo.g.SafeSEHQueue.head; node; node = node->next ) if ( node->elmt == sym ) break; } else { sym = SymCreate( tokenarray[i].string_ptr ); node = NULL; } if ( node == NULL ) { sym->used = TRUE; /* make sure an external reference will become strong */ #if 0 /* v2.11: use QAddItem() */ node = LclAlloc( sizeof( struct qnode ) ); node->elmt = sym; node->next = NULL; if ( ModuleInfo.g.SafeSEHQueue.head == 0 ) ModuleInfo.g.SafeSEHQueue.head = ModuleInfo.g.SafeSEHQueue.tail = node; else { ((struct qnode *)ModuleInfo.g.SafeSEHQueue.tail)->next = node; ModuleInfo.g.SafeSEHQueue.tail = node; } #else QAddItem( &ModuleInfo.g.SafeSEHQueue, sym ); #endif } } i++; if ( tokenarray[i].token != T_FINAL ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } return( NOT_ERROR ); }
ret_code PublicDirective( int i, struct asm_tok tokenarray[] ) /************************************************************/ { #if MANGLERSUPP char *mangle_type = NULL; #endif char *token; struct asym *sym; //struct dsym *dir; char skipitem; enum lang_type langtype; DebugMsg1(("PublicDirective(%u) enter\n", i)); i++; /* skip PUBLIC directive */ #if MANGLERSUPP mangle_type = Check4Mangler( &i, tokenarray ); #endif do { /* read the optional language type */ langtype = ModuleInfo.langtype; GetLangType( &i, tokenarray, &langtype ); if ( tokenarray[i].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } /* get the symbol name */ token = tokenarray[i++].string_ptr; DebugMsg1(("PublicDirective: sym=%s\n", token )); /* Add the public name */ sym = SymSearch( token ); if ( Parse_Pass == PASS_1 ) { if ( sym == NULL ) { if ( sym = SymCreate( token ) ) { sym_add_table( &SymTables[TAB_UNDEF], (struct dsym *)sym ); DebugMsg1(("PublicDirective(%s): new symbol\n", sym->name )); } else return( ERROR ); /* name was too long */ } skipitem = FALSE; } else { if ( sym == NULL || sym->state == SYM_UNDEFINED ) { EmitErr( SYMBOL_NOT_DEFINED, token ); //return( ERROR ); /* v2.04: dont exit */ } } if ( sym ) { switch ( sym->state ) { case SYM_UNDEFINED: break; case SYM_INTERNAL: if ( sym->scoped == TRUE ) { EmitErr( CANNOT_DECLARE_SCOPED_CODE_LABEL_AS_PUBLIC, sym->name ); skipitem = TRUE; //return( ERROR ); } break; case SYM_EXTERNAL: if ( sym->iscomm == TRUE ) { EmitErr( CANNOT_DEFINE_AS_PUBLIC_OR_EXTERNAL, sym->name ); skipitem = TRUE; //return( ERROR ); } else if ( sym->weak == FALSE ) { /* for EXTERNs, emit a different error msg */ EmitErr( SYMBOL_REDEFINITION, sym->name ); skipitem = TRUE; //return( ERROR ); } break; default: EmitErr( CANNOT_DEFINE_AS_PUBLIC_OR_EXTERNAL, sym->name ); skipitem = TRUE; //return( ERROR ); } if( Parse_Pass == PASS_1 && skipitem == FALSE ) { if ( sym->ispublic == FALSE ) { sym->ispublic = TRUE; AddPublicData( sym ); /* put it into the public table */ } SetMangler( sym, langtype, mangle_type ); } } if ( tokenarray[i].token != T_FINAL ) if ( tokenarray[i].token == T_COMMA ) { if ( (i + 1) < Token_Count ) i++; } else { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ) ); } } while ( i < Token_Count ); return( NOT_ERROR ); }
static ret_code HandleAltname( char *altname, struct asym *sym ) /**************************************************************/ { struct asym *symalt; if ( altname && sym->state == SYM_EXTERNAL ) { symalt = SymSearch( altname ); /* altname symbol changed? */ if ( sym->altname && sym->altname != symalt ) { return( EmitErr( SYMBOL_REDEFINITION, sym->name ) ); } if ( Parse_Pass > PASS_1 ) { if ( symalt->state == SYM_UNDEFINED ) { EmitErr( SYMBOL_NOT_DEFINED, altname ); } else if (symalt->state != SYM_INTERNAL && symalt->state != SYM_EXTERNAL ) { EmitErr( SYMBOL_TYPE_CONFLICT, altname ); } else { #if COFF_SUPPORT || ELF_SUPPORT if ( symalt->state == SYM_INTERNAL && symalt->ispublic == FALSE ) if ( Options.output_format == OFORMAT_COFF #if ELF_SUPPORT || Options.output_format == OFORMAT_ELF #endif ) { EmitErr( MUST_BE_PUBLIC_OR_EXTERNAL, altname ); } #endif if ( sym->mem_type != symalt->mem_type ) EmitErr( SYMBOL_TYPE_CONFLICT, altname ); } } else { if ( symalt ) { DebugMsg(("HandleAltname: symbol '%s' found, state=%u\n", altname, symalt->state )); if ( symalt->state != SYM_INTERNAL && symalt->state != SYM_EXTERNAL && symalt->state != SYM_UNDEFINED ) { return( EmitErr( SYMBOL_TYPE_CONFLICT, altname ) ); } } else { symalt = SymCreate( altname ); sym_add_table( &SymTables[TAB_UNDEF], (struct dsym *)symalt ); } /* make sure the alt symbol becomes strong if it is an external * v2.11: don't do this for OMF ( maybe neither for COFF/ELF? ) */ if ( Options.output_format != OFORMAT_OMF ) symalt->used = TRUE; /* symbol inserted in the "weak external" queue? * currently needed for OMF only. */ if ( sym->altname == NULL ) { sym->altname = symalt; #if 0 /* v2.11: removed. Member nextext wasn't free to use */ DebugMsg1(("HandleAltname: symbol '%s' added to AltQueue\n", sym->name )); ((struct dsym *)sym)->nextext = NULL; if ( ModuleInfo.g.AltQueue.head == NULL ) ModuleInfo.g.AltQueue.head = ModuleInfo.g.AltQueue.tail = (struct dsym *)sym; else { ((struct dsym *)ModuleInfo.g.AltQueue.tail)->nextext = (struct dsym *)sym; ModuleInfo.g.AltQueue.tail = (struct dsym *)sym; } #endif } } } return( NOT_ERROR ); }
ret_code CatStrDir( int i, struct asm_tok tokenarray[] ) /******************************************************/ { struct asym *sym; int count; char *p; /* struct expr opndx; */ DebugMsg1(("CatStrDir(%u) enter\n", i )); DebugCmd( catstrcnt++ ); #if 0 /* can't happen */ /* syntax must be <id> CATSTR textitem[,textitem,...] */ if ( i != 1 ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } if ( tokenarray[0].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) ); } #endif i++; /* go past CATSTR/TEXTEQU */ /* v2.08: don't copy to temp buffer */ //*StringBufferEnd = NULLC; /* check correct syntax and length of items */ 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] ) ); } /* v2.08: using tokenarray.stringlen is not quite correct, since some chars * are stored in 2 bytes (!) */ 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 ) ); } /* v2.08: don't copy to temp buffer */ //strcpy( StringBufferEnd + count, tokenarray[i].string_ptr ); 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 ) { /* v2.01: symbol has been used already. Using * a textmacro before it has been defined is * somewhat problematic. */ sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym ); #if FASTPASS SkipSavedState(); /* further passes must be FULL! */ #endif EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name ); } else if( sym->state != SYM_TMACRO ) { /* it is defined as something else, get out */ 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 /* v2.08: reuse string space if fastmem is on */ if ( sym->total_size < ( count+1 ) ) { LclFree( sym->string_ptr ); /* is a noop if fastmem is on */ sym->string_ptr = (char *)LclAlloc( count + 1 ); sym->total_size = count + 1; } #endif /* v2.08: don't use temp buffer */ //memcpy( sym->string_ptr, StringBufferEnd, count + 1 ); 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 ); }
/* SubStr() * defines a text equate. * syntax: name SUBSTR <string>, pos [, size] */ ret_code SubStrDir( int i, struct asm_tok tokenarray[] ) /******************************************************/ { struct asym *sym; char *name; char *p; //char *newvalue; int pos; int size; int cnt; bool chksize; struct expr opndx; DebugMsg1(("SubStrDir enter\n")); DebugCmd( substrcnt++ ); /* at least 5 items are needed * 0 1 2 3 4 5 6 * ID SUBSTR SRC_ID , POS [, LENGTH] */ #if 0 /* can't happen */ if ( i != 1 ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } if ( tokenarray[0].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) ); } #endif name = tokenarray[0].string_ptr; i++; /* go past SUBSTR */ /* third item must be a string */ 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++; /* get pos, must be a numeric value and > 0 */ /* v2.11: flag NOUNDEF added - no forward ref possible */ if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) { DebugMsg(("SubStrDir(%s): invalid pos value\n", name)); return( ERROR ); } /* v2.04: "string" constant allowed as second argument */ //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) { if ( opndx.kind != EXPR_CONST ) { DebugMsg(("SubStrDir(%s): pos value is not a constant\n", name)); return( EmitError( CONSTANT_EXPECTED ) ); } /* pos is expected to be 1-based */ 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++; /* get size, must be a constant */ /* v2.11: flag NOUNDEF added - no forward ref possible */ if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) { DebugMsg(("SubStrDir(%s): invalid size value\n", name)); return( ERROR ); } /* v2.04: string constant ok */ //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) { 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 cnt = pos; /* position p to start of substring */ for ( pos--; pos > 0 && *p ; pos--, p++ ) if ( *p == '!' && *(p+1) != NULLC ) p++; if ( *p == NULLC ) { return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, cnt ) ); } if ( *p == '!' && *(p+1) != NULLC ) p++; for ( newvalue = p, cnt = size; *p && cnt; cnt--, p++ ) if ( *p == '!' && *(p+1) != NULLC ) p++; /* v2.04: check added */ if ( chksize && cnt ) { return( EmitError( COUNT_VALUE_TOO_LARGE ) ); } size = p - newvalue; p = newvalue; #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 we've never seen it before, put it in */ if( sym == NULL ) { sym = SymCreate( name ); } else if( sym->state == SYM_UNDEFINED ) { /* it was referenced before being defined. This is * a bad idea for preprocessor text items, because it * will require a full second pass! */ 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 ) { /* it is defined as something incompatible, get out */ 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 ); }
/* * used by EQU if the value to be assigned to a symbol is text. * - sym: text macro name, may be NULL * - name: identifer ( if sym == NULL ) * - value: value of text macro ( original line, BEFORE expansion ) */ struct asym *SetTextMacro( struct asm_tok tokenarray[], struct asym *sym, const char *name, const char *value ) /*************************************************************************************************************/ { int count; //char *p; 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 /* the text macro was referenced before being defined. * this is valid usage, but it requires a full second pass. * just simply deactivate the fastpass feature for this module! */ 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 == '<' ) { /* the simplest case: value is a literal. define a text macro! */ /* just ONE literal is allowed */ 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 { /* * the original source is used, since the tokenizer has * deleted some information. */ //while ( isspace( *value ) ) value++; /* probably obsolete */ count = strlen( value ); /* skip trailing spaces */ 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 ); /* is a noop if fastmem is on */ 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 ); }