macross/buildStuff1.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));
}