2000-05-28 13:40:48 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* error.c */
|
|
|
|
/* */
|
|
|
|
/* Error handling for the cc65 C compiler */
|
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* */
|
2000-07-29 12:03:29 +00:00
|
|
|
/* (C) 1998-2000 Ullrich von Bassewitz */
|
|
|
|
/* Wacholderweg 14 */
|
|
|
|
/* D-70597 Stuttgart */
|
|
|
|
/* EMail: uz@musoftware.de */
|
2000-05-28 13:40:48 +00:00
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* This software is provided 'as-is', without any expressed or implied */
|
|
|
|
/* warranty. In no event will the authors be held liable for any damages */
|
|
|
|
/* arising from the use of this software. */
|
|
|
|
/* */
|
|
|
|
/* Permission is granted to anyone to use this software for any purpose, */
|
|
|
|
/* including commercial applications, and to alter it and redistribute it */
|
|
|
|
/* freely, subject to the following restrictions: */
|
|
|
|
/* */
|
|
|
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
|
|
|
/* claim that you wrote the original software. If you use this software */
|
|
|
|
/* in a product, an acknowledgment in the product documentation would be */
|
|
|
|
/* appreciated but is not required. */
|
|
|
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
|
|
|
/* be misrepresented as being the original software. */
|
|
|
|
/* 3. This notice may not be removed or altered from any source */
|
|
|
|
/* distribution. */
|
|
|
|
/* */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include "global.h"
|
2000-06-14 21:01:37 +00:00
|
|
|
#include "input.h"
|
2000-05-28 13:40:48 +00:00
|
|
|
#include "scanner.h"
|
|
|
|
#include "stmt.h"
|
|
|
|
#include "error.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* 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",
|
2000-06-12 18:31:40 +00:00
|
|
|
"Useless declaration",
|
2000-05-28 13:40:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 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",
|
2000-09-14 19:26:13 +00:00
|
|
|
"`,' expected",
|
2000-05-28 13:40:48 +00:00
|
|
|
"`(' 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",
|
2000-10-10 21:20:34 +00:00
|
|
|
"Macro redefinition is not identical",
|
2000-05-28 13:40:48 +00:00
|
|
|
"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",
|
2000-06-14 21:07:58 +00:00
|
|
|
"Cannot open include file `%s': %s",
|
2000-05-28 13:40:48 +00:00
|
|
|
"Invalid #error directive",
|
|
|
|
"#error: %s",
|
|
|
|
"Unexpected `#endif'",
|
|
|
|
"Unexpected `#else'",
|
|
|
|
"`#endif' expected",
|
|
|
|
"Compiler directive expected",
|
2000-08-14 22:18:26 +00:00
|
|
|
"Redefinition of `%s'",
|
|
|
|
"Conflicting types for `%s'",
|
2000-05-28 13:40:48 +00:00
|
|
|
"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",
|
2000-08-20 09:25:47 +00:00
|
|
|
"Operation not allowed with this type of argument",
|
2000-05-28 13:40:48 +00:00
|
|
|
"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",
|
2000-08-01 18:45:08 +00:00
|
|
|
"Illegal type qualifier",
|
2000-05-28 13:40:48 +00:00
|
|
|
"Illegal storage class",
|
2000-09-14 19:26:13 +00:00
|
|
|
"Illegal attribute",
|
2000-07-29 12:03:29 +00:00
|
|
|
"Illegal segment name: `%s'",
|
2000-05-28 13:40:48 +00:00
|
|
|
"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",
|
2000-06-12 18:31:40 +00:00
|
|
|
"Unknown identifier: `%s'",
|
2000-08-01 18:45:08 +00:00
|
|
|
"Duplicate qualifier: `%s'",
|
2000-08-14 22:18:26 +00:00
|
|
|
"Assignment to const",
|
|
|
|
"Pointer types differ in type qualifiers",
|
2000-05-28 13:40:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* Code */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Warning (unsigned WarnNum, ...)
|
|
|
|
/* Print warning message. */
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
if (!NoWarn) {
|
2000-06-14 21:01:37 +00:00
|
|
|
fprintf (stderr, "%s(%u): Warning #%u: ",
|
|
|
|
GetCurrentFile(), curpos, WarnNum);
|
2000-05-28 13:40:48 +00:00
|
|
|
|
|
|
|
va_start (ap, WarnNum);
|
|
|
|
vfprintf (stderr, WarnMsg [WarnNum-1], ap);
|
|
|
|
va_end (ap);
|
|
|
|
fprintf (stderr, "\n");
|
|
|
|
|
|
|
|
if (Verbose) {
|
|
|
|
fprintf (stderr, "Line: %s\n", line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++ WarningCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PPWarning (unsigned WarnNum, ...)
|
|
|
|
/* Print warning message. For use within the preprocessor. */
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
if (!NoWarn) {
|
2000-06-14 21:01:37 +00:00
|
|
|
fprintf (stderr, "%s(%u): Warning #%u: ",
|
|
|
|
GetCurrentFile(), GetCurrentLine(), WarnNum);
|
2000-05-28 13:40:48 +00:00
|
|
|
|
|
|
|
va_start (ap, WarnNum);
|
|
|
|
vfprintf (stderr, WarnMsg [WarnNum-1], ap);
|
|
|
|
va_end (ap);
|
|
|
|
fprintf (stderr, "\n");
|
|
|
|
}
|
|
|
|
++WarningCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Error (unsigned ErrNum, ...)
|
|
|
|
/* Print an error message */
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
2000-06-14 21:01:37 +00:00
|
|
|
fprintf (stderr, "%s(%u): Error #%u: ",
|
|
|
|
GetCurrentFile(), curpos, ErrNum);
|
2000-05-28 13:40:48 +00:00
|
|
|
|
|
|
|
va_start (ap, ErrNum);
|
|
|
|
vfprintf (stderr, ErrMsg [ErrNum-1], ap);
|
|
|
|
va_end (ap);
|
|
|
|
fprintf (stderr, "\n");
|
|
|
|
|
|
|
|
if (Verbose) {
|
|
|
|
fprintf (stderr, "Line: %s\n", line);
|
|
|
|
}
|
|
|
|
++ErrorCount;
|
|
|
|
if (ErrorCount > 10) {
|
|
|
|
Fatal (FAT_TOO_MANY_ERRORS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PPError (unsigned ErrNum, ...)
|
|
|
|
/* Print an error message. For use within the preprocessor. */
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
2000-06-14 21:01:37 +00:00
|
|
|
fprintf (stderr, "%s(%u): Error #%u: ",
|
|
|
|
GetCurrentFile(), GetCurrentLine(), ErrNum);
|
2000-05-28 13:40:48 +00:00
|
|
|
|
|
|
|
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 Fatal (unsigned FatNum, ...)
|
|
|
|
/* Print a message about a fatal error and die */
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
2000-06-14 21:01:37 +00:00
|
|
|
fprintf (stderr, "%s(%u): Fatal #%u: ",
|
|
|
|
GetCurrentFile(), curpos, FatNum);
|
2000-05-28 13:40:48 +00:00
|
|
|
|
|
|
|
va_start (ap, FatNum);
|
|
|
|
vfprintf (stderr, FatMsg [FatNum-1], ap);
|
|
|
|
va_end (ap);
|
|
|
|
fprintf (stderr, "\n");
|
|
|
|
|
|
|
|
if (Verbose) {
|
|
|
|
fprintf (stderr, "Line: %s\n", line);
|
|
|
|
}
|
|
|
|
exit (EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Internal (char* Format, ...)
|
|
|
|
/* Print a message about an internal compiler error and die. */
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
2000-06-14 21:01:37 +00:00
|
|
|
fprintf (stderr, "%s(%u): Internal compiler error:\n",
|
|
|
|
GetCurrentFile(), curpos);
|
2000-05-28 13:40:48 +00:00
|
|
|
|
|
|
|
va_start (ap, Format);
|
|
|
|
vfprintf (stderr, Format, ap);
|
|
|
|
va_end (ap);
|
|
|
|
fprintf (stderr, "\nLine: %s\n", line);
|
|
|
|
|
|
|
|
/* Use abort to create a core dump */
|
|
|
|
abort ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ErrorReport (void)
|
|
|
|
/* Report errors (called at end of compile) */
|
|
|
|
{
|
|
|
|
if (ErrorCount == 0 && Verbose) {
|
|
|
|
printf ("No errors.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-06-14 21:01:37 +00:00
|
|
|
|