mirror of
https://github.com/Museum-of-Art-and-Digital-Entertainment/macross.git
synced 2024-11-26 22:51:04 +00:00
500 lines
14 KiB
C
500 lines
14 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.
|
|
*/
|
|
/*
|
|
buildStuff1.c -- Routines to build parse-tree structures for the
|
|
Macross assembler. This module is target processor
|
|
independent.
|
|
|
|
Chip Morningstar -- Lucasfilm Ltd.
|
|
|
|
1-November-1984
|
|
|
|
*/
|
|
|
|
#include "macrossTypes.h"
|
|
#include "macrossGlobals.h"
|
|
#include "errorStuff.h"
|
|
#include "lookups.h"
|
|
#include "parserMisc.h"
|
|
|
|
/* Generic routine to create statement nodes */
|
|
|
|
statementType *
|
|
newStatement(statementKindType kind, statementBodyType body)
|
|
{
|
|
statementType *result;
|
|
|
|
result = typeAlloc(statementType);
|
|
result->kindOfStatement = kind;
|
|
result->labels = NULL;
|
|
result->statementBody = body;
|
|
result->nextStatement = NULL;
|
|
result->fileName = currentFileName;
|
|
result->lineNumber = currentLineNumber;
|
|
result->cumulativeLineNumber = cumulativeLineNumber;
|
|
return(result);
|
|
}
|
|
|
|
/*
|
|
These routines specifically build top-level parse-tree nodes corresponding
|
|
to the different types of Macross statements. There is one such routine of
|
|
the form "buildXxxxStatement" for each kind of Macross statement.
|
|
*/
|
|
|
|
statementType *
|
|
buildAlignStatement(expressionType *expression)
|
|
{
|
|
return(newStatement(ALIGN_STATEMENT,
|
|
(statementBodyType) expression));
|
|
}
|
|
|
|
statementType *
|
|
buildAssertStatement(expressionType *condition, expressionType *message)
|
|
{
|
|
assertStatementBodyType *result;
|
|
|
|
result = typeAlloc(assertStatementBodyType);
|
|
|
|
result->condition = condition;
|
|
result->message = message;
|
|
return(newStatement(ASSERT_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildBlockStatement(expressionListType *expressionList)
|
|
{
|
|
return(newStatement(BLOCK_STATEMENT,
|
|
(statementBodyType) expressionList));
|
|
}
|
|
|
|
statementType *
|
|
buildByteStatement(expressionListType *expressionList)
|
|
{
|
|
return(newStatement(BYTE_STATEMENT,
|
|
(statementBodyType) expressionList));
|
|
}
|
|
|
|
statementType *
|
|
buildConstrainStatement(expressionType *expression, blockType *block)
|
|
{
|
|
constrainStatementBodyType *result;
|
|
|
|
result = typeAlloc(constrainStatementBodyType);
|
|
|
|
result->constraint = expression;
|
|
result->constrainedBlock = block;
|
|
return(newStatement(CONSTRAIN_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildDbyteStatement(expressionListType *expressionList)
|
|
{
|
|
return(newStatement(DBYTE_STATEMENT,
|
|
(statementBodyType) expressionList));
|
|
}
|
|
|
|
statementType *
|
|
buildDefineStatement(stringType *name, expressionType *value)
|
|
{
|
|
defineStatementBodyType *result;
|
|
|
|
result = typeAlloc(defineStatementBodyType);
|
|
result->theSymbol = lookupOrEnterSymbol(name, UNKNOWN_SYMBOL);
|
|
result->theValue = value;
|
|
return(newStatement(DEFINE_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildDoUntilStatement(blockType *body, conditionType condition)
|
|
{
|
|
doUntilStatementBodyType *result;
|
|
|
|
result = typeAlloc(doUntilStatementBodyType);
|
|
result->doUntilCondition = condition;
|
|
result->doUntilLoop = body;
|
|
return(newStatement(DO_UNTIL_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildDoWhileStatement(blockType *body, conditionType condition)
|
|
{
|
|
doWhileStatementBodyType *result;
|
|
|
|
result = typeAlloc(doWhileStatementBodyType);
|
|
result->doWhileCondition = condition;
|
|
result->doWhileLoop = body;
|
|
return(newStatement(DO_WHILE_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildDoStatement(blockType *body, doEndType *end)
|
|
{
|
|
statementType *result;
|
|
|
|
if (end->doEndKind == UNTIL_END)
|
|
result = buildDoUntilStatement(body, end->doEndCondition);
|
|
else if (end->doEndKind == WHILE_END)
|
|
result = buildDoWhileStatement(body, end->doEndCondition);
|
|
else
|
|
botch("bad do-end kind: %d\n", end->doEndCondition);
|
|
qfree(end);
|
|
return(result);
|
|
}
|
|
|
|
statementType *
|
|
buildExternStatement(identifierListType *identifierList)
|
|
{
|
|
return(newStatement(EXTERN_STATEMENT,
|
|
(statementBodyType) identifierList));
|
|
}
|
|
|
|
statementType *
|
|
buildFreturnStatement(expressionType *expression)
|
|
{
|
|
return(newStatement(FRETURN_STATEMENT,
|
|
(statementBodyType) expression));
|
|
}
|
|
|
|
statementType *
|
|
buildFunctionStatement(stringType *name, argumentDefinitionListType *arguments, blockType *body)
|
|
{
|
|
functionStatementBodyType *result;
|
|
symbolTableEntryType *testSymbol;
|
|
|
|
testSymbol = lookupOrEnterSymbol(name, FUNCTION_SYMBOL);
|
|
if (testSymbol->context->usage != FUNCTION_SYMBOL && testSymbol->
|
|
context->usage != UNKNOWN_FUNCTION_SYMBOL) {
|
|
error(SYMBOL_ALREADY_THERE_ERROR, symbName(testSymbol));
|
|
return(NULL);
|
|
}
|
|
result = typeAlloc(functionStatementBodyType);
|
|
result->functionName = saveString(name);
|
|
result->theArguments = arguments;
|
|
result->theBlock = body;
|
|
return(newStatement(FUNCTION_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildGroupStatement(blockType *block)
|
|
{
|
|
return(newStatement(GROUP_STATEMENT,
|
|
(statementBodyType) block));
|
|
}
|
|
|
|
statementType *
|
|
buildIfStatement(ifHeadType *head, ifContinuationType continuation, ifContinuationKindType continuationKind)
|
|
{
|
|
ifStatementBodyType *result;
|
|
|
|
result = typeAlloc(ifStatementBodyType);
|
|
|
|
result->ifCondition = head->headCondition;
|
|
result->consequence = head->headBody;
|
|
if (continuationKind == NO_CONTINUATION)
|
|
result->continuation.blockUnion = NULL;
|
|
else if (continuationKind == ELSE_CONTINUATION) {
|
|
result->continuation.continuationBodyUnion =
|
|
typeAlloc(ifContinuationBodyType);
|
|
result->continuation.continuationBodyUnion->ifCondition =
|
|
ALWAYS_COND;
|
|
result->continuation.continuationBodyUnion->consequence =
|
|
continuation.blockUnion;
|
|
result->continuation.continuationBodyUnion->
|
|
continuation.continuationBodyUnion = NULL;
|
|
} else if (continuationKind == ELSEIF_CONTINUATION)
|
|
result->continuation = continuation;
|
|
else
|
|
botch("bad continuation kind: %d\n", continuationKind);
|
|
qfree(head);
|
|
return(newStatement(IF_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildIncludeStatement(expressionType *filename)
|
|
{
|
|
return(newStatement(INCLUDE_STATEMENT,
|
|
(statementBodyType) filename));
|
|
}
|
|
|
|
statementType *
|
|
buildInstructionStatement(opcodeTableEntryType *opcode, operandListType *operands)
|
|
{
|
|
instructionStatementBodyType *result;
|
|
|
|
result = typeAlloc(instructionStatementBodyType);
|
|
result->kindOfInstruction = OPCODE_INSTRUCTION;
|
|
result->theInstruction.opcodeUnion = opcode;
|
|
result->theOperands = operands;
|
|
return(newStatement(INSTRUCTION_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildLongStatement(expressionListType *expressionList)
|
|
{
|
|
return(newStatement(LONG_STATEMENT,
|
|
(statementBodyType) expressionList));
|
|
}
|
|
|
|
statementType *
|
|
buildMacroStatement(macroTableEntryType *macro, argumentDefinitionListType *arguments, blockType *body)
|
|
{
|
|
macroStatementBodyType *result;
|
|
|
|
result = typeAlloc(macroStatementBodyType);
|
|
result->theMacro = macro;
|
|
result->theArguments = arguments;
|
|
result->theBlock = body;
|
|
return(newStatement(MACRO_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildMacroInstructionStatement(macroTableEntryType *macro, operandListType *operands)
|
|
{
|
|
instructionStatementBodyType *result;
|
|
|
|
result = typeAlloc(instructionStatementBodyType);
|
|
result->kindOfInstruction = MACRO_INSTRUCTION;
|
|
result->theInstruction.macroUnion = macro;
|
|
result->theOperands = operands;
|
|
return(newStatement(INSTRUCTION_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildMdefineStatement(stringType *name, expressionType *value)
|
|
{
|
|
mdefineStatementBodyType *result;
|
|
|
|
result = typeAlloc(mdefineStatementBodyType);
|
|
result->theSymbol = lookupOrEnterSymbol(name, DEAD_SYMBOL);
|
|
result->theValue = value;
|
|
return(newStatement(MDEFINE_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildMdoUntilStatement(blockType *body, struct expressionTermStruct *condition)
|
|
{
|
|
mdoUntilStatementBodyType *result;
|
|
|
|
result = typeAlloc(mdoUntilStatementBodyType);
|
|
result->mdoUntilCondition = condition;
|
|
result->mdoUntilLoop = body;
|
|
return(newStatement(MDO_UNTIL_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildMdoWhileStatement(blockType *body, expressionType *condition)
|
|
{
|
|
mdoWhileStatementBodyType *result;
|
|
|
|
result = typeAlloc(mdoWhileStatementBodyType);
|
|
result->mdoWhileCondition = condition;
|
|
result->mdoWhileLoop = body;
|
|
return(newStatement(MDO_WHILE_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildMdoStatement(blockType *body, mdoEndType *end)
|
|
{
|
|
statementType *result;
|
|
|
|
if (end->mdoEndKind == UNTIL_END)
|
|
result = buildMdoUntilStatement(body, end->mdoEndCondition);
|
|
else if (end->mdoEndKind == WHILE_END)
|
|
result = buildMdoWhileStatement(body, end->mdoEndCondition);
|
|
else
|
|
botch("bad mdo-end kind: %d\n", end->mdoEndCondition);
|
|
qfree(end);
|
|
return(result);
|
|
}
|
|
|
|
statementType *
|
|
buildMforStatement(forExpressionsType *forExpressions, blockType *body)
|
|
{
|
|
mforStatementBodyType *result;
|
|
|
|
result = typeAlloc(mforStatementBodyType);
|
|
result->initExpression = forExpressions->initExpression;
|
|
result->testExpression = forExpressions->testExpression;
|
|
result->incrExpression = forExpressions->incrExpression;
|
|
result->forLoop = body;
|
|
qfree(forExpressions);
|
|
return(newStatement(MFOR_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildMifStatement(mifHeadType *head, mifContinuationType continuation, ifContinuationKindType continuationKind)
|
|
{
|
|
mifStatementBodyType *result;
|
|
|
|
result = typeAlloc(mifStatementBodyType);
|
|
|
|
result->mifCondition = head->headCondition;
|
|
result->mifConsequence = head->headBody;
|
|
if (continuationKind == NO_CONTINUATION)
|
|
result->mifContinuation.mifContinuationBodyUnion = NULL;
|
|
else if (continuationKind == ELSE_CONTINUATION) {
|
|
result->mifContinuation.mifContinuationBodyUnion =
|
|
typeAlloc(mifContinuationBodyType);
|
|
result->mifContinuation.mifContinuationBodyUnion->
|
|
mifCondition = NULL;
|
|
result->mifContinuation.mifContinuationBodyUnion->
|
|
mifConsequence = continuation.mifBlockUnion;
|
|
result->mifContinuation.mifContinuationBodyUnion->
|
|
mifContinuation.mifContinuationBodyUnion = NULL;
|
|
} else if (continuationKind == ELSEIF_CONTINUATION)
|
|
result->mifContinuation = continuation;
|
|
else
|
|
botch("bad mif continuation kind: %d\n", continuationKind);
|
|
qfree(head);
|
|
return(newStatement(MIF_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildMswitchStatement(expressionType *switchExpression, caseListType *cases)
|
|
{
|
|
mswitchStatementBodyType *result;
|
|
|
|
result = typeAlloc(mswitchStatementBodyType);
|
|
result->switchExpression = switchExpression;
|
|
result->cases = cases;
|
|
return(newStatement(MSWITCH_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildMvariableStatement(stringType *name, expressionListType *value, expressionType *dimension)
|
|
{
|
|
mvariableStatementBodyType *result;
|
|
|
|
result = typeAlloc(mvariableStatementBodyType);
|
|
result->theSymbol = lookupOrEnterSymbol(name, DEAD_SYMBOL);
|
|
result->theValue = value;
|
|
result->theDimension = dimension;
|
|
return(newStatement(MVARIABLE_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildMwhileStatement(expressionType *condition, blockType *body)
|
|
{
|
|
mwhileStatementBodyType *result;
|
|
|
|
result = typeAlloc(mwhileStatementBodyType);
|
|
result->mwhileCondition = condition;
|
|
result->mwhileLoop = body;
|
|
return(newStatement(MWHILE_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildNullStatement(void)
|
|
{
|
|
return(newStatement(NULL_STATEMENT, (statementBodyType){ .ifUnion = NULL }));
|
|
}
|
|
|
|
statementType *
|
|
buildOrgStatement(expressionType *expression)
|
|
{
|
|
return(newStatement(ORG_STATEMENT,
|
|
(statementBodyType) expression));
|
|
}
|
|
|
|
statementType *
|
|
buildPerformStatement(expressionType *expression)
|
|
{
|
|
return(newStatement(PERFORM_STATEMENT,
|
|
(statementBodyType) expression));
|
|
}
|
|
|
|
statementType *
|
|
buildRelStatement(void)
|
|
{
|
|
return(newStatement(REL_STATEMENT, (statementBodyType){ .ifUnion = NULL }));
|
|
}
|
|
|
|
statementType *
|
|
buildStartStatement(expressionType *expression)
|
|
{
|
|
return(newStatement(START_STATEMENT,
|
|
(statementBodyType) expression));
|
|
}
|
|
|
|
statementType *
|
|
buildStringStatement(expressionListType *expressionList)
|
|
{
|
|
return(newStatement(STRING_STATEMENT,
|
|
(statementBodyType) expressionList));
|
|
}
|
|
|
|
statementType *
|
|
buildStructStatement(symbolTableEntryType *name, blockType *body)
|
|
{
|
|
structStatementBodyType *result;
|
|
|
|
result = typeAlloc(structStatementBodyType);
|
|
result->structBody = body;
|
|
result->structName = name;
|
|
return(newStatement(STRUCT_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildTargetStatement(expressionType *expression)
|
|
{
|
|
return(newStatement(TARGET_STATEMENT,
|
|
(statementBodyType) expression));
|
|
}
|
|
|
|
statementType *
|
|
buildUndefineStatement(identifierListType *identifierList)
|
|
{
|
|
return(newStatement(UNDEFINE_STATEMENT,
|
|
(statementBodyType) identifierList));
|
|
}
|
|
|
|
statementType *
|
|
buildVariableStatement(stringType *name, expressionListType *value, expressionType *dimension)
|
|
{
|
|
variableStatementBodyType *result;
|
|
|
|
result = typeAlloc(variableStatementBodyType);
|
|
result->theSymbol = lookupOrEnterSymbol(name, VARIABLE_SYMBOL);
|
|
result->theValue = value;
|
|
result->theDimension = dimension;
|
|
return(newStatement(VARIABLE_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildWhileStatement(conditionType condition, blockType *body)
|
|
{
|
|
whileStatementBodyType *result;
|
|
|
|
result = typeAlloc(whileStatementBodyType);
|
|
result->whileCondition = condition;
|
|
result->whileLoop = body;
|
|
return(newStatement(WHILE_STATEMENT, (statementBodyType) result));
|
|
}
|
|
|
|
statementType *
|
|
buildWordStatement(expressionListType *expressionList)
|
|
{
|
|
return(newStatement(WORD_STATEMENT,
|
|
(statementBodyType) expressionList));
|
|
}
|
|
|