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.
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@h Creation.
|
2020-02-17 11:43:20 +02:00
|
|
|
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.
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
A purist view would be that a copy is simply an edition at a location in the
|
|
|
|
file system. And so it is. But copies are the main things Inbuild works on,
|
|
|
|
and we will need to generate data about them, some of which is most usefully
|
|
|
|
stored here.
|
|
|
|
|
2020-02-17 11:43:20 +02:00
|
|
|
=
|
|
|
|
typedef struct inbuild_copy {
|
2020-03-29 19:39:17 +03:00
|
|
|
struct inbuild_edition *edition; /* what is this a copy of? */
|
|
|
|
struct pathname *location_if_path; /* exactly one of these must be non-|NULL| */
|
2020-02-17 11:43:20 +02:00
|
|
|
struct filename *location_if_file;
|
2020-03-29 19:39:17 +03:00
|
|
|
|
2020-02-17 11:43:20 +02:00
|
|
|
general_pointer content; /* the type of which depends on the work's genre */
|
2020-03-29 19:39:17 +03:00
|
|
|
struct build_vertex *vertex; /* head vertex of build graph for this copy */
|
|
|
|
int source_text_read; /* have we attempted to read Inform source text from this? */
|
|
|
|
struct wording source_text; /* the source text we read, if so */
|
|
|
|
struct inbuild_requirement *found_by; /* if this was claimed in a search */
|
|
|
|
struct linked_list *errors_reading_source_text; /* of |copy_error| */
|
2020-02-17 11:43:20 +02:00
|
|
|
MEMORY_MANAGEMENT
|
|
|
|
} inbuild_copy;
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@ Copies are created by the managers for the respective genres, usually when
|
|
|
|
claiming. If you are a manager, do not call this...
|
|
|
|
|
|
|
|
=
|
|
|
|
inbuild_copy *Copies::new_p(inbuild_edition *edition) {
|
2020-02-17 11:43:20 +02:00
|
|
|
inbuild_copy *copy = CREATE(inbuild_copy);
|
|
|
|
copy->edition = edition;
|
|
|
|
copy->location_if_path = NULL;
|
|
|
|
copy->location_if_file = NULL;
|
2020-03-29 19:39:17 +03:00
|
|
|
copy->content = NULL_GENERAL_POINTER;
|
2020-03-30 14:23:06 +03:00
|
|
|
copy->vertex = Graphs::copy_vertex(copy);
|
2020-02-17 11:43:20 +02:00
|
|
|
copy->source_text_read = FALSE;
|
|
|
|
copy->source_text = EMPTY_WORDING;
|
|
|
|
copy->found_by = NULL;
|
2020-03-29 19:39:17 +03:00
|
|
|
copy->errors_reading_source_text = NEW_LINKED_LIST(copy_error);
|
2020-02-17 11:43:20 +02:00
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@ ...call one of these:
|
|
|
|
|
|
|
|
=
|
|
|
|
inbuild_copy *Copies::new_in_file(inbuild_edition *edition, filename *F) {
|
|
|
|
inbuild_copy *copy = Copies::new_p(edition);
|
2020-02-17 11:43:20 +02:00
|
|
|
copy->location_if_file = F;
|
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
inbuild_copy *Copies::new_in_path(inbuild_edition *edition, pathname *P) {
|
|
|
|
inbuild_copy *copy = Copies::new_p(edition);
|
2020-02-17 11:43:20 +02:00
|
|
|
copy->location_if_path = P;
|
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@ And then probably follow up by calling this, to attach a pointer to some
|
|
|
|
additional data specific to your genre:
|
|
|
|
|
|
|
|
=
|
2020-02-18 21:57:31 +02:00
|
|
|
void Copies::set_content(inbuild_copy *C, general_pointer ref) {
|
|
|
|
C->content = ref;
|
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@h List of errors.
|
|
|
|
When copies are found to be malformed, error messages are attached to them
|
|
|
|
for later reporting. These are stored in a list.
|
2020-02-17 11:43:20 +02:00
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
=
|
|
|
|
void Copies::attach_error(inbuild_copy *C, copy_error *CE) {
|
|
|
|
if (C == NULL) internal_error("no copy to attach to");
|
|
|
|
CopyErrors::supply_attached_copy(CE, C);
|
|
|
|
ADD_TO_LINKED_LIST(CE, copy_error, C->errors_reading_source_text);
|
2020-02-20 02:39:36 +02:00
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
void Copies::list_attached_errors(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++); CopyErrors::write(OUT, CE); WRITE("\n");
|
|
|
|
}
|
2020-02-17 11:43:20 +02:00
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@h Writing.
|
|
|
|
|
|
|
|
=
|
|
|
|
void Copies::write_copy(OUTPUT_STREAM, inbuild_copy *C) {
|
|
|
|
Editions::write(OUT, C->edition);
|
2020-03-10 22:21:55 +02:00
|
|
|
}
|
2020-02-22 16:09:13 +02:00
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@h Reading source text.
|
|
|
|
|
|
|
|
=
|
2020-03-10 12:08:45 +02:00
|
|
|
int Copies::source_text_has_been_read(inbuild_copy *C) {
|
|
|
|
if (C == NULL) internal_error("no copy");
|
|
|
|
return C->source_text_read;
|
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
wording Copies::get_source_text(inbuild_copy *C) {
|
2020-02-17 11:43:20 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@h Going operational.
|
|
|
|
|
|
|
|
=
|
|
|
|
void Copies::go_operational(inbuild_copy *C) {
|
|
|
|
VMETHOD_CALL(C->edition->work->genre, GENRE_GO_OPERATIONAL_MTID, C);
|
2020-02-17 11:43:20 +02:00
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@h Miscellaneous Inbuild commands.
|
|
|
|
This function implements the command-line instruction to |-inspect|.
|
|
|
|
|
|
|
|
=
|
2020-02-17 11:43:20 +02:00
|
|
|
void Copies::inspect(OUTPUT_STREAM, inbuild_copy *C) {
|
|
|
|
WRITE("%S: ", Genres::name(C->edition->work->genre));
|
2020-03-29 19:39:17 +03:00
|
|
|
Editions::inspect(OUT, C->edition);
|
2020-02-17 11:43:20 +02:00
|
|
|
if (C->location_if_path) {
|
|
|
|
WRITE(" at path %p", C->location_if_path);
|
|
|
|
}
|
|
|
|
if (C->location_if_file) {
|
2020-03-26 21:22:26 +02:00
|
|
|
pathname *P = Filenames::get_path_to(C->location_if_file);
|
|
|
|
if (P) WRITE(" in directory %p", P);
|
2020-02-17 11:43:20 +02:00
|
|
|
}
|
|
|
|
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) {
|
2020-03-29 19:39:17 +03:00
|
|
|
INDENT; Copies::list_attached_errors(OUT, C); OUTDENT;
|
2020-02-18 01:50:21 +02:00
|
|
|
}
|
2020-02-17 11:43:20 +02:00
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@ And here are |-build| and |-rebuild|, though note that |Copies::build|
|
|
|
|
is also called by the |core| module of the Inform 7 compiler to perform
|
|
|
|
its main task: building an Inform project.
|
2020-02-17 11:43:20 +02:00
|
|
|
|
|
|
|
=
|
2020-03-29 19:39:17 +03:00
|
|
|
void Copies::build(OUTPUT_STREAM, inbuild_copy *C, build_methodology *BM) {
|
|
|
|
build_vertex *V = C->vertex;
|
|
|
|
VMETHOD_CALL(C->edition->work->genre, GENRE_BUILDING_SOON_MTID, C, &V);
|
2020-03-30 02:30:20 +03:00
|
|
|
IncrementalBuild::build(OUT, V, BM);
|
2020-02-17 11:43:20 +02:00
|
|
|
}
|
2020-03-29 19:39:17 +03:00
|
|
|
void Copies::rebuild(OUTPUT_STREAM, inbuild_copy *C, build_methodology *BM) {
|
|
|
|
build_vertex *V = C->vertex;
|
|
|
|
VMETHOD_CALL(C->edition->work->genre, GENRE_BUILDING_SOON_MTID, C, &V);
|
2020-03-30 02:30:20 +03:00
|
|
|
IncrementalBuild::rebuild(OUT, V, BM);
|
2020-02-18 02:41:18 +02:00
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@ Now in quick succession |-graph|, |-build-needs|, |-use-needs|, |-build-missing|,
|
|
|
|
|-use-missing|:
|
|
|
|
|
|
|
|
=
|
|
|
|
void Copies::show_graph(OUTPUT_STREAM, inbuild_copy *C) {
|
|
|
|
build_vertex *V = C->vertex;
|
|
|
|
VMETHOD_CALL(C->edition->work->genre, GENRE_BUILDING_SOON_MTID, C, &V);
|
|
|
|
Graphs::describe(OUT, V, TRUE);
|
|
|
|
}
|
|
|
|
void Copies::show_needs(OUTPUT_STREAM, inbuild_copy *C, int uses_only) {
|
|
|
|
build_vertex *V = C->vertex;
|
|
|
|
VMETHOD_CALL(C->edition->work->genre, GENRE_BUILDING_SOON_MTID, C, &V);
|
|
|
|
Graphs::show_needs(OUT, C->vertex, uses_only);
|
|
|
|
}
|
|
|
|
void Copies::show_missing(OUTPUT_STREAM, inbuild_copy *C, int uses_only) {
|
|
|
|
build_vertex *V = C->vertex;
|
|
|
|
VMETHOD_CALL(C->edition->work->genre, GENRE_BUILDING_SOON_MTID, C, &V);
|
|
|
|
int N = Graphs::show_missing(OUT, C->vertex, uses_only);
|
|
|
|
if (N == 0) WRITE("Nothing is missing\n");
|
2020-02-17 11:43:20 +02:00
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@ And here is |-archive| and |-archive-to N|:
|
|
|
|
|
|
|
|
=
|
|
|
|
void Copies::archive(OUTPUT_STREAM, inbuild_copy *C, inbuild_nest *N, build_methodology *BM) {
|
|
|
|
build_vertex *V = C->vertex;
|
|
|
|
VMETHOD_CALL(C->edition->work->genre, GENRE_BUILDING_SOON_MTID, C, &V);
|
|
|
|
int NM = Graphs::show_missing(OUT, C->vertex, FALSE);
|
|
|
|
if (NM > 0) WRITE("Because there are missing resources, -archive is cancelled\n");
|
|
|
|
else if (N) Graphs::archive(OUT, C->vertex, N, BM);
|
2020-02-17 11:43:20 +02:00
|
|
|
}
|
2020-02-18 01:50:21 +02:00
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
@ And lastly |-copy-to N| and |-sync-to N|:
|
|
|
|
|
|
|
|
=
|
|
|
|
void Copies::copy_to(inbuild_copy *C, inbuild_nest *destination_nest, int syncing,
|
|
|
|
build_methodology *meth) {
|
|
|
|
if (destination_nest)
|
|
|
|
VMETHOD_CALL(C->edition->work->genre, GENRE_COPY_TO_NEST_MTID,
|
|
|
|
C, destination_nest, syncing, meth);
|
2020-02-19 22:48:30 +02:00
|
|
|
}
|
|
|
|
|
2020-03-29 19:39:17 +03:00
|
|
|
void Copies::overwrite_error(inbuild_copy *C, inbuild_nest *N) {
|
|
|
|
text_stream *ext = Str::new();
|
|
|
|
WRITE_TO(ext, "%X", C->edition->work);
|
|
|
|
Errors::with_text("already present (to overwrite, use -sync-to not -copy-to): '%S'", ext);
|
2020-02-18 01:50:21 +02:00
|
|
|
}
|