macross/semanticMisc.c

1264 lines
38 KiB
C

/*
* Copyright (c) 1987 Fujitsu
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
semanticMisc.c -- Miscellaneous helper routines for the semantic
portions of the Macross assembler.
Chip Morningstar -- Lucasfilm Ltd.
12-November-1984
*/
#include "macrossTypes.h"
#include "macrossGlobals.h"
#include "y.tab.h"
#include "semanticMisc.h"
#include "buildStuff.h"
#include "debugPrint.h"
#include "emitStuff.h"
#include "errorStuff.h"
#include "expressionSemantics.h"
#include "fixups.h"
#include "listing.h"
#include "lookups.h"
#include "object.h"
#include "operandStuff.h"
#include "parserMisc.h"
#include <string.h>
#define expansionOff() {saveExpansion=expandMacros; expandMacros=FALSE;}
#define expansionOn() expandMacros=saveExpansion;
/*
These are miscellaneous routines called by the primary semantics routines.
*/
bool
absoluteValue(valueType *address)
{
return(address->kindOfValue == ABSOLUTE_VALUE);
}
void
addAttributeToSymbol(symbolTableEntryType *symbol, symbolAttributesType attribute)
{
symbolInContextType *context;
symbolInContextType *getBaseContext(symbolTableEntryType *identifier);
context = getBaseContext(symbol);
if (context != NULL)
context->attributes |= attribute;
}
addressType
addressValue(valueType *value)
{
if (value->kindOfValue==STRING_VALUE ||
value->kindOfValue==CONDITION_VALUE ||
value->kindOfValue==FAIL)
error(VALUE_IS_NOT_AN_ADDRESS_ERROR);
else
return(value->value);
}
valueKindType
addValueKind(valueType *leftOperand, valueType *rightOperand)
{
/* This table MUST be maintained congruently with the definition of the
enumerated type 'valueKindType'. */
static valueKindType addValueKindTable[NUM_OF_VALUE_KINDS]
[NUM_OF_VALUE_KINDS] = {
/* ABSOLUTE_VALUE , DATA_VALUE , RELOCATABLE_VALUE ,
BSS_VALUE , STRUCT_VALUE , FIELD_VALUE ,
MACRO_VALUE , OPERAND_VALUE , STRING_VALUE ,
CONDITION_VALUE, UNDEFINED_VALUE, FUNCTION_VALUE ,
BLOCK_VALUE , BUILT_IN_FUNCTI, ARRAY_VALUE ,
FAIL ,*/
/*ABSOLUTE_VALUE */ ABSOLUTE_VALUE , DATA_VALUE , RELOCATABLE_VALUE ,
BSS_VALUE , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , UNDEFINED_VALUE, FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*DATA_VALUE */ DATA_VALUE , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , UNDEFINED_VALUE, FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*RELOCATABLE_VAL*/ RELOCATABLE_VALUE, FAIL , UNDEFINED_VALUE,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , UNDEFINED_VALUE, FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*BSS_VALUE */ BSS_VALUE , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , UNDEFINED_VALUE, FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*STRUCT_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*FIELD_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*MACRO_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*OPERAND_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*STRING_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , STRING_VALUE ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*CONDITION_VALUE*/ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*UNDEFINED_VALUE*/ UNDEFINED_VALUE, UNDEFINED_VALUE, UNDEFINED_VALUE,
UNDEFINED_VALUE, FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , UNDEFINED_VALUE, FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*FUNCTION_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*BLOCK_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*BUILT_IN_FUNCT-*/ FAIL , FAIL , FAIL ,
/*-ION_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*ARRAY_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*FAIL */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
};
return(addValueKindTable[(int)leftOperand->kindOfValue]
[(int)rightOperand->kindOfValue]);
}
bool
alreadyDefined(symbolInContextType *context)
{
return((context->attributes & DEFINED_VARIABLE_ATT) != 0);
}
bool
booleanTest(expressionType *expression)
{
bool result;
valueType *expressionResult;
bool saveExpansion;
expansionOff();
expressionResult = evaluateExpression(expression, NO_FIXUP);
expansionOn();
if (expressionResult == NULL) {
return(FALSE);
} else if (expressionResult->kindOfValue != ABSOLUTE_VALUE) {
error(INVALID_BOOLEAN_VALUE_ERROR,
valueKindString(expressionResult->kindOfValue));
result = FALSE;
} else {
result = (expressionResult->value != 0);
}
qfree(expressionResult);
return(result);
}
int
countArguments(functionDefinitionType *function)
{
int result;
argumentDefinitionListType *arguments;
arguments = function->arguments;
result = 0;
while (arguments != NULL) {
result++;
arguments = arguments->nextArgument;
}
return(result);
}
int
countParameters(operandListType *parameterList)
{
int result;
result = 0;
while (parameterList != NULL) {
result++;
parameterList = parameterList->nextOperand;
}
return(result);
}
arrayType *
allocArray(int size, valueType ***contentsPtr)
{
arrayType *result;
int i;
result = typeAlloc(arrayType);
result->arraySize = size;
result->arrayContents = *contentsPtr = (valueType **) malloc(size *
sizeof(valueType *));
for (i=0; i<size; ++i)
(*contentsPtr)[i] = NULL;
return(result);
}
valueType *
createArray(expressionType *dimension, expressionListType *initializers)
{
int initCount;
valueType *arraySizeValue;
int arraySize;
valueType **arrayContents;
arrayType *result;
int i;
initCount = expressionListLength(initializers);
if ((int)dimension == -1) {
arraySize = initCount;
} else {
arraySizeValue = evaluateExpression(dimension, NO_FIXUP);
if (arraySizeValue->kindOfValue != ABSOLUTE_VALUE) {
return(newValue(FAIL, 0, EXPRESSION_OPND));
} else {
arraySize = arraySizeValue->value;
}
}
result = allocArray(arraySize, &arrayContents);
if (initCount > arraySize) {
error(TOO_MANY_VARIABLE_INITIALIZERS_ERROR);
initCount = arraySize;
}
for (i=0; i<initCount; ++i) {
*arrayContents++ = evaluateExpression(initializers->
theExpression, NO_FIXUP);
initializers = initializers->nextExpression;
}
return(newValue(ARRAY_VALUE, result, EXPRESSION_OPND));
}
bool
decrementable(valueType *value)
{
/* This table MUST be maintained congruently with the definition of the
enumerated type 'valueKindType'. */
static bool decrementableTable[NUM_OF_VALUE_KINDS] = {
/* ABSOLUTE_VALUE */ TRUE,
/* DATA_VALUE */ TRUE,
/* RELOCATABLE_VALUE */ TRUE,
/* BSS_VALUE */ TRUE,
/* STRUCT_VALUE */ FALSE,
/* FIELD_VALUE */ FALSE,
/* MACRO_VALUE */ FALSE,
/* OPERAND_VALUE */ FALSE,
/* STRING_VALUE */ FALSE,
/* CONDITION_VALUE */ FALSE,
/* UNDEFINED_VALUE */ TRUE,
/* FUNCTION_VALUE */ FALSE,
/* BLOCK_VALUE */ FALSE,
/* BUILT_IN_FUNCTION_VALUE */ FALSE,
/* ARRAY_VALUE */ FALSE,
/* FAIL */ FALSE,
};
if (value == NULL)
return(FALSE);
else
return(decrementableTable[(int)value->kindOfValue]);
}
int
expressionListLength(expressionListType *expressionList)
{
int result;
result = 0;
while (expressionList != NULL) {
result++;
expressionList = expressionList->nextExpression;
}
return(result);
}
int
fieldValue(symbolTableEntryType *symbol)
{
valueType *value;
value = evaluateIdentifier(symbol, FALSE, NO_FIXUP);
if (value->kindOfValue != FIELD_VALUE) {
error(VALUE_IS_NOT_A_FIELD_ERROR, symbName(symbol));
return(0);
} else {
return(value->value);
}
}
bool
incrementable(valueType *value)
{
/* This table MUST be maintained congruently with the definition of the
enumerated type 'valueKindType'. */
static bool incrementableTable[NUM_OF_VALUE_KINDS] = {
/* ABSOLUTE_VALUE */ TRUE,
/* DATA_VALUE */ TRUE,
/* RELOCATABLE_VALUE */ TRUE,
/* BSS_VALUE */ TRUE,
/* STRUCT_VALUE */ FALSE,
/* FIELD_VALUE */ FALSE,
/* MACRO_VALUE */ FALSE,
/* OPERAND_VALUE */ FALSE,
/* STRING_VALUE */ FALSE,
/* CONDITION_VALUE */ FALSE,
/* UNDEFINED_VALUE */ TRUE,
/* FUNCTION_VALUE */ FALSE,
/* BLOCK_VALUE */ FALSE,
/* BUILT_IN_FUNCTION_VALUE */ FALSE,
/* ARRAY_VALUE */ FALSE,
/* FAIL */ FALSE,
};
if (value == NULL)
return(FALSE);
else
return(incrementableTable[(int)value->kindOfValue]);
}
int
intValue(valueType *value)
{
if (value->kindOfValue != ABSOLUTE_VALUE) {
error(VALUE_IS_NOT_AN_INT_ERROR);
return(0);
} else {
return(value->value);
}
}
bool
isAssignable(symbolInContextType *context)
{
return( context->usage==ARGUMENT_SYMBOL ||
context->usage==VARIABLE_SYMBOL ||
context->usage==MVARIABLE_SYMBOL );
}
bool
isBuiltInFunction(symbolInContextType *context)
{
return(context!=NULL && context->usage==BUILT_IN_FUNCTION_SYMBOL);
}
bool
isDefinable(symbolInContextType *context)
{
return( context->usage==DEFINE_SYMBOL ||
context->usage==DEAD_SYMBOL ||
context->usage==UNKNOWN_SYMBOL ||
context->usage==NESTED_UNKNOWN_SYMBOL );
}
bool
isExternal(symbolTableEntryType *symbol)
{
symbolInContextType *context;
context = getBaseContext(symbol);
return (context!=NULL && (context->attributes & GLOBAL_ATT)!=0 &&
context->usage != DEAD_SYMBOL);
}
bool
isFailure(valueType *value)
{
if (value == NULL)
return(FALSE);
else
return(value->kindOfValue == FAIL);
}
bool
isFunction(symbolInContextType *context)
{
return(context!=NULL && context->usage==FUNCTION_SYMBOL);
}
bool
isLastStatementInBlock(statementType *statement)
{
statement = statement->nextStatement;
while (statement != NULL) {
if (statement->kindOfStatement != BLOCK_STATEMENT &&
statement->kindOfStatement != BYTE_STATEMENT &&
statement->kindOfStatement != CONSTRAIN_STATEMENT &&
statement->kindOfStatement != DBYTE_STATEMENT &&
statement->kindOfStatement != DO_UNTIL_STATEMENT &&
statement->kindOfStatement != DO_WHILE_STATEMENT &&
statement->kindOfStatement != GROUP_STATEMENT &&
statement->kindOfStatement != IF_STATEMENT &&
statement->kindOfStatement != INCLUDE_STATEMENT &&
statement->kindOfStatement != INSTRUCTION_STATEMENT &&
statement->kindOfStatement != LONG_STATEMENT &&
statement->kindOfStatement != STRING_STATEMENT &&
statement->kindOfStatement != STRUCT_STATEMENT &&
statement->kindOfStatement != WHILE_STATEMENT &&
statement->kindOfStatement != MIF_STATEMENT &&
statement->kindOfStatement != MWHILE_STATEMENT &&
statement->kindOfStatement != MFOR_STATEMENT &&
statement->kindOfStatement != MDO_WHILE_STATEMENT &&
statement->kindOfStatement != MDO_UNTIL_STATEMENT &&
statement->kindOfStatement != MSWITCH_STATEMENT &&
statement->kindOfStatement != WORD_STATEMENT)
statement = statement->nextStatement;
else
return(FALSE);
}
return(TRUE);
}
bool
isLogicalOp(int op)
{
return (op==EQUAL_TO || op==GREATER_THAN || op==
GREATER_THAN_OR_EQUAL_TO || op==LESS_THAN || op==
LESS_THAN_OR_EQUAL_TO || op==NOT_EQUAL_TO || op==
LOGICAL_AND || op==LOGICAL_OR || op==LOGICAL_XOR);
}
bool
isPotentialVariable(symbolInContextType *context)
{
return( context->usage == VARIABLE_SYMBOL ||
context->usage == DEAD_SYMBOL ||
context->usage == NESTED_UNKNOWN_SYMBOL );
}
bool
isUndefined(valueType *value)
{
return(value==NULL || value->kindOfValue==UNDEFINED_VALUE);
}
bool
isUsable(valueType *value)
{
return(value!=NULL && value->kindOfValue!=UNDEFINED_VALUE &&
value->kindOfValue!=FAIL);
}
bool
logicalXOR(int int1, int int2)
{
return((int1 && !int2) || (int2 && !int1));
}
valueType *
newValue(valueKindType kindOfValue, int value, operandKindType addressMode)
{
valueType *result;
result = typeAlloc(valueType);
result->kindOfValue = kindOfValue;
result->value = value;
result->addressMode = addressMode;
return(result);
}
valueKindType
opValueKind(valueType *leftOperand, valueType *rightOperand)
{
if (leftOperand->kindOfValue==ABSOLUTE_VALUE && rightOperand->
kindOfValue==ABSOLUTE_VALUE)
return(ABSOLUTE_VALUE);
else if ((leftOperand->kindOfValue==ABSOLUTE_VALUE && rightOperand->
kindOfValue==UNDEFINED_VALUE) ||
(leftOperand->kindOfValue==UNDEFINED_VALUE && rightOperand->
kindOfValue==ABSOLUTE_VALUE) ||
(leftOperand->kindOfValue==RELOCATABLE_VALUE &&rightOperand->
kindOfValue==UNDEFINED_VALUE) ||
(leftOperand->kindOfValue==UNDEFINED_VALUE && rightOperand->
kindOfValue==RELOCATABLE_VALUE) ||
(leftOperand->kindOfValue==RELOCATABLE_VALUE &&rightOperand->
kindOfValue==ABSOLUTE_VALUE) ||
(leftOperand->kindOfValue==ABSOLUTE_VALUE && rightOperand->
kindOfValue==RELOCATABLE_VALUE) ||
(leftOperand->kindOfValue==RELOCATABLE_VALUE &&rightOperand->
kindOfValue==RELOCATABLE_VALUE) ||
(leftOperand->kindOfValue==UNDEFINED_VALUE && rightOperand->
kindOfValue==UNDEFINED_VALUE))
return(UNDEFINED_VALUE);
else
return(FAIL);
}
bool
relocatableValue(valueType *address)
{
return( address->kindOfValue==DATA_VALUE ||
address->kindOfValue==RELOCATABLE_VALUE );
}
valueKindType
selectValueKind(valueType *leftOperand, valueType *rightOperand)
{
if (rightOperand->kindOfValue!=FIELD_VALUE ||
(leftOperand->kindOfValue!=ABSOLUTE_VALUE &&
leftOperand->kindOfValue!=RELOCATABLE_VALUE &&
leftOperand->kindOfValue!=DATA_VALUE))
return(FAIL);
else
return(leftOperand->kindOfValue);
}
valueKindType
subValueKind(valueType *leftOperand, valueType *rightOperand)
{
/* This table MUST be maintained congruently with the definition of the
enumerated type 'valueKindType'. */
static valueKindType subValueKindTable[NUM_OF_VALUE_KINDS]
[NUM_OF_VALUE_KINDS] = {
/* ABSOLUTE_VALUE , DATA_VALUE , RELOCATABLE_VALUE ,
BSS_VALUE , STRUCT_VALUE , FIELD_VALUE ,
MACRO_VALUE , OPERAND_VALUE , STRING_VALUE ,
CONDITION_VALUE, UNDEFINED_VALUE, FUNCTION_VALUE ,
BLOCK_VALUE , BUILT_IN_FUNCTI, ARRAY_VALUE ,
FAIL , */
/*ABSOLUTE_VALUE */ ABSOLUTE_VALUE , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*DATA_VALUE */ DATA_VALUE , ABSOLUTE_VALUE , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*RELOCATABLE_VAL*/ RELOCATABLE_VALUE, FAIL , UNDEFINED_VALUE,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*BSS_VALUE */ BSS_VALUE , FAIL , FAIL ,
BSS_VALUE , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*STRUCT_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*FIELD_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*MACRO_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*OPERAND_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*STRING_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*CONDITION_VALUE*/ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*UNDEFINED_VALUE*/ UNDEFINED_VALUE, FAIL , UNDEFINED_VALUE,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , UNDEFINED_VALUE, FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*FUNCTION_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*BLOCK_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*BUILT_IN_FUNCT-*/ FAIL , FAIL , FAIL ,
/*-ION_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*ARRAY_VALUE */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
/*FAIL */ FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL , FAIL , FAIL ,
FAIL,
};
return(subValueKindTable[(int)leftOperand->kindOfValue]
[(int)rightOperand->kindOfValue]);
}
int
swabInt(int i)
{
return(((i & 0xFF) << 8) | ((i & 0xFF00) >> 8));
}
valueType *
swabValue(valueType *value)
{
return(newValue(value->kindOfValue, swabInt(value->value), value->
addressMode));
}
valueKindType
unopValueKind(valueType *operand)
{
return(operand->kindOfValue==ABSOLUTE_VALUE || operand->kindOfValue==
UNDEFINED_VALUE || operand->kindOfValue==RELOCATABLE_VALUE ?
operand->kindOfValue : FAIL);
}
void
valueField(symbolTableEntryType *symbol, valueType *value)
{
symbolInContextType *workingContext;
symbol = effectiveSymbol(symbol, &workingContext);
expand(moreLabel("%s:", symbol->symbolName));
if (workingContext->usage == DEAD_SYMBOL)
reincarnateSymbol(workingContext, STRUCT_FIELD_SYMBOL);
if (workingContext->usage!=LABEL_SYMBOL && workingContext->usage!=
UNKNOWN_SYMBOL && workingContext->usage!=
NESTED_UNKNOWN_SYMBOL)
error(SYMBOL_ALREADY_THERE_ERROR, symbName(symbol));
else if (workingContext->value==NULL || workingContext->value->
kindOfValue==UNDEFINED_VALUE) {
workingContext->value = value;
workingContext->usage = STRUCT_FIELD_SYMBOL;
workingContext->environmentNumber = GLOBAL_ENVIRONMENT_NUMBER;
} else
error(FIELD_ALREADY_DEFINED_ERROR, symbName(symbol));
}
void
valueLabel(symbolTableEntryType *symbol, valueType *value)
{
symbolInContextType *workingContext;
symbol = effectiveSymbol(symbol, &workingContext);
expand(moreLabel("%s:", symbol->symbolName));
if (workingContext->usage == DEAD_SYMBOL)
reincarnateSymbol(workingContext, LABEL_SYMBOL);
if (workingContext->usage!=LABEL_SYMBOL && workingContext->usage!=
UNKNOWN_SYMBOL && workingContext->usage!=
NESTED_UNKNOWN_SYMBOL)
error(SYMBOL_ALREADY_THERE_ERROR, symbName(symbol));
else if (symbName(symbol)[0] == '$') {
symbol = generateLocalLabel(symbol);
workingContext = getBaseContext(symbol);
workingContext->value = value;
if (targetOffset != 0) {
workingContext->value->kindOfValue = ABSOLUTE_VALUE;
workingContext->value->value -= targetOffset;
}
workingContext->usage = LABEL_SYMBOL;
workingContext->environmentNumber = GLOBAL_ENVIRONMENT_NUMBER;
} else if (workingContext->value==NULL || workingContext->value->
kindOfValue==UNDEFINED_VALUE) {
workingContext->value = value;
if (targetOffset != 0) {
workingContext->value->value -= targetOffset;
workingContext->value->kindOfValue = ABSOLUTE_VALUE;
}
workingContext->usage = LABEL_SYMBOL;
workingContext->environmentNumber = GLOBAL_ENVIRONMENT_NUMBER;
if (workingContext->attributes & TENTATIVE_GLOBAL_ATT)
workingContext->attributes |= GLOBAL_ATT;
} else
error(LABEL_ALREADY_DEFINED_ERROR, symbName(symbol));
symbol->referenceCount++;
}
/*
These routines deal with fixups and references.
*/
void
createFixup(expressionType *expression, addressType location, fixupKindType kindOfFixup, codeBufferKindType codeMode, int whichFixup)
{
fixupListType *newFixup;
if (debug || emitPrint)
printCreateFixup(expression, location, kindOfFixup);
newFixup = typeAlloc(fixupListType);
newFixup->locationToFixup = location;
newFixup->targetOffset = targetOffset;
newFixup->codeMode = codeMode;
newFixup->kindOfFixup = kindOfFixup;
newFixup->fileName = currentFileName;
newFixup->lineNumber = currentLineNumber;
expand(flushExpressionString());
newFixupAddressMode = EXPRESSION_OPND;
newFixup->theFixupExpression = generateFixupExpression(expression);
if (newFixupAddressMode != EXPRESSION_OPND)
fixupAddressMode[whichFixup] = newFixupAddressMode;
expand(finishOperand ? expandOperand(fixupAddressMode[whichFixup],
operandBuffer[whichFixup]) : /*expandExpression(NULL)*/0);
finishOperand = FALSE;
if (structNestingDepth == 0) {
newFixup->nextFixup = fixupList;
fixupList = newFixup;
} else {
newFixup->nextFixup = newStruct->structFixups;
newStruct->structFixups = newFixup;
}
}
void
finishUp(void)
{
if (listingOn)
terminateListingFiles();
performFixups(fixupList);
if (haveUserStartAddress && fixupStartAddress)
performStartAddressFixup();
outputObjectFile();
if (listingOn)
outputListing();
}
/*
bool
isReferenceToRemember(reference)
expressionReferenceListType *reference;
{
symbolInContextType *context;
symbolInContextType *getWorkingContext();
context = getWorkingContext(reference->expressionReferenced);
if (context != NULL)
return ((context->usage == LABEL_SYMBOL && context->value->
kindOfValue != ABSOLUTE_VALUE) || context->usage ==
EXTERNAL_SYMBOL || context->usage == UNKNOWN_SYMBOL
|| context->usage == NESTED_UNKNOWN_SYMBOL);
else
return(FALSE);
}
*/
void
noteAnonymousReference(void)
{
expressionReferenceListType *newReference;
if (!produceLinkableObject || targetOffset != 0)
return;
newReference = typeAlloc(expressionReferenceListType);
newReference->nextReference = expressionReferenceList[(int)
currentCodeMode];
expressionReferenceList[(int)currentCodeMode] = newReference;
newReference->expressionReferenced = NULL;
newReference->relocation.referenceAddress = currentLocationCounter.
value;
newReference->relocation.referenceExpression = -1;
newReference->relocation.referenceRelative = FALSE;
newReference->relocation.referenceKind = REF_WORD;
newReference->relocation.referenceExternal = FALSE;
newReference->relocation.referenceMode = (int)currentCodeMode;
}
void
noteReference(expressionType *expression, fixupKindType kindOfFixup, addressType location, codeBufferKindType codeMode)
{
expressionReferenceListType *newReference;
if (!produceLinkableObject)
return;
newReference = typeAlloc(expressionReferenceListType);
numberOfReferencesInList[(int)codeMode]++;
newReference->nextReference = expressionReferenceList[(int)codeMode];
expressionReferenceList[(int)codeMode] = newReference;
newReference->expressionReferenced = expression;
newReference->relocation.referenceAddress = location;
newReference->relocation.referenceMode = (int)codeMode;
newReference->relocation.referenceExpression = 0;
switch (kindOfFixup) {
case BYTE_FIXUP:
newReference->relocation.referenceRelative = FALSE;
newReference->relocation.referenceKind = REF_BYTE;
break;
case WORD_FIXUP:
newReference->relocation.referenceRelative = FALSE;
newReference->relocation.referenceKind = REF_WORD;
break;
case LONG_FIXUP:
newReference->relocation.referenceRelative = FALSE;
newReference->relocation.referenceKind = REF_LONG;
break;
case DBYTE_FIXUP:
newReference->relocation.referenceRelative = FALSE;
newReference->relocation.referenceKind = REF_DBYTE;
break;
case BYTE_RELATIVE_FIXUP:
newReference->relocation.referenceRelative = TRUE;
newReference->relocation.referenceKind = REF_BYTE;
break;
case WORD_RELATIVE_FIXUP:
newReference->relocation.referenceRelative = TRUE;
newReference->relocation.referenceKind = REF_WORD;
break;
default:
botch("bad fixup kind in noteReference %d\n",
kindOfFixup);
}
newReference->relocation.referenceExternal = FALSE; /* irrelevent? */
}
void
performFixups(fixupListType *fixups)
{
valueType *valueToPoke;
performingFixups = TRUE;
statementEvaluationDepth = 2; /* don't throw away functions! */
while (fixups != NULL) {
if (fixups->theFixupExpression == NULL)
break;
currentFileName = fixups->fileName;
currentLineNumber = fixups->lineNumber;
currentCodeMode = fixups->codeMode;
targetOffset = fixups->targetOffset;
valueToPoke = evaluateExpression(fixups->theFixupExpression,
NO_FIXUP);
if (isUndefined(valueToPoke)) {
noteReference(fixups->theFixupExpression, fixups->
kindOfFixup, fixups->locationToFixup, fixups->
codeMode);
} else {
switch (fixups->kindOfFixup) {
case BYTE_FIXUP:
pokeByteValue(fixups->locationToFixup,
valueToPoke);
break;
case WORD_FIXUP:
pokeWordValue(fixups->locationToFixup,
valueToPoke);
break;
case LONG_FIXUP:
pokeLongValue(fixups->locationToFixup,
valueToPoke);
break;
case DBYTE_FIXUP:
pokeWordValue(fixups->locationToFixup,
swabValue(valueToPoke));
break;
case BYTE_RELATIVE_FIXUP:
pokeRelativeByteValue(fixups->locationToFixup,
valueToPoke);
break;
case WORD_RELATIVE_FIXUP:
pokeRelativeWordValue(fixups->locationToFixup,
valueToPoke);
break;
default:
botch("bad fixup at end\n");
}
}
fixups = fixups->nextFixup;
}
}
void
performStartAddressFixup(void)
{
expressionType *startAddressExpression;
startAddressExpression = (expressionType *)startAddress;
startAddress = evaluateExpression(startAddressExpression,NO_FIXUP_OK);
if (startAddress->kindOfValue == UNDEFINED_VALUE &&
produceLinkableObject) {
startAddress = (valueType *)generateFixupExpression(
startAddressExpression);
} else if (startAddress->kindOfValue != ABSOLUTE_VALUE &&
startAddress->kindOfValue != RELOCATABLE_VALUE) {
error(BAD_START_ADDRESS_ERROR);
haveUserStartAddress = FALSE;
} else {
fixupStartAddress = FALSE;
}
}
void
putFixupsHere(fixupKindType kindOfFixupsToPut, int whichFixup)
{
int location;
location = structNestingDepth==0 ? currentLocationCounter.value :
currentFieldOffset;
if (pendingFixup[whichFixup] != NULL) {
createFixup(pendingFixup[whichFixup], location,
kindOfFixupsToPut, currentCodeMode, whichFixup);
}
}
/*
void
putReferencesHere(kindOfReferencesToPut, whichReference)
fixupKindType kindOfReferencesToPut;
{
expressionReferenceListType *worthyReference;
int currentLocation;
int currentMode;
if (!produceLinkableObject)
return;
currentLocation = structNestingDepth==0 ?
currentLocationCounter.value : currentFieldOffset;
currentMode = structNestingDepth==0 ? (int)currentCodeMode :
STRUCT_BUFFER;
while (referencesToNote[whichReference] != NULL) {
if (isReferenceToRemember(referencesToNote[whichReference])) {
switch (kindOfReferencesToPut) {
case BYTE_FIXUP:
referencesToNote[whichReference]->
relocation.referenceKind = REF_BYTE;
break;
case WORD_FIXUP:
referencesToNote[whichReference]->
relocation.referenceKind = REF_WORD;
break;
case LONG_FIXUP:
referencesToNote[whichReference]->
relocation.referenceKind = REF_LONG;
break;
case BYTE_RELATIVE_FIXUP:
referencesToNote[whichReference]->
relocation.referenceKind = REF_BYTE;
referencesToNote[whichReference]->
relocation.referenceRelative = TRUE;
break;
case WORD_RELATIVE_FIXUP:
referencesToNote[whichReference]->
relocation.referenceKind = REF_WORD;
referencesToNote[whichReference]->
relocation.referenceRelative = TRUE;
break;
case DBYTE_FIXUP:
referencesToNote[whichReference]->
relocation.referenceKind = REF_DBYTE;
break;
default:
botch("bad fixup kind in put references %d\n",
kindOfReferencesToPut);
break;
}
numberOfReferencesInList[currentMode]++;
referencesToNote[whichReference]->
relocation.referenceAddress = currentLocation;
referencesToNote[whichReference]->
relocation.referenceMode = currentMode;
worthyReference = referencesToNote[whichReference];
referencesToNote[whichReference] =
referencesToNote[whichReference]->
nextReference;
worthyReference->nextReference =
expressionReferenceList[currentMode];
expressionReferenceList[currentMode]= worthyReference;
} else {
worthyReference = referencesToNote[whichReference];
referencesToNote[whichReference] =
referencesToNote[whichReference]->
nextReference;
qsfree(worthyReference);
}
}
}
*/
/*
These routines handle contexts and dynamic symbol creation.
*/
void
addNewLocalVariable(symbolTableEntryType *symbol)
{
identifierListType *newLocalVariable;
newLocalVariable = typeAlloc(identifierListType);
newLocalVariable->theSymbol = symbol;
newLocalVariable->nextIdentifier = currentLocalVariableList;
currentLocalVariableList = newLocalVariable;
}
symbolTableEntryType *
effectiveSymbol(symbolTableEntryType *symbol, symbolInContextType **assignmentTargetContext)
{
symbolInContextType *context;
operandType *operand;
expressionType *expression;
environmentType *saveEnvironment;
context = getWorkingContext(symbol);
saveEnvironment = currentEnvironment;
while (context != NULL && context->usage == ARGUMENT_SYMBOL &&
context->value->kindOfValue == OPERAND_VALUE) {
operand = (operandType *)context->value->value;
if (operand->kindOfOperand == EXPRESSION_OPND) {
expression = operand->theOperand.expressionUnion;
if (expression->kindOfTerm == IDENTIFIER_EXPR) {
currentEnvironment = currentEnvironment->
previousEnvironment;
context =getWorkingContext(symbol=expression->
expressionTerm.identifierUnion);
} else {
break;
}
} else {
break;
}
}
currentEnvironment = saveEnvironment;
if (assignmentTargetContext != NULL)
*assignmentTargetContext = context;
return(symbol);
}
symbolTableEntryType *
generateLocalLabel(symbolTableEntryType *symbol)
{
return(lookupOrEnterSymbol(localLabelString(symbol), LABEL_SYMBOL));
}
symbolInContextType *
getBaseContext(symbolTableEntryType *identifier)
{
symbolInContextType *result;
result = identifier->context;
while (result != NULL && result->environmentNumber !=
GLOBAL_ENVIRONMENT_NUMBER)
result = result->pushedContexts;
return(result);
}
symbolInContextType *
getWorkingContext(symbolTableEntryType *identifier)
{
symbolInContextType *result;
result = identifier->context;
while (result != NULL && result->environmentNumber !=
GLOBAL_ENVIRONMENT_NUMBER && result->
environmentNumber != currentEnvironment->
environmentNumber)
result = result->pushedContexts;
return(result);
}
stringType *
localLabelString(symbolTableEntryType *symbol)
{
#define TEMP_SYMBOL_SIZE_LIMIT 200
char nameUnderConstruction[TEMP_SYMBOL_SIZE_LIMIT];
sprintf(nameUnderConstruction, "_%d_", localLabelTagValue(symbol));
strncat(nameUnderConstruction, &(symbName(symbol)[1]),
TEMP_SYMBOL_SIZE_LIMIT);
return(saveString(nameUnderConstruction));
}
int
localLabelTagValue(symbolTableEntryType *symbol)
{
symbolInContextType *context;
context = getWorkingContext(symbol);
if (context == NULL)
botch("local label doesn't have symbol context\n");
if(context->environmentNumber!=currentEnvironment->environmentNumber){
pushBinding(symbol, newValue(ABSOLUTE_VALUE,
currentLabelTagNumber, EXPRESSION_OPND),
LABEL_SYMBOL);
addNewLocalVariable(symbol);
return(currentLabelTagNumber);
}
return(context->value->value);
}
void
addBreak(codeBreakKindType kind, int data)
{
codeBreakType *newBreak;
newBreak = buildCodeBreak(kind, currentLocationCounter.value, data);
if (codeBreakList == NULL) {
codeBreakList = lastCodeBreak = newBreak;
} else {
lastCodeBreak->nextBreak = newBreak;
lastCodeBreak = newBreak;
}
}
void
reserveAbsolute(addressType startAddress, int blockSize)
{
if (reservationList != NULL && reservationList->startAddress +
reservationList->blockSize == startAddress)
reservationList->blockSize += blockSize;
else
reservationList = buildReservation(startAddress, blockSize,
reservationList);
}
bool
listableStatement(statementKindType kind)
{
return( kind == ALIGN_STATEMENT || kind == BLOCK_STATEMENT ||
kind == BYTE_STATEMENT || kind == CONSTRAIN_STATEMENT ||
kind == DBYTE_STATEMENT || kind == DO_UNTIL_STATEMENT ||
kind == DO_WHILE_STATEMENT || kind == IF_STATEMENT ||
/*kind == INSTRUCTION_STATEMENT ||*/ kind == ORG_STATEMENT ||
kind == REL_STATEMENT || kind == START_STATEMENT ||
kind == STRUCT_STATEMENT || kind == LONG_STATEMENT ||
kind == STRING_STATEMENT || kind == WHILE_STATEMENT ||
kind == WORD_STATEMENT || kind == DEFINE_STATEMENT ||
kind == EXTERN_STATEMENT || kind == INCLUDE_STATEMENT ||
kind == UNDEFINE_STATEMENT || kind == VARIABLE_STATEMENT ||
kind == TARGET_STATEMENT);
}