[Collater::] The Collater. To collate material generated by the weaver into finished, fully-woven files. @ \section{Collation.} This is the process of reading a template file, substituting material into placeholders in it, and writing the result. The collater needs to operate as a little processor interpreting a meta-language all of its very own, with a stack for holding nested repeat loops, and a program counter and -- well, and nothing else to speak of, in fact, except for the slightly unusual way that loop variables provide context by changing the subject of what is discussed rather than by being accessed directly. For convenience, we provide three ways to call: <<*>>= void Collater::for_web_and_pattern(text_stream *OUT, web *W, weave_pattern *pattern, filename *F, filename *into) { Collater::collate(OUT, W, I"", F, pattern, NULL, NULL, NULL, into); } void Collater::for_order(text_stream *OUT, weave_order *wv, filename *F, filename *into) { Collater::collate(OUT, wv->weave_web, wv->weave_range, F, wv->pattern, wv->navigation, wv->breadcrumbs, wv, into); } void Collater::collate(text_stream *OUT, web *W, text_stream *range, filename *template_filename, weave_pattern *pattern, filename *nav_file, linked_list *crumbs, weave_order *wv, filename *into) { collater_state actual_ies = Collater::initial_state(W, range, template_filename, pattern, nav_file, crumbs, wv, into); collater_state *ies = &actual_ies; Collater::process(OUT, ies); } @ The current state of the processor is recorded in the following. <<*>>= #define TRACE_COLLATER_EXECUTION FALSE /* set true for debugging */ #define MAX_TEMPLATE_LINES 8192 /* maximum number of lines in template */ #define CI_STACK_CAPACITY 8 /* maximum recursion of chapter/section iteration */ <<*>>= typedef struct collater_state { struct web *for_web; struct text_stream *tlines[MAX_TEMPLATE_LINES]; int no_tlines; int repeat_stack_level[CI_STACK_CAPACITY]; struct linked_list_item *repeat_stack_variable[CI_STACK_CAPACITY]; struct linked_list_item *repeat_stack_threshold[CI_STACK_CAPACITY]; int repeat_stack_startpos[CI_STACK_CAPACITY]; int sp; /* And this is our stack pointer for tracking of loops */ struct text_stream *restrict_to_range; struct weave_pattern *nav_pattern; struct filename *nav_file; struct linked_list *crumbs; int inside_navigation_submenu; struct filename *errors_at; struct weave_order *wv; struct filename *into_file; struct linked_list *modules; /* of [[module]] */ } collater_state; @ Note the unfortunate maximum size limit on the template file. It means that really humungous Javascript files in plugins might have trouble, though if so, they can always be subdivided. <<*>>= collater_state Collater::initial_state(web *W, text_stream *range, filename *template_filename, weave_pattern *pattern, filename *nav_file, linked_list *crumbs, weave_order *wv, filename *into) { collater_state cls; cls.no_tlines = 0; cls.restrict_to_range = Str::duplicate(range); cls.sp = 0; cls.inside_navigation_submenu = FALSE; cls.for_web = W; cls.nav_pattern = pattern; cls.nav_file = nav_file; cls.crumbs = crumbs; cls.errors_at = template_filename; cls.wv = wv; cls.into_file = into; cls.modules = NEW_LINKED_LIST(module); if (W) { int c = LinkedLists::len(W->md->as_module->dependencies); if (c > 0) <