1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 08:34:22 +03:00
inform7/inbuild/inbuild-module/Chapter 2/Copies.w

190 lines
5.4 KiB
OpenEdge ABL
Raw Normal View History

2020-02-17 11:43:20 +02:00
[Copies::] Copies.
A copy is an instance in the file system of a specific edition of a work.
@h Copies.
A "copy" of a work exists in the file system when we've actually got hold of
some edition of it. For some genres, copies will be files; for others,
directories holding a set of files.
=
typedef struct inbuild_copy {
struct inbuild_edition *edition;
struct pathname *location_if_path;
struct filename *location_if_file;
general_pointer content; /* the type of which depends on the work's genre */
struct build_vertex *vertex;
int source_text_read;
struct wording source_text;
struct linked_list *errors_reading_source_text;
struct inbuild_requirement *found_by;
MEMORY_MANAGEMENT
} inbuild_copy;
inbuild_copy *Copies::new_p(inbuild_edition *edition, general_pointer ref) {
inbuild_copy *copy = CREATE(inbuild_copy);
copy->edition = edition;
copy->location_if_path = NULL;
copy->location_if_file = NULL;
copy->content = ref;
copy->vertex = NULL;
copy->source_text_read = FALSE;
copy->source_text = EMPTY_WORDING;
copy->errors_reading_source_text = NEW_LINKED_LIST(copy_error);
copy->found_by = NULL;
return copy;
}
inbuild_copy *Copies::new_in_file(inbuild_edition *edition, filename *F, general_pointer ref) {
inbuild_copy *copy = Copies::new_p(edition, ref);
copy->location_if_file = F;
return copy;
}
inbuild_copy *Copies::new_in_path(inbuild_edition *edition, pathname *P, general_pointer ref) {
inbuild_copy *copy = Copies::new_p(edition, ref);
copy->location_if_path = P;
return copy;
}
void Copies::write_copy(OUTPUT_STREAM, inbuild_copy *C) {
2020-02-18 14:06:32 +02:00
Editions::write(OUT, C->edition);
2020-02-17 11:43:20 +02:00
}
void Copies::go_operational(inbuild_copy *C) {
VMETHOD_CALL(C->edition->work->genre, GENRE_GO_OPERATIONAL_MTID, C);
}
wording Copies::read_source_text_for(inbuild_copy *C) {
if (C->source_text_read == FALSE) {
C->source_text_read = TRUE;
feed_t id = Feeds::begin();
VMETHOD_CALL(C->edition->work->genre, GENRE_READ_SOURCE_TEXT_FOR_MTID, C);
wording W = Feeds::end(id);
if (Wordings::nonempty(W)) C->source_text = W;
}
return C->source_text;
}
inbuild_copy *Copies::claim(text_stream *arg) {
TEMPORARY_TEXT(ext);
int pos = Str::len(arg) - 1, dotpos = -1;
while (pos >= 0) {
wchar_t c = Str::get_at(arg, pos);
if (c == FOLDER_SEPARATOR) break;
if (c == '.') dotpos = pos;
pos--;
}
if (dotpos >= 0)
Str::substr(ext, Str::at(arg, dotpos+1), Str::end(arg));
int directory_status = NOT_APPLICABLE;
if (Str::get_last_char(arg) == FOLDER_SEPARATOR) {
Str::delete_last_character(arg);
directory_status = TRUE;
}
inbuild_copy *C = NULL;
inbuild_genre *G;
LOOP_OVER(G, inbuild_genre)
if (C == NULL)
VMETHOD_CALL(G, GENRE_CLAIM_AS_COPY_MTID, &C, arg, ext, directory_status);
DISCARD_TEXT(ext);
return C;
}
void Copies::inspect(OUTPUT_STREAM, inbuild_copy *C) {
WRITE("%S: ", Genres::name(C->edition->work->genre));
Copies::write_copy(STDOUT, C);
if (C->location_if_path) {
WRITE(" at path %p", C->location_if_path);
}
if (C->location_if_file) {
WRITE(" in directory %p", Filenames::get_path_to(C->location_if_file));
}
int N = LinkedLists::len(C->errors_reading_source_text);
if (N > 0) {
WRITE(" - %d error", N);
if (N > 1) WRITE("s");
}
WRITE("\n");
2020-02-18 01:50:21 +02:00
if (N > 0) {
INDENT; Copies::list_problems_arising(OUT, C); OUTDENT;
}
2020-02-17 11:43:20 +02:00
}
@h Errors.
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.
@e OPEN_FAILED_CE from 1
@e EXT_MISWORDED_CE
@e EXT_TITLE_TOO_LONG_CE
@e EXT_AUTHOR_TOO_LONG_CE
2020-02-17 11:43:20 +02:00
@e LEXER_CE
=
typedef struct copy_error {
int error_category;
int error_subcategory;
struct inbuild_copy *copy;
struct filename *file;
struct text_file_position pos;
struct text_stream *notes;
2020-02-18 01:50:21 +02:00
struct text_stream *details;
int details_N;
2020-02-18 01:50:21 +02:00
wchar_t *word;
2020-02-17 11:43:20 +02:00
MEMORY_MANAGEMENT
} copy_error;
copy_error *Copies::new_error(int cat, text_stream *NB) {
copy_error *CE = CREATE(copy_error);
CE->error_category = cat;
CE->error_subcategory = -1;
CE->file = NULL;
CE->notes = Str::duplicate(NB);
2020-02-18 01:50:21 +02:00
CE->details = NULL;
CE->details_N = -1;
2020-02-17 11:43:20 +02:00
CE->pos = TextFiles::nowhere();
CE->copy = NULL;
2020-02-18 01:50:21 +02:00
CE->word = NULL;
2020-02-17 11:43:20 +02:00
return CE;
}
copy_error *Copies::new_error_N(int cat, int N) {
copy_error *CE = Copies::new_error(cat, NULL);
CE->details_N = N;
return CE;
}
2020-02-17 11:43:20 +02:00
copy_error *Copies::new_error_on_file(int cat, filename *F) {
copy_error *CE = Copies::new_error(cat, NULL);
CE->file = F;
return CE;
}
void Copies::attach(inbuild_copy *C, copy_error *CE) {
if (C == NULL) internal_error("no copy to attach to");
CE->copy = C;
ADD_TO_LINKED_LIST(CE, copy_error, C->errors_reading_source_text);
}
2020-02-18 01:50:21 +02:00
void Copies::list_problems_arising(OUTPUT_STREAM, inbuild_copy *C) {
if (C == NULL) return;
copy_error *CE;
int c = 1;
LOOP_OVER_LINKED_LIST(CE, copy_error, C->errors_reading_source_text) {
WRITE("%d. ", c++);
switch (CE->error_category) {
case OPEN_FAILED_CE: WRITE("unable to open file %f", CE->file); break;
case EXT_MISWORDED_CE: WRITE("extension misworded: %S", CE->notes); break;
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;
2020-02-18 01:50:21 +02:00
case LEXER_CE: WRITE("%S", CE->notes); break;
default: internal_error("an unknown error occurred");
}
WRITE("\n");
}
}