1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-30 22:14:58 +03:00

Tidied up inblorb

This commit is contained in:
Graham Nelson 2019-02-10 11:27:48 +00:00
parent 1194ff940a
commit 0b72d7853a
15 changed files with 277 additions and 261 deletions

View file

@ -68,7 +68,10 @@
<td valign="top" halign="left" border="0"><img src='inform:/doc_images/folder3.png' border=0>&nbsp;<font [FONTTAG]><a href='[JAVASCRIPTPRELUDE]openFile("[*MATERIALSFOLDERPATHFILE]/Release/[*STORYFILE]")'><img src='[*CBLORBSTATUSIMAGE]' height=16 width=16 border=0></a>&nbsp;[STORYFILE]</font></td>
</tr>
</table></td></tr></table></center>
</p>
<p>
[CBLORBSTATUSTEXT]
<p>
</p>
</font>
</body>
</html>

View file

@ -7,22 +7,22 @@ This notation tangles out to the current build number as specified in the
contents section of this web.
@d INTOOL_NAME "inblorb"
@d CBLORB_BUILD "inblorb [[Build Number]]"
@h Setting up the memory manager.
We need to itemise the structures we'll want to allocate:
@e auxiliary_file_MT
@e skein_node_MT
@e chunk_metadata_MT
@e placeholder_MT
@e heading_MT
@e table_MT
@e segment_MT
@e placeholder_MT
@e rdes_record_MT
@e request_MT
@e resource_number_MT
@e segment_MT
@e skein_node_MT
@e table_MT
@e template_MT
@e template_path_MT
@e rdes_record_MT
@ And then expand:
@ -34,6 +34,7 @@ ALLOCATE_INDIVIDUALLY(placeholder)
ALLOCATE_INDIVIDUALLY(heading)
ALLOCATE_INDIVIDUALLY(table)
ALLOCATE_INDIVIDUALLY(rdes_record)
ALLOCATE_INDIVIDUALLY(resource_number)
ALLOCATE_INDIVIDUALLY(segment)
ALLOCATE_INDIVIDUALLY(request)
ALLOCATE_INDIVIDUALLY(template)

View file

@ -1,16 +1,16 @@
[BlorbErrors::] Text Files.
[BlorbErrors::] Blorb Errors.
To read text files of whatever flavour, one line at a time.
To spool error messages into the HTML report.
@h Error messages.
Inblorb is only minimally helpful when diagnosing problems, because it's
intended to be used as the back end of a system which only generates correct
blurb files, so that everything will work -- ideally, the Inform user will
never know that Inblorb exists.
@ Foundation has a perfectly good library of code for error messages, but
we won't use it, because we need to do something unusual with them: they
must not only be printed to standard error, but also spooled into HTML
format for possible use on a status HTML page. Hence this section.
Note that errors are spooled to a variable before being issued, so that
an HTML report can be generated which shows them. (This is why we don't
use the perfectly good errors system supplied in |foundation|.)
Inblorb is in any case only minimally helpful when diagnosing problems,
because it's intended to be used as the back end of a system which only
generates correct blurb files, so that everything will work -- ideally, the
Inform user will never know that Inblorb exists.
First, the current position of errors is recorded so that we can report
the source of the trouble:
@ -101,11 +101,10 @@ void BlorbErrors::errorf_2S(char *erm, text_stream *s1, text_stream *s2) {
DISCARD_TEXT(ERM);
}
@ As noted, errors are spooled to a placeholder, for the benefit of the report:
@ As noted, errors are spooled to a placeholder variable, for the benefit of
the report:
=
int error_count = 0; /* number of error messages produced so far */
void BlorbErrors::spool_error(OUTPUT_STREAM) {
Placeholders::append_to(I"CBLORBERRORS", I"<li>");
Placeholders::append_to(I"CBLORBERRORS", OUT);

View file

@ -1,6 +1,6 @@
[Parser::] Blurb Parser.
To read and follow the instructions in the blurb file, our main input.
Blurb is an interpreted language, and this is the interpreter for it.
@h Reading the file.
We divide the file into blurb commands at line breaks, so:
@ -14,69 +14,72 @@ void Parser::parse_blurb_file(filename *F) {
@ The sequence of values enumerated here must correspond exactly to
indexes into the syntaxes table below.
@d author_COMMAND 0
@d auxiliary_COMMAND 1
@d base64_COMMAND 2
@d copyright_COMMAND 3
@d cover_COMMAND 4
@d css_COMMAND 5
@d ifiction_COMMAND 6
@d ifiction_public_COMMAND 7
@d ifiction_file_COMMAND 8
@d interpreter_COMMAND 9
@d palette_COMMAND 10
@d palette_16_bit_COMMAND 11
@d palette_32_bit_COMMAND 12
@d picture_scaled_COMMAND 13
@d picture_COMMAND 14
@d picture_text_COMMAND 15
@d picture_noid_COMMAND 16
@d picture_with_alt_text_COMMAND 17
@d placeholder_COMMAND 18
@d project_folder_COMMAND 19
@d release_COMMAND 20
@d release_file_COMMAND 21
@d release_file_from_COMMAND 22
@d release_source_COMMAND 23
@d release_to_COMMAND 24
@d resolution_max_COMMAND 25
@d resolution_min_max_COMMAND 26
@d resolution_min_COMMAND 27
@d resolution_COMMAND 28
@d solution_COMMAND 29
@d solution_public_COMMAND 30
@d sound_music_COMMAND 31
@d sound_repeat_COMMAND 32
@d sound_forever_COMMAND 33
@d sound_song_COMMAND 34
@d sound_COMMAND 35
@d sound_text_COMMAND 36
@d sound_noid_COMMAND 37
@d sound_with_alt_text_COMMAND 38
@d source_COMMAND 39
@d source_public_COMMAND 40
@d status_COMMAND 41
@d status_alternative_COMMAND 42
@d status_instruction_COMMAND 43
@d storyfile_include_COMMAND 44
@d storyfile_COMMAND 45
@d storyfile_leafname_COMMAND 46
@d template_path_COMMAND 47
@d website_COMMAND 48
@e author_COMMAND from 0
@e auxiliary_COMMAND
@e base64_COMMAND
@e copyright_COMMAND
@e cover_COMMAND
@e css_COMMAND
@e ifiction_COMMAND
@e ifiction_public_COMMAND
@e ifiction_file_COMMAND
@e interpreter_COMMAND
@e palette_COMMAND
@e palette_16_bit_COMMAND
@e palette_32_bit_COMMAND
@e picture_scaled_COMMAND
@e picture_COMMAND
@e picture_text_COMMAND
@e picture_noid_COMMAND
@e picture_with_alt_text_COMMAND
@e placeholder_COMMAND
@e project_folder_COMMAND
@e release_COMMAND
@e release_file_COMMAND
@e release_file_from_COMMAND
@e release_source_COMMAND
@e release_to_COMMAND
@e resolution_max_COMMAND
@e resolution_min_max_COMMAND
@e resolution_min_COMMAND
@e resolution_COMMAND
@e solution_COMMAND
@e solution_public_COMMAND
@e sound_music_COMMAND
@e sound_repeat_COMMAND
@e sound_forever_COMMAND
@e sound_song_COMMAND
@e sound_COMMAND
@e sound_text_COMMAND
@e sound_noid_COMMAND
@e sound_with_alt_text_COMMAND
@e source_COMMAND
@e source_public_COMMAND
@e status_COMMAND
@e status_alternative_COMMAND
@e status_instruction_COMMAND
@e storyfile_include_COMMAND
@e storyfile_COMMAND
@e storyfile_leafname_COMMAND
@e template_path_COMMAND
@e website_COMMAND
@ A single number specifying various possible combinations of operands:
@ A single number specifying various possible combinations of operands. For
example, |NT_OPS| means "number, text". Clearly the list below is not
exhaustive of the possibilities, but these are the only ones arising for
Blurb commands.
@d OPS_NO 1
@d OPS_1TEXT 2
@d OPS_2TEXT 3
@d OPS_2TEXT_1NUMBER 4
@d OPS_1NUMBER 5
@d OPS_2NUMBER 6
@d OPS_1NUMBER_1TEXT 7
@d OPS_1NUMBER_2TEXTS 8
@d OPS_1NUMBER_1TEXT_1NUMBER 9
@d OPS_3NUMBER 10
@d OPS_3TEXT 11
@e VOID_OPS from 1
@e N_OPS
@e NN_OPS
@e NNN_OPS
@e NT_OPS
@e NTN_OPS
@e NTT_OPS
@e T_OPS
@e TT_OPS
@e TTN_OPS
@e TTT_OPS
@ Each legal command syntax is stored as one of these structures.
@ -84,7 +87,7 @@ indexes into the syntaxes table below.
typedef struct blurb_command {
char *explicated; /* plain English form of the command */
wchar_t *prototype; /* regular expression prototype */
int operands; /* one of the above |OPS_*| codes */
int operands; /* one of the above |*_OPS| codes */
int deprecated;
} blurb_command;
@ -99,66 +102,66 @@ but, as we shall see, has no effect.
=
blurb_command syntaxes[] = {
{ "author \"name\"", L"author \"(%q*)\"", OPS_1TEXT, FALSE },
{ "author \"name\"", L"author \"(%q*)\"", T_OPS, FALSE },
{ "auxiliary \"filename\" \"description\" \"subfolder\"",
L"auxiliary \"(%q*)\" \"(%q*)\" \"(%q*)\"", OPS_3TEXT, FALSE },
L"auxiliary \"(%q*)\" \"(%q*)\" \"(%q*)\"", TTT_OPS, FALSE },
{ "base64 \"filename\" to \"filename\"",
L"base64 \"(%q*)\" to \"(%q*)\"", OPS_2TEXT, FALSE },
{ "copyright \"message\"", L"copyright \"(%q*)\"", OPS_1TEXT, FALSE },
{ "cover \"filename\"", L"cover \"(%q*)\"", OPS_1TEXT, FALSE },
{ "css", L"css", OPS_NO, FALSE },
{ "ifiction", L"ifiction", OPS_NO, FALSE },
{ "ifiction public", L"ifiction public", OPS_NO, FALSE },
{ "ifiction \"filename\" include", L"ifiction \"(%q*)\" include", OPS_1TEXT, FALSE },
L"base64 \"(%q*)\" to \"(%q*)\"", TT_OPS, FALSE },
{ "copyright \"message\"", L"copyright \"(%q*)\"", T_OPS, FALSE },
{ "cover \"filename\"", L"cover \"(%q*)\"", T_OPS, FALSE },
{ "css", L"css", VOID_OPS, FALSE },
{ "ifiction", L"ifiction", VOID_OPS, FALSE },
{ "ifiction public", L"ifiction public", VOID_OPS, FALSE },
{ "ifiction \"filename\" include", L"ifiction \"(%q*)\" include", T_OPS, FALSE },
{ "interpreter \"interpreter-name\" \"vm-letter\"",
L"interpreter \"(%q*)\" \"([gz])\"", OPS_2TEXT, FALSE },
{ "palette { details }", L"palette {(%c*?)}", OPS_1TEXT, TRUE },
{ "palette 16 bit", L"palette 16 bit", OPS_NO, TRUE },
{ "palette 32 bit", L"palette 32 bit", OPS_NO, TRUE },
L"interpreter \"(%q*)\" \"([gz])\"", TT_OPS, FALSE },
{ "palette { details }", L"palette {(%c*?)}", T_OPS, TRUE },
{ "palette 16 bit", L"palette 16 bit", VOID_OPS, TRUE },
{ "palette 32 bit", L"palette 32 bit", VOID_OPS, TRUE },
{ "picture ID \"filename\" scale ...",
L"picture (%i+?) \"(%q*)\" scale (%c*)", OPS_3TEXT, TRUE },
{ "picture N \"filename\"", L"picture (%d+) \"(%q*)\"", OPS_1NUMBER_1TEXT, FALSE },
{ "picture ID \"filename\"", L"picture (%i+) \"(%q*)\"", OPS_2TEXT, FALSE },
{ "picture \"filename\"", L"picture \"(%q*)\"", OPS_1TEXT, FALSE },
{ "picture N \"filename\" \"alt-text\"", L"picture %d \"(%q*)\" \"(%q*)\"", OPS_1NUMBER_2TEXTS, FALSE },
{ "placeholder [name] = \"text\"", L"placeholder %[(%C+)%] = \"(%q*)\"", OPS_2TEXT, FALSE },
{ "project folder \"pathname\"", L"project folder \"(%q*)\"", OPS_1TEXT, FALSE },
{ "release \"text\"", L"release \"(%q*)\"", OPS_1TEXT, FALSE },
{ "release file \"filename\"", L"release file \"(%q*)\"", OPS_1TEXT, FALSE },
L"picture (%i+?) \"(%q*)\" scale (%c*)", TTT_OPS, TRUE },
{ "picture N \"filename\"", L"picture (%d+) \"(%q*)\"", NT_OPS, FALSE },
{ "picture ID \"filename\"", L"picture (%i+) \"(%q*)\"", TT_OPS, FALSE },
{ "picture \"filename\"", L"picture \"(%q*)\"", T_OPS, FALSE },
{ "picture N \"filename\" \"alt-text\"", L"picture %d \"(%q*)\" \"(%q*)\"", NTT_OPS, FALSE },
{ "placeholder [name] = \"text\"", L"placeholder %[(%C+)%] = \"(%q*)\"", TT_OPS, FALSE },
{ "project folder \"pathname\"", L"project folder \"(%q*)\"", T_OPS, FALSE },
{ "release \"text\"", L"release \"(%q*)\"", T_OPS, FALSE },
{ "release file \"filename\"", L"release file \"(%q*)\"", T_OPS, FALSE },
{ "release file \"filename\" from \"template\"",
L"release file \"(%q*)\" from \"(%q*)\"", OPS_2TEXT, FALSE },
L"release file \"(%q*)\" from \"(%q*)\"", TT_OPS, FALSE },
{ "release source \"filename\" using \"filename\" from \"template\"",
L"release source \"(%q*)\" using \"(%q*)\" from \"(%q*)\"", OPS_3TEXT, FALSE },
{ "release to \"pathname\"", L"release to \"(%q*)\"", OPS_1TEXT, FALSE },
{ "resolution NxN max NxN", L"resolution (%d+) max (%d+)", OPS_2NUMBER, TRUE },
{ "resolution NxN min NxN max NxN", L"resolution (%d+) min (%d+) max (%d+)", OPS_3NUMBER, TRUE },
{ "resolution NxN min NxN", L"resolution (%d+) min (%d+)", OPS_2NUMBER, TRUE },
{ "resolution NxN", L"resolution (%d+)", OPS_1NUMBER, TRUE },
{ "solution", L"solution", OPS_NO, FALSE },
{ "solution public", L"solution public", OPS_NO, FALSE },
{ "sound ID \"filename\" music", L"sound (%i+) \"(%q*)\" music", OPS_2TEXT, TRUE },
L"release source \"(%q*)\" using \"(%q*)\" from \"(%q*)\"", TTT_OPS, FALSE },
{ "release to \"pathname\"", L"release to \"(%q*)\"", T_OPS, FALSE },
{ "resolution NxN max NxN", L"resolution (%d+) max (%d+)", NN_OPS, TRUE },
{ "resolution NxN min NxN max NxN", L"resolution (%d+) min (%d+) max (%d+)", NNN_OPS, TRUE },
{ "resolution NxN min NxN", L"resolution (%d+) min (%d+)", NN_OPS, TRUE },
{ "resolution NxN", L"resolution (%d+)", N_OPS, TRUE },
{ "solution", L"solution", VOID_OPS, FALSE },
{ "solution public", L"solution public", VOID_OPS, FALSE },
{ "sound ID \"filename\" music", L"sound (%i+) \"(%q*)\" music", TT_OPS, TRUE },
{ "sound ID \"filename\" repeat N",
L"sound (%i+) \"(%q*)\" repeat (%d+)", OPS_2TEXT_1NUMBER, TRUE },
L"sound (%i+) \"(%q*)\" repeat (%d+)", TTN_OPS, TRUE },
{ "sound ID \"filename\" repeat forever",
L"sound (%i+) \"(%q*)\" repeat forever", OPS_2TEXT, TRUE },
{ "sound ID \"filename\" song", L"sound (%i+) \"(%q*)\" song", OPS_2TEXT, TRUE },
{ "sound N \"filename\"", L"sound (%d+) \"(%q*)\"", OPS_1NUMBER_1TEXT, FALSE },
{ "sound ID \"filename\"", L"sound (%i+) \"(%q*)\"", OPS_2TEXT, FALSE },
{ "sound \"filename\"", L"sound \"(%q*)\"", OPS_1TEXT, FALSE },
{ "sound N \"filename\" \"alt-text\"", L"sound (%d+) \"(%q*)\" \"(%q*)\"", OPS_1NUMBER_2TEXTS, FALSE },
{ "source", L"source", OPS_NO, FALSE },
{ "source public", L"source public", OPS_NO, FALSE },
{ "status \"template\" \"filename\"", L"status \"(%q*)\" \"(%q*)\"", OPS_2TEXT, FALSE },
L"sound (%i+) \"(%q*)\" repeat forever", TT_OPS, TRUE },
{ "sound ID \"filename\" song", L"sound (%i+) \"(%q*)\" song", TT_OPS, TRUE },
{ "sound N \"filename\"", L"sound (%d+) \"(%q*)\"", NT_OPS, FALSE },
{ "sound ID \"filename\"", L"sound (%i+) \"(%q*)\"", TT_OPS, FALSE },
{ "sound \"filename\"", L"sound \"(%q*)\"", T_OPS, FALSE },
{ "sound N \"filename\" \"alt-text\"", L"sound (%d+) \"(%q*)\" \"(%q*)\"", NTT_OPS, FALSE },
{ "source", L"source", VOID_OPS, FALSE },
{ "source public", L"source public", VOID_OPS, FALSE },
{ "status \"template\" \"filename\"", L"status \"(%q*)\" \"(%q*)\"", TT_OPS, FALSE },
{ "status alternative ||link to Inform documentation||",
L"status alternative ||(%c*)||", OPS_1TEXT, FALSE },
L"status alternative ||(%c*)||", T_OPS, FALSE },
{ "status instruction ||link to Inform source text||",
L"status instruction ||(%c*)||", OPS_1TEXT, FALSE },
{ "storyfile \"filename\" include", L"storyfile \"(%q*)\" include", OPS_1TEXT, FALSE },
{ "storyfile \"filename\"", L"storyfile \"(%q*)\"", OPS_1TEXT, TRUE },
{ "storyfile leafname \"leafname\"", L"storyfile leafname \"(%q*)\"", OPS_1TEXT, FALSE },
{ "template path \"folder\"", L"template path \"(%q*)\"", OPS_1TEXT, FALSE },
{ "website \"template\"", L"website \"(%q*)\"", OPS_1TEXT, FALSE },
{ NULL, NULL, OPS_NO, FALSE }
L"status instruction ||(%c*)||", T_OPS, FALSE },
{ "storyfile \"filename\" include", L"storyfile \"(%q*)\" include", T_OPS, FALSE },
{ "storyfile \"filename\"", L"storyfile \"(%q*)\"", T_OPS, TRUE },
{ "storyfile leafname \"leafname\"", L"storyfile leafname \"(%q*)\"", T_OPS, FALSE },
{ "template path \"folder\"", L"template path \"(%q*)\"", T_OPS, FALSE },
{ "website \"template\"", L"website \"(%q*)\"", T_OPS, FALSE },
{ NULL, NULL, VOID_OPS, FALSE }
};
@h Summary.
@ -188,7 +191,7 @@ void Parser::interpret_line(text_stream *command, text_file_position *tf, void *
if (Str::len(command) == 0) return; /* thus skip a line containing only blank space */
if (Str::get_first_char(command) == '!') return; /* thus skip a comment line */
if (trace_mode) PRINT("! %03d: %S\n", TextFiles::get_line_count(tf), command);
if (verbose_mode) PRINT("! %03d: %S\n", TextFiles::get_line_count(tf), command);
int num1 = 0, num2 = 0, num3 = 0, outcome = -1; /* which of the legal command syntaxes is used */
TEMPORARY_TEXT(text1);
@ -210,31 +213,31 @@ copied in |text1|, |num1|, ..., accordingly.
for (int t=0; syntaxes[t].prototype; t++)
if (Regexp::match(&mr, command, syntaxes[t].prototype)) {
switch (syntaxes[t].operands) {
case OPS_NO: break;
case OPS_1TEXT: Str::copy(text1, mr.exp[0]); break;
case OPS_2TEXT: Str::copy(text1, mr.exp[0]);
Str::copy(text2, mr.exp[1]); break;
case OPS_2TEXT_1NUMBER: Str::copy(text1, mr.exp[0]);
Str::copy(text2, mr.exp[1]);
num1 = Str::atoi(mr.exp[2], 0); break;
case OPS_1NUMBER: num1 = Str::atoi(mr.exp[0], 0); break;
case OPS_2NUMBER: num1 = Str::atoi(mr.exp[0], 0);
num2 = Str::atoi(mr.exp[1], 0); break;
case OPS_1NUMBER_1TEXT: num1 = Str::atoi(mr.exp[0], 0);
Str::copy(text1, mr.exp[1]); break;
case OPS_1NUMBER_2TEXTS: num1 = Str::atoi(mr.exp[0], 0);
Str::copy(text1, mr.exp[1]);
Str::copy(text2, mr.exp[2]); break;
case OPS_1NUMBER_1TEXT_1NUMBER: num1 = Str::atoi(mr.exp[0], 0);
Str::copy(text1, mr.exp[1]);
num2 = Str::atoi(mr.exp[2], 0); break;
case OPS_3NUMBER: num1 = Str::atoi(mr.exp[0], 0);
num2 = Str::atoi(mr.exp[1], 0);
num3 = Str::atoi(mr.exp[2], 0); break;
case OPS_3TEXT: Str::copy(text1, mr.exp[0]);
Str::copy(text2, mr.exp[1]);
Str::copy(text3, mr.exp[2]); break;
default: internal_error("unknown operand type");
case VOID_OPS: break;
case T_OPS: Str::copy(text1, mr.exp[0]); break;
case TT_OPS: Str::copy(text1, mr.exp[0]);
Str::copy(text2, mr.exp[1]); break;
case TTN_OPS: Str::copy(text1, mr.exp[0]);
Str::copy(text2, mr.exp[1]);
num1 = Str::atoi(mr.exp[2], 0); break;
case N_OPS: num1 = Str::atoi(mr.exp[0], 0); break;
case NN_OPS: num1 = Str::atoi(mr.exp[0], 0);
num2 = Str::atoi(mr.exp[1], 0); break;
case NT_OPS: num1 = Str::atoi(mr.exp[0], 0);
Str::copy(text1, mr.exp[1]); break;
case NTT_OPS: num1 = Str::atoi(mr.exp[0], 0);
Str::copy(text1, mr.exp[1]);
Str::copy(text2, mr.exp[2]); break;
case NTN_OPS: num1 = Str::atoi(mr.exp[0], 0);
Str::copy(text1, mr.exp[1]);
num2 = Str::atoi(mr.exp[2], 0); break;
case NNN_OPS: num1 = Str::atoi(mr.exp[0], 0);
num2 = Str::atoi(mr.exp[1], 0);
num3 = Str::atoi(mr.exp[2], 0); break;
case TTT_OPS: Str::copy(text1, mr.exp[0]);
Str::copy(text2, mr.exp[1]);
Str::copy(text3, mr.exp[2]); break;
default: internal_error("unknown operand type");
}
outcome = t; break;
}
@ -302,7 +305,10 @@ copied in |text1|, |num1|, ..., accordingly.
case sound_with_alt_text_COMMAND: Writer::sound_chunk(num1, Filenames::from_text(text1), text2); break;
case source_COMMAND: Requests::request_1(SOURCE_REQ, I"", TRUE); break;
case source_public_COMMAND: Requests::request_1(SOURCE_REQ, I"", FALSE); break;
case status_COMMAND: status_template = Filenames::from_text(text1); status_file = Filenames::from_text(text2); break;
case status_COMMAND:
status_template = Filenames::from_text(text1);
status_file = Filenames::from_text(text2);
break;
case status_alternative_COMMAND: Requests::request_1(ALTERNATIVE_REQ, text1, FALSE); break;
case status_instruction_COMMAND: Requests::request_1(INSTRUCTION_REQ, text1, FALSE); break;
case storyfile_include_COMMAND: Writer::executable_chunk(Filenames::from_text(text1)); break;

View file

@ -1,7 +1,7 @@
[Main::] Main.
To parse command-line arguments and take the necessary steps to
obey them.
To parse command-line arguments, then start the Blurb interpreter, then
report back to the user.
@h Some globals.
The following variables record HTML and Javascript-related points where
@ -18,7 +18,9 @@ int reverse_slash_openUrl = FALSE, reverse_slash_fileUrl = FALSE;
@ Some global variables:
=
int trace_mode = FALSE; /* print diagnostics to |stdout| while running? */
int error_count = 0; /* number of error messages produced so far */
int verbose_mode = FALSE; /* print diagnostics to |stdout| while running? */
int current_year_AD = 0; /* e.g., 2008 */
int blorb_file_size = 0; /* size in bytes of the blorb file written */
@ -80,7 +82,7 @@ int main(int argc, char *argv[]) {
status_file = NULL;
status_template = NULL;
@
@ We use Foundation's standard command-line routines.
@e VERBOSE_CLSW
@e PROJECT_CLSW
@ -89,7 +91,7 @@ int main(int argc, char *argv[]) {
@<Read the command-line switches@>;
@<Set platform-dependent HTML and Javascript variables@>;
if (trace_mode)
if (verbose_mode)
PRINT("! Blurb in: <%f>\n! Blorb out: <%f>\n",
blurb_filename, blorb_filename);
@ -117,7 +119,7 @@ int main(int argc, char *argv[]) {
@ =
void Main::switch(int id, int val, text_stream *arg, void *state) {
switch (id) {
case VERBOSE_CLSW: trace_mode = val; break;
case VERBOSE_CLSW: verbose_mode = val; break;
case PROJECT_CLSW: project_folder = Pathnames::from_text(arg); break;
default: internal_error("unimplemented switch");
}
@ -204,8 +206,8 @@ void Main::initialise_time_variables(void) {
@h Opening and closing banners.
Note that Inblorb customarily prints informational messages with an initial
|!|, so that the piped output from Inblorb could be used as an |Include|
file in I6 code; that isn't in fact how I7 uses Inblorb, but it's traditional
for blorbing programs to do this.
file in I6 code, where |!| is the comment character; that isn't in fact how
I7 uses Inblorb, but it's traditional for blorbing programs to do this.
=
void Main::print_banner(void) {
@ -231,8 +233,8 @@ void Main::print_report(void) {
}
@ If it isn't apparent what these placeholders do, take a look at
the template file for |StatusCblorb.html| in the Inform application -- that's
where they're used.
the template file called |CblorbModel.html| in the Inform application --
that's where they're used.
@<Set a whole pile of placeholders which will be needed to generate the status page@> =
if (error_count > 0) {

View file

@ -53,13 +53,13 @@ same goes for Pict resources. These two linked lists are used to store all the
resource numbers encountered.
=
typedef struct resource_list resource_list;
struct resource_list {
typedef struct resource_number {
int num;
struct resource_list *n;
};
resource_list *sound_resource = NULL;
resource_list *pict_resource = NULL;
MEMORY_MANAGEMENT
} resource_number;
linked_list *sound_resource = NULL; /* of |resource_number| */
linked_list *pict_resource = NULL; /* of |resource_number| */
@ And this is used to record alt-descriptions of resources, for the benefit
of partially sighted or deaf users:
@ -147,7 +147,7 @@ void Writer::add_chunk_to_blorb(char *id, int resource_num, filename *supplied_f
@<Compute the size in bytes of the chunk@>;
@<Advance the total chunk size@>;
if (trace_mode)
if (verbose_mode)
PRINT("! Begun chunk %s: fn is <%f> (innate size %d)\n",
current_chunk->chunk_type, current_chunk->chunk_file, current_chunk->size);
}
@ -231,17 +231,14 @@ exit with a fatal error. Otherwise, FALSE is returned, indicating that
everything is fine.
=
int Writer::resource_seen(resource_list **list, int value) {
resource_list *p;
for(p = *list; p; p = p->n) {
if (p->num == value) return TRUE;
}
p = *list;
*list = Memory::I7_malloc(sizeof(resource_list), RDES_MREASON);
if (*list == NULL)
BlorbErrors::fatal("Run out of memory");
(*list)->num = value;
(*list)->n = p;
int Writer::resource_seen(linked_list *L, int value) {
resource_number *rn;
LOOP_OVER_LINKED_LIST(rn, resource_number, L)
if (rn->num == value)
return TRUE;
rn = CREATE(resource_number);
rn->num = value;
ADD_TO_LINKED_LIST(rn, resource_number, L);
return FALSE;
}
@ -259,7 +256,7 @@ int Writer::chunk_type_is_already_an_IFF(char *type) {
=
void Writer::author_chunk(text_stream *t) {
if (trace_mode) PRINT("! Author: <%S>\n", t);
if (verbose_mode) PRINT("! Author: <%S>\n", t);
Writer::add_chunk_to_blorb("AUTH", 0, NULL, NULL, (unsigned char *) t, Str::len(t));
}
@ -267,7 +264,7 @@ void Writer::author_chunk(text_stream *t) {
=
void Writer::copyright_chunk(text_stream *t) {
if (trace_mode) PRINT("! Copyright declaration: <%S>\n", t);
if (verbose_mode) PRINT("! Copyright declaration: <%S>\n", t);
Writer::add_chunk_to_blorb("(c) ", 0, NULL, NULL, (unsigned char *) t, Str::len(t));
}
@ -276,7 +273,7 @@ cover art, in other words.
=
void Writer::frontispiece_chunk(int pn) {
if (trace_mode) PRINT("! Frontispiece is image %d\n", pn);
if (verbose_mode) PRINT("! Frontispiece is image %d\n", pn);
unsigned char data[4];
Writer::s_four_word(data, pn);
Writer::add_chunk_to_blorb("Fspc", 0, NULL, NULL, data, 4);
@ -286,7 +283,7 @@ void Writer::frontispiece_chunk(int pn) {
=
void Writer::release_chunk(int rn) {
if (trace_mode) PRINT("! Release number is %d\n", rn);
if (verbose_mode) PRINT("! Release number is %d\n", rn);
unsigned char data[2];
Writer::s_two_word(data, rn);
Writer::add_chunk_to_blorb("RelN", 0, NULL, NULL, data, 2);
@ -306,7 +303,9 @@ void Writer::picture_chunk(int n, filename *fn, text_stream *alt) {
"(expected e.g. '.png' for PNG, '.jpeg' for JPEG)", fn);
if (n < 1) BlorbErrors::fatal("Picture resource number is less than 1");
if (Writer::resource_seen(&pict_resource, n)) BlorbErrors::fatal("Duplicate Picture resource number");
if (pict_resource == NULL) pict_resource = NEW_LINKED_LIST(resource_number);
if (Writer::resource_seen(pict_resource, n))
BlorbErrors::fatal("Duplicate Picture resource number");
Writer::add_chunk_to_blorb(type, n, fn, "Pict", NULL, 0);
if (Str::len(alt) > 0) {
@ -354,7 +353,8 @@ void Writer::sound_chunk(int n, filename *fn, text_stream *alt) {
"(expected e.g. '.ogg', '.midi', '.mod' or '.aiff', as appropriate)", fn);
if (n < 3) BlorbErrors::fatal("Sound resource number is less than 3");
if (Writer::resource_seen(&sound_resource, n)) BlorbErrors::fatal("Duplicate Sound resource number");
if (sound_resource == NULL) sound_resource = NEW_LINKED_LIST(resource_number);
if (Writer::resource_seen(sound_resource, n)) BlorbErrors::fatal("Duplicate Sound resource number");
Writer::add_chunk_to_blorb(type, n, fn, "Snd ", NULL, 0);
if (Str::len(alt) > 0) {
@ -452,7 +452,7 @@ void Writer::write_blorb_file(filename *out) {
int RIdx_size, first_byte_after_index;
@<Calculate the sizes of the whole file and the index chunk@>;
@<Write the initial FORM chunk of the IFF file, and then the index@>;
if (trace_mode) @<Print out a copy of the chunk table@>;
if (verbose_mode) @<Print out a copy of the chunk table@>;
chunk_metadata *chunk;
LOOP_OVER(chunk, chunk_metadata) @<Write the chunk@>;

View file

@ -3,8 +3,7 @@
To produce base64-encoded story files ready for in-browser play by
a Javascript-based interpreter such as Parchment.
@h Base 64.
This encoding scheme is defined by the Internet standard RFC 1113.
@ The Base64 encoding scheme is defined by the Internet standard RFC 1113.
Broadly, the idea is to take a binary stream of bytes, break it into
threes, and then convert this into a sequence of four emailable
characters. To encode 24 bits in four characters, we need six bits per

View file

@ -153,7 +153,7 @@ void Links::request_copy_of_auxiliaries(void) {
auxiliary_file *aux;
LOOP_OVER(aux, auxiliary_file)
if (Str::eq(aux->format, I"link")) {
if (trace_mode)
if (verbose_mode)
PRINT("! COPY <%f> as <%S>\n", aux->full_filename, aux->aux_leafname);
TEMPORARY_TEXT(as_text);
WRITE_TO(as_text, "%f", aux->full_filename);

View file

@ -103,13 +103,13 @@ void Placeholders::append_to(text_stream *var, text_stream *text) {
=
void Placeholders::set_to_inner(text_stream *var, text_stream *text, int reservation, int extend) {
if (trace_mode) PRINT("! [%S] <-- \"%S\"\n", var, text);
if (verbose_mode) PRINT("! [%S] <-- \"%S\"\n", var, text);
placeholder *wv = Placeholders::find(var);
if ((wv) && (reservation > 0)) { BlorbErrors::error_1S("tried to set reserved variable %S", var); return; }
if (wv == NULL) {
wv = CREATE(placeholder);
if (trace_mode) PRINT("! Creating [%S]\n", var);
if (verbose_mode) PRINT("! Creating [%S]\n", var);
wv->pl_name = Str::duplicate(var);
wv->pl_contents = Str::new();
wv->reservation = reservation;

View file

@ -3,28 +3,27 @@
To manage requests to release material other than a Blorb file.
@h Requests.
If the previous section, "Blorb Writer.w", was the Lord High Executioner,
If the previous chapter, which wrote blorb files, was the Lord High Executioner,
then this one is the Lord High Everything Else: it keeps track of requests
to write all kinds of interesting things which are _not_ blorb files,
to write all kinds of interesting things which are not blorb files,
and then sees that they are carried out. The requests divide as follows:
@d COPY_REQ 0 /* a miscellaneous file */
@d IFICTION_REQ 1 /* the iFiction record of a project */
@d RELEASE_FILE_REQ 2 /* a template file */
@d RELEASE_SOURCE_REQ 3 /* the source text in HTML form */
@d SOLUTION_REQ 4 /* a solution file generated from the skein */
@d SOURCE_REQ 5 /* the source text of a project */
@d WEBSITE_REQ 6 /* a whole website */
@d INTERPRETER_REQ 7 /* an in-browser interpreter */
@d BASE64_REQ 8 /* a base64-encoded copy of a binary file */
@d INSTRUCTION_REQ 9 /* a release instruction copied to inblorb for reporting only */
@d ALTERNATIVE_REQ 10 /* an unused release instruction copied to inblorb for reporting only */
@e COPY_REQ from 0 /* a miscellaneous file */
@e IFICTION_REQ /* the iFiction record of a project */
@e RELEASE_FILE_REQ /* a template file */
@e RELEASE_SOURCE_REQ /* the source text in HTML form */
@e SOLUTION_REQ /* a solution file generated from the skein */
@e SOURCE_REQ /* the source text of a project */
@e WEBSITE_REQ /* a whole website */
@e INTERPRETER_REQ /* an in-browser interpreter */
@e BASE64_REQ /* a base64-encoded copy of a binary file */
@e INSTRUCTION_REQ /* a release instruction copied to inblorb for reporting only */
@e ALTERNATIVE_REQ /* an unused release instruction copied to inblorb for reporting only */
=
int website_requested = FALSE; /* has a |WEBSITE_REQ| been made? */
@ This would use a lot of memory if there were many requests, but there are
not and it does not.
@ Each request produces an instance of:
=
typedef struct request {
@ -92,14 +91,18 @@ void Requests::any_last_requests(void) {
if (default_cover_used == FALSE) {
text_stream *BIGCOVER = Placeholders::read(I"BIGCOVER");
if (Str::len(BIGCOVER) > 0) {
if (cover_is_in_JPEG_format) Requests::request_copy(BIGCOVER, I"Cover.jpg", I"--");
else Requests::request_copy(BIGCOVER, I"Cover.png", I"--");
if (cover_is_in_JPEG_format)
Requests::request_copy(BIGCOVER, I"Cover.jpg", I"--");
else
Requests::request_copy(BIGCOVER, I"Cover.png", I"--");
}
if (website_requested) {
text_stream *SMALLCOVER = Placeholders::read(I"SMALLCOVER");
if (Str::len(SMALLCOVER) > 0) {
if (cover_is_in_JPEG_format) Requests::request_copy(SMALLCOVER, I"Small Cover.jpg", I"--");
else Requests::request_copy(SMALLCOVER, I"Small Cover.png", I"--");
if (cover_is_in_JPEG_format)
Requests::request_copy(SMALLCOVER, I"Small Cover.jpg", I"--");
else
Requests::request_copy(SMALLCOVER, I"Small Cover.png", I"--");
}
}
}
@ -174,7 +177,7 @@ void Requests::create_requested_material(void) {
Placeholders::set_to(I"TEMPLATE", req->details3, 0);
filename *HTML_template = Templates::find_file_in_specific_template(req->details3, req->details2);
if (HTML_template == NULL) BlorbErrors::error_1S("can't find HTML template file", req->details2);
if (trace_mode) PRINT("! Web page %f from template %s\n", HTML_template, req->details3);
if (verbose_mode) PRINT("! Web page %f from template %s\n", HTML_template, req->details3);
Websites::web_copy_source(HTML_template, release_folder);
@ Interpreters are copied, not made. They're really just like website
@ -368,14 +371,14 @@ to the experts.
@<Release an HTML page from the template into the website@> =
Placeholders::set_to(I"TEMPLATE", t, 0);
if (trace_mode) PRINT("! Web page %S from template %S\n", name, t);
if (verbose_mode) PRINT("! Web page %S from template %S\n", name, t);
if (Str::eq_wide_string(name, L"source.html"))
Websites::web_copy_source(from, release_folder);
else
Websites::web_copy(from, write_to);
@<Release a binary file from the template into the website@> =
if (trace_mode) PRINT("! Binary file %S from template %S\n", name, t);
if (verbose_mode) PRINT("! Binary file %S from template %S\n", name, t);
BinaryFiles::copy(from, write_to, FALSE);
@ The home page will need links to any public released resources, and this

View file

@ -130,7 +130,7 @@ void Solution::read_skein_line(text_stream *line, int pass) {
current_skein_node->child = NULL;
current_skein_node->sibling = NULL;
current_skein_node->relevant = FALSE;
if (trace_mode) PRINT("Creating knot with ID '%S'\n", node_id);
if (verbose_mode) PRINT("Creating knot with ID '%S'\n", node_id);
@ We make |new_child| the youngest child of |current_skein_mode|:
@ -147,19 +147,19 @@ void Solution::read_skein_line(text_stream *line, int pass) {
@<Look for a "command" tag and set the command text from it@> =
text_stream *p = current_skein_node->command;
if (Solution::find_text_of_tag(p, line, "command")) {
if (trace_mode) PRINT("Raw command '%S'\n", p);
if (verbose_mode) PRINT("Raw command '%S'\n", p);
Solution::undo_XML_escapes_in_string(p);
LOOP_THROUGH_TEXT(pos, p)
Str::put(pos, Characters::toupper(Str::get(pos)));
if (trace_mode) PRINT("Processed command '%S'\n", p);
if (verbose_mode) PRINT("Processed command '%S'\n", p);
}
@<Look for an "annotation" tag and set the annotation text from it@> =
text_stream *p = current_skein_node->annotation;
if (Solution::find_text_of_tag(p, line, "annotation")) {
if (trace_mode) PRINT("Raw annotation '%S'\n", p);
if (verbose_mode) PRINT("Raw annotation '%S'\n", p);
Solution::undo_XML_escapes_in_string(p);
if (trace_mode) PRINT("Processed annotation '%S'\n", p);
if (verbose_mode) PRINT("Processed annotation '%S'\n", p);
}
@ Try to find a node ID element attached to a particular tag on the line:
@ -251,14 +251,14 @@ void Solution::identify_relevant_lines(void) {
skein_node *skn;
LOOP_OVER(skn, skein_node) {
text_stream *p = skn->annotation;
if (trace_mode) PRINT("Knot %S is annotated '%S'\n", skn->id, p);
if (verbose_mode) PRINT("Knot %S is annotated '%S'\n", skn->id, p);
if ((Str::get_at(p, 0) == '*') && (Str::get_at(p, 1) == '*') && (Str::get_at(p, 2) == '*')) {
int i = 3, j; while (Str::get_at(p, i) == ' ') i++;
for (j=0; Str::get_at(p, i); i++) Str::put_at(p, j++, Str::get_at(p, i)); Str::put_at(p, j, 0);
skein_node *knot;
for (knot = skn; knot; knot = knot->parent) {
knot->relevant = TRUE;
if (trace_mode) PRINT("Knot %S is relevant\n", knot->id);
if (verbose_mode) PRINT("Knot %S is relevant\n", knot->id);
}
}
}

View file

@ -29,7 +29,7 @@ int no_template_paths = 0;
void Templates::new_path(pathname *P) {
template_path *tp = CREATE(template_path);
tp->template_repository = P;
if (trace_mode)
if (verbose_mode)
PRINT("! Template search path %d: <%p>\n", ++no_template_paths, P);
}
@ -116,7 +116,7 @@ filename *Templates::try_single(template *t, text_stream *needed) {
pathname *T = Pathnames::subfolder(t->template_location->template_repository, t->template_name);
t->latest_use = Filenames::in_folder(T, needed);
if (trace_mode) PRINT("! Trying <%f>\n", t->latest_use);
if (verbose_mode) PRINT("! Trying <%f>\n", t->latest_use);
if (TextFiles::exists(t->latest_use)) return t->latest_use;
return NULL;
}

View file

@ -36,10 +36,13 @@ if there are no headings at all, for there to be no segments so that the
entire source text is "prefatory". If we have three segments, then, we
will split the source text into four HTML files:
|source0.html| -- "Page 1 of 4", the preface and then contents
|source1.html| -- "Page 2 of 4", first segment (with allocation ID 0)
|source2.html| -- "Page 3 of 4", second segment (with allocation ID 1)
|source3.html| -- "Page 4 of 4", third segment (with allocation ID 2)
|source0.html| -- "Page 1 of 4", the preface and then contents
|source1.html| -- "Page 2 of 4", first segment (with allocation ID 0)
|source2.html| -- "Page 3 of 4", second segment (with allocation ID 1)
|source3.html| -- "Page 4 of 4", third segment (with allocation ID 2)
Note that the prefatory lines contain no headings, that every heading
belongs to a unique segment (hence the |heading_to_segment| field above)
@ -79,16 +82,16 @@ variables, so Inblorb itself has to choose CSS styles for anything interesting
that is displayed there. We use the following style names, which a CSS file
is required to define:
|columnhead| -- the heading of a column in a Table in I7 source text
|comment| -- comments in I7 source text
|filetype| -- the "(pdf, 150KB)" text annotating links
|heading| -- heading or top line of a Table in I7 source text
|i6code| -- verbatim I6 code in I7 source text
|notecue| -- footnote cues which annotate I7 source text
|notesheading| -- the little "Notes" subheading above the footnotes to source text
|notetext| -- texts of footnotes which annotate I7 source text
|quote| -- double-quoted text in I7 source text
|substitution| -- text substitution inside double-quoted text in I7 source text
(a) |columnhead| -- the heading of a column in a Table in I7 source text
(b) |comment| -- comments in I7 source text
(c) |filetype| -- the "(pdf, 150KB)" text annotating links
(d) |heading| -- heading or top line of a Table in I7 source text
(e) |i6code| -- verbatim I6 code in I7 source text
(f) |notecue| -- footnote cues which annotate I7 source text
(g) |notesheading| -- the little "Notes" subheading above the footnotes to source text
(h) |notetext| -- texts of footnotes which annotate I7 source text
(i) |quote| -- double-quoted text in I7 source text
(j) |substitution| -- text substitution inside double-quoted text in I7 source text
In addition it must provide paragraph classes |indent0| to |indent9| for code
which begins at tab positions 0 to 9 (see below). Although "Standard.css"

View file

@ -20,8 +20,8 @@ Preliminaries
Chapter 1: Blurbs
"A little infrastructure, but basically, parsing of our instructions."
Basics
Blorb Errors
Main
Blorb Errors
Blurb Parser
Chapter 2: Blorbs

View file

@ -209,7 +209,7 @@ The file should be a valid iFiction record for the work. This is an XML file
specified in the Treaty of Babel, a cross-IF-system standard for specifying
bibliographic data; it will be embedded into the blorb.
|storyfile <filename>| -- unsupported by Inblorb
|storyfile <filename> ... unsupported by Inblorb|
|storyfile <filename> include|
Specifies the filename of the story file which these resources are being
@ -226,9 +226,9 @@ Inblorb always does this, and does not support |storyfile| without
@ Second, now-deprecated commands describing our ideal screen display:
|palette 16 bit| -- unsupported by Inblorb
|palette 32 bit| -- unsupported by Inblorb
|palette { <colour-1>| É |<colour-N> }| -- unsupported by Inblorb
|palette 16 bit ... unsupported by Inblorb|
|palette 32 bit ... unsupported by Inblorb|
|palette { <colour-1> ... <colour-N> } ... unsupported by Inblorb|
Blorb allows designers to signal to the interpreter that a particular
colour-scheme is in use. The first two options simply suggest that the
@ -239,10 +239,10 @@ continue over many lines. At least one and at most 256 colours may be
defined in this way. This is only a "clue" to the interpreter; see the
Blorb specification for details.
|resolution <dim>| -- unsupported by Inblorb
|resolution <dim> min <dim>| -- unsupported by Inblorb
|resolution <dim> max <dim>| -- unsupported by Inblorb
|resolution <dim> min <dim> max <dim>| -- unsupported by Inblorb
|resolution <dim> ... unsupported by Inblorb|
|resolution <dim> min <dim> ... unsupported by Inblorb|
|resolution <dim> max <dim> ... unsupported by Inblorb|
|resolution <dim> min <dim> max <dim> ... unsupported by Inblorb|
Allows the designer to signal a preferred screen size, in real pixels, in
case the interpreter should have any choice over this. The minimum and
@ -253,10 +253,10 @@ infinity by infinity.
@ Third, commands for adding audiovisual resources:
|sound <id> <filename>|
|sound <id> <filename> repeat <number>| -- unsupported by Inblorb
|sound <id> <filename> repeat forever| -- unsupported by Inblorb
|sound <id> <filename> music| -- unsupported by Inblorb
|sound <id> <filename> song| -- unsupported by Inblorb
|sound <id> <filename> repeat <number> ... unsupported by Inblorb|
|sound <id> <filename> repeat forever ... unsupported by Inblorb|
|sound <id> <filename> music ... unsupported by Inblorb|
|sound <id> <filename> song ... unsupported by Inblorb|
Tells us to take a sound sample from the named file and make it the sound
effect with the given number. Most forms of |sound| are now deprecated:
@ -267,9 +267,9 @@ sound formats. Nowadays the straight |sound| command should always
be used regardless of format.
|picture <id> <filename>|
|picture <id> <filename> scale <ratio>| -- unsupported by Inblorb
|picture <id> <filename> scale min <ratio>| -- unsupported by Inblorb
|picture <id> <filename> scale <ratio> min <ratio>| -- unsupported by Inblorb
|picture <id> <filename> scale <ratio> ... unsupported by Inblorb|
|picture <id> <filename> scale min <ratio> ... unsupported by Inblorb|
|picture <id> <filename> scale <ratio> min <ratio> ... unsupported by Inblorb|
(and so on) is a similar command for images. In 2001, the image file was required
to be a PNG, but it can now alternatively be a JPEG.