User Tools

Site Tools


blog:pushbx:2026:0823_mid_late_august_work_multi-aliases

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

blog:pushbx:2026:0823_mid_late_august_work_multi-aliases [2026-08-23 18:10:37 +0200 Aug Sun] (current)
ecm created
Line 1: Line 1:
 +====== Mid late August work: Multi-aliases ======
 +
 +**2026-08-23**
 +
 +Most of this week's work was about adding multi-alias support to the alias Extension for lDebug. Multi-aliases are injected into the debugger command loop using the inject handler rather than only replacing the command in the preprocess handler. This allows multi-aliases to consist of any number of commands, from zero to one to multiple. The old style aliases are called single-aliases.
 +
 +
 +===== LBACACHE =====
 +
 +  * [[https://hg.pushbx.org/ecm/lbacache/rev/f6001bf6c1d5|Eliminate the help flag]] and exit immediately after displaying the help.
 +  * Initial commit [[https://hg.pushbx.org/ecm/lbacache/rev/367db8f582fc|to check for resident instances by default]], rather than always installing anew when no parameters are supplied. This adds the INSTALL command, which can be used to force installing even if already resident.
 +  * Fix [[https://hg.pushbx.org/ecm/lbacache/rev/b003601ebde5|to drop a doubled dollar terminator]] for a message.
 +  * [[https://hg.pushbx.org/ecm/lbacache/rev/4f71285661f9|Add the donedefaultmsg]] if default flag is in effect.
 +  * Keep track of size flag [[https://hg.pushbx.org/ecm/lbacache/rev/0e7308d777f1|to indicate that a size was specified]].
 +  * [[https://hg.pushbx.org/ecm/lbacache/rev/44d152da4b24|Add the NOTUNA, NOTUNW, and NOTUNS keywords]].
 +  * Allow [[https://hg.pushbx.org/ecm/lbacache/rev/3ff7dab932ca|to modify the TUNA and TUNW flags]] of already resident instances.
 +  * [[https://hg.pushbx.org/ecm/lbacache/rev/374252f37d9a|Introduce the TUNE_ equates]] for tune flags, and use them where the flags are accessed.
 +
 +
 +===== lDebug =====
 +
 +These changes live in the new ldebug.exp experimental repo for now.
 +
 +  * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/ccfdb5dbf541|Add symsnip directory include option]] to the makefile. This is a step towards supporting the _LINK _SYMBOLIC build, albeit not sufficient. It may eventually come down to including symsnip (and scanptab) as subrepos of the lDebug repo so that the makefile knows exactly where to find these source files, so that the dependency checks can be done in the expected way.
 +  * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/48757d09454b|Hide extern.mac]] from the (trace) listing file to avoid spam of all extern labels for every listing file that's compiled into the trace listing file.
 +  * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/6ef3f13d3256|Move the generation of the cmd3 prompt into cmd3_getline_repeat]], to be used later by alias.eld interfacing.
 +  * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/4cff8418718f|Add most of the comlevels handler callouts]] to the debugger, and the handler variable.
 +  * Initial commit of testcoml.asm, [[https://hg.pushbx.org/ecm/ldebug.exp/rev/aa59d7e04a6f|the comlevels test Extension for lDebug]]. Initially only allows to display last detected comlevels call function code.
 +  * In ldmem.asm [[https://hg.pushbx.org/ecm/ldebug.exp/rev/98ad7e013f8f|support displaying the ELD comlevels handler]].
 +  * In testcoml.asm [[https://hg.pushbx.org/ecm/ldebug.exp/rev/9a76c7bf4cd4|display comlevels function codes and their names]] as they come in.
 +  * Fix lineio.asm [[https://hg.pushbx.org/ecm/ldebug.exp/rev/8c0ca63b794a|to not crash on yy sublabel]], due to confusion of @@ labels.
 +  * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/002ea7d3393d|Use ax as a signal register]] to exit to getline caller. This isn't fully used yet, the most recent alias.eld never zeroes ax and it still works as intended. The earlier introduction of comlevels callouts already included code that detects the getline call from cmd3 and will return with CY to this instead of looping to getline.
 +  * alias.asm:
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/1cf3b117567a|Add no-op comlevels handler]].
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/d94cfbb276c8|Expand alias format]] with a type byte and expand the content counter byte to a word. (The word is in anticipation of multi-aliases that may exceed 256 bytes using multiple alias commands (ACs) that each do not overflow 254 text bytes. The APPEND command must be used to enable creation of these.)
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/cb7996deb4a3|Fix to drop doubled msg label]]. Recent NASM versions do accept double labels if they are both addressing the same position in the output.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/4f45f90bb61e|Add the ADDMULTI command]] to define a multi-alias, and bare bones multi-alias support for LIST.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/a88d1cb6c445|Add the buffer end variables]] needed to support multi-aliases eventually.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/2b997cf43106|Set up the multi-alias instance]] and check that line_in won't overflow with the given command line tail.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/614c51b49b53|Ensure there's no ACT_APPEND type alias command]] if ALT_MULTI_IGNORE was specified as the alias lead type.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/347466cf62dd|Do not store the replacement]] if the ignore type is used.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/233b044f251f|Implement simple command injection]]. This first draft doesn't honour command levels yet.
 +
 +  * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/8945eb5d8dca|Fix values and order of comlevels]] for exit yy boot equates.
 +  * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/44774ed23174|Add a comlevel type and callout]] for exiting RC using the RC.ABORT command.
 +  * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/45d99377a7f4|Comment on a certain code part]] of lineio.asm being difficult to reach and possibly unused. This is relevant to alias.eld because it would have to zero ax on some exit comlevel callouts if this code was ever used.
 +
 +  * alias.asm:
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/c54806f8fedf|Extract function hookinject]], which makes sure that the inject handler is hooked. (It determines that it is hooked using the ELD's own ''injecting'' variable, not the current value of the ''ext_inject_handler'' variable.)
 +    * Comment on [[https://hg.pushbx.org/ecm/ldebug.exp/rev/76e713464e67|an error condition of corrupted AC]] if the alias command type exceeds ACT_MAX.
 +    * Implement [[https://hg.pushbx.org/ecm/ldebug.exp/rev/be08cdff5a35|a simple inhibition mechanism]] for comlevels precedence.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/2886cea5caf6|Clamp the counter decrement for inhibition]] to zero, so unexpected EXIT calls won't underflow.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/b8926eccafa4|Do not allow to delete a busy multi-alias]].
 +    * Upon deletion (of a non-busy alias), [[https://hg.pushbx.org/ecm/ldebug.exp/rev/0b57461e7ac4|relocate the active instances' pointers]] to their busy aliases.
 +    * Add the debugger's [[https://hg.pushbx.org/ecm/ldebug.exp/rev/e6e85947bcde|call_comlevel_bx_ax function]] which is for use by alias.eld
 +    * Implement [[https://hg.pushbx.org/ecm/ldebug.exp/rev/80b82f6fde9d|alias.eld calling out to the comlevels handlers]] to indicate INIT and EXIT of alias command levels. This is required to correctly support multiple alias.eld instances installed residently at the same time. It was tricky to juggle the various hook and unhook opportunities of the inject handler, which I completely failed to account for initially during the creation of this changeset. In particular, I learned that I have to preserve the ext_inject_handler zero invariant upon branching to the next inject handler. I settled with writing my old inject handler (once) before calling out for EXIT_ALIAS, then handling a nonzero ext_inject_handler that may result either from my old inject or the other alias.eld instance having hooked the inject handler.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/8db0ce22c0f7|Add ALIAS STOP and STOPALL commands]]. These set a flag in the instance that indicates to pop it upon the next time an alias command could run. This mechanism ensures that the EXIT_ALIAS callouts occur in the expected order.
 +
 +  * Fix a comlevels change (RC.ABORT) [[https://hg.pushbx.org/ecm/ldebug.exp/rev/f963e3ba5607|corrupting the @@ control flow]] in rr.asm
 +  * alias.asm:
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/7f0d7f6ccd80|Un-busy an alias when STOP marks an instance]] to be stopped. This zeroes the iAlias reference in the instance structure.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/d3bd646b1d0a|Extract the nextinstance function]] to calculate the address of the next instance.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/27e4b165a2d6|Add the \E escape code]] for an empty alias command (AC).
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/2c0b03489a71|Swap ?altype (alias lead type) and ?actype (alias command type) variables]] in multihandle, and pass in initial ?altype in al.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/8241f08b5071|Extract function setupexpansion]]
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/528b48167e4f|Add a comment]] on backslash E escape code.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/aebd6c48a805|Implement a simple APPEND command]], always appends to the very last alias in the alias buffer.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/4ff26683befc|Reject APPEND]] on old-style single-aliases.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/1e19c4eafd27|Add the \C escape code]] for appending to the prior last AC instead of adding a new AC.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/ad4a8345b4b9|Give a specific error for \C appending]] that would generate a too long line (not fitting line_in any longer). This doesn't detect lines that may overflow line_in during instance creation if the command line tail is appended.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/0c50d51fe0f0|Fix appending to the currently running alias]], if ACT_END is overwritten using \C then mark that instance with stop flag.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/75536e79e08d|Optimise some branches]] to multihandle.loop
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/4fb41b77ae3c|Add \S escape code]] to append the command line tail, but skip separators at its beginning. (In practice, whitespace and optionally one comma.) This is still broken at this point because the replacement string isn't necessarily terminated.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/cc898a965cba|Add some debugger links]] for alias.eld GOTO support.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/ce7bb20008ba|Extract function doexpand]]
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/cf9fc60e0e6b|Implement GOTO ::label]] for multi-aliases.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/60ba009d1fc2|Add an equate]], MASK_INHIBIT, to test inhibition masks only. (The iInhibitMask byte perhaps should be renamed, as it isn't used only for inhibition masks any longer.)
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/2cbb00cfd3af|Add ALIAS ECHO command]], no-op at this point.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/39398a4ee957|Implement alias echoing]] and handle the @ prefix.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/59d0e6d7cad7|Handle @ prefix in doexpand]], so that a label with @ prefix can be matched.
 +    * Fix [[https://hg.pushbx.org/ecm/ldebug.exp/rev/7a9ff2df8b3e|to allow skipcomma to change ax]].
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/d7616bb9483c|Correctly handle empty replacement]] in \S replace code.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/314eff47d578|Fix skip separator (\S escape) handling fully]], as the replacement string may be unterminated.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/0ae65fe2a444|Add RUNDEL command]] to delete busy aliases once they're unbusied.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/a2c21beb1e6f|Implement delete flag]] used by RUNDEL.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/b09fb074edf4|Add RUN command]] to immediately run an anonymous multi-alias. This is like RC.EXEC but better in basically every way.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/d29bec401243|Put command dispatch into a table]] to save some code space.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/7b82929b8e19|Spaghettify to shorten some jumps]].
 +    * Fix [[https://hg.pushbx.org/ecm/ldebug.exp/rev/4958235904ca|to align the buffer pointer after addition]], not before.
 +    * If expandmulti fails for an anonymous RUN multi-alias (such as because the instance ran into OOM) [[https://hg.pushbx.org/ecm/ldebug.exp/rev/6fa08845a899|then delete the alias]]. Required keeping around the pointer in bx and the delete flag in dl for longer.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/aabeb5857ab3|Update manual descriptions of alias.eld]]
 +    * Update manual [[https://hg.pushbx.org/ecm/ldebug.exp/rev/95ac04579a4d|on some inject handler details]].
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/a524a09783a0|Document eldcomlevels]] in the manual.
 +    * [[https://hg.pushbx.org/ecm/ldebug.exp/rev/5d6c90ae4889|Align the word fields of struc INSTANCE]] by re-ordering them. (Not currently needed as no xchg is used with iAlias or iNextCommand, so [[https://github.com/dosemu2/dosemu2/issues/2892|split lock detection]] won't happen. But it's neat.)
 +
 +
 +==== The comlevels mechanism ====
 +
 +Initially, I believed I would have to keep track of a dedicated "current level" variable. That would seem difficult to manage, especially as an EXIT of a comlevel doesn't imply what level is being exited to. So a stack may have been needed. It turns out that with only the INIT and EXIT callouts as well as the necessary inhibition flags and counters, multi-alias instances can inhibit their injection while more deeply nested comlevels are active.
 +
 +Technically, a single alias.eld instance has no needs for calling the comlevels handler with alias INIT and EXIT callouts. However, this may become useful eventually, and pathological cases with multiple alias.eld instances are possible to create.
 +
 +
 +==== The alias buffer format ====
 +
 +The single alias buffer is now used for two different data types that grow from opposite ends of the buffer towards the middle. This mirrors the design of the lDebug history buffer, as described [[https://hg.pushbx.org/ecm/ldebug.exp/file/5d6c90ae4889/source/lineio.asm#l2658|in a long comment]] and in [[https://github.com/Baron-von-Riedesel/DOS-debug/pull/1|some 2021 responses of mine to a 2020 pull request]] for (FreeDOS) Debug/X.
 +
 +The advantage is that the shared buffer is used for both types of data, so with less of one type there's more space for the other type of data. The additional setup needed for using a buffer this way is small.
 +
 +
 +==== The history buffer format comment ====
 +
 +<blockquote>The history buffer is implemented as two arrays that grow towards
 +the middle from either end of the buffer. The first is a byte array
 +storing text data that starts at the low end (start) of the buffer.
 +(This is offset 0 in the separate history segment, if used.) The
 +text is stored back to back, only the content of the lines, no
 +separators or terminators.
 +
 +The second array gives the *end* of each history entry's text.
 +There are N + 1 array entries, each a 16-bit offset word, where
 +N is the amount of history entries in use. The words are used as
 +displacement from a base that's the start of the history buffer.
 +(Again, the start base is at offset 0 for the separate history
 +segment. However, for simplicity of the code we always do store
 +the actual base start offset into a register and displace from
 +that, even when the actual value of that register will be zero.)
 +The very first entry of the high array is special. It always
 +holds the displacement value zero. When used as a displacement
 +added to the base this points at the very beginning of the
 +entire history buffer (and thus the start of the low array).
 +
 +The size of a history entry in the low array is obtained by
 +reading both the entry's end displacement from the high array,
 +and the prior entry (at the next higher address) also from the
 +high array to receive the end displacement of the prior history
 +entry. The end displacement of the prior entry is also the
 +start displacement of the current entry. The delta of the two
 +end displacements is the size of this history entry. This also
 +explains why the very first entry of the high array is needed,
 +and why it contains a zero displacement. It is needed in order
 +to determine the start displacement and size of the very first
 +actual history entry. (We could special case the first entry a
 +different way but using the special first entry of the high
 +array that holds a constant zero simplifies the code.)
 +
 +The history pointers in the word [history.first] as well as
 +word [history.last] point at the very first (special) entry
 +of the high array as well as the very last entry of the high
 +array. (Because the high array grows from the top down, the
 +first entry is at the highest address and the last entry is
 +at the lowest address.) Although the word [history.first] is
 +currently a constant, we use a variable to enable changing
 +the history allocation dynamically if desired later. If the
 +two pointers are one and the same then there is no actual
 +history entry stored in the history. Otherwise, if the
 +distance between the last high array entry and the last
 +low array entry is lower than X + 2 bytes then the history is
 +too full to insert a new entry, where X is the length of the
 +new history entry's text data and the additional 2 bytes are
 +for the high array entry to store the end displacement.
 +
 +The special first entry of the high array *must* be
 +initialised to hold the displacement value zero. This happens
 +in init.asm for the separate history buffer segment (when
 +initialising the entire segment with zeroes) or in the
 +zeroing of most of the DATASTACK section (when initialising
 +the variables from ..@init_first up to ..@init_behind).
 +
 +Insertion is simple, if enough space is left in the history
 +buffer: Copy the text to behind the last entry of the low
 +array (this is pointed to by the end displacement in the last
 +high array entry), then create a new last entry of the high
 +array which points behind the text's destination.
 +
 +Deletion is more difficult. (Generally we will delete the
 +oldest entry, that is the first history entry.) The second
 +entry of the high array needs to be deleted. All subsequent
 +entries of the high array need to move "forward" (towards
 +the higher address), and also must have the length of the
 +text of the entry to delete subtracted. In the low array the
 +text data of the first history entry needs to be overwritten
 +with any subsequent text data; the entire subsequent text data
 +must be moved "forward" (towards the lower address) by the
 +distance that equals the length of the entry's text to delete.
 +
 +<cite>[[https://hg.pushbx.org/ecm/ldebug.exp/file/5d6c90ae4889/source/lineio.asm#l2658|lineio.asm comment]] added [[https://hg.pushbx.org/ecm/ldebug/rev/c2dc7d65e87e|on 2022-10-14]]</cite></blockquote>
 +
 +
 +==== Review of Debug/X line history patch ====
 +
 +<blockquote>After implementing my own history recall feature in [[https://ulukai.org/ecm/web/#projects-ldebug|lDebug]] I compared yours in this PR to mine. Differences:
 +
 +1. I use 2 bytes for an offset per entry, you are using 4 bytes for the next/previous pointers
 +
 +2. I don't store the terminating CR as you seem to
 +
 +3. I don't have to scan a history entry to find its size
 +
 +4. I don't bother skipping leading whitespace
 +
 +5. I default to allocate the buffer in its own segment instead of in the debugger's data segment
 +
 +6. I started with 1 KiB for the data segment buffer and increased the size to 8 KiB for the additional segment buffer, whereas you use about 500 bytes by default
 +
 +7. I only allow using Up or Down to navigate the history recall if no editing took place yet
 +
 +8. It appears your history recall is only for rawinput, that is if inDOS is set. This is similar to mine, but [[https://ulukai.org/ecm/doc/ldebug.htm#interface-input|I document that]] and provide ways to enable using rawinput even if the input is from a DOS stdin terminal
 +
 +9. I allow [[https://hg.ulukai.org/ecm/ldebug/file/653a044b58da/source/lineio.asm#l2300|more than one way]] to encode the Up/Down arrow keypresses which makes it work on dosemu in -dumb mode
 +
 +Similarities also include rejecting empty lines and those duplicating the prior line.
 +
 +<cite>[[https://github.com/Baron-von-Riedesel/DOS-debug/pull/1#issuecomment-823395716|First comment]] on the ticket, 2021-04-20</cite></blockquote>
 +
 +<blockquote>Correction: It appears your patch does away with the interrupt 21h service 0Ah call entirely and always uses interrupt 16h to read input. In my implementation DOS application terminal input is still done with the DOS service by default, which means the debugger's line history is not available. (I do enter received lines into the history buffer regardless.) And if ''rawinput'' is used (eg DCO flag 800h set) then it can still use interrupt 21h to read input, but using services which read single bytes from stdin.
 +
 +<cite>[[https://github.com/Baron-von-Riedesel/DOS-debug/pull/1#issuecomment-823549323|Second comment]] on the ticket, 2021-04-20</cite></blockquote>
 +
 +{{tag>lbacache ldebug eld alias.eld}}
 +
 +
 +~~DISCUSSION~~
  
blog/pushbx/2026/0823_mid_late_august_work_multi-aliases.txt ยท Last modified: 2026-08-23 18:10:37 +0200 Aug Sun by ecm