OpenCores
URL https://opencores.org/ocsvn/forwardcom/forwardcom/trunk

Subversion Repositories forwardcom

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 57 to Rev 58
    Reverse comparison

Rev 57 → Rev 58

/forwardcom/bintools/error.cpp
0,0 → 1,525
/**************************** error.cpp **********************************
* Author: Agner Fog
* Date created: 2017-11-03
* Last modified: 2021-03-30
* Version: 1.11
* Project: Binary tools for ForwardCom instruction set
* Module: error.cpp
* Description:
* Standard procedure for error reporting to stderr
*
* Copyright 2006-2021 GNU General Public License http://www.gnu.org/licenses
******************************************************************************
 
You may set breakpoints here to trace errors (use stack trace)
 
Runtime errors during emulation are not going here, but to
CThread::interrupt in emulator6.cpp
 
*****************************************************************************/
 
#include "stdafx.h"
 
// Make and initialize error reporter object
CErrorReporter err;
 
// General error messages
 
// to do: remove unused error messages!
 
SErrorText errorTexts[] = {
// Unknown error
{0, 2, "Unknown error!"},
 
// Warning messages
{ERR_EMPTY_OPTION, 1, "Empty command line option"},
{ERR_UNKNOWN_OPTION, 2, "Unknown command line option: %s"},
{ERR_UNKNOWN_ERROR_NUM, 1, "Unknown warning/error number: %i"},
{ERR_OUTFILE_IGNORED, 1, "Output file name ignored"},
{ERR_MEMBER_NOT_FOUND_EXTRACT, 1, "Library member %s not found. Extraction failed"},
{ERR_MEMBER_NOT_FOUND_DEL, 1, "Library member %s not found. Deletion failed"},
{ERR_DUPLICATE_NAME_COMMANDL, 1, "Library member %s specified more than once"}, // duplicate name on command line
{ERR_DUPLICATE_NAME_IN_LIB, 1, "Library has more than one members named %s"}, // duplicate name in library
{ERR_DUPLICATE_SYMBOL_IN_LIB, 1, "More than one symbol named %s in modules %s"}, // duplicate symbol in library
{ERR_NO_SYMTAB_IN_LIB, 2, "No ForwardCom symbol table found in library"}, // probably wrong library type
{ERR_ABS_RELOCATION_WARN, 1, "Code at line %i is position dependent because it contains absolute address of symbol: %s"}, // warn if absolute address
 
 
{ERR_LIBRARY_FILE_TYPE, 2, "Library file has wrong type: %s"}, // expecting library file
{ERR_LIBRARY_FILE_CORRUPT, 2, "Library file is corrupt"}, // index out of range in library file
{ERR_LIBRARY_LIST_ONLY, 2, "Library list command cannnot be combined with other commands"}, // conflicting commands
{ERR_LIBRARY_MEMBER_TYPE, 2, "Library member %s has wrong type: %s"}, // expecting ForwardCom object file
 
{ERR_LINK_LIST_ONLY, 2, "Linker list command cannnot be combined with other commands"}, // conflicting commands
{ERR_LINK_FILE_TYPE, 2, "Wrong file type. Expecting ForwardCom object file: %s"}, // wrong file type to linker
{ERR_LINK_FILE_TYPE_LIB, 2, "Wrong file type. Expecting ForwardCom library file: %s"}, // wrong file type to linker
{ERR_LINK_FILE_TYPE_EXE, 2, "Wrong file type. Expecting ForwardCom executable file: %s"}, // wrong file type to emulator
{ERR_LINK_COMMUNAL, 1, "Communal section %s has different sizes in modules %s"}, // communal sections not identical
{ERR_LINK_DUPLICATE_SYMBOL, 1, "More than one symbol named %s in modules %s"}, // duplicate symbol encountered during linking
{ERR_LINK_DIFFERENT_BASE, 2, "Link source and target use different base pointers. Cannot link from module %s to symbol %s in module %s"}, // link source and target use different base pointers
{ERR_LINK_MISALIGNED_TARGET, 2, "Link target is misaligned. Scaling failed when linking from module %s to symbol %s in module %s"}, // link target alignment does not fit scale factor
{ERR_LINK_OVERFLOW, 2, "Address overflow when linking from module %s to symbol %s in module %s"}, // relocation overflow
{ERR_LINK_RELOCATION_OVERFLOW, 2, "Address overflow when linking to symbol %s"}, // relocation overflow
{ERR_LINK_REGUSE, 2, "Mismatched register use when linking from module %s to symbol %s. Missing registers: %s"}, // register use mismatch
{ERR_LINK_MODULE_NOT_FOUND, 2, "Module %s not found in library %s"}, // cannot find explicitly specified library module
{ERR_EVENT_SIZE, 1, "Wrong size of event handler records in module %s"}, // event section size not divisible by event record size
{ERR_REL_SYMBOL_NOT_FOUND, 2, "Relocated symbol not found"}, // relocation failed. should not occur
{ERR_CANT_RELINK_MODULE, 2, "Module %s is not relinkable. Cannot remove or replace"}, // attempt to delete or replace non-relinkable module
{ERR_CANT_RELINK_LIBRARY, 2, "Library %s is not relinkable. Cannot remove or replace"}, // attempt to delete or replace non-relinkable library
{ERR_RELINK_MODULE_NOT_FOUND, 1, "Module %s not found in input file. Cannot remove or replace"}, // attempt to delete or replace non-existing module
{ERR_RELINK_LIBRARY_NOT_FOUND, 1, "Library %s not found in input file. Cannot remove or replace"}, // attempt to delete or replace non-existing library
{ERR_RELINK_BASE_POINTER_MOD, 2, "Base pointer overridden during relinking. Relative addresses may be wrong"}, // base pointer has been overridden during relinking
{ERR_INPUT_NOT_RELINKABLE, 2, "File %s is not relinkable"}, // attempt to relink non-relinkable file
{ERR_LINK_UNRESOLVED, 2, "Unresolved external symbol %s in module %s"}, // symbol not found in any module or library
{ERR_LINK_UNRESOLVED_WARN, 1, "Unresolved external symbol %s in module %s"}, // symbol not found. warn only because incomplete output allowed
 
// Error messages
{ERR_MULTIPLE_IO_FILES, 2, "No more than one input file and one output file can be specified"}, //?
{ERR_MULTIPLE_COMMANDS, 2, "More than one command specified on command line: %s"},
{ERR_UNKNOWN_OPTION, 2, "Unknown command line option: %s"},
{ERR_FILES_SAME_NAME, 2, "Input file and output file cannot have same name: %s"},
{ERR_DUMP_NOT_SUPPORTED, 2, "Sorry. Dump of file type %s is not supported"},
{ERR_INDEX_OUT_OF_RANGE, 2, "Index out of range"},
 
{ERR_ELF_RECORD_SIZE, 2, "Error in ELF file. Record size wrong"},
{ERR_ELF_SYMTAB_MISSING, 2, "Symbol table not found in ELF file"},
{ERR_ELF_INDEX_RANGE, 2, "Index out of range in object file"},
{ERR_ELF_UNKNOWN_SECTION, 2, "Unknown section index in ELF file: %i"},
{ERR_ELF_STRING_TABLE, 2, "String table corrupt"},
{ERR_ELF_NO_SECTIONS, 2, "File with absolute constants must have at least one section, even if empty"},
 
{ERR_CONTAINER_INDEX, 2, "Index out of range in internal container"},
{ERR_CONTAINER_OVERFLOW, 2, "Overflow of internal container"},
 
{ERR_INPUT_FILE, 2, "Cannot read input file %s"},
{ERR_OUTPUT_FILE, 2, "Cannot write output file %s"},
{ERR_UNKNOWN_FILE_TYPE, 2, "Unknown file type %i: %s"},
{ERR_FILE_SIZE, 2, "Wrong size of file %s"},
 
{ERR_TOO_MANY_RESP_FILES, 2, "Too many response files"},
{ERR_FILE_NAME_LONG, 2, "File name %s too long"},
{ERR_INSTRUCTION_LIST_SYNTAX, 2, "Syntax error in instruction list: %s"},
{ERR_INSTRUCTION_LIST_QUOTE, 2, "Unmatched quote in instruction list, line %i"}, //?
 
// Fatal errors makes the program stop immediately:
{ERR_INTERNAL, 9, "Objconv program internal inconsistency"}, // table fault, etc.
{ERR_TOO_MANY_ERRORS, 9, "Too many errors. Aborting"},
{ERR_BIG_ENDIAN, 9, "This machine has big-endian memory organization or other incompatibility. Program cannot be compiled on this machine."},
{ERR_MEMORY_ALLOCATION, 9, "Memory allocation failed"},
 
// Mark end of list
{9999, 9999, "End of error text list"}
};
 
 
// Error messages for assembly file
SErrorText assemErrorTexts[] = {
// the status number indicates if an extra string is required
{0, 0, "misplaced unknown token"},
{TOK_NAM, 1, "unknown name: "},
{TOK_LAB, 1, "misplaced label: "},
{TOK_VAR, 1, "misplaced variable: "},
{TOK_SEC, 1, "misplaced section name: "},
{TOK_INS, 1, "misplaced instruction: "},
{TOK_OPR, 1, "misplaced operator: "},
{TOK_NUM, 1, "misplaced number: "},
{TOK_FLT, 1, "misplaced floating point number: "},
{TOK_CHA, 1, "misplaced character constant: "},
{TOK_STR, 1, "misplaced string: "},
{TOK_DIR, 1, "misplaced directive: "},
{TOK_ATT, 1, "misplaced attribute: "},
{TOK_TYP, 1, "misplaced type name: "},
{TOK_OPT, 1, "misplaced option: "},
{TOK_REG, 1, "misplaced register: "},
{TOK_SYM, 1, "misplaced symbol: "},
{TOK_XPR, 1, "misplaced expression: "},
{TOK_HLL, 1, "misplaced keyword: "},
 
{ERR_CONTROL_CHAR, 1, "illegal control character: "},
{ERR_ILLEGAL_CHAR, 1, "illegal character: "},
{ERR_COMMENT_BEGIN, 0, "unmatched comment begin: /*"},
{ERR_COMMENT_END, 0, "unmatched comment end: */"},
{ERR_BRACKET_BEGIN, 1, "unmatched begin bracket: "},
{ERR_BRACKET_END, 1, "unmatched end bracket: "},
{ERR_QUOTE_BEGIN, 1, "unmatched begin quote: "},
{ERR_QUESTION_MARK, 0, "unmatched '?'"},
{ERR_COLON, 0, "unmatched ':'"},
{ERR_SYMBOL_DEFINED, 1, "symbol already defined, cannot redefine: "},
{ERR_SYMBOL_UNDEFINED, 1, "symbol not defined: "},
{ERR_MULTIDIMENSIONAL, 1, "multidimensional array not allowed: "},
{ERR_UNFINISHED_VAR, 1, "unfinished variable declaration: "},
{ERR_MISSING_EXPR, 1, "expecting expression: "},
{ERR_CONFLICT_ARRAYSZ, 1, "conflicting array size: "},
{ERR_CONFLICT_TYPE, 1, "conflicting type of symbol: "},
{ERR_CONDITION, 1, "expression cannot be used for condition: "},
{ERR_OVERFLOW, 1, "expression overflow: "},
{ERR_WRONG_TYPE, 1, "wrong operand type for operator: "},
{ERR_WRONG_TYPE_VAR, 1, "wrong or mismatched type for variable (must be int64, double, string, register, or memory operand): "},
{ERR_WRONG_OPERANDS, 1, "wrong operands for this instruction: "},
{ERR_MISSING_DESTINATION,1, "this instruction needs a destination: "},
{ERR_NO_DESTINATION, 1, "this instruction should not have a destination: "},
{ERR_NOT_OP_AMBIGUOUS, 0, "'!' operator is ambiguous. For booleans and masks replace !A by A^1. For numeric operands replace !A by A==0"},
{ERR_TOO_COMPLEX, 1, "expression does not fit into a single instruction: "},
{ERR_MASK_NOT_REGISTER, 1, "mask must be a register: "},
{ERR_FALLBACK_WRONG, 1, "fallback must be a register 0-30 or zero: "},
{ERR_CONSTANT_TOO_LARGE, 1, "constant too large for specified type: "},
{ERR_ALIGNMENT, 1, "alignment must be a power of 2, not higher than 4096: "}, // maximum alignment value must equal MAX_ALIGN in assem.h
{ERR_SECTION_DIFFERENT_TYPE,1, "redefinition of section is different type: "},
{ERR_EXPECT_COLON, 1, "expecting colon after label: "},
{ERR_STRING_TYPE, 1, "string must have type int8: "},
{ERR_NONZERO_IN_BSS, 1, "data in uninitialized section must be zero: "},
{ERR_SYMBOL_REDEFINED, 1, "symbol has been assigned more than one value: "},
{ERR_EXPORT_EXPRESSION, 1, "cannot export expression: "},
{ERR_CANNOT_EXPORT, 1, "cannot export: "},
{ERR_CODE_WO_SECTION, 1, "code without section: "},
{ERR_DATA_WO_SECTION, 1, "data without section: "},
{ERR_MIX_DATA_AND_CODE, 1, "code and data in same section: "},
{ERR_MUST_BE_CONSTANT, 1, "value must be constant: "},
{ERR_MEM_COMPONENT_TWICE,1, "component of memory operand specified twice: "},
{ERR_SCALE_FACTOR, 1, "wrong scale factor for this instruction: "},
{ERR_MUST_BE_GP, 1, "vector length must be general purpose register: "},
{ERR_LIMIT_AND_OFFSET, 1, "memory operand cannot have both limit and offset: "},
{ERR_NOT_INSIDE_MEM, 1, "this option is not allowed inside memory operand: "},
{ERR_TOO_MANY_OPERANDS, 1, "too many operands: "},
{ERR_TOO_FEW_OPERANDS, 1, "not enough operands: "},
{ERR_OPERANDS_WRONG_ORDER,1, "operands in wrong order. register operands must come first: "},
{ERR_BOTH_MEM_AND_IMMEDIATE, 1, "this instruction cannot have both a memory operand and immediate constant: "}, // except store in format 2.7B and VARIANT_M1
{ERR_BOTH_MEM_AND_OPTIONS, 1, "this instruction cannot have both a memory operand and options: "},
{ERR_UNFINISHED_INSTRUCTION, 1, "unfinished instruction: "},
{ERR_TYPE_MISSING, 1, "type must be specified: "},
{ERR_MASK_FALLBACK_TYPE, 0, "mask and fallback must have same register type as destination"},
{ERR_NEG_INDEX_LENGTH, 0, "length register must be the same as negative index register"},
{ERR_INDEX_AND_LENGTH, 0, "memory operand cannot have length or broadcast with positive index"},
{ERR_MASK_REGISTER, 0, "mask must be register 0-6"},
{ERR_LIMIT_TOO_HIGH, 1, "limit on memory index cannot exceed 0xFFFF: "},
{ERR_NO_INSTRUCTION_FIT, 1, "no version of this instruction fits the specified operands: "},
{ERR_CANNOT_SWAP_VECT, 0, "cannot change the order of vector registers. if the vectors have the same length then put the register operands before the constant or memory operand"},
{ERR_EXPECT_JUMP_TARGET, 1, "expecting jump target: "},
{ERR_JUMP_TARGET_MISALIGN, 1, "jump target offset must be divisible by 4: "},
{ERR_ABS_RELOCATION, 1, "absolute address not possible here: "},
{ERR_RELOCATION_DOMAIN, 1, "cannot calculate difference between two symbols in different domains: "},
{ERR_WRONG_REG_TYPE, 1, "wrong type for register operand: "},
{ERR_CONFLICT_OPTIONS, 1, "conflicting options: "},
{ERR_VECTOR_OPTION, 1, "vector option applied to non-vector operands: "},
{ERR_LENGTH_OPTION_MISS, 1, "vector memory operand must have scalar, length, or broadcast option: "},
{ERR_DEST_BROADCAST, 0, "memory destination cannot have broadcast"},
{ERR_OFFSET_TOO_LARGE, 1, "address offset too large: "},
{ERR_LIMIT_TOO_LARGE, 1, "limit too large: "},
{ERR_IMMEDIATE_TOO_LARGE,1, "instruction format does not have space for full-size constant and option/signbits: "},
{ERR_TOO_LARGE_FOR_JUMP, 1, "conditional jump does not have space for 64-bit constant: "},
{ERR_CANNOT_HAVE_OPTION, 1, "this instruction cannot have options: "},
{ERR_CANNOT_HAVEFALLBACK1, 1, "this instruction cannot have a fallback register: "},
{ERR_CANNOT_HAVEFALLBACK2, 1, "the fallback must be the same as the first source operand when there is a memory operand with index or vector: "},
{ERR_3OP_AND_FALLBACK, 1, "the fallback must be the same as the first source operand on instructions with three operands: "},
{ERR_3OP_AND_MEM, 1, "the first source register must be the same as the destination when there is a memory operand with index or vector: "},
{ERR_R28_30_BASE, 1, "cannot use r28-r30 as base pointer with more than 8 bits offset: "},
{ERR_NO_BASE, 1, "memory operand has no base pointer: "},
{ERR_MEM_WO_BRACKET, 1, "memory operand requires [] bracket: "},
{ERR_UNKNOWN, 1, "unknown assembly error"},
{ERR_UNMATCHED_END, 0, "unmatched end"},
{ERR_SECTION_MISS_END, 1, "missing end of section: "},
{ERR_FUNCTION_MISS_END, 1, "missing end of function: "},
{ERR_ELSE_WO_IF, 1, "else without if: "},
{ERR_EXPECT_PARENTHESIS, 1, "expecting parenthesis: "},
{ERR_EXPECT_BRACKET, 1, "expecting '{' bracket: "},
{ERR_EXPECT_LOGICAL, 1, "expecting logical expression: "},
{ERR_MEM_NOT_ALLOWED, 1, "cannot have memory operand: "},
//{ERR_MUST_BE_POW2, 1, "constant must have only one bit set: "},
{ERR_WHILE_EXPECTED, 1, "'do' statement requires a 'while' here: "},
{ERR_MISPLACED_BREAK, 1, "nothing: to break out of: "},
{ERR_MISPLACED_CONTINUE, 1, "no loop to continue: "}
};
 
// buffer for text strings (this cannot be member of CMemoryBuffer because CErrorReporter must be defined before CMemoryBuffer)
static CMemoryBuffer strings;
 
// Members of class CErrorReporter: reporting of general errors
 
// Constructor for CErrorReporter
CErrorReporter::CErrorReporter() {
numErrors = numWarnings = worstError = 0;
maxWarnings = 50; // Max number of warning messages to pring
maxErrors = 50; // Max number of error messages to print
}
 
SErrorText * CErrorReporter::FindError(int ErrorNumber) {
// Search for error in ErrorTexts
int e;
const int ErrorTextsLength = sizeof(errorTexts) / sizeof(errorTexts[0]);
for (e = 0; e < ErrorTextsLength; e++) {
if (errorTexts[e].errorNumber == ErrorNumber) return errorTexts + e;
}
// Error number not found
static SErrorText UnknownErr = errorTexts[0];
UnknownErr.errorNumber = ErrorNumber;
UnknownErr.status = 0x102; // Unknown error
return &UnknownErr;
}
 
 
void CErrorReporter::submit(int ErrorNumber) {
// Print error message with no extra info
SErrorText * err = FindError(ErrorNumber);
handleError(err, err->text);
}
 
void CErrorReporter::submit(int ErrorNumber, int extra) {
// Print error message with extra numeric info
// ErrorTexts[ErrorNumber] must contain %i where extra is to be inserted
SErrorText * err = FindError(ErrorNumber);
strings.setSize((uint32_t)strlen(err->text) + 10);
sprintf((char*)strings.buf(), err->text, extra);
handleError(err, (char*)strings.buf());
}
 
void CErrorReporter::submit(int ErrorNumber, int extra1, int extra2) {
// Print error message with 2 extra numeric values inserted
// ErrorTexts[ErrorNumber] must contain two %i fields where extra numbers are to be inserted
SErrorText * err = FindError(ErrorNumber);
strings.setSize((uint32_t)strlen(err->text) + 20);
sprintf((char*)strings.buf(), err->text, extra1, extra2);
handleError(err, (char*)strings.buf());
}
 
void CErrorReporter::submit(int ErrorNumber, char const * extra) {
// Print error message with extra text info
// ErrorTexts[ErrorNumber] must contain %s where extra is to be inserted
if (extra == 0) extra = "???";
SErrorText * err = FindError(ErrorNumber);
strings.setSize((uint32_t)strlen(err->text) + (uint32_t)strlen(extra));
sprintf((char*)strings.buf(), err->text, extra);
handleError(err, (char*)strings.buf());
}
 
void CErrorReporter::submit(int ErrorNumber, char const * extra1, char const * extra2) {
// Print error message with two extra text info fields
// ErrorTexts[ErrorNumber] must contain %s where extra texts are to be inserted
if (extra1 == 0) extra1 = "???";
if (extra2 == 0) extra2 = "???";
SErrorText * err = FindError(ErrorNumber);
strings.setSize((uint32_t)strlen(err->text) + (uint32_t)strlen(extra1) + (uint32_t)strlen(extra2));
sprintf((char*)strings.buf(), err->text, extra1, extra2);
handleError(err, (char*)strings.buf());
}
 
void CErrorReporter::submit(int ErrorNumber, char const * extra1, char const * extra2, char const * extra3) {
// Print error message with three extra text info fields
// ErrorTexts[ErrorNumber] must contain %s where extra texts are to be inserted
if (extra1 == 0) extra1 = "???";
if (extra2 == 0) extra2 = "???";
if (extra3 == 0) extra3 = "???";
SErrorText * err = FindError(ErrorNumber);
strings.setSize((uint32_t)strlen(err->text) + (uint32_t)strlen(extra1) + (uint32_t)strlen(extra2) + (uint32_t)strlen(extra3));
sprintf((char*)strings.buf(), err->text, extra1, extra2, extra3);
handleError(err, (char*)strings.buf());
}
 
void CErrorReporter::submit(int ErrorNumber, int extra1, char const * extra2) {
// Print error message with two extra text fields inserted
// ErrorTexts[ErrorNumber] must contain %i and %s where extra texts are to be inserted
if (extra2 == 0) extra2 = "???";
SErrorText * err = FindError(ErrorNumber);
strings.setSize((uint32_t)strlen(err->text) + 10 + (uint32_t)strlen(extra2));
sprintf((char*)strings.buf(), err->text, extra1, extra2);
handleError(err, (char*)strings.buf());
}
 
// Write an error message.
 
void CErrorReporter::handleError(SErrorText * err, char const * text) {
// HandleError is used by submit functions
// check severity
int severity = err->status & 0x0F;
if (severity == 0) {
return; // Ignore message
}
if (severity > 1 && err->errorNumber > worstError) {
// Store highest error number
worstError = err->errorNumber;
}
if (severity == 1) {
// Treat message as warning
if (++numWarnings > maxWarnings) return; // Maximum number of warnings has been printed
// Treat message as warning
fprintf(stderr, "\nWarning %i: %s", err->errorNumber, text);
if (numWarnings == maxWarnings) {
// Maximum number reached
fprintf(stderr, "\nSupressing further warning messages");
}
}
else {
// Treat message as error
if (++numErrors > maxErrors) return; // Maximum number of warnings has been printed
fprintf(stderr, "\nError %i: %s", err->errorNumber, text);
if (numErrors == maxErrors) {
// Maximum number reached
fprintf(stderr, "\nSupressing further warning messages");
}
}
if (severity == 9) {
// Abortion required
fprintf(stderr, "\nAborting\n");
exit(err->errorNumber);
}
}
 
int CErrorReporter::number() {
// Get number of fatal errors
return numErrors;
}
 
int CErrorReporter::getWorstError() {
// Get highest warning or error number encountered
return worstError;
}
 
void CErrorReporter::clearError(int ErrorNumber) {
// Ignore further occurrences of this error
int e;
const int ErrorTextsLength = sizeof(errorTexts) / sizeof(errorTexts[0]);
for (e = 0; e < ErrorTextsLength; e++) {
if (errorTexts[e].errorNumber == ErrorNumber) break;
}
if (e < ErrorTextsLength) {
errorTexts[e].status = 0;
}
}
 
 
 
// Members of class CAssemErrors: reporting of errors in assembly file
CAssemErrors::CAssemErrors() { // Constructor
maxErrors = cmd.maxErrors;
}
 
void CAssemErrors::setOwner(CAssembler * a) {
// Give access to CAssembler
owner = a;
}
 
uint32_t CAssemErrors::numErrors() {
// Return number of errors
return list.numEntries();
}
 
bool CAssemErrors::tooMany() {
// true if too many errors
return list.numEntries() >= maxErrors;
}
 
// Report an error in assembly file
 
void CAssemErrors::report(uint32_t position, uint32_t stringLength, uint32_t num) {
// position: position in input file
// stringLength: length of token
// num = index into assemErrorTexts or token type
owner->lineError = true; // avoid reporting multiple errors on same line
uint32_t linei = owner->linei;
if (linei < owner->lines.numEntries()) {
owner->lines[owner->linei].type = LINE_ERROR; // mark current line as error
}
if (tooMany()) return;
 
SAssemError e;
e.pos = position;
e.stringLength = stringLength;
e.file = owner->filei;
e.num = num;
e.pass = owner->pass;
 
// save error record
list.push(e);
}
 
// Report a misplaced token
void CAssemErrors::report(SToken const & token) {
report(token.pos, token.stringLength, token.type);
}
 
// Report an error in current line
void CAssemErrors::reportLine(uint32_t num) {
int tokenB = owner->lines[owner->linei].firstToken;
int tokenN = owner->lines[owner->linei].numTokens;
if (tokenB <= 0 || tokenN <= 0) {
num = ERR_UNKNOWN;
tokenB = 0;
tokenN = 1;
}
report(owner->tokens[tokenB].pos,
owner->tokens[tokenB + tokenN - 1].pos + owner->tokens[tokenB + tokenN - 1].stringLength - owner->tokens[tokenB].pos, num);
}
 
void CAssemErrors::outputErrors() {
// Output errors to STDERR
const uint32_t tabstops = 8; // default position of tabstops
 
if (list.numEntries() == 0) return;
const char * text1;
char text2[256];
const char * filename = cmd.getFilename(cmd.inputFile); // owner->fileName; // to do: support include filenames
const uint32_t errorTextsLength = TableSize(assemErrorTexts);
uint32_t i, j, texti;
 
uint32_t lastPass = 0;
for (i = 0; i < list.numEntries() && i < maxErrors; i++) {
// tell which pass if verbose option
if (list[i].pass != lastPass && cmd.verbose) {
printf("\n\nDuring pass %i:", list[i].pass);
lastPass = list[i].pass;
}
 
// find line containing error
uint32_t line;
uint32_t numLines = owner->lines.numEntries();
uint32_t pos = list[i].pos;
for (line = 0; line < numLines; line++) {
if (pos < owner->lines[line].beginPos) break;
}
line--;
// if this line has multiple records in lines[] then find the first one
j = line;
while (j > 0 && owner->lines[j - 1].linenum == owner->lines[line].linenum) j--;
line = j;
 
// find column
uint32_t pos1 = owner->lines[line].beginPos;
uint32_t stringLength = list[i].stringLength;
uint32_t column = pos - pos1;
// count UTF-8 multibyte characters in line up to error position
int32_t extraBytes = 0;
int8_t c; // current character
for (uint32_t pp = pos1; pp < pos1 + column; pp++) {
if (pp >= owner->dataSize()) break;
c = *(owner->buf() + pp);
if ((c & 0xC0) == 0xC0) extraBytes--; // count UTF-8 continuation bytes
if (c == '\t') {
uint32_t pos2 = (pp + tabstops) % tabstops; // find next tabstop
extraBytes += pos2 - pp - 1;
}
}
// adjust column number to 1-based. count UTF-8 characters as one
column += extraBytes + 1;
 
// find text
texti = list[i].num;
for (j = 0; j < errorTextsLength; j++) {
if ((uint32_t)assemErrorTexts[j].errorNumber == texti) break;
}
if (j >= errorTextsLength) j = 0;
text1 = assemErrorTexts[j].text;
if (assemErrorTexts[j].status && stringLength < sizeof(text2)) {
// extra text required
memcpy(text2, owner->buf() + pos, stringLength);
text2[stringLength] = 0;
}
else text2[0] = 0;
 
if (filename) {
fprintf(stderr, "\n%s:", filename);
}
else {
fprintf(stderr, "\n");
}
fprintf(stderr, "%i:%i: %s%s", owner->lines[line].linenum, column, text1, text2);
}
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.