2020-03-29 19:39:17 +03:00
|
|
|
[CopyErrors::] Copy Errors.
|
|
|
|
|
|
|
|
A copy error is attached to a copy when scanning it reveals some malformation.
|
|
|
|
|
|
|
|
@ Copies can sometimes exist in a damaged form: for example, they are purportedly
|
|
|
|
extension files but have a mangled identification line. Each copy structure
|
|
|
|
therefore has a list attached of errors which occurred in reading it.
|
|
|
|
|
|
|
|
Each copy error has one of the following categories, and some are divided into
|
|
|
|
subcategories too. Otherwise an error has no real contents: only a ragbag of
|
|
|
|
contextual data -- exactly what word it is that is too long, where the
|
|
|
|
sentence is which is mis-punctuated, and such. In every case most of these
|
|
|
|
fields are blank.
|
|
|
|
|
|
|
|
@e OPEN_FAILED_CE from 1
|
2022-06-04 15:20:45 +03:00
|
|
|
@e METADATA_MALFORMED_CE
|
2020-03-29 19:39:17 +03:00
|
|
|
@e EXT_MISWORDED_CE
|
2023-02-02 01:17:23 +02:00
|
|
|
@e EXT_BAD_DIRNAME_CE
|
2023-02-09 00:08:44 +02:00
|
|
|
@e EXT_BAD_FILENAME_CE
|
2020-03-29 19:39:17 +03:00
|
|
|
@e EXT_TITLE_TOO_LONG_CE
|
|
|
|
@e EXT_AUTHOR_TOO_LONG_CE
|
2023-03-22 07:45:28 +02:00
|
|
|
@e EXT_RANEOUS_CE
|
2023-05-23 23:33:29 +03:00
|
|
|
@e PROJECT_MALFORMED_CE
|
2023-02-03 01:16:53 +02:00
|
|
|
@e LANGUAGE_UNAVAILABLE_CE
|
2023-02-05 15:45:38 +02:00
|
|
|
@e LANGUAGE_DEFICIENT_CE
|
2020-03-29 19:39:17 +03:00
|
|
|
@e LEXER_CE /* an error generated by the |words| module */
|
|
|
|
@e SYNTAX_CE /* an error generated by the |syntax| module, or by our reading of the tree */
|
|
|
|
|
|
|
|
=
|
|
|
|
typedef struct copy_error {
|
|
|
|
struct inbuild_copy *copy;
|
|
|
|
|
|
|
|
int error_category;
|
|
|
|
int error_subcategory;
|
|
|
|
|
|
|
|
struct text_stream *details;
|
|
|
|
struct filename *details_file;
|
|
|
|
int details_N;
|
|
|
|
struct wording details_W;
|
|
|
|
struct parse_node *details_node;
|
|
|
|
struct parse_node *details_node2;
|
|
|
|
struct inbuild_work *details_work;
|
|
|
|
struct inbuild_work *details_work2;
|
2023-09-05 10:36:51 +03:00
|
|
|
inchar32_t *details_word;
|
2020-03-29 19:39:17 +03:00
|
|
|
|
2020-05-09 15:07:39 +03:00
|
|
|
CLASS_DEFINITION
|
2020-03-29 19:39:17 +03:00
|
|
|
} copy_error;
|
|
|
|
|
|
|
|
@ And now some creators.
|
|
|
|
|
|
|
|
=
|
|
|
|
copy_error *CopyErrors::new(int cat, int subcat) {
|
|
|
|
copy_error *CE = CREATE(copy_error);
|
|
|
|
CE->copy = NULL;
|
|
|
|
CE->error_category = cat;
|
|
|
|
CE->error_subcategory = subcat;
|
|
|
|
CE->details = NULL;
|
|
|
|
CE->details_file = NULL;
|
|
|
|
CE->details_N = -1;
|
|
|
|
CE->details_W = EMPTY_WORDING;
|
|
|
|
CE->details_node = NULL;
|
|
|
|
CE->details_node2 = NULL;
|
|
|
|
CE->details_work = NULL;
|
|
|
|
CE->details_work2 = NULL;
|
|
|
|
CE->details_word = NULL;
|
|
|
|
return CE;
|
|
|
|
}
|
|
|
|
|
|
|
|
copy_error *CopyErrors::new_T(int cat, int subcat, text_stream *NB) {
|
|
|
|
copy_error *CE = CopyErrors::new(cat, subcat);
|
|
|
|
CE->details = Str::duplicate(NB);
|
|
|
|
return CE;
|
|
|
|
}
|
|
|
|
|
|
|
|
copy_error *CopyErrors::new_N(int cat, int subcat, int N) {
|
|
|
|
copy_error *CE = CopyErrors::new(cat, subcat);
|
|
|
|
CE->details_N = N;
|
|
|
|
return CE;
|
|
|
|
}
|
|
|
|
|
|
|
|
copy_error *CopyErrors::new_F(int cat, int subcat, filename *F) {
|
|
|
|
copy_error *CE = CopyErrors::new(cat, subcat);
|
|
|
|
CE->details_file = F;
|
|
|
|
return CE;
|
|
|
|
}
|
|
|
|
|
2023-09-05 10:36:51 +03:00
|
|
|
copy_error *CopyErrors::new_WT(int cat, int subcat, inchar32_t *details_word, text_stream *NB) {
|
2020-03-29 19:39:17 +03:00
|
|
|
copy_error *CE = CopyErrors::new(cat, subcat);
|
|
|
|
CE->details_word = details_word;
|
|
|
|
CE->details = Str::duplicate(NB);
|
|
|
|
return CE;
|
|
|
|
}
|
|
|
|
|
|
|
|
@ It becomes tiresome to make creators for every conceivable possibility, so
|
|
|
|
we also offer these functions to tack extra details on:
|
|
|
|
|
|
|
|
=
|
|
|
|
void CopyErrors::supply_wording(copy_error *CE, wording details_W) {
|
|
|
|
CE->details_W = details_W;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CopyErrors::supply_work(copy_error *CE, inbuild_work *w) {
|
|
|
|
CE->details_work = w;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CopyErrors::supply_works(copy_error *CE, inbuild_work *w1, inbuild_work *w2) {
|
|
|
|
CE->details_work = w1;
|
|
|
|
CE->details_work2 = w2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CopyErrors::supply_node(copy_error *CE, parse_node *n) {
|
|
|
|
CE->details_node = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CopyErrors::supply_nodes(copy_error *CE, parse_node *n1, parse_node *n2) {
|
|
|
|
CE->details_node = n1;
|
|
|
|
CE->details_node2 = n2;
|
|
|
|
}
|
|
|
|
|
|
|
|
@ The following should only be called from Copies.
|
|
|
|
|
|
|
|
=
|
|
|
|
void CopyErrors::supply_attached_copy(copy_error *CE, inbuild_copy *C) {
|
|
|
|
CE->copy = C;
|
|
|
|
}
|
|
|
|
|
|
|
|
@ This produces a textual summary of the issue described. It wouldn't do for
|
|
|
|
a proper Inform problem message, but it's fine for the Inbuild command line
|
|
|
|
output.
|
|
|
|
|
|
|
|
=
|
|
|
|
void CopyErrors::write(OUTPUT_STREAM, copy_error *CE) {
|
|
|
|
switch (CE->error_category) {
|
|
|
|
case OPEN_FAILED_CE: WRITE("unable to open file %f", CE->details_file); break;
|
|
|
|
case EXT_MISWORDED_CE: WRITE("extension misworded: %S", CE->details); break;
|
2023-02-02 01:17:23 +02:00
|
|
|
case EXT_BAD_DIRNAME_CE: WRITE("extension directory name wrong: %S", CE->details); break;
|
2023-02-09 00:08:44 +02:00
|
|
|
case EXT_BAD_FILENAME_CE: WRITE("extension filename wrong: %S", CE->details); break;
|
2023-03-22 07:45:28 +02:00
|
|
|
case EXT_RANEOUS_CE: WRITE("extraneous content: %S", CE->details); break;
|
2023-05-23 23:33:29 +03:00
|
|
|
case PROJECT_MALFORMED_CE: WRITE("project malformed: %S", CE->details); break;
|
2022-06-04 15:20:45 +03:00
|
|
|
case METADATA_MALFORMED_CE: WRITE("%S has incorrect metadata: %S",
|
|
|
|
CE->copy->edition->work->genre->genre_name, CE->details); break;
|
2020-03-29 19:39:17 +03:00
|
|
|
case EXT_TITLE_TOO_LONG_CE: WRITE("title too long: %d characters (max is %d)",
|
|
|
|
CE->details_N, MAX_EXTENSION_TITLE_LENGTH); break;
|
|
|
|
case EXT_AUTHOR_TOO_LONG_CE: WRITE("author name too long: %d characters (max is %d)",
|
|
|
|
CE->details_N, MAX_EXTENSION_AUTHOR_LENGTH); break;
|
2023-02-03 01:16:53 +02:00
|
|
|
case LANGUAGE_UNAVAILABLE_CE: WRITE("%S refers to an unavailable language: %S",
|
|
|
|
CE->copy->edition->work->genre->genre_name, CE->details); break;
|
2023-02-05 15:45:38 +02:00
|
|
|
case LANGUAGE_DEFICIENT_CE: WRITE("%S: %S",
|
|
|
|
CE->copy->edition->work->genre->genre_name, CE->details); break;
|
2020-03-29 19:39:17 +03:00
|
|
|
case LEXER_CE: @<Write a lexer error@>; break;
|
|
|
|
case SYNTAX_CE: @<Write a syntax error@>; break;
|
|
|
|
default: internal_error("an unknown error occurred");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@<Write a lexer error@> =
|
|
|
|
switch (CE->error_subcategory) {
|
|
|
|
case STRING_TOO_LONG_LEXERERROR:
|
|
|
|
WRITE("Too much text in quotation marks: %w", CE->details_word); break;
|
|
|
|
case WORD_TOO_LONG_LEXERERROR:
|
|
|
|
WRITE("Word too long: %w", CE->details_word); break;
|
|
|
|
case I6_TOO_LONG_LEXERERROR:
|
|
|
|
WRITE("I6 inclusion too long: %w", CE->details_word); break;
|
|
|
|
case STRING_NEVER_ENDS_LEXERERROR:
|
|
|
|
WRITE("Quoted text never ends: %S", CE->details); break;
|
|
|
|
case COMMENT_NEVER_ENDS_LEXERERROR:
|
|
|
|
WRITE("Square-bracketed text never ends: %S", CE->details); break;
|
|
|
|
case I6_NEVER_ENDS_LEXERERROR:
|
|
|
|
WRITE("I6 inclusion text never ends: %S", CE->details); break;
|
|
|
|
default:
|
|
|
|
WRITE("lexer error"); break;
|
|
|
|
}
|
|
|
|
|
|
|
|
@<Write a syntax error@> =
|
|
|
|
switch (CE->error_subcategory) {
|
|
|
|
case UnexpectedSemicolon_SYNERROR:
|
|
|
|
WRITE("unexpected semicolon in sentence"); break;
|
|
|
|
case ParaEndsInColon_SYNERROR:
|
|
|
|
WRITE("paragraph ends with a colon"); break;
|
|
|
|
case SentenceEndsInColon_SYNERROR:
|
|
|
|
WRITE("paragraph ends with a colon and full stop"); break;
|
|
|
|
case SentenceEndsInSemicolon_SYNERROR:
|
|
|
|
WRITE("paragraph ends with a semicolon and full stop"); break;
|
|
|
|
case SemicolonAfterColon_SYNERROR:
|
|
|
|
WRITE("paragraph ends with a colon and semicolon"); break;
|
|
|
|
case SemicolonAfterStop_SYNERROR:
|
|
|
|
WRITE("paragraph ends with a full stop and semicolon"); break;
|
|
|
|
case HeadingOverLine_SYNERROR:
|
|
|
|
WRITE("heading contains a line break"); break;
|
|
|
|
case HeadingStopsBeforeEndOfLine_SYNERROR:
|
|
|
|
WRITE("heading stops before end of line"); break;
|
|
|
|
case ExtNoBeginsHere_SYNERROR:
|
|
|
|
WRITE("extension has no beginning"); break;
|
|
|
|
case ExtNoEndsHere_SYNERROR:
|
|
|
|
WRITE("extension has no end"); break;
|
|
|
|
case ExtSpuriouslyContinues_SYNERROR:
|
|
|
|
WRITE("extension continues after end"); break;
|
|
|
|
case ExtMultipleBeginsHere_SYNERROR:
|
|
|
|
WRITE("extension has multiple 'begins here' sentences"); break;
|
|
|
|
case ExtBeginsAfterEndsHere_SYNERROR:
|
|
|
|
WRITE("extension has a 'begins here' after its 'ends here'"); break;
|
|
|
|
case ExtEndsWithoutBegins_SYNERROR:
|
|
|
|
WRITE("extension has an 'ends here' but no 'begins here'"); break;
|
|
|
|
case ExtMultipleEndsHere_SYNERROR:
|
|
|
|
WRITE("extension has multiple 'ends here' sentences"); break;
|
|
|
|
case BadTitleSentence_SYNERROR:
|
|
|
|
WRITE("bibliographic sentence at the start is malformed"); break;
|
|
|
|
case UnknownLanguageElement_SYNERROR:
|
|
|
|
WRITE("unrecognised stipulation about Inform language elements"); break;
|
|
|
|
case UnknownVirtualMachine_SYNERROR:
|
|
|
|
WRITE("unrecognised stipulation about virtual machine"); break;
|
|
|
|
case UseElementWithdrawn_SYNERROR:
|
|
|
|
WRITE("use language element is no longer supported"); break;
|
|
|
|
case IncludeExtQuoted_SYNERROR:
|
|
|
|
WRITE("extension name should not be double-quoted"); break;
|
|
|
|
case BogusExtension_SYNERROR:
|
|
|
|
WRITE("can't find this extension"); break;
|
|
|
|
case ExtVersionTooLow_SYNERROR:
|
|
|
|
WRITE("extension version too low"); break;
|
|
|
|
case ExtVersionMalformed_SYNERROR:
|
|
|
|
WRITE("extension version is malformed"); break;
|
|
|
|
case ExtInadequateVM_SYNERROR:
|
|
|
|
WRITE("extension is not compatible with the target virtual machine"); break;
|
|
|
|
case ExtMisidentifiedEnds_SYNERROR:
|
|
|
|
WRITE("extension has an 'ends here' which doesn't match the 'begins here'"); break;
|
|
|
|
case HeadingInPlaceOfUnincluded_SYNERROR:
|
|
|
|
WRITE("heading is in place of an extension not included"); break;
|
|
|
|
case UnequalHeadingInPlaceOf_SYNERROR:
|
2022-04-30 17:58:37 +03:00
|
|
|
WRITE("heading is in place of another heading but of a different level"); break;
|
2020-03-29 19:39:17 +03:00
|
|
|
case HeadingInPlaceOfSubordinate_SYNERROR:
|
|
|
|
WRITE("heading is in place of another heading subordinate to itself"); break;
|
|
|
|
case HeadingInPlaceOfUnknown_SYNERROR:
|
2022-06-23 19:37:16 +03:00
|
|
|
WRITE("heading is in place of another heading which doesn't exist"); break;
|
|
|
|
case UnavailableLOS_SYNERROR:
|
|
|
|
WRITE("this language bundle does not provide Preform syntax"); break;
|
2022-09-01 15:04:08 +03:00
|
|
|
case DialogueOnSectionsOnly_SYNERROR:
|
|
|
|
WRITE("only 'Section' headings can be marked as '(dialogue)'"); break;
|
|
|
|
case UnexpectedDialogue_SYNERROR:
|
|
|
|
WRITE("something other than a cue or a line under a dialogue heading"); break;
|
2022-09-02 01:02:03 +03:00
|
|
|
case UnquotedDialogue_SYNERROR:
|
|
|
|
WRITE("speech in dialogue which is not just a single double-quoted text"); break;
|
2022-09-02 15:01:25 +03:00
|
|
|
case EmptyDialogueClause_SYNERROR:
|
|
|
|
WRITE("empty clause in brackets in dialogue"); break;
|
|
|
|
case MisbracketedDialogueClause_SYNERROR:
|
|
|
|
WRITE("brackets '(' and ')' used in an unmatched way in dialogue"); break;
|
2022-11-01 00:59:25 +02:00
|
|
|
case MissingSourceFile_SYNERROR:
|
|
|
|
WRITE("cannot find source file: '%S'", CE->details); break;
|
|
|
|
case HeadingWithFileNonempty_SYNERROR:
|
|
|
|
WRITE("heading should refer only to source file '%S' but also contains material",
|
|
|
|
CE->details); break;
|
|
|
|
case MisheadedSourceFile_SYNERROR:
|
|
|
|
WRITE("source file '%S' does not begin with a heading matching 'see ...' line",
|
|
|
|
CE->details); break;
|
2022-11-02 01:56:24 +02:00
|
|
|
case HeadingTooGreat_SYNERROR:
|
|
|
|
WRITE("source file contains a heading of too high a level"); break;
|
2020-03-29 19:39:17 +03:00
|
|
|
default:
|
|
|
|
WRITE("syntax error"); break;
|
|
|
|
}
|