/* * 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. */ /* WARNING: this file has not yet been separated into 6502 and non-6052 parts */ /* encode.c -- Routines to encode expressions for Macross object files. Chip Morningstar -- Lucasfilm Ltd. 8-November-1985 */ #include "macrossTypes.h" #include "macrossGlobals.h" #include "y.tab.h" #include "encode.h" #include "debugPrint.h" #include "errorStuff.h" #include "parserMisc.h" #include "semanticMisc.h" #include "slinkyExpressions.h" #define nullEncode(thing) if (thing==NULL) return(TRUE); #define byteOp(op) ((op)-256) bool encodingFunction; bool encodeByte(byte aByte) { if (expressionBufferSize < EXPRESSION_BUFFER_LIMIT) { expressionBuffer[expressionBufferSize++] = aByte; return(TRUE); } else { error(EXPRESSION_TOO_BIG_TO_FIT_IN_OBJECT_ERROR); return(FALSE); } } bool encodeBigword(int bigword) { int i; for (i=0; i>= 8; } return(TRUE); } bool encodeAssignmentTerm(binopTermType *assignmentTerm) { nullEncode(assignmentTerm); if ((assignmentKindType)assignmentTerm->binop != ASSIGN_ASSIGN) { error(FUNNY_ASSIGNMENT_KIND_IN_OBJECT_EXPRESSION_ERROR); return(FALSE); } return( encodeByte(BINOP_TAG) && encodeByte(byteOp(ASSIGN)) && encodeIdentifier(assignmentTerm->leftArgument) && encodeExpression(assignmentTerm->rightArgument) ); } bool encodeBinopTerm(binopTermType *binopTerm) { nullEncode(binopTerm); return ( encodeByte(BINOP_TAG) && encodeByte(byteOp(binopTerm->binop)) && encodeExpression(binopTerm->leftArgument) && encodeExpression(binopTerm->rightArgument) ); } bool encodeCondition(conditionType condition) { return( encodeByte(CONDITION_CODE_TAG) && encodeByte(condition) ); } int functionNumber(functionDefinitionType *function) { if (function->ordinal == -1) { function->ordinal = externalFunctionCount++; if (externalFunctionList == NULL) { externalFunctionList = endOfExternalFunctionList = function; } else { endOfExternalFunctionList->nextExternalFunction = function; endOfExternalFunctionList = function; } } return(function->ordinal); } bool encodeFunctionCall(functionCallTermType *functionCall) { functionDefinitionType *theFunction; int functionOrdinal; symbolInContextType *workingContext; operandListType *parameterList; nullEncode(functionCall); workingContext = getWorkingContext(functionCall->functionName); if (isFunction(workingContext)) { if (!encodeByte(FUNCTION_CALL_TAG)) return(FALSE); theFunction = (functionDefinitionType *)workingContext-> value->value; if (!encodeBigword(functionNumber(theFunction))) return(FALSE); } else if (isBuiltInFunction(workingContext)) { functionOrdinal = workingContext->value->value; if (builtInFunctionTable[functionOrdinal].isSpecialFunction) return(encodeValue((*builtInFunctionTable[ functionOrdinal].functionEntry)(functionCall-> parameters, NO_FIXUP))); if (!encodeByte(BUILTIN_FUNCTION_CALL_TAG)) return(FALSE); if (builtInFunctionTable[functionOrdinal].ordinal < 0) { error(BUILT_IN_FUNCTION_NOT_AVAILABLE_IN_OBJECT_ERROR, builtInFunctionTable[functionOrdinal]. functionName); return(FALSE); } else if (!encodeBigword(builtInFunctionTable[ functionOrdinal].ordinal)) { return(FALSE); } } else { error(NOT_A_FUNCTION_ERROR, symbName(functionCall-> functionName)); return(FALSE); } parameterList = functionCall->parameters; if (!encodeByte(countParameters(parameterList))) return(FALSE); while (parameterList != NULL) if (!encodeOperand(parameterList)) return(FALSE); else parameterList = parameterList->nextOperand; return(TRUE); } bool encodeHere(void) { return(encodeByte(HERE_TAG)); } bool encodeIdentifier(symbolTableEntryType *identifier) { symbolInContextType *workingContext; environmentType *saveEnvironment; bool result; nullEncode(identifier); if (symbName(identifier)[0] == '$') { error(TEMP_SYMBOL_IN_OBJECT_ERROR, symbName(identifier)); return(FALSE); } if (encodingFunction) { return(encodeByte(IDENTIFIER_TAG) && encodeBigword(identifier->ordinal)); } if ((workingContext = getWorkingContext(identifier)) == NULL) { error(UNDEFINED_SYMBOL_ERROR, symbName(identifier)); return(FALSE); } if (workingContext->usage == FUNCTION_SYMBOL || workingContext->usage == BUILT_IN_FUNCTION_SYMBOL) { error(FUNCTION_IS_NOT_A_VALUE_ERROR, symbName(identifier)); return(FALSE); } if (workingContext->value == NULL) { error(UNDEFINED_SYMBOL_ERROR, symbName(identifier)); return(FALSE); } if (workingContext->value->kindOfValue == UNDEFINED_VALUE) { if (workingContext->attributes & GLOBAL_ATT) { return(encodeByte(IDENTIFIER_TAG) && encodeBigword(identifier->ordinal)); } else { error(UNDEFINED_SYMBOL_ERROR, symbName(identifier)); return(FALSE); } } if (workingContext->value->kindOfValue == RELOCATABLE_VALUE) { return(encodeByte(IDENTIFIER_TAG) && encodeBigword(identifier->ordinal)); } if (workingContext->value->kindOfValue == FAIL) { error(UNASSIGNED_SYMBOL_ERROR, symbName(identifier)); return(FALSE); } if (workingContext->value->kindOfValue == OPERAND_VALUE) { saveEnvironment = currentEnvironment; if (workingContext->usage == ARGUMENT_SYMBOL) { currentEnvironment = currentEnvironment-> previousEnvironment; } result = encodeOperand(workingContext->value->value); currentEnvironment = saveEnvironment; return(result); } if (workingContext->value->kindOfValue == BLOCK_VALUE) { error(BLOCK_OPERAND_IN_OBJECT_EXPRESSION_ERROR); return(FALSE); } return(encodeValue(workingContext->value)); } bool encodeNumber(numberTermType number) { return( encodeByte(NUMBER_TAG) && encodeBigword(number) ); } bool encodeRelocatableNumber(numberTermType number) { return( encodeByte(RELOCATABLE_TAG) && encodeBigword(number) ); } bool encodeOperand(operandType *operand) { switch (operand->kindOfOperand) { case EXPRESSION_OPND: case IMMEDIATE_OPND: case INDIRECT_OPND: case POST_INDEXED_Y_OPND: case PRE_INDEXED_X_OPND: case X_INDEXED_OPND: case Y_INDEXED_OPND: return(encodeExpression(operand->theOperand.expressionUnion)); case A_REGISTER_OPND: case X_REGISTER_OPND: case Y_REGISTER_OPND: error(REGISTER_OPERAND_IN_OBJECT_EXPRESSION_ERROR); return(FALSE); case X_SELECTED_OPND: case Y_SELECTED_OPND: case PRE_SELECTED_X_OPND: error(SELECTION_OPERAND_IN_OBJECT_EXPRESSION_ERROR); return(FALSE); case STRING_OPND: return(encodeString(operand->theOperand.stringUnion)); case BLOCK_OPND: error(BLOCK_OPERAND_IN_OBJECT_EXPRESSION_ERROR); return(FALSE); } } bool encodePostopTerm(postOpTermType *postopTerm) { nullEncode(postopTerm); return( encodeByte(POSTOP_TAG) && encodeByte(byteOp(postopTerm->postOp)) && encodeExpression(postopTerm->postOpArgument) ); } bool encodePreopTerm(preOpTermType *preopTerm) { nullEncode(preopTerm); return( encodeByte(PREOP_TAG) && encodeByte(byteOp(preopTerm->preOp)) && encodeExpression(preopTerm->preOpArgument) ); } bool encodeString(stringType *string) { if (!encodeByte(STRING_TAG)) return(FALSE); while (*string != '\0') { if (!encodeByte(*string++)) return(FALSE); } return(encodeByte('\0')); } bool encodeUnopTerm(unopTermType *unopTerm) { nullEncode(unopTerm); return( encodeByte(UNOP_TAG) && encodeByte(byteOp(unopTerm->unop)) && encodeExpression(unopTerm->unopArgument) ); } bool encodeValue(valueType *value) { switch (value->kindOfValue) { case ABSOLUTE_VALUE: return(encodeNumber(value->value)); case RELOCATABLE_VALUE: return(encodeRelocatableNumber(value->value)); case OPERAND_VALUE: return(encodeOperand(value->value)); case STRING_VALUE: return(encodeString(value->value)); case CONDITION_VALUE: return(encodeCondition(value->value)); case DATA_VALUE: case BSS_VALUE: case STRUCT_VALUE: case FIELD_VALUE: case MACRO_VALUE: case UNDEFINED_VALUE: case FUNCTION_VALUE: case BLOCK_VALUE: case BUILT_IN_FUNCTION_VALUE: case ARRAY_VALUE: case FAIL: error(WRONG_KIND_OF_VALUE_IN_OBJECT_EXPRESSION_ERROR, valueKindString(value->kindOfValue)); return(FALSE); } } bool encodeExpression(expressionType *expression) { nullEncode(expression); switch (expression->kindOfTerm) { case ARRAY_EXPR: error(ARRAY_TERM_IN_OBJECT_EXPRESSION_ERROR); return(FALSE); break; case ASSIGN_EXPR: return(encodeAssignmentTerm(expression->expressionTerm.binopUnion)); break; case BINOP_EXPR: return(encodeBinopTerm(expression->expressionTerm.binopUnion)); break; case CONDITION_CODE_EXPR: return(encodeCondition(expression->expressionTerm.conditionTypeUnion)); break; case FUNCTION_CALL_EXPR: return(encodeFunctionCall(expression->expressionTerm.functionCallUnion)); break; case HERE_EXPR: return(encodeHere()); break; case IDENTIFIER_EXPR: return(encodeIdentifier(expression->expressionTerm.identifierUnion)); break; case NUMBER_EXPR: return(encodeNumber(expression->expressionTerm.numberUnion)); break; case POSTOP_EXPR: return(encodePostopTerm(expression->expressionTerm.postOpUnion)); break; case PREOP_EXPR: return(encodePreopTerm(expression->expressionTerm.preOpUnion)); break; case SUBEXPRESSION_EXPR: encodeExpression(expression->expressionTerm.expressionUnion); break; case STRING_EXPR: return(encodeString(expression->expressionTerm.stringUnion)); break; case UNOP_EXPR: return(encodeUnopTerm(expression->expressionTerm.unopUnion)); break; case VALUE_EXPR: return(encodeValue(expression->expressionTerm.valueUnion)); break; default: botch("encodeExpression: funny expression kind %d\n", expression->kindOfTerm); break; } } bool encodeAssertStatement(assertStatementBodyType *assertStatement) { return( encodeByte(ASSERT_TAG) && encodeExpression(assertStatement->condition) && encodeExpression(assertStatement->message) ); } bool encodeFreturnStatement(freturnStatementBodyType *freturnStatement) { return( encodeByte(FRETURN_TAG) && encodeExpression(freturnStatement) ); } bool encodeMdefineStatement(defineStatementBodyType *mdefineStatement) { return( encodeByte(MDEFINE_TAG) && encodeIdentifier(mdefineStatement->theSymbol) && encodeExpression(mdefineStatement->theValue) ); } bool encodeMdoUntilStatement(mdoUntilStatementBodyType *mdoUntilStatement) { return( encodeByte(MDOUNTIL_TAG) && encodeExpression(mdoUntilStatement->mdoUntilCondition) && encodeBlock(mdoUntilStatement->mdoUntilLoop) ); } bool encodeMdoWhileStatement(mdoWhileStatementBodyType *mdoWhileStatement) { return( encodeByte(MDOWHILE_TAG) && encodeExpression(mdoWhileStatement->mdoWhileCondition) && encodeBlock(mdoWhileStatement->mdoWhileLoop) ); } bool encodeMforStatement(mforStatementBodyType *mforStatement) { return( encodeByte(MFOR_TAG) && encodeExpression(mforStatement->initExpression) && encodeExpression(mforStatement->testExpression) && encodeExpression(mforStatement->incrExpression) && encodeBlock(mforStatement->forLoop) ); } bool encodeMifStatement(mifStatementBodyType *mifStatement) { return( encodeByte(MIF_TAG) && encodeExpression(mifStatement->mifCondition) && encodeBlock(mifStatement->mifConsequence) && encodeBlock(mifStatement->mifContinuation.mifBlockUnion) ); } bool encodeMswitchStatement(mswitchStatementBodyType *mswitchStatement) { caseListType *caseList; caseType *theCase; expressionListType *tagExpressionList; if (!(encodeByte(MSWITCH_TAG) && encodeExpression(mswitchStatement-> switchExpression))) return(FALSE); for (caseList=mswitchStatement->cases; caseList!=NULL; caseList=caseList-> nextCase) { theCase = caseList->theCase; for (tagExpressionList=theCase->caseTags; tagExpressionList!=NULL; tagExpressionList=tagExpressionList->nextExpression) { if (!encodeExpression(tagExpressionList->theExpression)) return(FALSE); } if (!encodeBlock(theCase->caseBody)) return(FALSE); } return(encodeByte(END_TAG)); } bool encodeMvariableStatement(mvariableStatementBodyType *mvariableStatement) { int length; if ((length=expressionListLength(mvariableStatement->theValue) > 1) || mvariableStatement->theDimension!=NULL) { error(ARRAY_MVARIABLE_IN_OBJECT_FUNCTION_ERROR); return(FALSE); } if (!(encodeByte(MVARIABLE_TAG) && encodeIdentifier(mvariableStatement-> theSymbol))) return(FALSE); if (length == 1) return(encodeExpression(mvariableStatement->theValue-> theExpression)); else return(encodeExpression(NULL)); } bool encodeMwhileStatement(mwhileStatementBodyType *mwhileStatement) { return( encodeByte(MWHILE_TAG) && encodeExpression(mwhileStatement->mwhileCondition) && encodeBlock(mwhileStatement->mwhileLoop) ); } bool encodeStatement(statementType *statement) { switch(statement->kindOfStatement) { case ALIGN_STATEMENT: case BLOCK_STATEMENT: case BYTE_STATEMENT: case CONSTRAIN_STATEMENT: case DBYTE_STATEMENT: case DEFINE_STATEMENT: case DO_UNTIL_STATEMENT: case DO_WHILE_STATEMENT: case EXTERN_STATEMENT: case FUNCTION_STATEMENT: case IF_STATEMENT: case INCLUDE_STATEMENT: case INSTRUCTION_STATEMENT: case LONG_STATEMENT: case MACRO_STATEMENT: case ORG_STATEMENT: case REL_STATEMENT: case START_STATEMENT: case STRING_STATEMENT: case STRUCT_STATEMENT: case TARGET_STATEMENT: case UNDEFINE_STATEMENT: case VARIABLE_STATEMENT: case WHILE_STATEMENT: case WORD_STATEMENT: error(ILLEGAL_STATEMENT_IN_OBJECT_FILE_FUNCTION_ERROR, statementKindString(statement->kindOfStatement)); return(FALSE); case ASSERT_STATEMENT: return(encodeAssertStatement(statement->statementBody.assertUnion)); case FRETURN_STATEMENT: return(encodeFreturnStatement(statement->statementBody.freturnUnion)); case GROUP_STATEMENT: return(encodeBlock(statement->statementBody.groupUnion)); case MDEFINE_STATEMENT: return(encodeMdefineStatement(statement->statementBody.defineUnion)); case MDO_UNTIL_STATEMENT: return(encodeMdoUntilStatement(statement->statementBody.mdoUntilUnion)); case MDO_WHILE_STATEMENT: return(encodeMdoWhileStatement(statement->statementBody.mdoWhileUnion)); case MFOR_STATEMENT: return(encodeMforStatement(statement->statementBody.mforUnion)); case MIF_STATEMENT: return(encodeMifStatement(statement->statementBody.mifUnion)); case MSWITCH_STATEMENT: return(encodeMswitchStatement(statement->statementBody.mswitchUnion)); case MVARIABLE_STATEMENT: return(encodeMvariableStatement(statement->statementBody.mvariableUnion)); case MWHILE_STATEMENT: return(encodeMwhileStatement(statement->statementBody.mwhileUnion)); case NULL_STATEMENT: return(TRUE); case PERFORM_STATEMENT: return(encodeExpression(statement->statementBody.expressionUnion)); default: botch("encodeStatementBody doesn't know kind %d\n", statement->kindOfStatement); return(FALSE); } } bool encodeBlock(blockType *block) { if (!encodeByte(BLOCK_TAG)) return(FALSE); while (block != NULL) { if (!encodeStatement(block)) return(FALSE); block = block->nextStatement; } return(encodeByte(END_TAG)); }