mirror of
https://github.com/Museum-of-Art-and-Digital-Entertainment/macross.git
synced 2024-11-30 04:55:00 +00:00
1437 lines
40 KiB
C
1437 lines
40 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.
|
|
*/
|
|
/*
|
|
statementSemantics.c -- Routines to eat up a parse tree and spit out
|
|
code.
|
|
|
|
Chip Morningstar -- Lucasfilm Ltd.
|
|
|
|
12-November-1984
|
|
*/
|
|
|
|
#include "macrossTypes.h"
|
|
#include "macrossGlobals.h"
|
|
#include "actions.h"
|
|
#include "debugPrint.h"
|
|
#include "emitBranch.h"
|
|
#include "emitStuff.h"
|
|
#include "errorStuff.h"
|
|
#include "expressionSemantics.h"
|
|
#include "fixups.h"
|
|
#include "garbage.h"
|
|
#include "lexer.h"
|
|
#include "listing.h"
|
|
#include "lookups.h"
|
|
#include "operandStuff.h"
|
|
#include "parserMisc.h"
|
|
#include "semanticMisc.h"
|
|
#include "statementSemantics.h"
|
|
#include "structSemantics.h"
|
|
#include "tokenStrings.h"
|
|
|
|
operandType *dbOperand; /* safe temps for dbx hacking */
|
|
expressionType *dbExpression;
|
|
symbolTableEntryType *dbSymbol;
|
|
|
|
bool newIncludeFile = FALSE;
|
|
static bool insideConstraintBlock = FALSE;
|
|
bool nullStatementFlag = FALSE;
|
|
|
|
#define nullAssemble(thing) if (thing==NULL) return;
|
|
#define nullAssembleNULL(thing) if (thing==NULL) return NULL;
|
|
#define sideEffectBomb() if (beneathFunction) {\
|
|
error(SIDE_EFFECT_ERROR, currentFunctionName);\
|
|
break; }
|
|
|
|
#define expansionOff() {saveExpansion=expandMacros; expandMacros=FALSE;}
|
|
#define expansionOn() expandMacros=saveExpansion;
|
|
|
|
void
|
|
assembleBlock(blockType *block)
|
|
{
|
|
nullAssemble(block);
|
|
assembleStatement(block, FALSE, NULL);
|
|
}
|
|
|
|
simpleFixupListType *
|
|
assembleBlockInsideIf(blockType *block, simpleFixupListType *ongoingFixupList)
|
|
{
|
|
nullAssembleNULL(block);
|
|
return(assembleStatement(block, TRUE, ongoingFixupList));
|
|
}
|
|
|
|
bool
|
|
operandCheck(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<numberOfOperands; i++) {
|
|
if ((operandClassTable[(int)operandKindField(
|
|
evaluatedOperands[i]->addressMode)] & opcode->
|
|
permissibleOperandModes) == 0) {
|
|
error(ILLEGAL_OPERAND_TYPE_ERROR, opcode->mnemonic);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
void
|
|
assembleMachineInstruction(opcodeTableEntryType *opcode, operandListType *operands)
|
|
{
|
|
int i;
|
|
int op;
|
|
valueType *evaluatedOperands[MAX_NUMBER_OF_OPERANDS];
|
|
valueType *value;
|
|
|
|
nullAssemble(opcode);
|
|
expand(moreText("%s\t", opcode->mnemonic));
|
|
for (op=1; operands!=NULL && op<=opcode->maxNumberOfOperands;
|
|
op++, operands=operands->nextOperand) {
|
|
newFixupAddressMode = EXPRESSION_OPND;
|
|
evaluatedOperands[op-1] = value = evaluateOperand(operands);
|
|
fixupAddressMode[op-1] = newFixupAddressMode;
|
|
currentOperandNumber++;
|
|
expand(isUndefined(value) ? (finishOperand = TRUE) :
|
|
expandOperand(value->addressMode,
|
|
operandBuffer[op-1]));
|
|
if (value==NULL || value->kindOfValue == FAIL){
|
|
error(BAD_INSTRUCTION_OPERAND_ERROR, opcode->
|
|
mnemonic);
|
|
if (freeFlag)
|
|
for (i=1; i<op; i++)
|
|
free(evaluatedOperands[i-1]);
|
|
currentOperandNumber = 0;
|
|
return;
|
|
}
|
|
}
|
|
currentOperandNumber = 0;
|
|
op--;
|
|
if (operands != NULL) {
|
|
error(TOO_MANY_INSTRUCTION_OPERANDS_ERROR, opcode->mnemonic,
|
|
opcode->maxNumberOfOperands);
|
|
} else if (op < opcode->minNumberOfOperands) {
|
|
error(TOO_FEW_INSTRUCTION_OPERANDS_ERROR, opcode->mnemonic,
|
|
opcode->minNumberOfOperands);
|
|
} else if (operandCheck(opcode, op, evaluatedOperands)) {
|
|
(*instructionActionTable[(int)opcode->addressClass])(opcode,
|
|
op, evaluatedOperands);
|
|
}
|
|
expand((expandOperands(op), endLine()));
|
|
if (freeFlag)
|
|
for (i=0; i<op; i++)
|
|
free(evaluatedOperands[i]);
|
|
}
|
|
|
|
void
|
|
assembleMacro(macroTableEntryType *macroInstruction, operandListType *operands)
|
|
{
|
|
int numberBound;
|
|
identifierListType *savedLocalVariableList;
|
|
int savedLabelTagNumber;
|
|
bool savedErrorFlag;
|
|
bool saveListingOn;
|
|
environmentType newEnvironment;
|
|
|
|
nullAssemble(macroInstruction);
|
|
if (macroInstruction->body == NULL) {
|
|
error(UNDEFINED_MACRO_ERROR, macroInstruction->macroName);
|
|
return;
|
|
}
|
|
pushEnvironment(newEnvironment);
|
|
savedLocalVariableList = currentLocalVariableList;
|
|
currentLocalVariableList = NULL;
|
|
savedLabelTagNumber = currentLabelTagNumber;
|
|
currentLabelTagNumber = nextLabelTagNumber++;
|
|
savedErrorFlag = errorFlag;
|
|
errorFlag = FALSE;
|
|
saveListingOn = listingOn;
|
|
if ((numberBound = bindMacroArguments(macroInstruction->arguments,
|
|
operands, macroInstruction->macroName)) > 0) {
|
|
macroCallDepth++;
|
|
listingOn = amExpanding();
|
|
assembleBlock(macroInstruction->body);
|
|
macroCallDepth--;
|
|
} else
|
|
numberBound = -numberBound;
|
|
if (numberBound > 1)
|
|
unbindArguments(macroInstruction->arguments, numberBound-1);
|
|
unbindLocalVariables(currentLocalVariableList);
|
|
if (errorFlag)
|
|
error(ERROR_INSIDE_MACRO_ERROR, macroInstruction->macroName);
|
|
else
|
|
errorFlag = savedErrorFlag;
|
|
currentLabelTagNumber = savedLabelTagNumber;
|
|
currentLocalVariableList = savedLocalVariableList;
|
|
listingOn = saveListingOn;
|
|
popEnvironment();
|
|
}
|
|
|
|
void
|
|
assembleAlignStatement(alignStatementBodyType *alignStatement)
|
|
{
|
|
int alignment;
|
|
bool saveExpansion;
|
|
|
|
nullAssemble(alignStatement);
|
|
expansionOff();
|
|
alignment = intValue(evaluateExpression(alignStatement, NO_FIXUP));
|
|
expansionOn();
|
|
expand((moreText("align\t0x%x", alignment), endLine()));
|
|
if (alignment > 0)
|
|
if (currentCodeMode == ABSOLUTE_BUFFER) {
|
|
if (structNestingDepth == 0)
|
|
currentLocationCounter.value = alignment *
|
|
((currentLocationCounter.value +
|
|
alignment - 1) / alignment);
|
|
else
|
|
currentFieldOffset = alignment *
|
|
((currentFieldOffset + alignment -
|
|
1) / alignment);
|
|
} else {
|
|
if (insideConstraintBlock)
|
|
error(ALIGN_INSIDE_CONSTRAIN_ERROR);
|
|
else
|
|
addBreak(ALIGN_BREAK, alignment);
|
|
}
|
|
else
|
|
error(IMPROPER_ALIGNMENT_VALUE_ERROR);
|
|
}
|
|
|
|
void
|
|
assembleAssertStatement(assertStatementBodyType *assertStatement)
|
|
{
|
|
valueType *test;
|
|
valueType *message;
|
|
bool saveExpansion;
|
|
|
|
expansionOff();
|
|
test = evaluateExpression(assertStatement->condition, NO_FIXUP);
|
|
expansionOn();
|
|
if (test == NULL || test->kindOfValue != ABSOLUTE_VALUE) {
|
|
error(INVALID_ASSERT_CONDITION_ERROR);
|
|
} else if (!test->value) {
|
|
if (assertStatement->message == NULL)
|
|
error(ASSERT_ERROR);
|
|
else {
|
|
expansionOff();
|
|
message = evaluateExpression(assertStatement->message,
|
|
NO_FIXUP);
|
|
expansionOn();
|
|
if (message == NULL || message->kindOfValue !=
|
|
STRING_VALUE)
|
|
error(INVALID_ASSERT_MESSAGE_ERROR);
|
|
else
|
|
error(ASSERT_WITH_MESSAGE_ERROR, message->
|
|
value);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleBlockStatement(blockStatementBodyType *blockStatement)
|
|
{
|
|
valueType *blockIncrement;
|
|
int blockSize;
|
|
|
|
blockSize = 0;
|
|
nullAssemble(blockStatement);
|
|
expand(moreText("block\t"));
|
|
while (blockStatement != NULL) {
|
|
blockIncrement = evaluateExpression(blockStatement->
|
|
theExpression, NO_FIXUP);
|
|
blockSize += intValue(blockIncrement);
|
|
blockStatement = blockStatement->nextExpression;
|
|
expand((expandExpression(NULL, NULL), blockStatement!=NULL ?
|
|
moreText(", ") : 0));
|
|
qfree(blockIncrement);
|
|
}
|
|
expand(endLine());
|
|
if (blockSize >= 0) {
|
|
if (structNestingDepth != 0) {
|
|
while (blockSize-- > 0)
|
|
emitByte(0);
|
|
} else if (currentCodeMode == RELOCATABLE_BUFFER) {
|
|
while (blockSize-- > 0)
|
|
emitByte(0);
|
|
} else {
|
|
if (produceLinkableObject)
|
|
reserveAbsolute(currentLocationCounter.value,
|
|
blockSize);
|
|
currentLocationCounter.value += blockSize;
|
|
}
|
|
} else
|
|
error(NEGATIVE_BLOCK_SIZE_ERROR);
|
|
}
|
|
|
|
void
|
|
assembleByteStatement(byteStatementBodyType *byteStatement)
|
|
{
|
|
valueType *byteValue;
|
|
|
|
nullAssemble(byteStatement);
|
|
expand(moreText("byte\t"));
|
|
while (byteStatement != NULL) {
|
|
byteValue = evaluateExpression(byteStatement->theExpression,
|
|
BYTE_FIXUP);
|
|
if (byteValue->kindOfValue == STRING_VALUE) {
|
|
emitString(byteValue->value);
|
|
} else {
|
|
putFixupsHere(BYTE_FIXUP, 0);
|
|
emitByteValue(byteValue);
|
|
}
|
|
qfree(byteValue);
|
|
byteStatement = byteStatement->nextExpression;
|
|
expand((expandExpression(NULL, NULL), byteStatement != NULL ?
|
|
moreText(", ") : 0));
|
|
}
|
|
expand(endLine());
|
|
}
|
|
|
|
void
|
|
assembleConstrainStatement(constrainStatementBodyType *constrainStatement)
|
|
{
|
|
valueType *constraintValue;
|
|
int constraint;
|
|
addressType startAddress;
|
|
addressType endAddress;
|
|
bool saveExpansion;
|
|
|
|
expansionOff();
|
|
constraintValue = evaluateExpression(constrainStatement->constraint,
|
|
NO_FIXUP);
|
|
expansionOn();
|
|
if (constraintValue == NULL || constraintValue->kindOfValue !=
|
|
ABSOLUTE_VALUE) {
|
|
error(INVALID_CONSTRAINT_VALUE_ERROR);
|
|
return;
|
|
}
|
|
constraint = constraintValue->value;
|
|
expand((moreText("constrain (0x%x) {", constraint), endLine(),
|
|
tabCount++));
|
|
if (currentCodeMode == ABSOLUTE_BUFFER) {
|
|
startAddress = currentLocationCounter.value;
|
|
assembleBlock(constrainStatement->constrainedBlock);
|
|
endAddress = currentLocationCounter.value;
|
|
if ((startAddress / constraint) != (endAddress / constraint))
|
|
error(CONSTRAINT_ERROR, constraint);
|
|
} else {
|
|
if (insideConstraintBlock) {
|
|
error(CONSTRAIN_INSIDE_CONSTRAIN_ERROR);
|
|
assembleBlock(constrainStatement->constrainedBlock);
|
|
} else {
|
|
insideConstraintBlock = TRUE;
|
|
addBreak(CONSTRAIN_BREAK, constraint);
|
|
assembleBlock(constrainStatement->constrainedBlock);
|
|
addBreak(END_CONSTRAIN_BREAK, 0);
|
|
insideConstraintBlock = FALSE;
|
|
}
|
|
}
|
|
expand((tabCount--, startLineMarked(), tabIndent(), moreText("}"),
|
|
endLine()));
|
|
}
|
|
|
|
void
|
|
assembleDbyteStatement(dbyteStatementBodyType *dbyteStatement)
|
|
{
|
|
valueType *wordValue;
|
|
|
|
nullAssemble(dbyteStatement);
|
|
expand(moreText("dbyte\t"));
|
|
while (dbyteStatement != NULL) {
|
|
wordValue = swabValue(evaluateExpression(dbyteStatement->
|
|
theExpression, DBYTE_FIXUP));
|
|
dbyteStatement = dbyteStatement->nextExpression;
|
|
expand((expandExpression(NULL, NULL), dbyteStatement != NULL ?
|
|
moreText(", ") : 0));
|
|
putFixupsHere(DBYTE_FIXUP, 0);
|
|
emitWordValue(wordValue);
|
|
qfree(wordValue);
|
|
}
|
|
expand(endLine());
|
|
}
|
|
|
|
void
|
|
assembleDefineStatement(defineStatementBodyType *defineStatement)
|
|
{
|
|
symbolTableEntryType *symbolToDefine;
|
|
symbolInContextType *contextToDefine;
|
|
bool saveExpansion;
|
|
|
|
nullAssemble(defineStatement);
|
|
symbolToDefine = effectiveSymbol(defineStatement->theSymbol,
|
|
&contextToDefine);
|
|
if (isDefinable(contextToDefine)) {
|
|
expand(moreText("define %s = ", symbName(symbolToDefine)));
|
|
if (contextToDefine->usage == DEAD_SYMBOL) {
|
|
reincarnateSymbol(contextToDefine, DEFINE_SYMBOL);
|
|
} else if (contextToDefine->usage == NESTED_UNKNOWN_SYMBOL) {
|
|
contextToDefine->usage = DEFINE_SYMBOL;
|
|
}
|
|
if (alreadyDefined(contextToDefine))
|
|
error(REDEFINITION_OF_SYMBOL_ERROR, symbName(
|
|
symbolToDefine));
|
|
else {
|
|
if (defineStatement->theValue != NULL) {
|
|
contextToDefine->value =
|
|
evaluateDefineExpression(
|
|
defineStatement->theValue);
|
|
contextToDefine->usage = DEFINE_SYMBOL;
|
|
expand(expandExpression(NULL, NULL));
|
|
} else
|
|
contextToDefine->value = newValue(FAIL, 0,
|
|
EXPRESSION_OPND);
|
|
contextToDefine->environmentNumber =
|
|
GLOBAL_ENVIRONMENT_NUMBER;
|
|
contextToDefine->attributes |= DEFINED_VARIABLE_ATT;
|
|
}
|
|
expand(endLine());
|
|
} else {
|
|
error(SYMBOL_ALREADY_THERE_ERROR, symbName(symbolToDefine));
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleDoUntilStatement(doUntilStatementBodyType *doUntilStatement)
|
|
{
|
|
valueType topOfLoop;
|
|
|
|
nullAssemble(doUntilStatement);
|
|
topOfLoop = currentLocationCounter;
|
|
if (doUntilStatement->doUntilCondition == NEVER_COND)
|
|
topOfLoop.value -= targetOffset;
|
|
expand((moreText("do {"), endLine(), tabCount++));
|
|
assembleBlock(doUntilStatement->doUntilLoop);
|
|
expand((tabCount--, startLineMarked(), tabIndent(),
|
|
moreText("} until %s", conditionString(doUntilStatement->
|
|
doUntilCondition)), endLine()));
|
|
if (doUntilStatement->doUntilCondition == ALWAYS_COND) {
|
|
return;
|
|
} else if (doUntilStatement->doUntilCondition != NEVER_COND) {
|
|
emitRelativeBranch(invertConditionCode(doUntilStatement->
|
|
doUntilCondition), &topOfLoop, NULL);
|
|
} else {
|
|
emitJump(&topOfLoop, NULL);
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleDoWhileStatement(doWhileStatementBodyType *doWhileStatement)
|
|
{
|
|
valueType topOfLoop;
|
|
|
|
nullAssemble(doWhileStatement);
|
|
topOfLoop = currentLocationCounter;
|
|
if (doWhileStatement->doWhileCondition == ALWAYS_COND)
|
|
topOfLoop.value -= targetOffset;
|
|
expand((moreText("do {"), endLine(), tabCount++));
|
|
assembleBlock(doWhileStatement->doWhileLoop);
|
|
expand((tabCount--, startLineMarked(), tabIndent(),
|
|
moreText("} while %s", conditionString(doWhileStatement->
|
|
doWhileCondition)), endLine()));
|
|
if (doWhileStatement->doWhileCondition == NEVER_COND) {
|
|
return;
|
|
} else if (doWhileStatement->doWhileCondition != ALWAYS_COND) {
|
|
emitRelativeBranch(doWhileStatement->doWhileCondition,
|
|
&topOfLoop, NULL);
|
|
} else {
|
|
emitJump(&topOfLoop, NULL);
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleExternStatement(externStatementBodyType *externStatement)
|
|
{
|
|
symbolInContextType *context;
|
|
symbolTableEntryType *theSymbol;
|
|
|
|
expand(moreText("extern\t"));
|
|
while (externStatement != NULL) {
|
|
theSymbol = effectiveSymbol(externStatement->theSymbol,
|
|
&context);
|
|
expand(moreText("%s", symbName(theSymbol)));
|
|
if (context != NULL) {
|
|
if (context->usage == LABEL_SYMBOL || context->usage
|
|
== EXTERNAL_SYMBOL || context->usage
|
|
== UNKNOWN_SYMBOL || context->usage
|
|
== NESTED_UNKNOWN_SYMBOL) {
|
|
context->attributes |= GLOBAL_ATT;
|
|
} else {
|
|
error(BAD_KIND_OF_SYMBOL_TO_MAKE_EXTERNAL_ERROR,
|
|
usageString(context->usage));
|
|
}
|
|
}
|
|
externStatement = externStatement->nextIdentifier;
|
|
expand(externStatement != NULL ? moreText(", ") : 0);
|
|
}
|
|
expand(endLine());
|
|
}
|
|
|
|
void
|
|
assembleFreturnStatement(freturnStatementBodyType *freturnStatement)
|
|
{
|
|
freturnExit = TRUE;
|
|
resultOfLastFunctionCall = evaluateExpression(freturnStatement,
|
|
NO_FIXUP_OK);
|
|
}
|
|
|
|
void
|
|
assembleFunctionStatement(functionStatementBodyType *functionStatement)
|
|
{
|
|
symbolTableEntryType *newFunctionSymbol;
|
|
functionDefinitionType *newFunction;
|
|
symbolInContextType *context;
|
|
|
|
nullAssemble(functionStatement);
|
|
if (currentEnvironment != &globalEnvironment) {
|
|
error(FUNCTION_DEFINITION_INSIDE_FUNCTION_ERROR);
|
|
return;
|
|
}
|
|
newFunctionSymbol = lookupOrEnterSymbol(functionStatement->
|
|
functionName, FUNCTION_SYMBOL);
|
|
context = getBaseContext(newFunctionSymbol);
|
|
if (context->usage != FUNCTION_SYMBOL) {
|
|
if (context->usage == UNKNOWN_FUNCTION_SYMBOL) {
|
|
context->usage = FUNCTION_SYMBOL;
|
|
} else {
|
|
error(SYMBOL_ALREADY_THERE_ERROR, symbName(
|
|
newFunctionSymbol));
|
|
return;
|
|
}
|
|
} else if (isDefined(context->value)) {
|
|
error(FUNCTION_ALREADY_EXISTS_ERROR, symbName(
|
|
newFunctionSymbol));
|
|
return;
|
|
}
|
|
newFunction = typeAlloc(functionDefinitionType);
|
|
newFunction->functionName = newFunctionSymbol;
|
|
newFunction->arguments = functionStatement->theArguments;
|
|
newFunction->body = functionStatement->theBlock;
|
|
newFunction->ordinal = -1;
|
|
newFunction->nextExternalFunction = NULL;
|
|
context->value = newValue(FUNCTION_VALUE, newFunction,
|
|
EXPRESSION_OPND);
|
|
context->environmentNumber = GLOBAL_ENVIRONMENT_NUMBER;
|
|
}
|
|
|
|
void
|
|
assembleGroupStatement(blockType *groupStatement)
|
|
{
|
|
expand((startLineMarked(), tabIndent(), moreText("{"), endLine(),
|
|
tabCount++));
|
|
assembleBlock(groupStatement);
|
|
expand((tabCount--, startLineMarked(), tabIndent(), moreText("}"),
|
|
endLine()));
|
|
}
|
|
|
|
simpleFixupListType *
|
|
assembleIfStatement(ifStatementBodyType *ifStatement, bool terminalIf, simpleFixupListType *ongoingFixupList)
|
|
{
|
|
valueType fixupLocation1[COMPOUND_BRANCH_MAX];
|
|
simpleFixupListType *fixupLocation2;
|
|
|
|
if (backwardsCompatibleIfFlag) {
|
|
assembleIfStatementOldStyle(ifStatement);
|
|
return(NULL);
|
|
}
|
|
|
|
nullAssembleNULL(ifStatement);
|
|
fixupLocation2 = ongoingFixupList;
|
|
if (ifStatement->ifCondition != ALWAYS_COND && ifStatement->
|
|
ifCondition != NEVER_COND) {
|
|
emitRelativeBranch(invertConditionCode(ifStatement->
|
|
ifCondition), NULL, fixupLocation1);
|
|
expand((moreText("if %s {", conditionString(ifStatement->
|
|
ifCondition)), endLine(), tabCount++));
|
|
} else if (ifStatement->ifCondition == ALWAYS_COND) {
|
|
expand((moreText("{"), endLine(), tabCount++));
|
|
}
|
|
if (ifStatement->consequence != NULL && ifStatement->ifCondition !=
|
|
NEVER_COND)
|
|
fixupLocation2 = assembleBlockInsideIf(ifStatement->
|
|
consequence, fixupLocation2);
|
|
expand((tabCount--, startLineMarked()));
|
|
if (ifStatement->continuation.continuationBodyUnion != NULL &&
|
|
ifStatement->ifCondition != NEVER_COND &&
|
|
ifStatement->ifCondition != ALWAYS_COND)
|
|
fixupLocation2 = emitJump(NULL, fixupLocation2);
|
|
if (ifStatement->ifCondition != ALWAYS_COND && ifStatement->
|
|
ifCondition != NEVER_COND)
|
|
fixupBranch(fixupLocation1, currentLocationCounter);
|
|
if (ifStatement->continuation.continuationBodyUnion != NULL &&
|
|
ifStatement->ifCondition != ALWAYS_COND) {
|
|
expand((tabIndent(), moreText("} else ")));
|
|
fixupLocation2 = assembleIfStatement(ifStatement->
|
|
continuation.continuationBodyUnion, terminalIf, fixupLocation2);
|
|
} else {
|
|
expand((tabIndent(), moreText("}"), endLine()));
|
|
}
|
|
if (terminalIf) {
|
|
return(fixupLocation2);
|
|
} else {
|
|
fixupJump(fixupLocation2, currentLocationCounter);
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleIfStatementOldStyle(ifStatementBodyType *ifStatement)
|
|
{
|
|
valueType fixupLocation1[COMPOUND_BRANCH_MAX];
|
|
simpleFixupListType *fixupLocation2;
|
|
|
|
nullAssemble(ifStatement);
|
|
if (ifStatement->ifCondition != ALWAYS_COND) {
|
|
emitRelativeBranch(invertConditionCode(ifStatement->
|
|
ifCondition), NULL, fixupLocation1);
|
|
expand((moreText("if %s {", conditionString(ifStatement->
|
|
ifCondition)), endLine(), tabCount++));
|
|
} else {
|
|
expand((moreText("{"), endLine(), tabCount++));
|
|
}
|
|
if (ifStatement->consequence != NULL)
|
|
assembleBlock(ifStatement->consequence);
|
|
expand((tabCount--, startLineMarked()));
|
|
if (ifStatement->continuation.continuationBodyUnion != NULL)
|
|
fixupLocation2 = emitJump(NULL, NULL);
|
|
if (ifStatement->ifCondition != ALWAYS_COND)
|
|
fixupBranch(fixupLocation1, currentLocationCounter);
|
|
if (ifStatement->continuation.continuationBodyUnion != NULL) {
|
|
expand((tabIndent(), moreText("} else ")));
|
|
assembleIfStatementOldStyle(ifStatement->continuation.continuationBodyUnion);
|
|
} else {
|
|
expand((tabIndent(), moreText("}"), endLine()));
|
|
}
|
|
if (ifStatement->continuation.continuationBodyUnion != NULL)
|
|
fixupJump(fixupLocation2, currentLocationCounter);
|
|
}
|
|
|
|
void
|
|
assembleIncludeStatement(includeStatementBodyType *includeStatement)
|
|
{
|
|
stringType *fileName;
|
|
valueType *possibleFileName;
|
|
bool saveExpansion;
|
|
|
|
expansionOff();
|
|
possibleFileName = evaluateExpression(includeStatement, NO_FIXUP);
|
|
expansionOn();
|
|
if (possibleFileName->kindOfValue == STRING_VALUE) {
|
|
fileName = (stringType *)possibleFileName->value;
|
|
newIncludeFile = TRUE;
|
|
expand((moreText("include \"%s\"", fileName), endLine()));
|
|
pushInputFileStack(saveString(fileName));
|
|
} else {
|
|
error(INCLUDE_FILE_NOT_A_STRING_VALUE_ERROR);
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleInstructionStatement(instructionStatementBodyType *instructionStatement, int cumulativeLineNumber)
|
|
{
|
|
nullAssemble(instructionStatement);
|
|
switch(instructionStatement->kindOfInstruction) {
|
|
|
|
case OPCODE_INSTRUCTION:
|
|
if (amListing())
|
|
saveIndexForListing(INSTRUCTION_STATEMENT,
|
|
cumulativeLineNumber);
|
|
expand((startLine(), expandLabel(), tabIndent()));
|
|
assembleMachineInstruction(instructionStatement->
|
|
theInstruction.opcodeUnion, instructionStatement->theOperands);
|
|
break;
|
|
|
|
case MACRO_INSTRUCTION:
|
|
if (amListing() && !amExpanding())
|
|
saveIndexForListing(INSTRUCTION_STATEMENT,
|
|
cumulativeLineNumber);
|
|
assembleMacro(instructionStatement->theInstruction.macroUnion,
|
|
instructionStatement->theOperands);
|
|
break;
|
|
|
|
default:
|
|
botch("bad instruction type=%d\n", instructionStatement->
|
|
kindOfInstruction, 0, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleLongStatement(longStatementBodyType *longStatement)
|
|
{
|
|
valueType *longValue;
|
|
|
|
nullAssemble(longStatement);
|
|
expand(moreText("long\t"));
|
|
while (longStatement != NULL) {
|
|
longValue = evaluateExpression(longStatement->theExpression,
|
|
LONG_FIXUP);
|
|
longStatement = longStatement->nextExpression;
|
|
expand((expandExpression(NULL, NULL), longStatement != NULL ?
|
|
moreText(", ") : 0));
|
|
putFixupsHere(LONG_FIXUP, 0);
|
|
emitLongValue(longValue);
|
|
qfree(longValue);
|
|
}
|
|
expand(endLine());
|
|
}
|
|
|
|
void
|
|
assembleMacroStatement(macroStatementBodyType *macroStatement)
|
|
{
|
|
macroTableEntryType *newMacro;
|
|
|
|
nullAssemble(macroStatement);
|
|
if (currentEnvironment != &globalEnvironment) {
|
|
error(MACRO_DEFINITION_INSIDE_MACRO_ERROR);
|
|
return;
|
|
}
|
|
newMacro = macroStatement->theMacro;
|
|
if (newMacro == NULL)
|
|
return;
|
|
if (newMacro->body != NULL) {
|
|
error(MACRO_ALREADY_EXISTS_ERROR, macroStatement->theMacro->
|
|
macroName);
|
|
return;
|
|
}
|
|
newMacro->arguments = macroStatement->theArguments;
|
|
newMacro->body = macroStatement->theBlock;
|
|
}
|
|
|
|
void
|
|
assembleMdefineStatement(defineStatementBodyType *mdefineStatement)
|
|
{
|
|
bool saveExpansion;
|
|
|
|
nullAssemble(mdefineStatement);
|
|
expansionOff();
|
|
pushBinding(mdefineStatement->theSymbol, evaluateDefineExpression(
|
|
mdefineStatement->theValue), MDEFINE_SYMBOL);
|
|
expansionOn();
|
|
addNewLocalVariable(mdefineStatement->theSymbol);
|
|
}
|
|
|
|
void
|
|
assembleMdoUntilStatement(mdoUntilStatementBodyType *mdoUntilStatement)
|
|
{
|
|
bool saveListingOn;
|
|
|
|
nullAssemble(mdoUntilStatement);
|
|
saveListingOn = listingOn;
|
|
do {
|
|
assembleBlock(mdoUntilStatement->mdoUntilLoop);
|
|
listingOn = amExpanding();
|
|
} while (!booleanTest(mdoUntilStatement->mdoUntilCondition));
|
|
listingOn = saveListingOn;
|
|
}
|
|
|
|
void
|
|
assembleMdoWhileStatement(mdoWhileStatementBodyType *mdoWhileStatement)
|
|
{
|
|
bool saveListingOn;
|
|
|
|
nullAssemble(mdoWhileStatement);
|
|
saveListingOn = listingOn;
|
|
do {
|
|
assembleBlock(mdoWhileStatement->mdoWhileLoop);
|
|
listingOn = amExpanding();
|
|
} while (booleanTest(mdoWhileStatement->mdoWhileCondition));
|
|
listingOn = saveListingOn;
|
|
}
|
|
|
|
void
|
|
assembleMforStatement(mforStatementBodyType *mforStatement)
|
|
{
|
|
bool saveListingOn;
|
|
bool saveExpansion;
|
|
|
|
nullAssemble(mforStatement);
|
|
saveListingOn = listingOn;
|
|
expansionOff();
|
|
for (evaluateExpression(mforStatement->initExpression, NO_FIXUP);
|
|
booleanTest(mforStatement->testExpression);
|
|
evaluateExpression(mforStatement->incrExpression, NO_FIXUP)) {
|
|
expansionOn();
|
|
assembleBlock(mforStatement->forLoop);
|
|
listingOn = amExpanding();
|
|
expansionOff();
|
|
}
|
|
expansionOn();
|
|
listingOn = saveListingOn;
|
|
}
|
|
|
|
void
|
|
assembleMifStatement(mifStatementBodyType *mifStatement, int cumulativeLineNumber)
|
|
{
|
|
while (mifStatement != NULL) {
|
|
if (mifStatement->mifCondition == NULL) {
|
|
assembleBlock(mifStatement->mifConsequence);
|
|
break;
|
|
} else if (booleanTest(mifStatement->mifCondition)) {
|
|
assembleBlock(mifStatement->mifConsequence);
|
|
break;
|
|
} else {
|
|
mifStatement = mifStatement->mifContinuation.
|
|
mifContinuationBodyUnion;
|
|
}
|
|
}
|
|
if (amListing())
|
|
saveEndMifForListing(cumulativeLineNumber);
|
|
}
|
|
|
|
void
|
|
assembleMswitchStatement(mswitchStatementBodyType *mswitchStatement)
|
|
{
|
|
valueType *switchValue;
|
|
caseListType *caseList;
|
|
caseType *theCase;
|
|
bool matched;
|
|
expressionListType *tagExpressionList;
|
|
valueType *tagValue;
|
|
bool saveExpansion;
|
|
|
|
expansionOff();
|
|
switchValue = evaluateExpression(mswitchStatement->switchExpression,
|
|
NO_FIXUP);
|
|
expansionOn();
|
|
if (switchValue->kindOfValue != ABSOLUTE_VALUE && switchValue->kindOfValue
|
|
!= STRING_VALUE) {
|
|
error(INVALID_SWITCH_VALUE_KIND, valueKindString(switchValue->
|
|
kindOfValue));
|
|
return;
|
|
}
|
|
for (caseList=mswitchStatement->cases; caseList!=NULL; caseList=caseList->
|
|
nextCase) {
|
|
theCase = caseList->theCase;
|
|
if (theCase->caseTags == NULL) {
|
|
assembleBlock(theCase->caseBody);
|
|
break;
|
|
} else {
|
|
matched = FALSE;
|
|
for (tagExpressionList=theCase->caseTags; tagExpressionList!=NULL;
|
|
tagExpressionList=tagExpressionList->nextExpression) {
|
|
expansionOff();
|
|
tagValue = evaluateExpression(tagExpressionList->
|
|
theExpression, NO_FIXUP);
|
|
expansionOn();
|
|
if (tagValue->kindOfValue != ABSOLUTE_VALUE && tagValue->
|
|
kindOfValue != STRING_VALUE) {
|
|
error(INVALID_CASE_VALUE_KIND, valueKindString(tagValue->
|
|
kindOfValue));
|
|
continue;
|
|
}
|
|
if (tagValue->kindOfValue != switchValue->kindOfValue)
|
|
continue;
|
|
if (tagValue->kindOfValue == ABSOLUTE_VALUE) {
|
|
if (tagValue->value != switchValue->value)
|
|
continue;
|
|
} else {
|
|
if (strcmplc(tagValue->value, switchValue->value) != 0)
|
|
continue;
|
|
}
|
|
matched = TRUE;
|
|
break;
|
|
}
|
|
if (matched) {
|
|
assembleBlock(theCase->caseBody);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleMvariableStatement(mvariableStatementBodyType *mvariableStatement)
|
|
{
|
|
identifierListType *newLocalVariable;
|
|
int initCount;
|
|
bool saveExpansion;
|
|
|
|
nullAssemble(mvariableStatement);
|
|
expansionOff();
|
|
if (mvariableStatement->theDimension == NULL) {
|
|
if ((initCount = expressionListLength(mvariableStatement->
|
|
theValue)) == 1) {
|
|
pushBinding(mvariableStatement->theSymbol,
|
|
evaluateExpression(mvariableStatement->
|
|
theValue->theExpression, NO_FIXUP),
|
|
MVARIABLE_SYMBOL);
|
|
} else if (initCount > 1) {
|
|
error(TOO_MANY_VARIABLE_INITIALIZERS_ERROR);
|
|
} else {
|
|
pushBinding(mvariableStatement->theSymbol, NULL,
|
|
MVARIABLE_SYMBOL);
|
|
}
|
|
} else {
|
|
pushBinding(mvariableStatement->theSymbol, createArray(
|
|
mvariableStatement->theDimension, mvariableStatement->
|
|
theValue), MVARIABLE_SYMBOL);
|
|
}
|
|
expansionOn();
|
|
newLocalVariable = typeAlloc(identifierListType);
|
|
newLocalVariable->theSymbol = mvariableStatement->theSymbol;
|
|
newLocalVariable->nextIdentifier = currentLocalVariableList;
|
|
currentLocalVariableList = newLocalVariable;
|
|
}
|
|
|
|
void
|
|
assembleMwhileStatement(mwhileStatementBodyType *mwhileStatement)
|
|
{
|
|
bool saveListingOn;
|
|
|
|
nullAssemble(mwhileStatement);
|
|
saveListingOn = listingOn;
|
|
while (booleanTest(mwhileStatement->mwhileCondition)) {
|
|
assembleBlock(mwhileStatement->mwhileLoop);
|
|
listingOn = amExpanding();
|
|
}
|
|
listingOn = saveListingOn;
|
|
}
|
|
|
|
void
|
|
assembleOrgStatement(orgStatementBodyType *orgStatement)
|
|
{
|
|
valueType *orgAddress;
|
|
bool saveExpansion;
|
|
|
|
nullAssemble(orgStatement);
|
|
targetOffset = 0;
|
|
expansionOff();
|
|
orgAddress = evaluateExpression(orgStatement, NO_FIXUP);
|
|
expansionOn();
|
|
if (absoluteValue(orgAddress) || relocatableValue(orgAddress)) {
|
|
if (relocatableValue(¤tLocationCounter) &&
|
|
absoluteValue(orgAddress)) {
|
|
savedRelocatableCurrentLocationCounter =
|
|
currentLocationCounter;
|
|
currentCodeMode = ABSOLUTE_BUFFER;
|
|
}
|
|
currentLocationCounter.kindOfValue = orgAddress->kindOfValue;
|
|
currentLocationCounter.value = orgAddress->value;
|
|
expand((moreText("org\t0x%x", orgAddress->value), endLine()));
|
|
} else {
|
|
error(BAD_ORG_ADDRESS_ERROR, valueKindString(orgAddress->
|
|
kindOfValue));
|
|
}
|
|
qfree(orgAddress);
|
|
}
|
|
|
|
void
|
|
assemblePerformStatement(performStatementBodyType *performStatement)
|
|
{
|
|
nullAssemble(performStatement);
|
|
sideEffectFlag = FALSE;
|
|
evaluateExpressionStandalone(performStatement);
|
|
if (!sideEffectFlag)
|
|
warning(PERFORM_WITHOUT_SIDE_EFFECT_ERROR);
|
|
}
|
|
|
|
void
|
|
assembleRelStatement(relStatementBodyType *relStatement)
|
|
{
|
|
targetOffset = 0;
|
|
if (!relocatableValue(¤tLocationCounter)) {
|
|
currentLocationCounter =
|
|
savedRelocatableCurrentLocationCounter;
|
|
currentCodeMode = RELOCATABLE_BUFFER;
|
|
}
|
|
expand((moreText("rel"), endLine()));
|
|
addBreak(BREAK_BREAK, 0);
|
|
}
|
|
|
|
void
|
|
assembleStartStatement(startStatementBodyType *startStatement)
|
|
{
|
|
nullAssemble(startStatement);
|
|
expand(moreText("start\t"));
|
|
if (haveUserStartAddress) {
|
|
expand((moreText("*fail*"), endLine()));
|
|
error(START_ADDRESS_ALREADY_GIVEN_ERROR);
|
|
} else {
|
|
startAddress = evaluateExpression(startStatement,NO_FIXUP_OK);
|
|
if (startAddress->kindOfValue == UNDEFINED_VALUE) {
|
|
startAddress = (valueType *)generateFixupExpression(
|
|
startStatement);
|
|
haveUserStartAddress = TRUE;
|
|
fixupStartAddress = TRUE;
|
|
} else if (startAddress->kindOfValue != ABSOLUTE_VALUE &&
|
|
startAddress->kindOfValue!=RELOCATABLE_VALUE){
|
|
expand((moreText("*fail*"), endLine()));
|
|
error(BAD_START_ADDRESS_ERROR);
|
|
} else {
|
|
expand((expandExpression(NULL, NULL), endLine()));
|
|
haveUserStartAddress = TRUE;
|
|
fixupStartAddress = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleStringStatement(stringStatementBodyType *stringStatement)
|
|
{
|
|
valueType *byteValue;
|
|
|
|
nullAssemble(stringStatement);
|
|
expand(moreText("string\t"));
|
|
while (stringStatement != NULL) {
|
|
byteValue = evaluateExpression(stringStatement->theExpression,
|
|
BYTE_FIXUP);
|
|
if (byteValue->kindOfValue == STRING_VALUE) {
|
|
emitString(byteValue->value);
|
|
emitByte('\0');
|
|
} else {
|
|
putFixupsHere(BYTE_FIXUP, 0);
|
|
emitByteValue(byteValue);
|
|
}
|
|
qfree(byteValue);
|
|
stringStatement = stringStatement->nextExpression;
|
|
expand((expandExpression(NULL, NULL), stringStatement != NULL ?
|
|
moreText(", ") : 0));
|
|
}
|
|
expand(endLine());
|
|
}
|
|
|
|
void
|
|
assembleStructStatement(structStatementBodyType *structStatement)
|
|
{
|
|
nullAssemble(structStatement);
|
|
if (structStatement->structBody == NULL)
|
|
instantiateStruct(structStatement);
|
|
else
|
|
assembleStructDefinition(structStatement);
|
|
}
|
|
|
|
void
|
|
assembleTargetStatement(targetStatementBodyType *targetStatement)
|
|
{
|
|
valueType *targetAddress;
|
|
bool saveExpansion;
|
|
|
|
nullAssemble(targetStatement);
|
|
targetOffset = 0;
|
|
expansionOff();
|
|
targetAddress = evaluateExpression(targetStatement, NO_FIXUP);
|
|
expansionOn();
|
|
if (absoluteValue(targetAddress)) {
|
|
expand((moreText("target\t0x%x", targetAddress->
|
|
value), endLine()));
|
|
targetOffset = currentLocationCounter.value -
|
|
targetAddress->value;
|
|
} else {
|
|
error(BAD_TARGET_ADDRESS_ERROR, valueKindString(
|
|
targetAddress->kindOfValue));
|
|
}
|
|
qfree(targetAddress);
|
|
}
|
|
|
|
void
|
|
assembleUndefineStatement(undefineStatementBodyType *undefineStatement)
|
|
{
|
|
expand(moreText("undefine\t"));
|
|
while (undefineStatement != NULL) {
|
|
expand(moreText("%s", symbName(undefineStatement->theSymbol)));
|
|
purgeSymbol(effectiveSymbol(undefineStatement->theSymbol,
|
|
NULL));
|
|
undefineStatement = undefineStatement->nextIdentifier;
|
|
expand(undefineStatement != NULL ? moreText(", ") : 0);
|
|
}
|
|
expand(endLine());
|
|
}
|
|
|
|
void
|
|
assembleVariableStatement(variableStatementBodyType *variableStatement)
|
|
{
|
|
symbolTableEntryType *newVariable;
|
|
symbolInContextType *contextForVariable;
|
|
int initCount;
|
|
|
|
nullAssemble(variableStatement);
|
|
newVariable = effectiveSymbol(variableStatement->theSymbol,
|
|
&contextForVariable);
|
|
if (isPotentialVariable(contextForVariable)) {
|
|
expand(moreText("variable %s = ", symbName(newVariable)));
|
|
if (contextForVariable->usage == DEAD_SYMBOL) {
|
|
reincarnateSymbol(contextForVariable, VARIABLE_SYMBOL);
|
|
} else if (contextForVariable->usage == NESTED_UNKNOWN_SYMBOL) {
|
|
contextForVariable->usage = VARIABLE_SYMBOL;
|
|
}
|
|
if (alreadyDefined(contextForVariable)) {
|
|
error(REDEFINITION_OF_SYMBOL_ERROR, symbName(newVariable));
|
|
} else {
|
|
if (variableStatement->theDimension == NULL) {
|
|
if ((initCount = expressionListLength(variableStatement->
|
|
theValue)) == 1) {
|
|
contextForVariable->value = evaluateExpression(
|
|
variableStatement->theValue->theExpression, NO_FIXUP);
|
|
expand(expandExpression(NULL, NULL));
|
|
} else {
|
|
if (initCount > 1)
|
|
error(TOO_MANY_VARIABLE_INITIALIZERS_ERROR);
|
|
expand(moreText("*fail*"));
|
|
contextForVariable->value = newValue(FAIL, 0,
|
|
EXPRESSION_OPND);
|
|
}
|
|
} else {
|
|
contextForVariable->value = createArray(variableStatement->
|
|
theDimension, variableStatement->theValue);
|
|
}
|
|
contextForVariable->environmentNumber = GLOBAL_ENVIRONMENT_NUMBER;
|
|
contextForVariable->attributes |= DEFINED_VARIABLE_ATT;
|
|
}
|
|
expand(endLine());
|
|
} else {
|
|
error(SYMBOL_ALREADY_THERE_ERROR, symbName(newVariable));
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleWhileStatement(whileStatementBodyType *whileStatement)
|
|
{
|
|
valueType topOfLoop;
|
|
valueType fixupLocation[COMPOUND_BRANCH_MAX];
|
|
|
|
nullAssemble(whileStatement);
|
|
if (whileStatement->whileCondition == NEVER_COND) {
|
|
return;
|
|
} else if (whileStatement->whileCondition != ALWAYS_COND) {
|
|
emitRelativeBranch(invertConditionCode(whileStatement->
|
|
whileCondition), NULL, fixupLocation);
|
|
topOfLoop = currentLocationCounter;
|
|
} else {
|
|
topOfLoop = currentLocationCounter;
|
|
topOfLoop.value -= targetOffset;
|
|
}
|
|
expand((moreText("while %s {", conditionString(whileStatement->
|
|
whileCondition)), endLine(), tabCount++));
|
|
assembleBlock(whileStatement->whileLoop);
|
|
expand((tabCount--, startLineMarked(), tabIndent(), moreText("}"),
|
|
endLine()));
|
|
if (whileStatement->whileCondition != ALWAYS_COND) {
|
|
emitRelativeBranch(whileStatement->whileCondition, &topOfLoop,
|
|
NULL);
|
|
fixupBranch(fixupLocation, currentLocationCounter);
|
|
} else {
|
|
emitJump(&topOfLoop, NULL);
|
|
}
|
|
}
|
|
|
|
void
|
|
assembleWordStatement(wordStatementBodyType *wordStatement)
|
|
{
|
|
valueType *word;
|
|
|
|
nullAssemble(wordStatement);
|
|
expand(moreText("word\t"));
|
|
while (wordStatement != NULL) {
|
|
word = evaluateExpression(wordStatement->theExpression,
|
|
WORD_FIXUP);
|
|
wordStatement = wordStatement->nextExpression;
|
|
expand((expandExpression(NULL, NULL), wordStatement != NULL ?
|
|
moreText(", ") : 0));
|
|
putFixupsHere(WORD_FIXUP, 0);
|
|
emitWordValue(word);
|
|
qfree(word);
|
|
}
|
|
expand(endLine());
|
|
}
|
|
|
|
bool
|
|
assembleStatementBody(statementKindType kind, statementBodyType body, int cumulativeLineNumber, bool worryAboutIf, simpleFixupListType **ifFixupList)
|
|
{
|
|
bool result;
|
|
|
|
result = TRUE;
|
|
if (amListing() && kind != INSTRUCTION_STATEMENT && !beneathFunction)
|
|
saveIndexForListing(kind, cumulativeLineNumber);
|
|
switch (kind) {
|
|
|
|
case ALIGN_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleAlignStatement(body.alignUnion);
|
|
if (amListing())
|
|
saveIndexForListing(ALIGN_STATEMENT,
|
|
cumulativeLineNumber);
|
|
break;
|
|
|
|
case ASSERT_STATEMENT:
|
|
assembleAssertStatement(body.assertUnion);
|
|
break;
|
|
|
|
case BLOCK_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleBlockStatement(body.blockUnion);
|
|
break;
|
|
|
|
case BYTE_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleByteStatement(body.byteUnion);
|
|
break;
|
|
|
|
case CONSTRAIN_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleConstrainStatement(body.constrainUnion);
|
|
break;
|
|
|
|
case DBYTE_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleDbyteStatement(body.dbyteUnion);
|
|
break;
|
|
|
|
case DEFINE_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleDefineStatement(body.defineUnion);
|
|
break;
|
|
|
|
case DO_UNTIL_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleDoUntilStatement(body.doUntilUnion);
|
|
break;
|
|
|
|
case DO_WHILE_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleDoWhileStatement(body.doWhileUnion);
|
|
break;
|
|
|
|
case EXTERN_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleExternStatement(body.externUnion);
|
|
break;
|
|
|
|
case FRETURN_STATEMENT:
|
|
assembleFreturnStatement(body.freturnUnion);
|
|
/* result = FALSE;*/
|
|
break;
|
|
|
|
case FUNCTION_STATEMENT:
|
|
assembleFunctionStatement(body.functionUnion);
|
|
break;
|
|
|
|
case GROUP_STATEMENT:
|
|
assembleGroupStatement(body.groupUnion);
|
|
break;
|
|
|
|
case IF_STATEMENT:
|
|
sideEffectBomb();
|
|
if (worryAboutIf) {
|
|
*ifFixupList = assembleIfStatement(body.ifUnion, worryAboutIf,
|
|
*ifFixupList);
|
|
} else {
|
|
assembleIfStatement(body.ifUnion, worryAboutIf, NULL);
|
|
}
|
|
break;
|
|
|
|
case INCLUDE_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleIncludeStatement(body.includeUnion);
|
|
break;
|
|
|
|
case INSTRUCTION_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleInstructionStatement(body.instructionUnion, cumulativeLineNumber);
|
|
break;
|
|
|
|
case LONG_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleLongStatement(body.longUnion);
|
|
break;
|
|
|
|
case MACRO_STATEMENT:
|
|
assembleMacroStatement(body.macroUnion);
|
|
break;
|
|
|
|
case MDEFINE_STATEMENT:
|
|
assembleMdefineStatement(body.defineUnion);
|
|
break;
|
|
|
|
case MDO_UNTIL_STATEMENT:
|
|
assembleMdoUntilStatement(body.mdoUntilUnion);
|
|
break;
|
|
|
|
case MDO_WHILE_STATEMENT:
|
|
assembleMdoWhileStatement(body.mdoWhileUnion);
|
|
break;
|
|
|
|
case MFOR_STATEMENT:
|
|
assembleMforStatement(body.mforUnion);
|
|
break;
|
|
|
|
case MIF_STATEMENT:
|
|
assembleMifStatement(body.mifUnion, cumulativeLineNumber);
|
|
break;
|
|
|
|
case MSWITCH_STATEMENT:
|
|
assembleMswitchStatement(body.mswitchUnion);
|
|
break;
|
|
|
|
case MVARIABLE_STATEMENT:
|
|
assembleMvariableStatement(body.mvariableUnion);
|
|
break;
|
|
|
|
case MWHILE_STATEMENT:
|
|
assembleMwhileStatement(body.mwhileUnion);
|
|
break;
|
|
|
|
case NULL_STATEMENT:
|
|
nullStatementFlag = TRUE;
|
|
expand(labeledLine() ? (startLineMarked(), expandLabel(),
|
|
endLine()) : 0);
|
|
break;
|
|
|
|
case ORG_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleOrgStatement(body.orgUnion);
|
|
if (amListing())
|
|
saveIndexForListing(ORG_STATEMENT,
|
|
cumulativeLineNumber);
|
|
break;
|
|
|
|
case PERFORM_STATEMENT:
|
|
assemblePerformStatement(body.performUnion);
|
|
break;
|
|
|
|
case REL_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleRelStatement(body.relUnion);
|
|
if (amListing())
|
|
saveIndexForListing(REL_STATEMENT,
|
|
cumulativeLineNumber);
|
|
break;
|
|
|
|
case START_STATEMENT:
|
|
assembleStartStatement(body.startUnion);
|
|
break;
|
|
|
|
case STRING_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleStringStatement(body.stringUnion);
|
|
break;
|
|
|
|
case STRUCT_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleStructStatement(body.structUnion);
|
|
break;
|
|
|
|
case TARGET_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleTargetStatement(body.targetUnion);
|
|
break;
|
|
|
|
case UNDEFINE_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleUndefineStatement(body.undefineUnion);
|
|
break;
|
|
|
|
case VARIABLE_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleVariableStatement(body.variableUnion);
|
|
break;
|
|
|
|
case WHILE_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleWhileStatement(body.whileUnion);
|
|
break;
|
|
|
|
case WORD_STATEMENT:
|
|
sideEffectBomb();
|
|
assembleWordStatement(body.wordUnion);
|
|
break;
|
|
|
|
default:
|
|
botch("assembleStatementBody doesn't know kind %d\n", kind, 0, 0);
|
|
break;
|
|
}
|
|
/* return(result);*/
|
|
return(!freturnExit);
|
|
}
|
|
|
|
void
|
|
assembleLabelList(labelListType *labelList)
|
|
{
|
|
while (labelList != NULL) {
|
|
if (structNestingDepth == 0)
|
|
valueLabel(labelList->theLabel,
|
|
newValue(currentLocationCounter.kindOfValue,
|
|
currentLocationCounter.value,
|
|
EXPRESSION_OPND));
|
|
else
|
|
valueField(labelList->theLabel, newValue(FIELD_VALUE,
|
|
currentFieldOffset, EXPRESSION_OPND));
|
|
labelList = labelList->nextLabel;
|
|
}
|
|
}
|
|
|
|
simpleFixupListType *
|
|
assembleStatement(statementType *statement, bool insideIf, simpleFixupListType *ongoingFixupList)
|
|
{
|
|
char *saveFileName;
|
|
int saveLineNumber;
|
|
int saveCumulativeLineNumber;
|
|
simpleFixupListType *result;
|
|
|
|
statementEvaluationDepth++;
|
|
expand(flushExpressionString());
|
|
saveFileName = currentFileName;
|
|
saveLineNumber = currentLineNumber;
|
|
result = ongoingFixupList;
|
|
while (statement != NULL) {
|
|
currentFileName = statement->fileName;
|
|
currentLineNumber = statement->lineNumber;
|
|
expand(listableStatement(statement->kindOfStatement) ?
|
|
startLine() : 0);
|
|
assembleLabelList(statement->labels);
|
|
expand(listableStatement(statement->kindOfStatement) ?
|
|
(expandLabel(), tabIndent()) : 0);
|
|
if (assembleStatementBody(statement->kindOfStatement,
|
|
statement->statementBody, statement->
|
|
cumulativeLineNumber, insideIf &&
|
|
isLastStatementInBlock(statement), &result)) {
|
|
statementType *next = statement->nextStatement;
|
|
if (freeFlag && statementEvaluationDepth == 1)
|
|
freeStatement(statement);
|
|
statement = next;
|
|
} else {
|
|
if (freeFlag && statementEvaluationDepth == 1)
|
|
freeStatement(statement);
|
|
freturnExit = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!newIncludeFile) {
|
|
currentFileName = saveFileName;
|
|
currentLineNumber = saveLineNumber;
|
|
} else {
|
|
newIncludeFile = FALSE;
|
|
}
|
|
statementEvaluationDepth--;
|
|
return(result);
|
|
}
|
|
|
|
void
|
|
eatStatement(statementType *statement)
|
|
{
|
|
if (debug) {
|
|
printf("assembling:\n");
|
|
printStatement(statement);
|
|
}
|
|
assembleStatement(statement, FALSE, NULL);
|
|
}
|