diff --git a/README.md b/README.md
index fb892e0ce..2e70af8ae 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Inform 7
-[Version](notes/versioning.md): 10.2.0-beta+6W35 'Krypton' (22 April 2023)
+[Version](notes/versioning.md): 10.2.0-beta+6W55 'Krypton' (4 June 2023)
## About Inform
@@ -148,7 +148,7 @@ Other extensions shipped with Inform are not presented as webs, but as single fi
* [Inanimate Listeners by Emily Short](
-Array StorageForShortName buffer 250; +Constant SHORT_NAME_BUFFER_LEN = 160; + +#Ifdef TARGET_ZCODE; +Allow a generous overrun +Array StorageForShortName buffer SHORT_NAME_BUFFER_LEN+90; +#Ifnot; +Array StorageForShortName --> SHORT_NAME_BUFFER_LEN; +#Endif; [ CPrintOrRun obj prop v length i; - if ((obj ofclass String or Routine) || (prop == 0)) - VM_PrintToBuffer (StorageForShortName, 160, obj); + if ((obj ofclass String or Routine) || (prop == 0)) { + #Ifdef TARGET_ZCODE; + length = VM_PrintToBuffer (StorageForShortName, SHORT_NAME_BUFFER_LEN, obj); + #Ifnot; + length = Glulx_PrintAnyToArrayUni(StorageForShortName, SHORT_NAME_BUFFER_LEN, obj); + #Endif; + } else { if (obj.prop == NULL) rfalse; - if (metaclass(obj.prop) == Routine or String) - VM_PrintToBuffer(StorageForShortName, 160, obj, prop); - else return RunTimeError(2, obj, prop); + if (metaclass(obj.prop) == Routine or String) { + #Ifdef TARGET_ZCODE; + length = VM_PrintToBuffer(StorageForShortName, SHORT_NAME_BUFFER_LEN, obj, prop); + #Ifnot; + length = Glulx_PrintAnyToArrayUni(StorageForShortName, SHORT_NAME_BUFFER_LEN, obj.prop); + #Endif; + } + else { + return RunTimeError(2, obj, prop); + } } - length = StorageForShortName-->0; - + #Ifdef TARGET_ZCODE; StorageForShortName->WORDSIZE = VM_LowerToUpperCase(StorageForShortName->WORDSIZE); for (i=WORDSIZE: i<length+WORDSIZE: i++) print (char) StorageForShortName->i; - if (i>WORDSIZE) say__p = 1; + #Ifnot; + if (length > SHORT_NAME_BUFFER_LEN) length = SHORT_NAME_BUFFER_LEN; + ### length = glk_buffer_to_title_case_uni(StorageForShortName, SHORT_NAME_BUFFER_LEN, length, false); + ### glk_put_buffer_uni(StorageForShortName, length); + if (length) + StorageForShortName-->0 = VM_LowerToUpperCase(StorageForShortName-->0); + glk_put_buffer_uni(StorageForShortName, length); + #Endif; + + if (length) say__p = 1; return; ]; @@ -204,9 +231,7 @@ the following "for" rule. String: print "<string ~", (string) obj, "~>"; return; nothing: print "<illegal object number ", obj, ">"; return; } - #Ifdef LanguagePrintShortName; if (LanguagePrintShortName(obj)) return; - #Endif; LanguagePrintShortName if (indef_mode && obj provides short_name_indef && PrintOrRun(obj, short_name_indef, true) ~= 0) return; if (caps_mode && @@ -262,6 +287,7 @@ indefinite singular depends on the text of the object's name. if (i < 3 || (i >= 6 && i < 9)) i = i + 3; } i = LanguageGNAsToArticles-->i; + artform = LanguageArticles + 3*WORDSIZE*LanguageContractionForms*(short_name_case + i*LanguageCases); @@ -276,7 +302,7 @@ indefinite singular depends on the text of the object's name. } #Ifdef TARGET_ZCODE; if (standard_interpreter ~= 0 && findout) { - StorageForShortName-->0 = 160; + StorageForShortName-->0 = SHORT_NAME_BUFFER_LEN; @output_stream 3 StorageForShortName; if (pluralise) print (number) pluralise; else print (PSN__) obj; @output_stream -3; @@ -285,9 +311,9 @@ indefinite singular depends on the text of the object's name. #Ifnot; TARGET_GLULX if (findout) { if (pluralise) - Glulx_PrintAnyToArray(StorageForShortName, 160, EnglishNumber, pluralise); + Glulx_PrintAnyToArrayUni(StorageForShortName, SHORT_NAME_BUFFER_LEN, EnglishNumber, pluralise); else - Glulx_PrintAnyToArray(StorageForShortName, 160, PSN__, obj); + Glulx_PrintAnyToArrayUni(StorageForShortName, SHORT_NAME_BUFFER_LEN, PSN__, obj); acode = acode + 3*LanguageContraction(StorageForShortName); } #Endif; TARGET_ diff --git a/docs/BasicInformKit/S-blc.html b/docs/BasicInformKit/S-blc.html index ea1367b08..858817364 100644 --- a/docs/BasicInformKit/S-blc.html +++ b/docs/BasicInformKit/S-blc.html @@ -593,8 +593,6 @@ depending on the task in hand. Constant WRITE_FILE_KOVS = 13; Constant HASH_KOVS = 14; Constant DEBUG_KOVS = 15; - -Constant BLKVALUE_TRACE; ! Uncomment this to expose masses of tracery
§13. Creation. To create a block value, call:
@@ -630,7 +628,7 @@ outside the heap, for reasons to be seen below. kovs = KOVSupportFunction(strong_kind, "impossible allocation"); short_block = kovs(CREATE_KOVS, strong_kind, short_block); - #ifdef BLKVALUE_TRACE; print "Created: ", (BlkValueDebug) short_block, "^"; #endif; + #ifdef LKTRACE_HEAP; print "Created: ", (BlkValueDebug) short_block, "^"; #endif; The new value is represented in I6 as the pointer to its short block: return short_block; @@ -854,7 +852,7 @@ asking the kind's support function: if (from_bv == 0) BlkValueError("copy from null value"); if (to_bv == from_bv) return; - #ifdef BLKVALUE_TRACE; + #ifdef LKTRACE_HEAP; print "Copy: ", (BlkValueDebug) to_bv, " to equal ", (BlkValueDebug) from_bv, "^"; #endif; @@ -902,7 +900,7 @@ a list must not, for example, contain itself.[ BlkValueDestroyPrimitive bv kovs long_block; - #ifdef BLKVALUE_TRACE; print "Destroying ", (BlkValueDebug) bv, "^"; #endif; + #ifdef LKTRACE_HEAP; print "Destroying ", (BlkValueDebug) bv, "^"; #endif; if (BlkValueDecRefCountPrimitive(bv) == 0) { kovs(DESTROY_KOVS, bv); long_block = BlkValueGetLongBlock(bv); @@ -919,7 +917,7 @@ replace the small block with a new one (at the same address).[ BlkValueRecyclePrimitive bv kovs; - #ifdef BLKVALUE_TRACE; print "Recycling ", (BlkValueDebug) bv, "^"; #endif; + #ifdef LKTRACE_HEAP; print "Recycling ", (BlkValueDebug) bv, "^"; #endif; if (BlkValueDecRefCountPrimitive(bv) == 0) { kovs(DESTROY_KOVS, bv); BlkValueIncRefCountPrimitive(bv); @@ -952,7 +950,7 @@ a temporary one-value stack frame instead to hold it. if (bv == 0) BlkValueError("tried to make null block mutable"); if (BlkValueGetRefCountPrimitive(bv) > 1) { - #ifdef BLKVALUE_TRACE; print "Make mutable: ", (BlkValueDebug) bv, "^"; #endif; + #ifdef LKTRACE_HEAP; print "Make mutable: ", (BlkValueDebug) bv, "^"; #endif; BlkValueDecRefCountPrimitive(bv); diff --git a/docs/BasicInformKit/S-dfn.html b/docs/BasicInformKit/S-dfn.html index 8489b337d..efcb78102 100644 --- a/docs/BasicInformKit/S-dfn.html +++ b/docs/BasicInformKit/S-dfn.html @@ -65,12 +65,13 @@ MathJax = {
Miscellaneous constant definitions, usually providing symbolic names for otherwise inscrutable numbers, which are used throughout the template layer.
-Constant BASICINFORMKIT = 1; +Constant SERIAL_COMMA = BasicInformKit`SERIAL_COMMA_CFGF;
§2. Z-Machine Definitions. The Z-machine contains certain special constants and variables at fixed position in its "header"; the addresses of these are given below. See @@ -150,8 +151,12 @@ of the template layer, and would only get in the way here. Constant ROM_GAMERELEASE = $34; short word Constant ROM_GAMESERIAL = $36; six ASCII characters -Constant #dict_par1 = 11; -Constant #dict_par2 = 13; +The following constants describe the layout of a dictionary word entry. +The math is copied from the I6 compiler. + +Constant DICT_ENTRY_BYTES = 12+DICT_WORD_SIZE*WORDSIZE; +Constant #dict_par1 = DICT_WORD_SIZE*WORDSIZE+4+1; +Constant #dict_par2 = DICT_WORD_SIZE*WORDSIZE+4+3; #Endif; @@ -634,23 +639,6 @@ future use. Global formal_par7; Global unicode_temp; -
§23. Template Configuration. To minimise the need for conditional compilation in the template, the -constant KIT_CONFIGURATION_BITMAP must be generated by the user -(i.e., by I7). It's made up of these bits: -
- --Constant USE_SCORING_TCBIT = 1; -Constant PREVENT_UNDO_TCBIT = 2; -Constant SERIAL_COMMA_TCBIT = 4; -Constant PROGRAMMING_EXPONENTS_TCBIT = 8; -Constant FIX_RNG_TCBIT = 16; -Constant ECHO_COMMANDS_TCBIT = 32; -Constant NO_VERB_VERB_DEFINED_TCBIT = 64; -Constant DIALECT_US_TCBIT = 128; -Constant STORY_AUTHOR_TCBIT = 256; -Constant RANKING_TABLE_TCBIT = 512; -diff --git a/docs/BasicInformKit/S-flx.html b/docs/BasicInformKit/S-flx.html index 350512107..cc7081937 100644 --- a/docs/BasicInformKit/S-flx.html +++ b/docs/BasicInformKit/S-flx.html @@ -65,7 +65,7 @@ MathJax = {
To allocate flexible-sized blocks of memory as needed to hold arbitrary-length strings of text, stored actions or other block values.
-§1. Blocks. The purpose of the Flex routines is to manage flexible-sized "blocks" of
memory for any general-purpose use. The main customer for this service is
@@ -166,10 +166,17 @@ byte offset BLK_DATA_MULTI_OF
Constant BLK_DATA_MULTI_OFFSET = BLK_DATA_OFFSET + 2*WORDSIZE;
Constant BLK_NEXT 3;
Constant BLK_PREV 4;
-
-Constant BLKVALUE_TRACE = 1; ! Uncomment this for debugging purposes
- §3. The Heap. Properly speaking, a "heap" is a specific kind of structure often used for
+ §3. Tracing. Uncomment this line and rebuild the kit to enable tracing of what the algorithm
+below is doing. (This constant should not be used anywhere except in this file
+and in BlockValues.i6t, where #Ifdef on it will have the expected effect:
+elsewhere, it might not.)
+ §4. The Heap. Properly speaking, a "heap" is a specific kind of structure often used for
managing uneven-sized or unpredictably changing data. We use "heap" here in
the looser sense of being an amorphous-sized collection of blocks of memory,
some free, others allocated; our actual representation of free space on the
@@ -221,7 +228,7 @@ freed and added to the free space object.
§4. Initialisation. To recap: the constant MEMORY_HEAP_SIZE has been predefined by the Inform compiler,
+ §5. Initialisation. To recap: the constant MEMORY_HEAP_SIZE has been predefined by the Inform compiler,
and is always itself a power of 2, say \(2^n\). We therefore have \(2^n + 2^4\)
bytes available to us, and we format these as a free space list of two
blocks: the \(2^4\)-sized "head-free-block" described above followed by
@@ -246,7 +253,7 @@ a \(2^n\)-sized block exactly containing the whole of the rest of the heap.
blk2-->BLK_PREV = Flex_Heap;
];
- §5. Net Free Space. "Net" in the sense of "after deductions for the headers": this is the
+ §6. Net Free Space. "Net" in the sense of "after deductions for the headers": this is the
actual number of free bytes left on the heap which could be used for data.
Note that it is used to predict whether it is possible to fit something
further in: so there are two answers, depending on whether the something
@@ -264,7 +271,7 @@ data) or single-block data (smaller header, more room).
return asize;
];
- §6. Make Space. The following routine determines if there is enough free space to accommodate
+ §7. Make Space. The following routine determines if there is enough free space to accommodate
another size bytes of data, given that it has to be multiple-block data if
the multiple flag is set. If the answer turns out to be "no", we see if
the host virtual machine is able to allocate more for us: if it is, then
@@ -317,7 +324,7 @@ which handles non-multiple blocks better.)
Flex_Heap-->BLK_NEXT = newblock;
newblock-->BLK_PREV = Flex_Heap;
.Linked; ;
- #ifdef BLKVALUE_TRACE;
+ #ifdef LKTRACE_HEAP;
print "Increasing heap to free space map: "; FlexDebugDecomposition(Flex_Heap, 0);
#endif;
}
@@ -346,7 +353,7 @@ which handles non-multiple blocks better.)
}
];
- §7. Block Allocation. Now for the Flex routines. Those with names ending in Internal are private
+ §8. Block Allocation. Now for the Flex routines. Those with names ending in Internal are private
and should only be called by other Flex routines. Even the public ones must
be used with care, or memory leaks or crashes will occur.
§8. Errors. In the event that FlexAllocate returns 0, the caller may not be able
+ §9. Errors. In the event that FlexAllocate returns 0, the caller may not be able
to survive, so the following is provided as a standardised way to halt
the virtual machine.
§9. Merging. Given a free block block, find the maximal contiguous run of free blocks
+ §10. Merging. Given a free block block, find the maximal contiguous run of free blocks
which contains it, and then call FlexRecutInternal to recut it to conform to
invariant (b) above.
§10. Recutting. Given a segment of the free block list, containing blocks known to be contiguous
+ §11. Recutting. Given a segment of the free block list, containing blocks known to be contiguous
in memory, we recut into a sequence of blocks satisfying invariant (b): we
repeatedly cut the largest \(2^m\)-sized chunk off the back end until it is all
used up.
@@ -552,7 +559,7 @@ used up.
rtrue;
];
- §11. Deallocation. As noted above, FlexFree must be called exactly once on each nonzero
+ §12. Deallocation. As noted above, FlexFree must be called exactly once on each nonzero
pointer returned by FlexAllocate.
§12. Resizing. A block which has been allocated, but not yet freed, can sometimes have
+ §13. Resizing. A block which has been allocated, but not yet freed, can sometimes have
its data capacity changed by FlexResize.
§13. Block Size. These two routines are provided for the use of the BlockValue routines
+ §14. Block Size. These two routines are provided for the use of the BlockValue routines
only.
§14. Debugging Routines. These two routines are purely for testing the above code.
+ §15. Debugging Routines. These two routines are purely for testing the above code.
+Constant LKTRACE_HEAP;
+
+
Array Flex_Heap -> (MEMORY_HEAP_SIZE + BLK_DATA_MULTI_OFFSET); allow room for head-free-block
-
diff --git a/docs/BasicInformKit/S-gll.html b/docs/BasicInformKit/S-gll.html
index a43696a29..08819d2e3 100644
--- a/docs/BasicInformKit/S-gll.html
+++ b/docs/BasicInformKit/S-gll.html
@@ -104,9 +104,9 @@ wants out of these arrays.
Constant MAX_BUFFER_WORDS = 20;
Constant PARSE_BUFFER_LEN = 61;
-Array buffer buffer INPUT_BUFFER_LEN;
-Array buffer2 buffer INPUT_BUFFER_LEN;
-Array buffer3 buffer INPUT_BUFFER_LEN;
+Array buffer --> INPUT_BUFFER_LEN;
+Array buffer2 --> INPUT_BUFFER_LEN;
+Array buffer3 --> INPUT_BUFFER_LEN;
Array parse --> PARSE_BUFFER_LEN;
Array parse2 --> PARSE_BUFFER_LEN;
@@ -1054,7 +1054,7 @@ light to the Dark Room.")
gg_backgroundchan = glk_schannel_create(GG_BACKGROUNDCHAN_ROCK);
}
- if (KIT_CONFIGURATION_BITMAP & FIX_RNG_TCBIT) {
+ if (BasicInformKit`FIX_RNG_CFGF) {
@random 10000 i;
i = -i-2000;
@setrandom i;
@@ -1315,8 +1315,8 @@ to document all of that.
[ VM_ReadKeyboard a_buffer a_table done ix;
if (gg_commandstr ~= 0 && gg_command_reading ~= false) {
- done = glk_get_line_stream(gg_commandstr, a_buffer+WORDSIZE,
- (INPUT_BUFFER_LEN-WORDSIZE)-1);
+ done = glk_get_line_stream_uni(gg_commandstr, a_buffer+WORDSIZE,
+ (INPUT_BUFFER_LEN-1)-1);
if (done == 0) {
glk_stream_close(gg_commandstr, 0);
gg_commandstr = 0;
@@ -1324,17 +1324,17 @@ to document all of that.
}
else {
Trim the trailing newline
- if ((a_buffer+WORDSIZE)->(done-1) == 10) done = done-1;
+ if ((a_buffer+WORDSIZE)-->(done-1) == 10) done = done-1;
a_buffer-->0 = done;
VM_Style(INPUT_VMSTY);
- glk_put_buffer(a_buffer+WORDSIZE, done);
+ glk_put_buffer_uni(a_buffer+WORDSIZE, done);
VM_Style(NORMAL_VMSTY);
print "^";
jump KPContinue;
}
}
done = false;
- glk_request_line_event(gg_mainwin, a_buffer+WORDSIZE, INPUT_BUFFER_LEN-WORDSIZE, 0);
+ glk_request_line_event_uni(gg_mainwin, a_buffer+WORDSIZE, INPUT_BUFFER_LEN-1, 0);
while (~~done) {
glk_select(gg_event);
switch (gg_event-->0) {
@@ -1361,9 +1361,9 @@ to document all of that.
glk_window_close(gg_quotewin, 0);
gg_quotewin = 0;
}
- if (KIT_CONFIGURATION_BITMAP & ECHO_COMMANDS_TCBIT) {
+ if (BasicInformKit`ECHO_COMMANDS_CFGF) {
print "** ";
- for (ix=WORDSIZE: ix<(a_buffer-->0)+WORDSIZE: ix++) print (char) a_buffer->ix;
+ for (ix=0: ix<(a_buffer-->0): ix++) print (char) a_buffer-->(1+ix);
print "^";
}
];
@@ -1393,46 +1393,50 @@ languages of play, and is not called in the template.
[ VM_CopyBuffer bto bfrom i;
- for (i=0: i<INPUT_BUFFER_LEN: i++) bto->i = bfrom->i;
+ for (i=0: i<INPUT_BUFFER_LEN: i++) bto-->i = bfrom-->i;
];
[ VM_PrintToBuffer buf len a b c;
if (b) {
if (metaclass(a) == Object && a.#b == WORDSIZE
&& metaclass(a.b) == String)
- buf-->0 = Glulx_PrintAnyToArray(buf+WORDSIZE, len, a.b);
+ buf-->0 = Glulx_PrintAnyToArrayUni(buf+WORDSIZE, len, a.b);
else if (metaclass(a) == Routine)
- buf-->0 = Glulx_PrintAnyToArray(buf+WORDSIZE, len, a, b, c);
+ buf-->0 = Glulx_PrintAnyToArrayUni(buf+WORDSIZE, len, a, b, c);
else
- buf-->0 = Glulx_PrintAnyToArray(buf+WORDSIZE, len, a, b);
+ buf-->0 = Glulx_PrintAnyToArrayUni(buf+WORDSIZE, len, a, b);
}
else if (metaclass(a) == Routine)
- buf-->0 = Glulx_PrintAnyToArray(buf+WORDSIZE, len, a, b, c);
+ buf-->0 = Glulx_PrintAnyToArrayUni(buf+WORDSIZE, len, a, b, c);
else
- buf-->0 = Glulx_PrintAnyToArray(buf+WORDSIZE, len, a);
+ buf-->0 = Glulx_PrintAnyToArrayUni(buf+WORDSIZE, len, a);
if (buf-->0 > len) buf-->0 = len;
return buf-->0;
];
+Constant LOWERCASE_BUF_SIZE = 2*DICT_WORD_SIZE;
+Array gg_lowercasebuf --> LOWERCASE_BUF_SIZE;
+
[ VM_Tokenise buf tab
- cx numwords len bx ix wx wpos wlen val res dictlen entrylen;
+ cx numwords len bx ix wx wpos wlen val res dictlen ch bytesperword uninormavail;
len = buf-->0;
buf = buf+WORDSIZE;
+
First, split the buffer up into words. We use the standard Infocom
list of word separators (comma, period, double-quote).
cx = 0;
numwords = 0;
while (cx < len) {
- while (cx < len && buf->cx == ' ') cx++;
+ while (cx < len && buf-->cx == ' ') cx++;
if (cx >= len) break;
bx = cx;
- if (buf->cx == '.' or ',' or '"') cx++;
+ if (buf-->cx == '.' or ',' or '"') cx++;
else {
- while (cx < len && buf->cx ~= ' ' or '.' or ',' or '"') cx++;
+ while (cx < len && buf-->cx ~= ' ' or '.' or ',' or '"') cx++;
}
tab-->(numwords*3+2) = (cx-bx);
- tab-->(numwords*3+3) = WORDSIZE+bx;
+ tab-->(numwords*3+3) = 1+bx;
numwords++;
if (numwords >= MAX_BUFFER_WORDS) break;
}
@@ -1441,20 +1445,37 @@ languages of play, and is not called in the template.
Now we look each word up in the dictionary.
dictlen = #dictionary_table-->0;
- entrylen = DICT_WORD_SIZE + 7;
+ bytesperword = DICT_WORD_SIZE * WORDSIZE;
+ uninormavail = glk_gestalt(16, 0);
for (wx=0 : wx<numwords : wx++) {
wlen = tab-->(wx*3+2);
wpos = tab-->(wx*3+3);
Copy the word into the gg_tokenbuf array, clipping to DICT_WORD_SIZE
- characters and lower case.
+ characters and lower case. We'll do this in two steps, because
+ lowercasing might (theoretically) condense characters and allow more
+ to fit into gg_tokenbuf.
+ if (wlen > LOWERCASE_BUF_SIZE) wlen = LOWERCASE_BUF_SIZE;
+ cx = wpos - 1;
+ for (ix=0 : ix<wlen : ix++) {
+ ch = buf-->(cx+ix);
+ gg_lowercasebuf-->ix = ch;
+ }
+ wlen = glk_buffer_to_lower_case_uni(gg_lowercasebuf, LOWERCASE_BUF_SIZE, wlen);
+ if (uninormavail) {
+ Also normalize the Unicode — combine accent marks with letters
+ where possible.
+ wlen = glk_buffer_canon_normalize_uni(gg_lowercasebuf, LOWERCASE_BUF_SIZE, wlen); buffer_canon_normalize_uni
+ }
if (wlen > DICT_WORD_SIZE) wlen = DICT_WORD_SIZE;
- cx = wpos - WORDSIZE;
- for (ix=0 : ix<wlen : ix++) gg_tokenbuf->ix = VM_UpperToLowerCase(buf->(cx+ix));
- for (: ix<DICT_WORD_SIZE : ix++) gg_tokenbuf->ix = 0;
+ for (ix=0: ix<wlen : ix++) {
+ gg_tokenbuf-->ix = gg_lowercasebuf-->ix;
+ }
+ for (: ix<DICT_WORD_SIZE : ix++) gg_tokenbuf-->ix = 0;
+
val = #dictionary_table + WORDSIZE;
- @binarysearch gg_tokenbuf DICT_WORD_SIZE val entrylen dictlen 1 1 res;
+ @binarysearch gg_tokenbuf bytesperword val DICT_ENTRY_BYTES dictlen 4 1 res;
tab-->(wx*3+1) = res;
}
];
@@ -1463,6 +1484,8 @@ languages of play, and is not called in the template.
Protect us from strict mode, as this isn't an array in quite the
sense it expects
+ (This is not an issue now that buffer is a word array, but I'm
+ keeping the alias.)
b = buffer;
Insert character ch into buffer at point i.
@@ -1471,8 +1494,8 @@ languages of play, and is not called in the template.
if (y > INPUT_BUFFER_LEN) y = INPUT_BUFFER_LEN;
Move the subsequent text along one character:
- for (y=y+WORDSIZE : y>i : y--) b->y = b->(y-1);
- b->i = ch;
+ for (y=y+1 : y>i : y--) b-->y = b-->(y-1);
+ b-->i = ch;
And the text is now one character longer:
if (b-->0 < INPUT_BUFFER_LEN) (b-->0)++;
@@ -1505,11 +1528,11 @@ since, on Glulx, they are the same, these are each the identity function.
[ VM_DictionaryAddressToNumber w; return w; ];
[ VM_NumberToDictionaryAddress n; return n; ];
-Array gg_tokenbuf -> DICT_WORD_SIZE;
+Array gg_tokenbuf --> DICT_WORD_SIZE;
[ GGWordCompare str1 str2 ix jx;
for (ix=0 : ix<DICT_WORD_SIZE : ix++) {
- jx = (str1->ix) - (str2->ix);
+ jx = (str1-->ix) - (str2-->ix);
if (jx ~= 0) return jx;
}
return 0;
@@ -1658,6 +1681,10 @@ including discarded characters.) The character set stored here is ZSCII,
not Unicode.
Glulx_PrintAnyToArrayUni does the same again, but the output is sent to a +word array in memory. The stored characters are Unicode code points. +
+Glulx_ChangeAnyToCString calls Glulx_PrintAnyToArray on a particular array, then amends the result to make it a C-style string — that is, a sequence of byte-sized characters which are null terminated. The character @@ -1736,6 +1763,28 @@ set stored here is once again ZSCII, not Unicode. return len; ]; +[ Glulx_PrintAnyToArrayUni _vararg_count arr arrlen str oldstr len; + @copy sp arr; + @copy sp arrlen; + _vararg_count = _vararg_count - 2; + + oldstr = glk_stream_get_current(); + str = glk_stream_open_memory_uni(arr, arrlen, 1, 0); + if (str == 0) return 0; + + glk_stream_set_current(str); + + @call Glulx_PrintAnything _vararg_count 0; + + glk_stream_set_current(oldstr); + @copy $ffffffff sp; + @copy str sp; + @glk $0044 2 0; stream_close + @copy sp len; + @copy sp 0; + return len; +]; + Constant GG_ANYTOSTRING_LEN 66; Array AnyToStrArr -> GG_ANYTOSTRING_LEN+1; diff --git a/docs/BasicInformKit/S-lst.html b/docs/BasicInformKit/S-lst.html index ba551947a..58c6f1986 100644 --- a/docs/BasicInformKit/S-lst.html +++ b/docs/BasicInformKit/S-lst.html @@ -272,7 +272,7 @@ use the "listing contents of..." activity in any circumstances. if (i<no_items-2) print ", "; if (i==no_items-2) { if (format == 1) print ", "; else { - if (KIT_CONFIGURATION_BITMAP & SERIAL_COMMA_TCBIT) { + if (BasicInformKit`SERIAL_COMMA_CFGF) { if (no_items ~= 2) print ","; } LIST_WRITER_INTERNAL_RM('C'); diff --git a/docs/BasicInformKit/S-mth.html b/docs/BasicInformKit/S-mth.html index 0ffe15de5..af1a90e23 100644 --- a/docs/BasicInformKit/S-mth.html +++ b/docs/BasicInformKit/S-mth.html @@ -358,7 +358,7 @@ cases used to check the floating-point extensions to Glulx. expon expnegative count; print "FloatParse <"; -for (ix=0: ix<len: ix++) print (char) buf->ix; +for (ix=0: ix<len: ix++) print (char) buf-->ix; print ">^"; if (len == 0) @@ -371,7 +371,7 @@ cases used to check the floating-point extensions to Glulx. @numtof 10 ten; Sign character (optional) - ch = buf->ix; + ch = buf-->ix; if (ch == '-') { negative = true; ix++; @@ -382,7 +382,7 @@ cases used to check the floating-point extensions to Glulx. Some digits (optional) for (count=0 : ix<len : ix++, count++) { - ch = buf->ix; + ch = buf-->ix; if (ch < '0' || ch > '9') break; val = (ch - '0'); @@ -392,11 +392,11 @@ cases used to check the floating-point extensions to Glulx. } Decimal point and more digits (optional) - if (ix<len && buf->ix == '.') { + if (ix<len && buf-->ix == '.') { ix++; @numtof 1 fracdiv; for ( : ix<len : ix++, count++) { - ch = buf->ix; + ch = buf-->ix; if (ch < '0' || ch > '9') break; val = (ch - '0'); @@ -416,8 +416,8 @@ cases used to check the floating-point extensions to Glulx. @fadd intpart fracpart res; Exponent (optional) - if (ix<len && buf->ix == 'e' or 'E' or ' ' or '*' or 'x' or 'X' or $D7) { - if (buf->ix == 'e' or 'E') { + if (ix<len && buf-->ix == 'e' or 'E' or ' ' or '*' or 'x' or 'X' or $D7) { + if (buf-->ix == 'e' or 'E') { no spaces, just the 'e' ix++; if (ix == len) @@ -425,31 +425,31 @@ cases used to check the floating-point extensions to Glulx. } else { any number of spaces, "*", any number of spaces more, "10^" - while (ix < len && buf->ix == ' ') + while (ix < len && buf-->ix == ' ') ix++; if (ix == len) return FLOAT_NAN; - if (buf->ix ~= '*' or 'x' or 'X' or $D7) + if (buf-->ix ~= '*' or 'x' or 'X' or $D7) return FLOAT_NAN; ix++; - while (ix < len && buf->ix == ' ') + while (ix < len && buf-->ix == ' ') ix++; if (ix == len) return FLOAT_NAN; - if (buf->ix ~= '1') + if (buf-->ix ~= '1') return FLOAT_NAN; ix++; - if (buf->ix ~= '0') + if (buf-->ix ~= '0') return FLOAT_NAN; ix++; - if (buf->ix ~= $5E) + if (buf-->ix ~= $5E) return FLOAT_NAN; ix++; } Sign character (optional) expnegative = false; - ch = buf->ix; + ch = buf-->ix; if (ch == '-') { expnegative = true; ix++; @@ -461,7 +461,7 @@ cases used to check the floating-point extensions to Glulx. expon = 0; Some digits (mandatory) for (count=0 : ix<len : ix++, count++) { - ch = buf->ix; + ch = buf-->ix; if (ch < '0' || ch > '9') break; expon = 10*expon + (ch - '0'); @@ -599,8 +599,8 @@ cases used to check the floating-point extensions to Glulx. } Print the exponent. There are two conventions coded here: the - programmatic ("1.0e+00") and the literary ("1.0 x 10^0"). - if (KIT_CONFIGURATION_BITMAP & PROGRAMMING_EXPONENTS_TCBIT == 0) { + engineering notation ("1.0e+00") and the mathematical ("1.0 x 10^0"). + if (BasicInformKit`PRINT_ENGINEER_EXPS_CFGF == 0) { PrintMultiplicationSign(); @streamchar '1'; @streamchar '0'; diff --git a/docs/BasicInformKit/S-prg.html b/docs/BasicInformKit/S-prg.html index 66a7c1716..eab76a969 100644 --- a/docs/BasicInformKit/S-prg.html +++ b/docs/BasicInformKit/S-prg.html @@ -51,7 +51,7 @@
To manage the line skips which space paragraphs out.
-§1. Paragraph Control. Ah, yes: the paragraph breaking algorithm. In {\it \TeX: The Program}, Donald Knuth writes at section 768: "It's sort of a miracle whenever \halign @@ -196,7 +196,15 @@ of the huge number of circumstances in which paragraphs are printed: so change nothing without very careful testing.
-§2. State. The current state is stored in a combination of two global variables: +
§2. Tracing. Uncomment this line and rebuild the kit to enable tracing of what the algorithm +below is doing. (This constant should not be used anywhere except in this file, +where #Ifdef on it will have the expected effect: elsewhere, it might not.) +
+ +
+onstant LKTRACE_SPACING;
+
+§3. State. The current state is stored in a combination of two global variables:
-onstant TRACE_I7_SPACING; - [ ClearParagraphing r; say__p = 0; say__pc = 0; ]; [ DivideParagraphPoint; - #ifdef TRACE_I7_SPACING; print "[DPP", say__p, say__pc, "]"; #endif; + #ifdef LKTRACE_SPACING; print "[DPP", say__p, say__pc, "]"; #endif; if (say__p) { new_line; say__p = 0; say__pc = say__pc | PARA_COMPLETED; say__pc_save = true; if (say__pc & PARA_PROMPTSKIP) say__pc = say__pc - PARA_PROMPTSKIP; if (say__pc & PARA_SUPPRESSPROMPTSKIP) say__pc = say__pc - PARA_SUPPRESSPROMPTSKIP; } - #ifdef TRACE_I7_SPACING; print "[-->", say__p, say__pc, "]"; #endif; + #ifdef LKTRACE_SPACING; print "[-->", say__p, say__pc, "]"; #endif; say__pc = say__pc | PARA_CONTENTEXPECTED; say__pc_save = (say__pc & PARA_COMPLETED); ]; [ AdjustParagraphPoint; - #ifdef TRACE_I7_SPACING; print "[APP ", say__p, " ", say__pc, " ", say__pc_save, "]^"; #endif; + #ifdef LKTRACE_SPACING; print "[APP ", say__p, " ", say__pc, " ", say__pc_save, "]^"; #endif; if (say__pc_save) say__pc = (say__pc | PARA_COMPLETED); ]; @@ -280,14 +286,14 @@ below. ]; [ RunParagraphOn; - #ifdef TRACE_I7_SPACING; print "[RPO", say__p, say__pc, "]"; #endif; + #ifdef LKTRACE_SPACING; print "[RPO", say__p, say__pc, "]"; #endif; say__p = 0; say__pc = say__pc | PARA_PROMPTSKIP; say__pc = say__pc | PARA_SUPPRESSPROMPTSKIP; ]; [ SpecialLookSpacingBreak; - #ifdef TRACE_I7_SPACING; print "[SLS", say__p, say__pc, "]"; #endif; + #ifdef LKTRACE_SPACING; print "[SLS", say__p, say__pc, "]"; #endif; say__p = 0; say__pc = say__pc | PARA_PROMPTSKIP; ]; @@ -307,7 +313,7 @@ below. say__pc = 0; ];-
§3. Say Number. The global variable say__n is set to the numerical value of any quantity +
§4. Say Number. The global variable say__n is set to the numerical value of any quantity printed, and this is used for the text substitution "[s]", so that "You have been awake for [turn count] turn[s]." will expand correctly.
@@ -317,7 +323,7 @@ printed, and this is used for the text substitution "[s]", so that if (say__n ~= 1) print "s"; ]; -§4. Print English Number. Another traditional name, this: in fact it prints the number as text in +
§5. Print English Number. Another traditional name, this: in fact it prints the number as text in whatever is the current language of play.
@@ -353,7 +359,7 @@ whatever is the current language of play. print (LanguageNumber) n/100, " hundred"; n = n%100; f = 1; } if (n == 0) rfalse; - if (KIT_CONFIGURATION_BITMAP & DIALECT_US_TCBIT) { + if (BasicInformKit`AMERICAN_DIALECT_CFGF) { if (f == 1) print " "; } else { if (f == 1) print " and "; diff --git a/docs/BasicInformKit/S-rlb.html b/docs/BasicInformKit/S-rlb.html index 911204c45..035bddac5 100644 --- a/docs/BasicInformKit/S-rlb.html +++ b/docs/BasicInformKit/S-rlb.html @@ -312,7 +312,7 @@ occur, in so far as memory economy allows this. [ DB_Rule R N blocked; if (R==0) return; print "[Rule ~", (RulePrintingRule) R, "~ "; - #ifdef NUMBERED_RULES; print "(", N, ") "; #endif; + if (BasicInformKit`NUMBERED_RULES_CFGF) print "(", N, ") "; if (blocked == false) "applies.]"; print "does not apply (wrong "; if (blocked == 1) print "scene"; diff --git a/docs/BasicInformKit/S-txt.html b/docs/BasicInformKit/S-txt.html index 85049ce47..3c8382771 100644 --- a/docs/BasicInformKit/S-txt.html +++ b/docs/BasicInformKit/S-txt.html @@ -99,8 +99,9 @@ number of characters, plus one for the null terminator. ];§3. Character Set. On the Z-machine, we use the 8-bit ZSCII character set, stored in bytes; -on Glulx, we use the opening 16-bit subset of Unicode (which though only a -subset covers almost all letter forms used on Earth), stored in half-words. +on Glulx, we use full 32-bit Unicode, stored in words. (Until May 2023, +16-bit half-words were used, but that restricted the range of Unicode points +so as to omit such essentials as "Smiling Cat Face With Heart-Shaped Eyes".)
The Z-machine does have very partial Unicode support, but not in a way that @@ -110,7 +111,7 @@ OS X, using the Lucida Grande font) can produce many thousands of glyphs. But it is not capable of printing those characters into memory rather than the screen, an essential technique for texts: it can only write each character to a single byte, and it does so in ZSCII. That forces our hand when it comes to -choosing the indexed-text character set. +choosing the character set here. For Unicode, use Glulx.
@@ -118,7 +119,7 @@ choosing the indexed-text character set. Constant TEXT_TY_Storage_Flags = BLK_FLAG_MULTIPLE; Constant ZSCII_Tables; #IFNOT; -Constant TEXT_TY_Storage_Flags = BLK_FLAG_MULTIPLE + BLK_FLAG_16_BIT; +Constant TEXT_TY_Storage_Flags = BLK_FLAG_MULTIPLE + BLK_FLAG_WORD; Constant Large_Unicode_Tables; #ENDIF;@@ -274,6 +275,7 @@ memory as necessary so that we can always avoid overruns entirely.
+Constant TEXT_TY_BufferSize = BasicInformKit`TEXT_BUFFER_SIZE_CFGV + 3; Constant TEXT_TY_NoBuffers = 2; #ifdef TARGET_ZCODE; diff --git a/docs/BasicInformKit/S-unc.html b/docs/BasicInformKit/S-unc.html index 1e6b6aea5..3ad1def1a 100644 --- a/docs/BasicInformKit/S-unc.html +++ b/docs/BasicInformKit/S-unc.html @@ -65,7 +65,7 @@ MathJax = {
To tabulate casings in the character set.
-§1. Source. When this section is included, exactly one of the following constants is defined: @@ -73,12 +73,19 @@ defined:
At one time we also supported, but essentially never used, +
+ +This has now been removed. +
+Whichever is defined, we must create two arrays:
@@ -107,7 +114,7 @@ not included in the ranges below is not a letter.-#IFDEF ZSCII_Tables; +#Ifdef TARGET_ZCODE; Array CharCasingChart0 --> $0061 ( 26) ( -32) $009b ( 3) ( 3) $00a1 ( 1) UNIC_NCT $00a4 ( 2) ( 3) $00a6 ( 1) UNIC_NCT $00a9 ( 6) ( 6) @@ -122,28 +129,12 @@ not included in the ranges below is not a letter. $00ca ( -3) ( -1) $00d0 ( 3) ( -3) $00d4 ( -3) ( -1) $00d9 ( 2) ( -2) $00dd ( 1) ( -1) $0000 ; -#ENDIF; ZSCII_Tables +#Endif; TARGET_ZCODE-
§3. Small Unicode Casing Tables.
+§3. Large Unicode Casing Tables.
-#IFDEF Small_Unicode_Tables; -Array CharCasingChart0 --> - $0061 ( 26) ( -32) $00aa ( 1) UNIC_NCT $00b5 ( 1) UNIC_NCT $00ba ( 1) UNIC_NCT - $00df ( 1) UNIC_NCT $00e0 ( 23) ( -32) $00f8 ( 7) ( -32) $00ff ( 1) UNIC_NCT - $0000 -; - -Array CharCasingChart1 --> - $0041 ( 26) ( 32) $00c0 ( 23) ( 32) $00d8 ( 7) ( 32) $0000 -; - -#ENDIF; Small_Unicode_Tables --
§4. Large Unicode Casing Tables.
- --#IFDEF Large_Unicode_Tables; +#Ifdef TARGET_GLULX; Array CharCasingChart0 --> $0061 ( 26) ( -32) $00aa ( 1) UNIC_NCT $00b5 ( 1) ( 743) $00ba ( 1) UNIC_NCT $00df ( 1) UNIC_NCT $00e0 ( 23) ( -32) $00f8 ( 7) ( -32) $00ff ( 1) ( 121) @@ -223,7 +214,7 @@ not included in the ranges below is not a letter. $213e ( 2) UNIC_NCT $2145 ( 1) UNIC_NCT $ff21 ( 26) ( 32) $0000 ; -#ENDIF; Large_Unicode_Tables +#Endif; TARGET_GLULX