jwasm/label.c
Ilya V. Matveychikov 3b4ec5258f Fix notes produced by clang compiler
note: use '==' to turn this assignment into an equality comparison
2015-07-30 19:11:43 +03:00

292 lines
11 KiB
C

/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Label directive, (anonymous) code labels
*
****************************************************************************/
#include "globals.h"
#include "parser.h"
#include "fixup.h"
#include "segment.h"
#include "proc.h"
#include "assume.h"
#include "types.h"
#include "label.h"
#include "listing.h"
/* LABELARRAY: syntax extension to LABEL directive:
* <label> LABEL <qualified type>[: index]
*/
#ifdef __I86__
#define LABELARRAY 0 /* not for jwasmr.exe */
#else
#define LABELARRAY 1
#endif
#if LABELARRAY
#include "expreval.h"
#endif
void LabelInit( void )
/********************/
{
ModuleInfo.g.anonymous_label = 0;
}
char *GetAnonymousLabel( char *buffer, int value )
/************************************************/
{
sprintf( buffer, "L&_%04u", ModuleInfo.g.anonymous_label + value );
return( buffer );
}
/* define a (code) label.
* - name: name of the label; ensured to be a valid identifier
* - mem_type: label's memory type
* - ti: qualified type pointer, used if memtype is MT_TYPE or MT_PROC
* - bLocal: if TRUE, code label is to be defined locally; it's ensured
* that CurrProc is != NULL and ModuleInfo.scoped == TRUE then.
*/
struct asym *CreateLabel( const char *name, enum memtype mem_type, struct qualified_type *ti, bool bLocal )
/*********************************************************************************************************/
{
struct asym *sym;
uint_32 addr;
char buffer[20];
DebugMsg1(("CreateLabel(%s, memtype=%Xh, %" I32_SPEC "Xh, %u) enter\n", name, mem_type, ti, bLocal));
if( CurrSeg == NULL ) {
EmitError( MUST_BE_IN_SEGMENT_BLOCK );
return( NULL );
}
/* v2.06: don't allow a code label (NEAR, FAR, PROC) if CS is
* assumed ERROR. This was previously checked for labels with
* trailing colon only [in ParseLine()].
*/
if ( ( mem_type & MT_SPECIAL_MASK) == MT_ADDRESS ) {
if ( SegAssumeTable[ASSUME_CS].error ) { /* CS assumed to ERROR? */
DebugMsg(("CreateLabel: code label and CS assumed error\n" ));
EmitError( USE_OF_REGISTER_ASSUMED_TO_ERROR );
return( NULL );
}
}
//if( strcmp( name, "@@" ) == 0 ) {
if( name[0] == '@' && name[1] == '@' && name[2] == NULLC ) {
sprintf( buffer, "L&_%04u", ++ModuleInfo.g.anonymous_label );
name = buffer;
}
sym = ( bLocal ? SymLookupLocal( name ) : SymLookup( name ) );
/* v2.11: SymLookup...() cannot fail */
//if( sym == NULL ) /* name invalid or too long? */
// return( NULL );
if( Parse_Pass == PASS_1 ) {
if( sym->state == SYM_EXTERNAL && sym->weak == TRUE ) {
/* don't accept EXTERNDEF for a local label! */
/* v2.04: also never accept PROTOs for extern to intern conversion */
//if ( bLocal && CurrProc ) {
if ( sym->isproc || ( bLocal && CurrProc ) ) {
DebugMsg(("CreateLabel(%s): error, EXTERNDEF for local label\n", sym->name));
EmitErr( SYMBOL_REDEFINITION, name );
return( NULL );
}
/* ensure that type of symbol is compatible! */
if ( sym->mem_type != MT_EMPTY &&
sym->mem_type != mem_type ) {
DebugMsg(("CreateLabel(%s): error, memtype conflict %X-%X\n", sym->name, sym->mem_type, mem_type));
EmitErr( SYMBOL_TYPE_CONFLICT, name );
}
sym_ext2int( sym );
} else if( sym->state == SYM_UNDEFINED ) {
sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym );
sym->state = SYM_INTERNAL;
} else {
/* v2.04: emit a more distinctive error msg */
if ( sym->state == SYM_INTERNAL && sym->mem_type == mem_type )
/* fixme: if label has exactly the same value ( segment+offset ),
* it's ok.
*/
EmitErr( SYMBOL_ALREADY_DEFINED, name );
else
EmitErr( SYMBOL_REDEFINITION, name );
return( NULL );
}
/* add the label to the linked list attached to curr segment */
/* this allows to reduce the number of passes (see fixup.c) */
((struct dsym *)sym)->next = (struct dsym *)CurrSeg->e.seginfo->label_list;
CurrSeg->e.seginfo->label_list = sym;
/* a possible language type set by EXTERNDEF must be kept! */
if ( sym->langtype == LANG_NONE )
sym->langtype = ModuleInfo.langtype;
/* v2.05: added to accept type prototypes */
if ( mem_type == MT_PROC ) {
DebugMsg1(("CreateLabel(%s): memtype MT_PROC detected, sym.isproc=%u\n", sym->name, sym->isproc ));
if ( sym->isproc == FALSE ) {
CreateProc( sym, NULL, SYM_INTERNAL );
CopyPrototype( (struct dsym *)sym, (struct dsym *)ti->symtype );
}
mem_type = ti->symtype->mem_type;
ti->symtype = NULL;
}
sym->mem_type = mem_type;
if ( ti ) {
if ( mem_type == MT_TYPE )
sym->type = ti->symtype;
else {
sym->Ofssize = ti->Ofssize;
sym->is_ptr = ti->is_ptr;
sym->isfar = ti->is_far;
sym->target_type = ti->symtype;
sym->ptr_memtype = ti->ptr_memtype;
}
}
} else {
/* save old offset */
addr = sym->offset;
}
sym->isdefined = TRUE;
/* v2.05: the label may be "data" - due to the way struct initialization
* is handled. Then fields first_size and first_length must not be
* touched!
*/
if ( sym->isdata == FALSE )
sym->asmpass = Parse_Pass;
SetSymSegOfs( sym );
// DebugMsg(("CreateLabel(%s): ofs=%X\n", sym->name, sym->offset));
if( Parse_Pass != PASS_1 && sym->offset != addr ) {
#ifdef DEBUG_OUT
if ( !ModuleInfo.PhaseError )
DebugMsg(("CreateLabel: Phase error, pass %u, sym >%s< first time, new=%" I32_SPEC "X - old=%" I32_SPEC "X\n", Parse_Pass+1, sym->name, sym->offset, addr));
else
DebugMsg(("CreateLabel: pass %u, sym >%s< changed, new=%" I32_SPEC "X - old=%" I32_SPEC "X\n", Parse_Pass+1, sym->name, sym->offset, addr));
#endif
ModuleInfo.PhaseError = TRUE;
}
BackPatch( sym );
return( sym );
}
/* LABEL directive.
* syntax: <label_name> LABEL <qualified type>
*/
ret_code LabelDirective( int i, struct asm_tok tokenarray[] )
/***********************************************************/
{
struct qualified_type ti;
struct asym *sym;
#if LABELARRAY
uint_32 length;
#endif
if( i != 1 ) { /* LABEL must be preceded by an ID */
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
i++;
ti.size = 0;
ti.is_ptr = 0;
ti.is_far = FALSE;
ti.mem_type = MT_EMPTY;
ti.ptr_memtype = MT_EMPTY;
ti.symtype = NULL;
ti.Ofssize = ModuleInfo.Ofssize;
if ( GetQualifiedType( &i, tokenarray, &ti ) == ERROR )
return( ERROR );
DebugMsg1(("LabelDirective(%s): memtype=%Xh, far=%u, ptr=%u, ofssize=%u, type=%s)\n",
tokenarray[0].string_ptr, ti.mem_type, ti.is_far, ti.is_ptr, ti.Ofssize, ti.symtype ? ti.symtype->name : "NULL" ));
#if LABELARRAY
length = -1;
#endif
/* v2.10: first if()-block is to handle all address types ( MT_NEAR, MT_FAR and MT_PROC ) */
//if ( ti.mem_type == MT_NEAR || ti.mem_type == MT_FAR ) {
if ( ( ti.mem_type & MT_SPECIAL_MASK) == MT_ADDRESS ) {
/* dont allow near16/far16/near32/far32 if size won't match */
if ( ti.Ofssize != USE_EMPTY && ModuleInfo.Ofssize != ti.Ofssize ) {
return( EmitError( OFFSET_SIZE_MISMATCH ) );
}
}
#if LABELARRAY
else if ( tokenarray[i].token == T_COLON && tokenarray[i+1].token != T_FINAL && Options.strict_masm_compat == FALSE ) {
struct expr opnd;
i++;
if ( EvalOperand( &i, tokenarray, Token_Count, &opnd, 0 ) == ERROR )
return( ERROR );
if ( opnd.kind != EXPR_CONST ) {
if ( opnd.sym && opnd.sym->state == SYM_UNDEFINED )
opnd.value = 1;
else {
return( EmitError( CONSTANT_EXPECTED ) );
}
}
length = opnd.value;
}
#endif
if ( tokenarray[i].token != T_FINAL ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ) ); /* v2.10: display tokpos */
}
if ( ModuleInfo.list )
LstWrite( LSTTYPE_LABEL, 0, NULL );
/* v2.08: if label is a DATA label, set total_size and total_length */
if ( (sym = CreateLabel( tokenarray[0].string_ptr, ti.mem_type, &ti, FALSE )) != NULL ) {
DebugMsg1(("LabelDirective(%s): label created, memtype=%Xh size=%u\n", sym->name, sym->mem_type, ti.size ));
/* sym->isdata must be 0, else the LABEL directive was generated within data_item()
* and fields total_size & total_length must not be modified then!
* v2.09: data_item() no longer creates LABEL directives.
*/
if ( sym->isdata == FALSE && ( sym->mem_type & MT_SPECIAL_MASK ) != MT_ADDRESS )
#if LABELARRAY
if ( length != -1 ) {
sym->total_size = ti.size * length;
sym->total_length = length;
sym->isarray = TRUE;
} else
#endif
{
sym->total_size = ti.size;
sym->total_length = 1;
}
return( NOT_ERROR );
}
return( ERROR );
}