/* Error handling for gpasm
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
James Bowman, Craig Franklin
This file is part of gputils.
gputils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
gputils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with gputils; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "stdhdr.h"
#include "libgputils.h"
#include "gpasm.h"
#include "gperror.h"
#include "lst.h"
struct error_list {
int value;
struct error_list *next;
};
static struct error_list *errorcodes_list = NULL;
void add_code(int code)
{
struct error_list *new;
struct error_list *list;
if ((code <= -100) && (code >= -199)) {
gpwarning(GPW_DISABLE_ERROR, NULL);
} else {
new = (struct error_list *)malloc(sizeof(*new));
new->value = code;
new->next = NULL;
if (errorcodes_list) {
/* the list has been started, scan the list for the end */
list = errorcodes_list;
while(list->next) {
list = list->next;
}
list->next = new; /* append the new value to the end of list */
} else {
errorcodes_list = new; /* new list */
}
}
}
static int check_code(int code)
{
struct error_list *p;
int print = 1;
p = errorcodes_list;
while(p) {
if (p->value == code){
print = 1;
} else if (p->value == -(code)) {
print = 0;
}
p = p->next;
}
return print;
}
char *gp_geterror(unsigned int code)
{
switch(code) {
case GPE_OPENPAR:
return "Unmatched (";
case GPE_CLOSEPAR:
return "Unmatched )";
case GPE_BADCHAR:
return "Illegal character.";
case GPE_NOSYM:
return "Symbol not previously defined.";
case GPE_DIVBY0:
return "Divide by zero.";
case GPE_DUPLAB:
return "Duplicate label or redefining symbol that cannot be redefined.";
case GPE_DIFFLAB:
return "Address label duplicated or different in second pass.";
case GPE_ADDROVF:
return "Address wrapped around 0. ";
case GPE_ADDROVR:
return "Overwriting previous address contents.";
case GPE_BAD_CALL_ADDR:
return "Call or jump not allowed at this address (must be in low half of page)";
case GPE_ILLEGAL_LABEL:
return "Illegal label.";
case GPE_ILLEGAL_DIR:
return "Illegal directive (Not Valid for this processor).";
case GPE_ILLEGAL_ARGU:
return "Illegal argument.";
case GPE_ILLEGAL_COND:
return "Illegal condition.";
case GPE_RANGE:
return "Argument out of range.";
case GPE_TOO_MANY_ARGU:
return "Too many arguments.";
case GPE_MISSING_ARGU:
return "Missing argument(s).";
case GPE_EXPECTED:
return "Expected";
case GPE_EXTRA_PROC:
return "Processor type previously defined.";
case GPE_UNDEF_PROC:
return "Processor type is undefined.";
case GPE_UNKNOWN_PROC:
return "Unknown processor.";
case GPE_IHEX:
return "Hex file format INHX32 required.";
case GPE_NO_MACRO_NAME:
return "Macro name missing.";
case GPE_DUPLICATE_MACRO:
return "Duplicate macro name.";
case GPE_BAD_WHILE_LOOP:
return "WHILE must terminate within 256 iterations.";
case GPE_ILLEGAL_NESTING:
return "Illegal nesting.";
case GPE_UNMATCHED_ENDM:
return "Unmatched ENDM.";
case GPE_OBJECT_ONLY:
return "Directive only allowed when generating an object file.";
case GPE_UNRESOLVABLE:
return "Operand contains unresolvable labels or is too complex.";
case GPE_WRONG_SECTION:
return "Executable code and data must be defined in an appropriate section.";
case GPE_CONTIG_SECTION:
return "Each object file section must be contiguous.";
case GPE_MUST_BE_LABEL:
return "Operand must be an address label.";
case GPE_FILL_ODD:
return "Cannot use FILL Directive with odd number of bytes.";
case GPE_CONTIG_CONFIG:
return "__CONFIG directives must be contiguous.";
case GPE_CONTIG_IDLOC:
return "__IDLOC directives must be contiguous.";
case GPE_MISSING_BRACKET:
return "Square brackets required around offset operand.";
case GPE_UNKNOWN:
default:
return "UNKNOWN";
}
}
void gperror(unsigned int code,
char *message)
{
char full_message[BUFSIZ];
if (state.pass == 2) {
if(message == NULL)
message = gp_geterror(code);
#ifndef GP_USER_ERROR
/* standard output */
if (!state.quiet) {
if (state.src)
snprintf(full_message, sizeof(full_message),
"%s:%d:Error [%03d] %s",
state.src->name,
state.src->line_number,
code,
message);
else
snprintf(full_message, sizeof(full_message),
"Error [%03d] %s",
code,
message);
printf("%s\n", full_message);
}
#else
user_error(code, message);
#endif
/* list file output */
snprintf(full_message, sizeof(full_message),
"Error [%03d] : %s",
code,
message);
lst_line(full_message);
state.num.errors++;
}
}
char *gp_getwarning(unsigned int code)
{
switch(code) {
case GPW_NOT_DEFINED:
return "Symbol not previously defined.";
case GPW_RANGE:
return "Argument out of range. Least significant bits used.";
case GPW_OP_COLUMN_ONE:
return "Found opcode in column 1.";
case GPW_DIR_COLUMN_ONE:
return "Found directive in column 1.";
case GPW_MACRO_COLUMN_ONE:
return "Found call to macro in column 1.";
case GPW_LABEL_COLUMN:
return "Found label after column 1.";
case GPW_MISSING_QUOTE:
return "Missing quote.";
case GPW_EXTRANEOUS:
return "Extraneous arguments on the line.";
case GPW_EXPECTED:
return "Expected.";
case GPW_CMDLINE_PROC:
return "Processor superseded by command line.";
case GPW_CMDLINE_RADIX:
return "Radix superseded by command line.";
case GPW_CMDLINE_HEXFMT:
return "Hex file format specified on command line.";
case GPW_RADIX:
return "Expected dec, oct, hex. Will use hex.";
case GPW_INVALID_RAM:
return "Invalid RAM location specified.";
case GPW_DISABLE_ERROR:
return "Error messages cannot be disabled.";
case GPW_REDEFINING_PROC:
return "Redefining processor.";
case GPW_NOT_RECOMMENDED:
return "Use of this instruction is not recommended.";
case GPW_INVALID_ROM:
return "Invalid ROM location specified.";
case GPW_UNKNOWN:
default:
return "UNKNOWN";
}
}
void gpwarning(unsigned int code,
char *message)
{
char full_message[BUFSIZ];
if (state.pass ==2) {
if ((state.error_level <= 1) && check_code(code)) {
if(message == NULL)
message = gp_getwarning(code);
#ifndef GP_USER_WARNING
/* standard output */
if (!state.quiet) {
if (state.src)
snprintf(full_message, sizeof(full_message),
"%s:%d:Warning [%03d] %s",
state.src->name,
state.src->line_number,
code,
message);
else
snprintf(full_message, sizeof(full_message),
"Warning [%03d] %s",
code,
message);
printf("%s\n", full_message);
}
#else
user_warning(code, message);
#endif
/* list file output */
snprintf(full_message, sizeof(full_message),
"Warning [%03d] : %s",
code,
message);
lst_line(full_message);
state.num.warnings++;
} else {
state.num.warnings_suppressed++;
}
}
}
char *gp_getmessage(unsigned int code)
{
switch(code) {
case GPM_USER:
return "MESSAGE:";
case GPM_BANK:
return "Register in operand not in bank 0. Ensure bank bits are correct.";
case GPM_RANGE:
return "Program word too large. Truncated to core size.";
case GPM_IDLOC:
return "ID Locations value too large. Last four hex digits used.";
case GPM_NOF:
return "Using default destination of 1 (file).";
case GPM_PAGE:
return "Crossing page boundary -- ensure page bits are set.";
case GPM_PAGEBITS:
return "Setting page bits.";
case GPM_SUPVAL:
return "Warning level superceded by command line value.";
case GPM_SUPLIN:
return "Macro expansion superceded by command line value.";
case GPM_SUPRAM:
return "Superceding current maximum RAM and RAM map.";
case GPM_EXTPAGE:
return "Page or Bank selection not needed for this device.";
case GPM_CBLOCK:
return "CBLOCK will begin at address 0.";
case GPM_W_MODIFIED:
return "W Register modified.";
case GPM_SPECIAL_MNEMONIC:
return "Special Instruction Mnemonic used.";
case GPM_UNKNOWN:
default:
return "UNKNOWN MESSAGE";
}
}
void gpmessage(unsigned int code,
char *message)
{
char full_message[BUFSIZ];
if (state.pass==2) {
if ((state.error_level == 0) && check_code(code)){
if(message == NULL)
message = gp_getmessage(code);
#ifndef GP_USER_MESSAGE
/* standard output */
if (!state.quiet) {
if (state.src)
snprintf(full_message, sizeof(full_message),
"%s:%d:Message [%03d] %s",
state.src->name,
state.src->line_number,
code,
message);
else
snprintf(full_message, sizeof(full_message),
"Message [%03d] %s",
code,
message);
printf("%s\n", full_message);
}
#else
user_message(code, message);
#endif
/* list file output */
snprintf(full_message, sizeof(full_message),
"Message [%03d] : %s",
code,
message);
lst_line(full_message);
state.num.messages++;
} else {
state.num.messages_suppressed++;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1