/* "errors" : Warnings, errors and fatal errors */
/* (with error throwback code for RISC OS machines) */
/* */
-/* Copyright (c) Graham Nelson 1993 - 2020 */
-/* */
-/* This file is part of Inform. */
+/* Part of Inform 6.42 */
+/* copyright (c) Graham Nelson 1993 - 2024 */
/* */
/* Inform is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
ErrorPosition ErrorReport; /* Maintained by "lexer.c" */
+static char other_pos_buff[ERROR_BUFLEN+1]; /* Used by location_text() */
+
static void print_preamble(void)
{
/* Only really prints the preamble to an error or warning message:
if (!(ErrorReport.main_flag)) printf("\"%s\", ", p);
printf("line %d: ", ErrorReport.line_number);
+
if (ErrorReport.orig_file) {
char *op;
if (ErrorReport.orig_file <= 0 || ErrorReport.orig_file > total_files)
}
printf("%s", p);
if (with_extension_flag) printf("%s", Source_Extension);
- printf("(%d): ", ErrorReport.line_number);
+ printf("(%d)", ErrorReport.line_number);
+
+ if (ErrorReport.orig_file) {
+ char *op;
+ if (ErrorReport.orig_file <= 0 || ErrorReport.orig_file > total_files)
+ op = ErrorReport.orig_source;
+ else
+ op = InputFiles[ErrorReport.orig_file-1].filename;
+ printf("|%s", op);
+ if (ErrorReport.orig_line) {
+ printf("(%d", ErrorReport.orig_line);
+ if (ErrorReport.orig_char) {
+ printf(":%d", ErrorReport.orig_char);
+ }
+ printf(")");
+ }
+ }
+
+ printf(": ");
break;
case 2: /* Macintosh Programmer's Workshop error message format */
- printf("File \"%s\"; Line %d\t# ", p, ErrorReport.line_number);
+ printf("File \"%s\"; Line %d", p, ErrorReport.line_number);
+
+ if (ErrorReport.orig_file) {
+ char *op;
+ if (ErrorReport.orig_file <= 0 || ErrorReport.orig_file > total_files)
+ op = ErrorReport.orig_source;
+ else
+ op = InputFiles[ErrorReport.orig_file-1].filename;
+ printf(": (\"%s\"", op);
+ if (ErrorReport.orig_line) {
+ printf("; Line %d", ErrorReport.orig_line);
+ if (ErrorReport.orig_char) {
+ printf("; Char %d", ErrorReport.orig_char);
+ }
+ }
+ printf(")");
+ }
+
+ printf("\t# ");
break;
}
}
+static char *location_text(brief_location report_line)
+{
+ int j;
+ char *p;
+ int len;
+
+ /* Convert the location to a brief string.
+ (Some error messages need to report a secondary location.)
+ This uses the static buffer other_pos_buff. */
+
+ ErrorPosition errpos;
+ errpos.file_number = -1;
+ errpos.source = NULL;
+ errpos.line_number = 0;
+ errpos.main_flag = 0;
+ errpos.orig_source = NULL;
+ export_brief_location(report_line, &errpos);
+
+ j = errpos.file_number;
+ if (j <= 0 || j > total_files) p = errpos.source;
+ else p = InputFiles[j-1].filename;
+
+ if (!p && errpos.line_number == 0) {
+ /* Special case */
+ strcpy(other_pos_buff, "compiler setup");
+ return other_pos_buff;
+ }
+
+ if (!p) p = "";
+
+ len = 0;
+
+ if (!(errpos.main_flag)) {
+ snprintf(other_pos_buff+len, ERROR_BUFLEN-len,
+ "\"%s\", ", p);
+ len = strlen(other_pos_buff);
+ }
+ snprintf(other_pos_buff+len, ERROR_BUFLEN-len,
+ "line %d", errpos.line_number);
+
+ return other_pos_buff;
+}
+
+char *current_location_text(void)
+{
+ /* Convert the current lexer location to a brief string.
+ (Called by some trace messages.)
+ This uses the static buffer other_pos_buff. */
+ return location_text(get_brief_location(&ErrorReport));
+}
+
static void ellipsize_error_message_buff(void)
{
/* If the error buffer was actually filled up by a message, it was
#endif
#ifdef MAC_FACE
close_all_source();
- if (temporary_files_switch) remove_temp_files();
abort_transcript_file();
free_arrays();
- if (store_the_text)
- my_free(&all_text,"transcription text");
longjmp(g_fallback, 1);
#endif
exit(1);
}
+extern void fatalerror_fmt(const char *format, ...)
+{
+ va_list argument_pointer;
+ va_start(argument_pointer, format);
+ vsnprintf(error_message_buff, ERROR_BUFLEN, format, argument_pointer);
+ va_end(argument_pointer);
+ ellipsize_error_message_buff();
+ fatalerror(error_message_buff);
+}
+
extern void fatalerror_named(char *m, char *fn)
{ snprintf(error_message_buff, ERROR_BUFLEN, "%s \"%s\"", m, fn);
ellipsize_error_message_buff();
fatalerror(error_message_buff);
}
-extern void memory_out_error(int32 size, int32 howmany, char *name)
+extern void fatalerror_memory_out(int32 size, int32 howmany, char *name)
{ if (howmany == 1)
snprintf(error_message_buff, ERROR_BUFLEN,
"Run out of memory allocating %d bytes for %s", size, name);
fatalerror(error_message_buff);
}
-extern void memoryerror(char *s, int32 size)
-{
- snprintf(error_message_buff, ERROR_BUFLEN,
- "The memory setting %s (which is %ld at present) has been \
-exceeded. Try running Inform again with $%s=<some-larger-number> on the \
-command line.",s,(long int) size,s);
- ellipsize_error_message_buff();
- fatalerror(error_message_buff);
-}
-
/* ------------------------------------------------------------------------- */
/* Survivable diagnostics: */
/* compilation errors style 1 */
/* warnings style 2 */
-/* linkage errors style 3 */
+/* linkage errors style 3 (no longer used) */
/* compiler errors style 4 (these should never happen and */
/* indicate a bug in Inform) */
/* ------------------------------------------------------------------------- */
-static int errors[MAX_ERRORS];
-
-int no_errors, no_warnings, no_suppressed_warnings, no_link_errors,
- no_compiler_errors;
+int no_errors, no_warnings, no_suppressed_warnings, no_compiler_errors;
char *forerrors_buff;
int forerrors_pointer;
static void message(int style, char *s)
-{ int throw_style = style;
+{
if (hash_printed_since_newline) printf("\n");
hash_printed_since_newline = FALSE;
print_preamble();
switch(style)
{ case 1: printf("Error: "); no_errors++; break;
case 2: printf("Warning: "); no_warnings++; break;
- case 3: printf("Error: [linking '%s'] ", current_module_filename);
- no_link_errors++; no_errors++; throw_style=1; break;
+ case 3: printf("Error: [linking] "); no_errors++; break;
case 4: printf("*** Compiler error: ");
- no_compiler_errors++; throw_style=1; break;
+ no_compiler_errors++; break;
}
printf(" %s\n", s);
#ifdef ARC_THROWBACK
- throwback(throw_style, s);
+ throwback(((style <= 2) ? style : 1), s);
#endif
#ifdef MAC_FACE
ProcessEvents (&g_proc);
if (g_proc != true)
{ free_arrays();
- if (store_the_text)
- my_free(&all_text,"transcription text");
close_all_source ();
- if (temporary_files_switch) remove_temp_files();
abort_transcript_file();
longjmp (g_fallback, 1);
}
extern void error(char *s)
{ if (no_errors == MAX_ERRORS)
fatalerror("Too many errors: giving up");
- errors[no_errors] = no_syntax_lines;
message(1,s);
}
-extern void error_named(char *s1, char *s2)
-{ snprintf(error_message_buff, ERROR_BUFLEN,"%s \"%s\"",s1,s2);
+extern void error_fmt(const char *format, ...)
+{
+ va_list argument_pointer;
+ va_start(argument_pointer, format);
+ vsnprintf(error_message_buff, ERROR_BUFLEN, format, argument_pointer);
+ va_end(argument_pointer);
ellipsize_error_message_buff();
error(error_message_buff);
}
-extern void error_numbered(char *s1, int val)
-{
- snprintf(error_message_buff, ERROR_BUFLEN,"%s %d.",s1,val);
+extern void error_named(char *s1, char *s2)
+{ snprintf(error_message_buff, ERROR_BUFLEN,"%s \"%s\"",s1,s2);
ellipsize_error_message_buff();
error(error_message_buff);
}
ErrorReport = E; concise_switch = i;
}
-extern void no_such_label(char *lname)
-{ error_named("No such label as",lname);
-}
-
extern void ebf_error(char *s1, char *s2)
{ snprintf(error_message_buff, ERROR_BUFLEN, "Expected %s but found %s", s1, s2);
ellipsize_error_message_buff();
error(error_message_buff);
}
+extern void ebf_curtoken_error(char *s)
+{
+ /* This is "Expected (s) but found (the current token_text)". We use
+ token_type as a hint for how to display token_text. */
+
+ if (token_type == DQ_TT) {
+ snprintf(error_message_buff, ERROR_BUFLEN, "Expected %s but found string \"%s\"", s, token_text);
+ }
+ else if (token_type == SQ_TT && strlen(token_text)==1) {
+ snprintf(error_message_buff, ERROR_BUFLEN, "Expected %s but found char '%s'", s, token_text);
+ }
+ else if (token_type == SQ_TT) {
+ snprintf(error_message_buff, ERROR_BUFLEN, "Expected %s but found dict word '%s'", s, token_text);
+ }
+ else {
+ /* Symbols, unquoted strings, and numbers can be printed directly. EOF will have "<end of file>" in token_text. */
+ snprintf(error_message_buff, ERROR_BUFLEN, "Expected %s but found %s", s, token_text);
+ }
+
+ ellipsize_error_message_buff();
+ error(error_message_buff);
+}
+
+extern void ebf_symbol_error(char *s1, char *name, char *type, brief_location report_line)
+{ snprintf(error_message_buff, ERROR_BUFLEN, "\"%s\" is a name already in use and may not be used as a %s (%s \"%s\" was defined at %s)", name, s1, type, name, location_text(report_line));
+ ellipsize_error_message_buff();
+ error(error_message_buff);
+}
+
extern void char_error(char *s, int ch)
{ int32 uni;
error(error_message_buff);
}
+extern void error_max_dynamic_strings(int index)
+{
+ if (index >= 96 && !glulx_mode)
+ snprintf(error_message_buff, ERROR_BUFLEN, "Only dynamic strings @(00) to @(95) may be used in Z-code");
+ else if (MAX_DYNAMIC_STRINGS == 0)
+ snprintf(error_message_buff, ERROR_BUFLEN, "Dynamic strings may not be used, because $MAX_DYNAMIC_STRINGS has been set to 0. Increase MAX_DYNAMIC_STRINGS.");
+ else if (MAX_DYNAMIC_STRINGS == 32 && !glulx_mode)
+ snprintf(error_message_buff, ERROR_BUFLEN, "Only dynamic strings @(00) to @(%02d) may be used, because $MAX_DYNAMIC_STRINGS has its default value of %d. Increase MAX_DYNAMIC_STRINGS.", MAX_DYNAMIC_STRINGS-1, MAX_DYNAMIC_STRINGS);
+ else
+ snprintf(error_message_buff, ERROR_BUFLEN, "Only dynamic strings @(00) to @(%02d) may be used, because $MAX_DYNAMIC_STRINGS has been set to %d. Increase MAX_DYNAMIC_STRINGS.", MAX_DYNAMIC_STRINGS-1, MAX_DYNAMIC_STRINGS);
+
+ ellipsize_error_message_buff();
+ error(error_message_buff);
+}
+
+extern void error_max_abbreviations(int index)
+{
+ /* This is only called for Z-code. */
+ if (index >= 96)
+ error("The number of abbreviations has exceeded 96, the limit in Z-code");
+ else
+ error("The number of abbreviations has exceeded MAX_ABBREVS. Increase MAX_ABBREVS.");
+}
+
/* ------------------------------------------------------------------------- */
/* Style 2: Warning message routines */
/* ------------------------------------------------------------------------- */
message(2,s1);
}
-extern void warning_numbered(char *s1, int val)
-{ if (nowarnings_switch) { no_suppressed_warnings++; return; }
- snprintf(error_message_buff, ERROR_BUFLEN,"%s %d.", s1, val);
+extern void warning_fmt(const char *format, ...)
+{
+ va_list argument_pointer;
+ if (nowarnings_switch) { no_suppressed_warnings++; return; }
+ va_start(argument_pointer, format);
+ vsnprintf(error_message_buff, ERROR_BUFLEN, format, argument_pointer);
+ va_end(argument_pointer);
ellipsize_error_message_buff();
message(2,error_message_buff);
}
message(2,error_message_buff);
}
+extern void warning_at(char *name, brief_location report_line)
+{ int i;
+ ErrorPosition E = ErrorReport;
+ if (nowarnings_switch) { no_suppressed_warnings++; return; }
+ export_brief_location(report_line, &ErrorReport);
+ snprintf(error_message_buff, ERROR_BUFLEN, "%s", name);
+ ellipsize_error_message_buff();
+ i = concise_switch; concise_switch = TRUE;
+ message(2,error_message_buff);
+ concise_switch = i;
+ ErrorReport = E;
+}
+
+extern void symtype_warning(char *context, char *name, char *type, char *wanttype)
+{
+ if (nowarnings_switch) { no_suppressed_warnings++; return; }
+ if (name)
+ snprintf(error_message_buff, ERROR_BUFLEN, "In %s, expected %s but found %s \"%s\"", context, wanttype, type, name);
+ else
+ snprintf(error_message_buff, ERROR_BUFLEN, "In %s, expected %s but found %s", context, wanttype, type);
+ ellipsize_error_message_buff();
+ message(2,error_message_buff);
+}
+
extern void dbnu_warning(char *type, char *name, brief_location report_line)
{ int i;
ErrorPosition E = ErrorReport;
message(2,error_message_buff);
}
-/* ------------------------------------------------------------------------- */
-/* Style 3: Link error message routines */
-/* ------------------------------------------------------------------------- */
-
-extern void link_error(char *s)
-{ if (no_errors==MAX_ERRORS) fatalerror("Too many errors: giving up");
- errors[no_errors] = no_syntax_lines;
- message(3,s);
-}
-
-extern void link_error_named(char *s1, char *s2)
-{ snprintf(error_message_buff, ERROR_BUFLEN,"%s \"%s\"",s1,s2);
- ellipsize_error_message_buff();
- link_error(error_message_buff);
-}
-
/* ------------------------------------------------------------------------- */
/* Style 4: Compiler error message routines */
/* ------------------------------------------------------------------------- */
extern void print_sorry_message(void)
{ printf(
"***********************************************************************\n\
-Compiler errors should never occur if Inform is working properly.\n\
-Check to see if there is a more recent version available, from which\n\
-the problem may have been removed. If not, please report this fault\n\
-and if at all possible, please include your source code, as faults\n\
-such as these are rare and often difficult to reproduce. Sorry.\n\
-***********************************************************************\n",
- (RELEASE_NUMBER/100)%10, RELEASE_NUMBER%100, RELEASE_DATE);
+* 'Compiler errors' should never occur if Inform is working properly. *\n\
+* Check to see if there is a more recent version available, from which *\n\
+* the problem may have been removed. If not, please report this fault *\n\
+* and if at all possible, please include your source code, as faults *\n\
+* such as these are rare and often difficult to reproduce. Sorry. *\n\
+***********************************************************************\n");
}
extern int compiler_error(char *s)
-{ if (no_link_errors > 0) return FALSE;
+{
if (no_errors > 0) return FALSE;
if (no_compiler_errors==MAX_ERRORS)
fatalerror("Too many compiler errors: giving up");
}
extern int compiler_error_named(char *s1, char *s2)
-{ if (no_link_errors > 0) return FALSE;
+{
if (no_errors > 0) return FALSE;
snprintf(error_message_buff, ERROR_BUFLEN, "%s \"%s\"",s1,s2);
ellipsize_error_message_buff();
}
extern void errors_allocate_arrays(void)
-{ forerrors_buff = my_malloc(512, "errors buffer");
+{ forerrors_buff = my_malloc(FORERRORS_SIZE, "errors buffer");
}
extern void errors_free_arrays(void)