X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Ferror.c;h=f73f0a4a0c24dbde36d2b65de714936ed1837d29;hb=112ae0e3db511ddd92e769c11328646ebe2a6240;hp=9d0455ae99793fb23346a760885d9105fc5deda7;hpb=64dac7e7b7814a0ee5295608f47faae024825058;p=cc65 diff --git a/src/cc65/error.c b/src/cc65/error.c index 9d0455ae9..f73f0a4a0 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2009, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -37,8 +37,13 @@ #include #include +/* common */ +#include "print.h" + +/* cc65 */ #include "global.h" #include "input.h" +#include "lineinfo.h" #include "scanner.h" #include "stmt.h" #include "error.h" @@ -46,280 +51,260 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ -static char* WarnMsg [WARN_COUNT-1] = { - "Unreachable code", - "Condition is never true", - "Condition is always true", - "Converting pointer to integer without a cast", - "Converting integer to pointer without a cast", - "Function call without a prototype", - "Unknown #pragma", - "No case labels", - "Function must be extern", - "Parameter `%s' is never used", - "`%s' is defined but never used", - "Constant is long", - "`/*' found inside a comment", - "Useless declaration", -}; - - - -/* Error messages sorted by ErrTypes */ -static char* ErrMsg [ERR_COUNT-1] = { - "Invalid character (%u)", - "Unexpected newline", - "End-of-file reached in comment starting at line %u", - "Syntax error", - "`\"' expected", - "`:' expected", - "`;' expected", - "`(' expected", - "`)' expected", - "`[' expected", - "`]' expected", - "`{' expected", - "`}' expected", - "Identifier expected", - "Type expected", - "Incompatible types", - "Incompatible pointer types", - "Too many arguments in function call", - "Too few arguments in function call", - "Macro argument count mismatch", - "Duplicate macro parameter: %s", - "Variable identifier expected", - "Integer expression expected", - "Constant expression expected", - "No active loop", - "`\"' or `<' expected", - "Missing terminator or name too long", - "Include file `%s' not found", - "Cannot open include file `%s': %s", - "Invalid #error directive", - "#error: %s", - "Unexpected `#endif'", - "Unexpected `#else'", - "`#endif' expected", - "Compiler directive expected", - "Redefinition of `%s'", - "Conflicting types for `%s'", - "String literal expected", - "`while' expected", - "Function must return a value", - "Function cannot return a value", - "Unexpected `continue'", - "Undefined symbol: `%s'", - "Undefined label: `%s'", - "Include nesting too deep", - "Too many local variables", - "Too many initializers", - "Cannot initialize incomplete type", - "Cannot subscript", - "Operation not allowed with this type of argument", - "Struct expected", - "Struct/union has no field named `%s'", - "Struct pointer expected", - "lvalue expected", - "Expression expected", - "Preprocessor expression expected", - "Illegal type", - "Illegal function call", - "Illegal indirection", - "Illegal address", - "Illegal macro call", - "Illegal hex digit", - "Illegal character constant", - "Illegal modifier", - "Illegal type qualifier", - "Illegal storage class", - "Illegal segment name: `%s'", - "Division by zero", - "Modulo operation with zero", - "Range error", - "Symbol is already different kind", - "Too many lexical levels", - "Parameter name omitted", - "Old style function decl used as prototype", - "Declaration for parameter `%s' but no such parameter", - "Cannot take address of a register variable", - "Illegal size of data type", - "__fastcall__ is not allowed for C functions", - "Variable has unknown size", - "Unknown identifier: `%s'", - "Duplicate qualifier: `%s'", - "Assignment to const", - "Pointer types differ in type qualifiers", -}; - - - -static char* FatMsg [FAT_COUNT-1] = { - "Too many errors", - "Cannot open output file: %s", - "Cannot write to output file (disk full?)", - "Cannot open input file: %s", - "Out of memory", - "Stack overflow", - "Stack empty", - "Out of string space", - "Too many case labels", -}; - - - /* Count of errors/warnings */ unsigned ErrorCount = 0; unsigned WarningCount = 0; +/* Warning and error options */ +IntStack WarnEnable = INTSTACK(1); /* Enable warnings */ +IntStack WarningsAreErrors = INTSTACK(0); /* Treat warnings as errors */ +IntStack WarnStructParam = INTSTACK(1); /* Warn about structs passed by val */ +IntStack WarnUnusedLabel = INTSTACK(1); /* Warn about unused labels */ +IntStack WarnUnusedParam = INTSTACK(1); /* Warn about unused parameters */ +IntStack WarnUnusedVar = INTSTACK(1); /* Warn about unused variables */ +IntStack WarnUnknownPragma = INTSTACK(1); /* Warn about unknown #pragmas */ + +/* Map the name of a warning to the intstack that holds its state */ +typedef struct WarnMapEntry WarnMapEntry; +struct WarnMapEntry { + IntStack* Stack; + const char* Name; +}; +static WarnMapEntry WarnMap[] = { + /* Keep sorted, even if this isn't used for now */ + { &WarningsAreErrors, "error" }, + { &WarnStructParam, "struct-param" }, + { &WarnUnknownPragma, "unknown-pragma" }, + { &WarnUnusedLabel, "unused-label" }, + { &WarnUnusedParam, "unused-param" }, + { &WarnUnusedVar, "unused-var" }, +}; + /*****************************************************************************/ -/* Code */ +/* Handling of fatal errors */ /*****************************************************************************/ -void Warning (unsigned WarnNum, ...) -/* Print warning message. */ +void Fatal (const char* Format, ...) +/* Print a message about a fatal error and die */ { va_list ap; - if (!NoWarn) { - fprintf (stderr, "%s(%u): Warning #%u: ", - GetCurrentFile(), curpos, WarnNum); + const char* FileName; + unsigned LineNum; + if (CurTok.LI) { + FileName = GetInputName (CurTok.LI); + LineNum = GetInputLine (CurTok.LI); + } else { + FileName = GetCurrentFile (); + LineNum = GetCurrentLine (); + } - va_start (ap, WarnNum); - vfprintf (stderr, WarnMsg [WarnNum-1], ap); - va_end (ap); - fprintf (stderr, "\n"); + fprintf (stderr, "%s(%u): Fatal: ", FileName, LineNum); + + va_start (ap, Format); + vfprintf (stderr, Format, ap); + va_end (ap); + fprintf (stderr, "\n"); - if (Verbose) { - fprintf (stderr, "Line: %s\n", line); - } + if (Line) { + Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } - ++ WarningCount; + exit (EXIT_FAILURE); } -void PPWarning (unsigned WarnNum, ...) -/* Print warning message. For use within the preprocessor. */ +void Internal (const char* Format, ...) +/* Print a message about an internal compiler error and die. */ { va_list ap; - if (!NoWarn) { - fprintf (stderr, "%s(%u): Warning #%u: ", - GetCurrentFile(), GetCurrentLine(), WarnNum); + const char* FileName; + unsigned LineNum; + if (CurTok.LI) { + FileName = GetInputName (CurTok.LI); + LineNum = GetInputLine (CurTok.LI); + } else { + FileName = GetCurrentFile (); + LineNum = GetCurrentLine (); + } + + fprintf (stderr, "%s(%u): Internal compiler error:\n", + FileName, LineNum); - va_start (ap, WarnNum); - vfprintf (stderr, WarnMsg [WarnNum-1], ap); - va_end (ap); - fprintf (stderr, "\n"); + va_start (ap, Format); + vfprintf (stderr, Format, ap); + va_end (ap); + fprintf (stderr, "\n"); + + if (Line) { + fprintf (stderr, "\nInput: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } - ++WarningCount; + + /* Use abort to create a core dump */ + abort (); } -void Error (unsigned ErrNum, ...) -/* Print an error message */ -{ - va_list ap; +/*****************************************************************************/ +/* Handling of errors */ +/*****************************************************************************/ - fprintf (stderr, "%s(%u): Error #%u: ", - GetCurrentFile(), curpos, ErrNum); - va_start (ap, ErrNum); - vfprintf (stderr, ErrMsg [ErrNum-1], ap); - va_end (ap); + +static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va_list ap) +/* Print an error message - internal function*/ +{ + fprintf (stderr, "%s(%u): Error: ", Filename, LineNo); + vfprintf (stderr, Msg, ap); fprintf (stderr, "\n"); - if (Verbose) { - fprintf (stderr, "Line: %s\n", line); + if (Line) { + Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } ++ErrorCount; if (ErrorCount > 10) { - Fatal (FAT_TOO_MANY_ERRORS); + Fatal ("Too many errors"); } } -void PPError (unsigned ErrNum, ...) -/* Print an error message. For use within the preprocessor. */ +void Error (const char* Format, ...) +/* Print an error message */ { va_list ap; + va_start (ap, Format); + IntError (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap); + va_end (ap); +} - fprintf (stderr, "%s(%u): Error #%u: ", - GetCurrentFile(), GetCurrentLine(), ErrNum); - va_start (ap, ErrNum); - vfprintf (stderr, ErrMsg [ErrNum-1], ap); - va_end (ap); - fprintf (stderr, "\n"); - ++ErrorCount; - if (ErrorCount > 10) { - Fatal (FAT_TOO_MANY_ERRORS); - } +void LIError (const LineInfo* LI, const char* Format, ...) +/* Print an error message with the line info given explicitly */ +{ + va_list ap; + va_start (ap, Format); + IntError (GetInputName (LI), GetInputLine (LI), Format, ap); + va_end (ap); } -void Fatal (unsigned FatNum, ...) -/* Print a message about a fatal error and die */ +void PPError (const char* Format, ...) +/* Print an error message. For use within the preprocessor. */ { va_list ap; + va_start (ap, Format); + IntError (GetCurrentFile(), GetCurrentLine(), Format, ap); + va_end (ap); +} - fprintf (stderr, "%s(%u): Fatal #%u: ", - GetCurrentFile(), curpos, FatNum); - va_start (ap, FatNum); - vfprintf (stderr, FatMsg [FatNum-1], ap); - va_end (ap); - fprintf (stderr, "\n"); - if (Verbose) { - fprintf (stderr, "Line: %s\n", line); +/*****************************************************************************/ +/* Handling of warnings */ +/*****************************************************************************/ + + + +static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, va_list ap) +/* Print warning message - internal function. */ +{ + if (IS_Get (&WarningsAreErrors)) { + + /* Treat the warning as an error */ + IntError (Filename, LineNo, Msg, ap); + + } else if (IS_Get (&WarnEnable)) { + + fprintf (stderr, "%s(%u): Warning: ", Filename, LineNo); + vfprintf (stderr, Msg, ap); + fprintf (stderr, "\n"); + + if (Line) { + Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); + } + ++WarningCount; + } - exit (EXIT_FAILURE); } -void Internal (char* Format, ...) -/* Print a message about an internal compiler error and die. */ +void Warning (const char* Format, ...) +/* Print warning message. */ +{ + va_list ap; + va_start (ap, Format); + IntWarning (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap); + va_end (ap); +} + + + +void LIWarning (const LineInfo* LI, const char* Format, ...) +/* Print a warning message with the line info given explicitly */ { va_list ap; + va_start (ap, Format); + IntWarning (GetInputName (LI), GetInputLine (LI), Format, ap); + va_end (ap); +} + - fprintf (stderr, "%s(%u): Internal compiler error:\n", - GetCurrentFile(), curpos); +void PPWarning (const char* Format, ...) +/* Print warning message. For use within the preprocessor. */ +{ + va_list ap; va_start (ap, Format); - vfprintf (stderr, Format, ap); + IntWarning (GetCurrentFile(), GetCurrentLine(), Format, ap); va_end (ap); - fprintf (stderr, "\nLine: %s\n", line); +} - /* Use abort to create a core dump */ - abort (); + + +IntStack* FindWarning (const char* Name) +/* Search for a warning in the WarnMap table and return a pointer to the + * intstack that holds its state. Return NULL if there is no such warning. + */ +{ + unsigned I; + + /* For now, do a linear search */ + for (I = 0; I < sizeof(WarnMap) / sizeof (WarnMap[0]); ++I) { + if (strcmp (WarnMap[I].Name, Name) == 0) { + return WarnMap[I].Stack; + } + } + return 0; } +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + void ErrorReport (void) /* Report errors (called at end of compile) */ { - if (ErrorCount == 0 && Verbose) { - printf ("No errors.\n"); - } + Print (stdout, 1, "%u errors, %u warnings\n", ErrorCount, WarningCount); } -