home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / commercial-software / programming / Z80TOOLS.ZIP / DISK1.ZIP / MODULES.ANT < prev    next >
Text File  |  1998-07-30  |  48KB  |  1,973 lines

  1.     name    'CHKOPS'
  2. ; CHKOPS: save command tail, check count of operands and
  3. ; check for "?" in first operand.  Parameters are:
  4. ;    reg B = min tokens allowed
  5. ;    reg C = max tokens allowed
  6. ;    DE-> usage message ending in $
  7. ; returns count of command tokens in reg. A.
  8. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  9.  
  10.     maclib    environ
  11.  
  12.     dseg
  13. usage    dw    0    ; save ->message
  14.     cseg
  15.  
  16.     public    CHKOPS
  17.     entersub
  18. CHKOPS:
  19.     push    h    ; save caller's HL
  20.     xchg
  21.     shld    usage    ; save ->message
  22.     savetail    ; A = count of tokens
  23.     push    psw    ; ..save for exit
  24.  
  25.     cmp    b    ; count :: min
  26.     jc    quit    ; (less than min)
  27.  
  28.     ora    a    ; were there zero operands?
  29.     jz    exit    ; (yes, must be right number)
  30.  
  31.     dcr    a    ; reduce count to force carry
  32.     cmp    c    ; ..on comparison to max
  33.     jnc    quit    ; (count > max)
  34.  
  35.     mvi    a,1    ; get DE->first token
  36.     tailtokn @A
  37.     xchg        ; make that HL->token
  38.     mov    a,m
  39.     cpi    '?'    ; does it start with "?"
  40.     jnz    exit    ; (nope)
  41.     inx    h
  42.     mov    a,m    ; is it maybe "?xxx" or
  43.     ora    a    ; ..is it exactly ?,null
  44.     jnz    exit    ; (was "?xx...")
  45.  
  46. quit:    lhld    usage
  47.     xchg        ; DE->abort-message
  48.     abort    ,@D
  49.  
  50. exit:    pop    psw    ; A = count of tokens
  51.     lhld    usage    ; restore
  52.     xchg        ; ..caller's DE
  53.     pop    h    ; ..and HL
  54.     ret
  55.  
  56.     end
  57. rt    ,@D
  58.  
  59. exit:    pop    psw    ; A = count of tokens
  60.     lhld    usage    ; restor    name    'OPENIN'
  61. ;
  62. ; OPENIN(operand-number,filedef) -- assign the specified command
  63. ; operand to the filedef and open it.  Abort with one of three
  64. ; messages if problems arise:
  65. ;
  66. ;    FRUMMAGE is not a valid filespec.
  67. ;    FRUMMAGE is ambiguous; an explicit name is needed.
  68. ;    FRUMMAGE is empty or does not exist.
  69. ;
  70. ; A = operand number to assign
  71. ; DE->filedef to use
  72. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  73.  
  74.     maclib     environ
  75.     dseg
  76. is:    strconst ' is '
  77. inval:    strconst 'not a valid filespec'
  78. ambig:    strconst 'ambiguous; an explicit name is needed'
  79. empty:    strconst 'empty or does not exist'
  80. dotdol: strconst '.$'
  81. msg:    strspace 64
  82.     cseg
  83.     entersub
  84.     public    OPENIN
  85. OPENIN:
  86.     push    psw
  87.     push    b
  88.     push    d
  89.     push    h
  90.     xchg        ; save ->file in HL
  91.     tailtokn @A    ; DE->operand
  92.     xchg        ; ok, HL->operand, DE->file
  93.     fassign @D,@H
  94.     lxi    b,inval ; (set up for invalid)
  95.     jz    error    ; oops, not a valid filespec
  96.     cpi    '?'    ; was it ambiguous?
  97.     lxi    b,ambig ; (prepare in case it was)
  98.     jz    error    ; (yes)
  99.     freset    @D    ; try to open it
  100.     lxi    b,empty ; (but assume we can't)
  101.     jz    error    ; (we couldn't)
  102.     pop    h
  103.     pop    d
  104.     pop    b
  105.     pop    psw
  106.     ret
  107.  
  108. ; Something went wrong, and BC->the details of why.  Build
  109. ; an abort message and quit.
  110.  
  111. error:
  112. ; copy the operand to the message field first
  113.  
  114.     lxi    d,msg
  115.     strcopy @Dupdate,@Hupdate
  116.  
  117. ; add the word " is "
  118.  
  119.     lxi    h,is
  120.     strappnd @Dupdate,@Hupdate
  121.  
  122. ; then add the specific explanation
  123.  
  124.     mov h,b ! mov l,c
  125.     strappnd @Dupdate,@Hupdate
  126.  
  127. ; finish up with a period and a dollar sign
  128.  
  129.     lxi    h,dotdol
  130.     strappnd @Dupdate,@Hupdate
  131.  
  132. ; that does it -- byebye
  133.  
  134.     lxi    d,msg
  135.     abort    ,@D
  136.  
  137.     end
  138. and a dol    name    'OPENUT'
  139. ;===============================================================
  140. ;
  141. ;    OPENUT module
  142. ;
  143. ; Function OPENIN( A=operand number, DE->filedef)
  144. ; Acquire the given operand string and assign it to the filedef,
  145. ; then open the file for input.  If problems, abort with one of
  146. ; three messages:
  147. ;
  148. ;    FRUMMAGE is not a valid filespec.
  149. ;    FRUMMAGE is ambiguous; an explicit name is needed.
  150. ;    FRUMMAGE is empty or does not exist.
  151. ;
  152. ; Function OPENOU( A=operand, DE->filedef, BC->default filedef)
  153. ; As for OPENIN, but allows a default filedef, opens for output
  154. ; with frewrite and hence doesn't care if file is empty.
  155. ;
  156. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  157.  
  158.     maclib     environ
  159.  
  160.     dseg
  161. is:    strconst ' is '
  162. inval:    strconst 'not a valid filespec'
  163. ambig:    strconst 'ambiguous; an explicit name is needed'
  164. empty:    strconst 'empty or does not exist'
  165. dotdol: strconst '.$'
  166. msg:    strspace 64
  167.  
  168.     cseg
  169.     entersub
  170.  
  171.     public    OPENIN
  172. OPENIN:
  173.     push    psw
  174.     push    b
  175.     push    d
  176.     push    h
  177.  
  178.     lxi    b,0    ; no default filedef for input
  179.     call    Assign    ; assign & check the operand
  180.     freset    @D    ; try to open it
  181.     lxi    b,empty ; (but assume we can't)
  182.     cz    Error    ; (we couldn't)
  183.  
  184.     pop    h
  185.     pop    d
  186.     pop    b
  187.     pop    psw
  188.     ret
  189.  
  190.     public    OPENOU
  191. OPENOU:
  192.     push    psw
  193.     push    b
  194.     push    d
  195.     push    h
  196.  
  197.     call    Assign    ; try the assignment
  198.     frewrite @D    ; and open for output
  199.  
  200.     pop    h
  201.     pop    d
  202.     pop    b
  203.     pop    psw
  204.     ret
  205.  
  206. ; Internal subroutine Assign(A=op#, DE->file, BC->dflt) --
  207. ; Attempt the assign of operand to file with default and
  208. ; abort if necessary.
  209.  
  210. Assign:
  211.  
  212.     push    d    ; save ->file
  213.     tailtokn @A    ; get DE->operand string
  214.     xchg        ; and move to HL
  215.     pop    d    ; recover DE->file
  216.     fassign @D,@H,@B
  217.     lxi    b,inval ; (set up for invalid)
  218.     cz    Error    ; oops, not a valid filespec
  219.     cpi    '?'    ; was it ambiguous?
  220.     lxi    b,ambig ; (prepare in case it was)
  221.     cz    Error    ; (yes)
  222.     ret        ; assigned ok...
  223.  
  224. ; Internal subroutine Error(BC->submessage, HL->operand)
  225. ; Not really a subroutine because it always aborts and never
  226. ; returns -- construct an abort message including the operand
  227. ; string and abort the program.
  228.  
  229. Error:
  230. ; copy the operand to the message field first
  231.  
  232.     lxi    d,msg
  233.     strcopy @Dupdate,@Hupdate
  234.  
  235. ; add the word " is "
  236.  
  237.     lxi    h,is
  238.     strappnd @Dupdate,@Hupdate
  239.  
  240. ; then add the specific explanation
  241.  
  242.     mov h,b ! mov l,c
  243.     strappnd @Dupdate,@Hupdate
  244.  
  245. ; finish up with a period and a dollar sign
  246.  
  247.     lxi    h,dotdol
  248.     strappnd @Dupdate,@Hupdate
  249.  
  250. ; that does it -- byebye
  251.  
  252.     lxi    d,msg
  253.     abort    ,@D
  254.  
  255.     end
  256. and a dollar sign
  257.  
  258.     lxi    h,dotdol
  259.         name    'ANTINP'
  260. ;===============================================================
  261. ; copyin(DE=r): record r has been allocated to the current file
  262. ; and the AntSeq file is not at end of file.  Read its next
  263. ; 128-byte record and write it to the anthology data file.
  264. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  265.  
  266.     maclib    environ
  267.     entersub
  268.  
  269.     dseg
  270. buffer: ds    128    ; buffer for data I/O
  271.     cseg
  272.  
  273.     public    ANTINP
  274. ANTINP:
  275.     push    psw
  276.     push    b
  277.     push    d
  278.     push    h
  279.     push    d    ; save record number again
  280.  
  281.     lxi    d,AntSeq
  282.     lxi    h,buffer
  283.     lxi    b,128
  284.     fgetblok @D,@H,@B
  285.  
  286.     lxi    d,AntDat
  287.     pop    h    ; HL=record number
  288.     frecseek @D,@H    ; seek to data record
  289.  
  290.     lxi    h,buffer
  291.     lxi    b,128
  292.     fputblok @D,@H,@B
  293.  
  294.     pop    h
  295.     pop    d
  296.     pop    b
  297.     pop    psw
  298.     ret
  299.  
  300.     common    /ANTCOM/
  301. ; This common area definition is included in all, or most
  302. ; anthology programs.  It defines the directory in storage.
  303. ; The filedefs are assembled in module ANTSUP.
  304.  
  305. AntHdr    equ    $    ; following words precede directory
  306. SizeR    ds    2    ; size of array R
  307. SpanR    ds    2    ; # of 128-byte records over R
  308. SizeF    ds    2    ; size of array FS
  309. SpanF    ds    2    ; # of 128-byte records over FS
  310. AlFiles ds    2    ; count of allocated files
  311. Frecs    ds    2    ; count of free records
  312. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  313. Base    ds    2    ; ->base of dir. (array R)
  314. TopR    ds    2    ; ->low free byte
  315. BotF    ds    2    ; ->bottom byte of FS
  316. TopF    ds    2    ; ->byte after directory
  317.  
  318. SizeDir equ    16384    ; in-core size of directory
  319. FSsize    equ    14    ; offset to size in FS entry
  320. FSlen    equ    16    ; size of an FS entry
  321.  
  322. AntDat    ds    FcrLen    ; data file antname.ANT
  323. AntDirX ds    FcrLen    ; directory copy antname.ANX
  324. AntDirY ds    FcrLen    ; directory copy antname.ANY
  325. AntSeq    ds    FcrLen    ; sequential file in/out
  326.     cseg ; end of common
  327. antname.ANX
  328. AntDirY ds    FcrLen    ; directory copy    name    'ANTOUT'
  329. ;===============================================================
  330. ; copyout(DE=r): record r is the next in sequence for the
  331. ; current output file.    Read it from the data file and write it
  332. ; to the output file.  If the seek operation returns Z true,
  333. ; meaning "seek to unwritten data," abort -- we're confused.
  334. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  335.  
  336.     maclib    environ
  337.     entersub
  338.  
  339.     dseg
  340. buffer: ds    128    ; buffer for data I/O
  341. msgIC3: db    'Integrity check #3.$'
  342.     cseg
  343.  
  344.     public    ANTOUT
  345. ANTOUT:
  346.  
  347.     push    psw
  348.     push    b
  349.     push    d
  350.     push    h
  351.  
  352.     xchg        ; HL=record number
  353.     lxi    d,AntDat
  354.     frecseek @D,@H
  355.     abort    z,msgIC3
  356.  
  357.     lxi    h,buffer
  358.     lxi    b,128
  359.     fgetblok @D,@H,@B
  360.  
  361.     lxi    d,AntSeq
  362.     lxi    b,128
  363.     fputblok @D,@H,@B
  364.  
  365.     pop    h
  366.     pop    d
  367.     pop    b
  368.     pop    psw
  369.     ret
  370.  
  371.     common    /ANTCOM/
  372. ; This common area definition is included in all, or most
  373. ; anthology programs.  It defines the directory in storage.
  374. ; The filedefs are assembled in module ANTSUP.
  375.  
  376. AntHdr    equ    $    ; following words precede directory
  377. SizeR    ds    2    ; size of array R
  378. SpanR    ds    2    ; # of 128-byte records over R
  379. SizeF    ds    2    ; size of array FS
  380. SpanF    ds    2    ; # of 128-byte records over FS
  381. AlFiles ds    2    ; count of allocated files
  382. Frecs    ds    2    ; count of free records
  383. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  384. Base    ds    2    ; ->base of dir. (array R)
  385. TopR    ds    2    ; ->low free byte
  386. BotF    ds    2    ; ->bottom byte of FS
  387. TopF    ds    2    ; ->byte after directory
  388.  
  389. SizeDir equ    16384    ; in-core size of directory
  390. FSsize    equ    14    ; offset to size in FS entry
  391. FSlen    equ    16    ; size of an FS entry
  392.  
  393. AntDat    ds    FcrLen    ; data file antname.ANT
  394. AntDirX ds    FcrLen    ; directory copy antname.ANX
  395. AntDirY ds    FcrLen    ; directory copy antname.ANY
  396. AntSeq    ds    FcrLen    ; sequential file in/out
  397.     cseg ; end of common
  398. antna    name    'ANTFIN'
  399. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  400.  
  401. ;===============================================================
  402. ; find(DE->string): returns HL->FS entry or HL=zero
  403.  
  404.     maclib    environ
  405.  
  406.     public    ANTFIN
  407. ANTFIN:
  408.     push    psw
  409.     push    b
  410.  
  411.     lhld    TopF
  412. FINloop:
  413.     lxi    b,FSlen
  414.     ora    a    ; clear carry
  415.     dsbc    b    ; HL->next lower FS entry
  416.     lbcd    BotF    ; is HL now lower than lowest?
  417.     dsbc    b    ; (carry is still clear)
  418.     jrc    FINfail ; (yes, we tried them all)
  419.     dad    b    ; no, restore HL
  420.     strcmp    @D,@H    ; is this the wanted entry?
  421.     jrz    FINhit    ; (yes, stop)
  422.     jmp    FINloop
  423.  
  424. FINfail: lxi     h,0    ; return HL=0 for failure
  425. FINhit:         ; return HL->FS entry for success
  426.     pop    b
  427.     pop    psw
  428.     ret
  429.  
  430.     common    /ANTCOM/
  431. ; This common area definition is included in all, or most
  432. ; anthology programs.  It defines the directory in storage.
  433. ; The filedefs are assembled in module ANTSUP.
  434.  
  435. AntHdr    equ    $    ; following words precede directory
  436. SizeR    ds    2    ; size of array R
  437. SpanR    ds    2    ; # of 128-byte records over R
  438. SizeF    ds    2    ; size of array FS
  439. SpanF    ds    2    ; # of 128-byte records over FS
  440. AlFiles ds    2    ; count of allocated files
  441. Frecs    ds    2    ; count of free records
  442. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  443. Base    ds    2    ; ->base of dir. (array R)
  444. TopR    ds    2    ; ->low free byte
  445. BotF    ds    2    ; ->bottom byte of FS
  446. TopF    ds    2    ; ->byte after directory
  447.  
  448. SizeDir equ    16384    ; in-core size of directory
  449. FSsize    equ    14    ; offset to size in FS entry
  450. FSlen    equ    16    ; size of an FS entry
  451.  
  452. AntDat    ds    FcrLen    ; data file antname.ANT
  453. AntDirX ds    FcrLen    ; directory copy antname.ANX
  454. AntDirY ds    FcrLen    ; directory copy antname.ANY
  455. AntSeq    ds    FcrLen    ; sequential file in/out
  456.     cseg ; end of common
  457. antname.ANX
  458. AntDirY ds    FcrLen    ; directory copy antname.ANY
  459. AntSeq    ds    FcrLen    ; sequential file i    name    'ANTFRE'
  460. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  461.  
  462. ;===============================================================
  463. ; free(HL->FS entry): Find all record slots now owned by this
  464. ; file and disown them by putting -1 in each.  Check that the
  465. ; number found agree with the size field, aborting if it does
  466. ; not.
  467. ;
  468. ; The marked slots are not added to Frecs at this time.  They
  469. ; will be made officially free (zero) during the next Commit.
  470.  
  471.     maclib    environ
  472.     entersub
  473.  
  474.     dseg
  475. msgIC2: db    'Integrity check #2.$'
  476.     cseg
  477.  
  478.     public    ANTFRE
  479. ANTFRE:
  480.     push    psw
  481.     push    b
  482.     push    d
  483.     push    h
  484.  
  485.     lbcd    TopR    ; BC holds TopR for end-check
  486.     xchg        ; DE contains ->FS as comparand
  487.     lxi    h,0    ; count of found records...
  488.     push    h    ; ..is kept on top of stack
  489.     lhld    Base    ; HL scans array R
  490.  
  491. FREloop:
  492.     ora    a
  493.     dsbc    b    ; TopR = HL?
  494.     jnc    FREdone ; (yes, done)
  495.     dad    b    ; no, restore HL
  496.     mov a,m ! inx h ; A = low byte, HL->2nd byte
  497.     cmp    e
  498.     jnz    FREmiss ; (low-byte mismatch)
  499.     mov    a,m
  500.     sub    d    ; (leave A=0 if equal)
  501.     jnz    FREmiss ; (high-byte mismatch)
  502.     dcr    a    ; A = FFh
  503.     dcx    h
  504.     mov    m,a    ; 1st byte = FF
  505.     inx    h    ; HL->2nd byte again
  506.     mov    m,a    ; record slot = -1 (FFFF)
  507.     xthl
  508.     inx    h    ; increment count of freed slots
  509.     xthl
  510. FREmiss: inx    h    ; HL->next slot
  511.     jmp    FREloop
  512.  
  513. ; All in-use slots of R have been scanned.  Those that were
  514. ; owned by the indicated file have been set to -1, and the count
  515. ; of such slots is on the stack.  Make sure it's the same as the
  516. ; size field of the FS entry, and set that size to zero.
  517. FREdone:
  518.     lxi    h,FSsize
  519.     dad    d    ; HL-> size field
  520.     pop    d    ; DE=count
  521.     mov    a,e
  522.     cmp    m
  523.     jrnz    FREugh
  524.     mvi    m,0    ; zero low byte
  525.     inx    h
  526.     mov    a,d
  527.     cmp    m
  528.     jrnz    FREugh
  529.     mvi    m,0    ; ..and high byte
  530.  
  531.     pop    h
  532.     pop    d
  533.     pop    b
  534.     pop    psw
  535.     ret
  536.  
  537. FREugh: abort    ,msgIC2
  538.  
  539.     common    /ANTCOM/
  540. ; This common area definition is included in all, or most
  541. ; anthology programs.  It defines the directory in storage.
  542. ; The filedefs are assembled in module ANTSUP.
  543.  
  544. AntHdr    equ    $    ; following words precede directory
  545. SizeR    ds    2    ; size of array R
  546. SpanR    ds    2    ; # of 128-byte records over R
  547. SizeF    ds    2    ; size of array FS
  548. SpanF    ds    2    ; # of 128-byte records over FS
  549. AlFiles ds    2    ; count of allocated files
  550. Frecs    ds    2    ; count of free records
  551. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  552. Base    ds    2    ; ->base of dir. (array R)
  553. TopR    ds    2    ; ->low free byte
  554. BotF    ds    2    ; ->bottom byte of FS
  555. TopF    ds    2    ; ->byte after directory
  556.  
  557. SizeDir equ    16384    ; in-core size of directory
  558. FSsize    equ    14    ; offset to size in FS entry
  559. FSlen    equ    16    ; size of an FS entry
  560.  
  561. AntDat    ds    FcrLen    ; data file antname.ANT
  562. AntDirX ds    FcrLen    ; directory copy antname.ANX
  563. AntDirY ds    FcrLen    ; directory copy antname.ANY
  564. AntSeq    ds    FcrLen    ; sequential file in/out
  565.     cseg ; end of common
  566. antname.ANX
  567. AntDi    name    'ANTADD'
  568. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  569.  
  570. ;===============================================================
  571. ; add(DE->string): returns HL->new FS entry initialized with
  572. ; the filename string -- or, if there are no free entries,
  573. ; aborts with "Directory space is full."
  574.  
  575.     maclib    environ
  576.     entersub
  577.  
  578.     dseg
  579. NoDir:    db    'Directory space is full.$'
  580.     cseg
  581.  
  582.     public    ANTADD
  583. ANTADD:
  584.     push    psw
  585.     push    b
  586.  
  587.     lhld    TopF
  588. ADDloop:
  589.     lxi    b,FSlen
  590.     ora    a
  591.     dsbc    b    ; HL->next lower FS entry
  592.     push    h    ; (save that)
  593.     lbcd    BotF
  594.     dsbc    b    ; off the bottom now?
  595.     pop    h    ; (recover ->next entry)
  596.     jrc    ADDnew    ; (yes, allocate a new name)
  597.     mov a,m ! ora a ; no, does HL->free entry (null)?
  598.     jrz    ADDold    ; (yes, reuse old name)
  599.     jmp    ADDloop ; no, try another
  600.  
  601. ; All allocated FS entries are in use.    HL=BotF-16, which will
  602. ; do for a new entry provided it doesn't overlap TopR.
  603. ADDnew:
  604.     lbcd    TopR
  605.     push    h
  606.     ora    a
  607.     dsbc    b    ; compare HL vs. TopR
  608.     pop    h
  609.     abort    c,NoDir ; ..and quit if overlap.
  610.     shld    BotF    ; set the new BotF, extending array
  611.     mvi    m,0    ; make new entry null
  612.  
  613. ; HL->an available FS entry (contains a null string).  Copy
  614. ; DE->string into it...
  615. ADDold:
  616.     xchg        ; append wants DE->target, HL->source
  617.     strappnd @D,@H
  618.     xchg        ; recover HL->array entry
  619.  
  620. ; ...and set its size word to zero
  621.  
  622.     push    h
  623.     lxi    b,FSsize
  624.     dad    b    ; HL->size field
  625.     xra    a
  626.     mov m,a ! inx h ; zero it
  627.     mov m,a
  628.     pop    h
  629.  
  630. ; Whatever we did, there is now one more active file entry.
  631.  
  632.     lbcd    AlFiles
  633.     inx    b
  634.     sbcd    AlFiles
  635.  
  636.     pop    b
  637.     pop    psw
  638.     ret
  639.  
  640.     common    /ANTCOM/
  641. ; This common area definition is included in all, or most
  642. ; anthology programs.  It defines the directory in storage.
  643. ; The filedefs are assembled in module ANTSUP.
  644.  
  645. AntHdr    equ    $    ; following words precede directory
  646. SizeR    ds    2    ; size of array R
  647. SpanR    ds    2    ; # of 128-byte records over R
  648. SizeF    ds    2    ; size of array FS
  649. SpanF    ds    2    ; # of 128-byte records over FS
  650. AlFiles ds    2    ; count of allocated files
  651. Frecs    ds    2    ; count of free records
  652. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  653. Base    ds    2    ; ->base of dir. (array R)
  654. TopR    ds    2    ; ->low free byte
  655. BotF    ds    2    ; ->bottom byte of FS
  656. TopF    ds    2    ; ->byte after directory
  657.  
  658. SizeDir equ    16384    ; in-core size of directory
  659. FSsize    equ    14    ; offset to size in FS entry
  660. FSlen    equ    16    ; size of an FS entry
  661.  
  662. AntDat    ds    FcrLen    ; data file antname.ANT
  663. AntDirX ds    FcrLen    ; directory copy antname.ANX
  664. AntDirY ds    FcrLen    ; directory copy antname.ANY
  665. AntSeq    ds    FcrLen    ; sequential file in/out
  666.     cseg ; end of common
  667. antname.ANX
  668. AntDirY ds    FcrLen    ; directory copy antname.ANY
  669. AntSeq    ds    FcrLen    ; sequential file in/out
  670.     cseg ; end of common    name    'ANTND'
  671. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  672.  
  673. ;===============================================================
  674. ; nextdat(HL->FS entry, DE=last record number):
  675. ; Return the next record number after DE which is owned by
  676. ; HL->file. The caller is expected to know whether there IS a
  677. ; next record or not, so if there is not, we abort with an
  678. ; integrity check 1.
  679. ;
  680. ; We receive and return DE as an integer record number "r" from
  681. ; 1 to (TopR-Base)/2.  Internally we deal with addresses of
  682. ; record slots, Base+2*r.
  683. ;
  684. ; Record numbers are origin-1 while the array is really origin-0
  685. ; so the slot indexed by DE on entry is Base+2*(DE-1).    But we
  686. ; want to start with the NEXT slot, so we begin at Base+2*DE.
  687.  
  688.     maclib    environ
  689.     entersub
  690.  
  691.     dseg
  692. msgIC1: db    'Integrity check #1.$'
  693.     cseg
  694.  
  695.     public    ANTND
  696. ANTND:
  697.     push    psw
  698.     push    b
  699.  
  700.     push    h    ; save FS pointer
  701.     lhld    Base
  702.     dad    d    ; Base + 2*DE gives...
  703.     dad    d    ; ...HL->next record slot
  704.     pop    d    ; DE=FS pointer to compare
  705.     lbcd    TopR    ; BC=limit address for checking
  706. NDloop:
  707.     ora    a
  708.     dsbc    b    ; has HL got up to TopR?
  709.     abort    nc,msgIC1; (if so, somebody goofed)
  710.     dad    b    ; no, restore HL
  711.     mov a,m ! inx h
  712.     cmp    e    ; compare low bytes
  713.     mov    a,m    ; and set up for high ones
  714.     jnz    NDmiss
  715.     cmp    d
  716.     jz    NDhit
  717. NDmiss: inx    h
  718.     jmp    NDloop
  719.  
  720. ; HL->2nd byte of the next record slot that names DE->FS entry.
  721. ; Convert HL into a record number as (HL-Base)/2 + 1.
  722. NDhit:
  723.     dcx    h    ; back to 1st byte of word
  724.     lbcd    Base
  725.     ora    a
  726.     dsbc    b    ; (carry now clear, HL was >= BC)
  727.     rarr    h    ; 0 >> H >> carry
  728.     rarr    l    ; carry >> L >> carry
  729.     inx    h    ; make origin-1
  730.     xchg        ; DE=record #, HL->FS entry
  731.     pop    b
  732.     pop    psw
  733.     ret
  734.  
  735.     common    /ANTCOM/
  736. ; This common area definition is included in all, or most
  737. ; anthology programs.  It defines the directory in storage.
  738. ; The filedefs are assembled in module ANTSUP.
  739.  
  740. AntHdr    equ    $    ; following words precede directory
  741. SizeR    ds    2    ; size of array R
  742. SpanR    ds    2    ; # of 128-byte records over R
  743. SizeF    ds    2    ; size of array FS
  744. SpanF    ds    2    ; # of 128-byte records over FS
  745. AlFiles ds    2    ; count of allocated files
  746. Frecs    ds    2    ; count of free records
  747. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  748. Base    ds    2    ; ->base of dir. (array R)
  749. TopR    ds    2    ; ->low free byte
  750. BotF    ds    2    ; ->bottom byte of FS
  751. TopF    ds    2    ; ->byte after directory
  752.  
  753. SizeDir equ    16384    ; in-core size of directory
  754. FSsize    equ    14    ; offset to size in FS entry
  755. FSlen    equ    16    ; size of an FS entry
  756.  
  757. AntDat    ds    FcrLen    ; data file antname.ANT
  758. AntDirX ds    FcrLen    ; directory copy antname.ANX
  759. AntDirY ds    FcrLen    ; directory copy antname.ANY
  760. AntSeq    ds    FcrLen    ; sequential file in/out
  761.     cseg ; end of common
  762. an    name    'ANTNF'
  763. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  764.  
  765. ;===============================================================
  766. ; nextfree(HL->FS entry, DE=record number):
  767. ; Return the record number of the next FREE record slot after
  768. ; DE, and allocate it to HL=file address.  If no free (zero)
  769. ; entries are found before TopR, create one by sliding TopR
  770. ; up, aborting if that overlaps BotF.
  771. ;
  772. ; See notes on index arithmetic in ANTND.
  773.  
  774.     maclib    environ
  775.     entersub
  776.  
  777.     dseg
  778. NoDat:    db    'Data space is full.$'
  779.     cseg
  780.  
  781.     public    ANTNF
  782. ANTNF:
  783.     push    psw
  784.     push    b
  785.  
  786.     push    h    ; save FS pointer
  787.     lhld    Base
  788.     dad    d
  789.     dad    d    ; HL->next record slot
  790.     pop    d    ; DE=FS pointer to compare
  791.     lbcd    TopR    ; BC=limit of ever-used records
  792. NFloop:
  793.     ora    a
  794.     dsbc    b    ; has HL got up to TopR?
  795.     jnc    NFnew    ; (yes, make a new one)
  796.     dad    b    ; no, restore HL
  797.     mov a,m ! inx h
  798.     ora    m    ; is this slot zero?
  799.     jz    NFold    ; (yes, use it)
  800.     inx    h    ; no, step over it
  801.     jmp    NFloop    ; ..and continue
  802.  
  803. ; BC=HL=TopR, and no zero entries were seen.  If TopR+2 < BotF,
  804. ; increment TopR and use this slot.  Otherwise abort.
  805. NFnew:
  806.     inx b ! inx b    ; new TopR, maybe
  807.     lhld    BotF
  808.     dsbc    b    ; new TopR > BotF? (equal is ok)
  809.     abort    c,NoDat ; (yes, array R is full)
  810.     sbcd    TopR    ; no, ok, store new TopR
  811.     mov h,b ! mov l,c ; and set up HL
  812.     dcx    h    ; ..to point to 2nd byte of slot
  813.     jmp    NFboth
  814.  
  815. ; We found a record entry that was previously used but is now
  816. ; free.  We will use it, so decrement Frecs.
  817. NFold:
  818.     lbcd    Frecs
  819.     dcx    b
  820.     sbcd    Frecs
  821.  
  822. ; HL->2nd byte of a record slot that is available.  Store DE
  823. ; into it to claim ownership.  Then convert the address into
  824. ; a record number: 1+(HL-Base)/2
  825. NFboth:
  826.     mov    m,d
  827.     dcx    h
  828.     mov    m,e
  829.     lbcd    Base
  830.     ora    a
  831.     dsbc    b
  832.     rarr    h
  833.     rarr    l
  834.     inx    h
  835.     xchg        ; DE=record #, HL->FS entry
  836.     pop    b
  837.     pop    psw
  838.     ret
  839.  
  840.     common    /ANTCOM/
  841. ; This common area definition is included in all, or most
  842. ; anthology programs.  It defines the directory in storage.
  843. ; The filedefs are assembled in module ANTSUP.
  844.  
  845. AntHdr    equ    $    ; following words precede directory
  846. SizeR    ds    2    ; size of array R
  847. SpanR    ds    2    ; # of 128-byte records over R
  848. SizeF    ds    2    ; size of array FS
  849. SpanF    ds    2    ; # of 128-byte records over FS
  850. AlFiles ds    2    ; count of allocated files
  851. Frecs    ds    2    ; count of free records
  852. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  853. Base    ds    2    ; ->base of dir. (array R)
  854. TopR    ds    2    ; ->low free byte
  855. BotF    ds    2    ; ->bottom byte of FS
  856. TopF    ds    2    ; ->byte after directory
  857.  
  858. SizeDir equ    16384    ; in-core size of directory
  859. FSsize    equ    14    ; offset to size in FS entry
  860. FSlen    equ    16    ; size of an FS entry
  861.  
  862. AntDat    ds    FcrLen    ; data file antname.ANT
  863. AntDirX ds    FcrLen    ; directory copy antname.ANX
  864. AntDirY ds    FcrLen    ; directory copy antname.ANY
  865. AntSeq    ds    FcrLen    ; sequential file in/out
  866.     cseg ; end of common
  867. antname.ANX
  868. AntDirY ds    FcrLen    ; directory copy antname.ANY
  869. AntSeq    ds    FcrLen    ; sequential file in/out
  870.     cseg ; e    name    'ANTSET'
  871. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  872.  
  873. ;===============================================================
  874. ; Setup(DE->usage message):
  875. ; Get the first command operand and use it to set up all three
  876. ; anthology filedefs in the common area with drivecode, filename
  877. ; and password, and their appropriate filetypes.
  878. ;
  879. ; If there is no first operand, or if it starts with "?," abort
  880. ; with the given usage message.  Other messages:
  881. ;
  882. ;    FRUMMAGE is not a valid anthology filespec
  883. ;    FRUMMAGE is ambiguous; anthology spec must be explicit
  884.  
  885.     maclib    environ
  886.     entersub
  887.  
  888.     common    /ANTCOM/
  889. ; This common area definition is included in all, or most
  890. ; anthology programs.  It defines the directory in storage.
  891. ; The filedefs are assembled in module ANTSUP.
  892.  
  893. AntHdr    equ    $    ; following words precede directory
  894. SizeR    ds    2    ; size of array R
  895. SpanR    ds    2    ; # of 128-byte records over R
  896. SizeF    ds    2    ; size of array FS
  897. SpanF    ds    2    ; # of 128-byte records over FS
  898. AlFiles ds    2    ; count of allocated files
  899. Frecs    ds    2    ; count of free records
  900. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  901. Base    ds    2    ; ->base of dir. (array R)
  902. TopR    ds    2    ; ->low free byte
  903. BotF    ds    2    ; ->bottom byte of FS
  904. TopF    ds    2    ; ->byte after directory
  905.  
  906. SizeDir equ    16384    ; in-core size of directory
  907. FSsize    equ    14    ; offset to size in FS entry
  908. FSlen    equ    16    ; size of an FS entry
  909.  
  910. AntDat    ds    FcrLen    ; data file antname.ANT
  911. AntDirX ds    FcrLen    ; directory copy antname.ANX
  912. AntDirY ds    FcrLen    ; directory copy antname.ANY
  913. AntSeq    ds    FcrLen    ; sequential file in/out
  914.     cseg ; end of common
  915.  
  916. ; Reopen the common definition and assemble into it the filedefs
  917. ; of the anthology files.
  918.  
  919.     common    /ANTCOM/
  920.     org    AntDat    ; assemble filedefs into common
  921.     filedef 2048
  922.     org    AntDirX
  923.     filedef 1024
  924.     org    AntDirY
  925.     filedef 1024
  926.     org    AntSeq
  927.     filedef 1024
  928.  
  929.     dseg
  930. tokens    ds    1    ; save token-count for exit
  931. usage    ds    2    ; save ->usage message
  932. string    strspace 80    ; space to build abort-message
  933. Ant:    strconst 'ANT'
  934. Anx:    strconst 'ANX'
  935. Any:    strconst 'ANY'
  936. inval:
  937.     strconst ' is not a valid anthology filespec.$'
  938. ambig:
  939.     strconst ' is ambiguous; anthology spec must be explicit.$'
  940.  
  941.     cseg
  942.  
  943.     public    ANTSET
  944. ANTSET:
  945.     push    b
  946.     push    d
  947.     push    h
  948.     xchg
  949.     shld    usage
  950.  
  951.     savetail
  952.     sta    tokens
  953.     ora    a    ; any tokens at all?
  954.     jnz    SET1    ; (yes, continue)
  955. abusage: ; come here if token 1 is "?"
  956.     lhld    usage
  957.     xchg
  958.     abort    ,@D
  959.  
  960. SET1:    mvi    a,1
  961.     tailtokn @A
  962.     ldax    d
  963.     cpi    '?'    ; a plea for help?
  964.     jrz    abusage ; (yes, abort w/ usage msg)
  965.  
  966. ; The first token is present and is not a question mark.  Test
  967. ; it by assigning it to one file.
  968.  
  969.     xchg        ; HL->token 1
  970.     lxi    d,AntDat
  971.     fassign @D,@H    ; assign D:filename.typ;pass
  972.     lxi    d,inval
  973.     jz    abspec    ; (bad filespec)
  974.     lxi    d,ambig
  975.     cpi    '?'
  976.     jz    abspec    ; (ambiguous spec)
  977.  
  978. ; The first-token filespec is a valid one at least for the
  979. ; general case.  Assign it to the other two files as well.
  980.  
  981.     lxi    d,AntDirX
  982.     fassign @D,@H
  983.     lxi    d,AntDirY
  984.     fassign @D,@H
  985.  
  986. ; Now force all three to have their correct filetypes, over-
  987. ; riding any filetype the user may have given.
  988.  
  989. typeonly equ    00100b ; no pass, do type, no name, no drive
  990.  
  991.     lxi    d,AntDat
  992.     lxi    h,Ant
  993.     fassign @D,@H,,typeonly
  994.     lxi    d,AntDirX
  995.     lxi    h,Anx
  996.     fassign @D,@H,,typeonly
  997.     lxi    d,AntDirY
  998.     lxi    h,Any
  999.     fassign @D,@H,,typeonly
  1000.  
  1001. ; That's that, the filedefs are ready to open.
  1002.  
  1003.     lda    Tokens
  1004.     pop    h
  1005.     pop    d
  1006.     pop    b
  1007.     ret
  1008.  
  1009. ; common routine to abort with a message composed of HL->string
  1010. ; followed by DE->string.
  1011. abspec:
  1012.     push    d
  1013.     lxi    d,string
  1014.     strcopy @D,@H
  1015.     pop    h
  1016.     strappnd @D,@H
  1017.     lxi    d,string
  1018.     abort    ,@D
  1019.  followed by DE->string.
  1020. abspec:
  1021.     push    d
  1022.     lxi    d,string
  1023.     strcopy @    name    'ANTOPE'
  1024. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  1025.  
  1026. ;===============================================================
  1027. ; ANTOPEn: Open all three anthology files with freset.    All must
  1028. ; have some data in them (even a new, empty anthology has one
  1029. ; data record and one record in each directory) -- so abort if
  1030. ; they don't.  (Note that the use of a device-name, e.g.
  1031. ; "antdir con:," will result in this error because we append
  1032. ; a filetype.  The filespec "con:.anx" is a (nonexistent) disk
  1033. ; file by toolkit rules.)
  1034.  
  1035.     maclib    environ
  1036.     entersub
  1037.  
  1038.     dseg
  1039. string: strspace 64 ; space for message
  1040. empty:
  1041.     strconst ' is empty or nonexistent.$'
  1042.     cseg
  1043.  
  1044.     public    ANTOPE
  1045. ANTOPE:
  1046.     push    psw
  1047.     push    b
  1048.     push    d
  1049.     push    h
  1050.  
  1051.     lxi    d,AntDat
  1052.     freset    @D
  1053.     jz    abempty
  1054.  
  1055.     lxi    d,AntDirX
  1056.     freset    @D
  1057.     jz    abempty
  1058.  
  1059.     lxi    d,AntDirY
  1060.     freset    @D
  1061.     jz    abempty
  1062.  
  1063.     pop    h
  1064.     pop    b
  1065.     pop    d
  1066.     pop    psw
  1067.     ret
  1068.  
  1069. abempty:
  1070.     lxi    h,string
  1071.     fgetspec @D,@H    ; filespec to string area
  1072.     xchg
  1073.     lxi    h,empty
  1074.     strappnd @D,@H
  1075.     abort    ,@D
  1076.  
  1077.     common    /ANTCOM/
  1078. ; This common area definition is included in all, or most
  1079. ; anthology programs.  It defines the directory in storage.
  1080. ; The filedefs are assembled in module ANTSUP.
  1081.  
  1082. AntHdr    equ    $    ; following words precede directory
  1083. SizeR    ds    2    ; size of array R
  1084. SpanR    ds    2    ; # of 128-byte records over R
  1085. SizeF    ds    2    ; size of array FS
  1086. SpanF    ds    2    ; # of 128-byte records over FS
  1087. AlFiles ds    2    ; count of allocated files
  1088. Frecs    ds    2    ; count of free records
  1089. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  1090. Base    ds    2    ; ->base of dir. (array R)
  1091. TopR    ds    2    ; ->low free byte
  1092. BotF    ds    2    ; ->bottom byte of FS
  1093. TopF    ds    2    ; ->byte after directory
  1094.  
  1095. SizeDir equ    16384    ; in-core size of directory
  1096. FSsize    equ    14    ; offset to size in FS entry
  1097. FSlen    equ    16    ; size of an FS entry
  1098.  
  1099. AntDat    ds    FcrLen    ; data file antname.ANT
  1100. AntDirX ds    FcrLen    ; directory copy antname.ANX
  1101. AntDirY ds    FcrLen    ; directory copy antname.ANY
  1102. AntSeq    ds    FcrLen    ; sequential file in/out
  1103.     cseg ; end of common
  1104. antname.ANX
  1105. A    name    'ANTLOA'
  1106. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  1107. ;===============================================================
  1108. ;    module    ANTLOA
  1109. ;
  1110. ; Load a directory from disk into storage.  Assumes that ANTPRE
  1111. ; has done its work of assigning filespecs and opening files.
  1112. ;
  1113. ; In contrast to ANTSAV, this module does only the most gross
  1114. ; validity checks.  That is so that, if a directory is only
  1115. ; slightly damaged, files can still be extracted from it.  Any
  1116. ; inconsistencies in the R and FS arrays will be trapped if
  1117. ; and when ANTSAV is called to update the directory.
  1118. ;
  1119. ; Since ANTSAV writes a directory in two distinct parts (which
  1120. ; may have overlapped in storage but are separate on disk) we
  1121. ; must read it back in two distinct parts.  However, we can
  1122. ; read it from low to high in two simple block-reads.
  1123. ;
  1124. ; messages
  1125. ;    abort "Integrity check #9" invalid SizeX or SpanX
  1126. ; history:
  1127. ; initial code 8/1/84
  1128. ;===============================================================
  1129.     maclib    environ
  1130.     entersub
  1131.  
  1132.     common    /ANTCOM/
  1133. ; This common area definition is included in all, or most
  1134. ; anthology programs.  It defines the directory in storage.
  1135. ; The filedefs are assembled in module ANTSUP.
  1136.  
  1137. AntHdr    equ    $    ; following words precede directory
  1138. SizeR    ds    2    ; size of array R (128-multiple)
  1139. SpanR    ds    2    ; # of 128-byte records over R
  1140. SizeF    ds    2    ; size of array FS (ditto)
  1141. SpanF    ds    2    ; # of 128-byte records over FS
  1142. AlFiles ds    2    ; count of allocated files
  1143. Frecs    ds    2    ; count of free records
  1144. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  1145. Base    ds    2    ; ->base of dir. (array R)
  1146. TopR    ds    2    ; ->low free byte
  1147. BotF    ds    2    ; ->bottom byte of FS
  1148. TopF    ds    2    ; ->byte after directory
  1149.  
  1150. SizeDir equ    16384    ; in-core size of directory
  1151. FSsize    equ    14    ; offset to size in FS entry
  1152. FSlen    equ    16    ; size of an FS entry
  1153.  
  1154. AntDat    ds    FcrLen    ; data file antname.ANT
  1155. AntDirX ds    FcrLen    ; directory copy antname.ANX
  1156. AntDirY ds    FcrLen    ; directory copy antname.ANY
  1157. AntSeq    ds    FcrLen    ; sequential file in/out
  1158.     cseg ; end of common
  1159.  
  1160.     dseg
  1161. msgIC9    db    'Integrity check #9.$'
  1162. screen: msgfile
  1163. load1    strconst 'Loading directory...'
  1164. load2    strconst 'done'
  1165.     cseg
  1166.  
  1167.     public    ANTLOA
  1168. ANTLOA:
  1169.     push    psw
  1170.     push    b
  1171.     push    d
  1172.     push    h
  1173.  
  1174.     fputstr screen,load1
  1175.  
  1176. ;    fgetblok(ANX,significant numbers)
  1177. ;    if (SizeR+SizeF > SizeDir) then abort(#9)
  1178.  
  1179.     lxi    d,AntDirX
  1180.     lxi    b,AntHdrLen
  1181.     lxi    h,AntHdr
  1182.     fgetblok @D,@H,@B
  1183.  
  1184.     lhld    SizeR
  1185.     xchg
  1186.     lhld    SizeF
  1187.     dad    d
  1188.     lxi    b,SizeDir
  1189.     ora    a
  1190.     dsbc    b
  1191.     jnc    IC9    ; must be a garbage file
  1192.  
  1193. ;    Base := DSalloc(SizeDir)
  1194. ;    TopR := Base+SizeR
  1195. ;    TopF := Base+SizeDir
  1196. ;    BotF := TopF-SizeF
  1197.  
  1198.     dslow    @B
  1199.     shld    Base
  1200.     xchg        ; save Base in DE
  1201.     lhld    SizeR
  1202.     dad    d    ; HL = Base+SizeR
  1203.     shld    TopR
  1204.     mov h,b ! mov l,c
  1205.     dad    d    ; HL = Base+SizeDir
  1206.     shld    TopF
  1207.     xchg
  1208.     lhld    SizeF
  1209.     xchg        ; HL=TopF, DE=SizeF
  1210.     ora    a
  1211.     dsbc    d    ; HL=TopF-SizeF
  1212.     shld    BotF
  1213.  
  1214. ;    seek(ANX,record #2)
  1215. ;    amount := SpanR*128
  1216. ;    start := Base
  1217. ;    getblock(ANX,start,amount)
  1218. ;    amount := SpanF*128
  1219. ;    start := TopF-SpanF*128
  1220. ;    getblock(ANX,start,amount)
  1221.  
  1222.     lxi    d,AntDirX
  1223.     lxi    h,2
  1224.     frecseek @D,@H
  1225.     lda    SpanR    ; both spans must be <256
  1226.     ora    a
  1227.     rar        ; 0 >> A >> carry
  1228.     mov    b,a
  1229.     mvi    a,0
  1230.     rar        ; carry >> A
  1231.     mov    c,a    ; BC = SpanR*128
  1232.     push    b    ; (save for integrity check)
  1233.     lhld    Base
  1234. ; n.b. fgetblok handles the case of length=0 ok
  1235.     fgetblok @D,@H,@B
  1236.     pop    h    ; HL=count we asked for
  1237.     ora    a    ; BC=count we got
  1238.     dsbc    b    ; they better be the same,
  1239.     jnz    IC9    ; ..or something is very wrong
  1240.  
  1241.     lda    spanF
  1242.     ora    a
  1243.     rar
  1244.     mov    b,a
  1245.     mvi    a,0
  1246.     rar
  1247.     mov    c,a    ; BC=count of bytes to get
  1248.     push    b    ; (save)
  1249.     ora    a
  1250.     lhld    TopF
  1251.     dsbc    b    ; HL->where it goes
  1252.     fgetblok @D,@H,@B
  1253.     pop    h    ; count we asked for
  1254.     ora    a
  1255.     dsbc    b    ; ..versus what we got
  1256.     jnz    IC9
  1257.  
  1258. ;    for j := 1 to MaxR do
  1259. ;        if (R[r] <> 0) then {should be filepointer}
  1260. ;        R[r] := TopF - R[r]
  1261. ;        endif
  1262. ;    end for
  1263.  
  1264. ; This loop's purpose is to convert file-pointers from relative
  1265. ; back to absolute addresses.  In it we could validity-check
  1266. ; the pointers.  But any corruption that makes a pointer
  1267. ; invalid must lead to integrity check #1 or #3 during ANTGET
  1268. ; or #2 during ANTERA or #4, #5, or #6 during the next ANTSAV,
  1269. ; so why gild the lily?
  1270.  
  1271.     lhld    Base
  1272. Ldloop:
  1273.     lbcd    TopR
  1274.     ora    a
  1275.     dsbc    b
  1276.     jnc    Lddone
  1277.     dad    b
  1278.  
  1279.     mov c,m ! inx h
  1280.     mov    b,m    ; BC=R[r], HL->2nd byte of it
  1281.     mov a,b ! ora c
  1282.     jrz    Ldstep    ; R[r]=0=free slot
  1283.  
  1284.     xchg
  1285.     lhld    TopF
  1286.     dsbc    b
  1287.     xchg        ; DE = TopF - R[r]
  1288.     mov m,d ! dcx h
  1289.     mov m,e ! inx h
  1290. Ldstep: inx    h
  1291.     jmp    Ldloop
  1292.  
  1293. Lddone:
  1294.     fputline screen,load2
  1295.     pop    h
  1296.     pop    d
  1297.     pop    b
  1298.     pop    psw
  1299.     ret
  1300.  
  1301. IC9:    abort    ,msgIC9
  1302.  
  1303.     end
  1304. : inx    h
  1305.     jmp    Ldloop
  1306.  
  1307. Lddone:
  1308.     fputline screen,load2
  1309.     pop    h
  1310.     pop    d
  1311.     pop    b
  1312.     pop    psw
  1313.     ret
  1314.  
  1315.     name    'ANTSAV'
  1316. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  1317. ;===============================================================
  1318. ;    module    ANTSAV
  1319. ;
  1320. ; Contains the logic needed to commit the anthology directory
  1321. ; to disk, including validation of its consistency and writing
  1322. ; it in such a way that a crash for disk-full will leave the
  1323. ; original directory unaltered.
  1324. ;
  1325. ; messages
  1326. ;    abort "Integrity check #4" record owned by non-file
  1327. ;    abort "Integrity check #5" Frecs <> free records
  1328. ;    abort "Integrity check #6" file size incorrect
  1329. ;    abort "Integrity check #7" AlFiles <> in-use files
  1330. ;    abort "Integrity check #8" error in size arithmetic
  1331. ;
  1332. ; History:
  1333. ; initial code 8/1/84
  1334. ;===============================================================
  1335.     maclib    environ
  1336.     entersub
  1337.  
  1338.     common    /ANTCOM/
  1339. ; This common area definition is included in all, or most
  1340. ; anthology programs.  It defines the directory in storage.
  1341. ; The filedefs are assembled in module ANTSUP.
  1342.  
  1343. AntHdr    equ    $    ; following words precede directory
  1344. SizeR    ds    2    ; size of array R (128-multiple)
  1345. SpanR    ds    2    ; # of 128-byte records over R
  1346. SizeF    ds    2    ; size of array FS (ditto)
  1347. SpanF    ds    2    ; # of 128-byte records over FS
  1348. AlFiles ds    2    ; count of allocated files
  1349. Frecs    ds    2    ; count of free records
  1350. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  1351. Base    ds    2    ; ->base of dir. (array R)
  1352. TopR    ds    2    ; ->low free byte
  1353. BotF    ds    2    ; ->bottom byte of FS
  1354. TopF    ds    2    ; ->byte after directory
  1355.  
  1356. SizeDir equ    16384    ; in-core size of directory
  1357. FSsize    equ    14    ; offset to size in FS entry
  1358. FSlen    equ    16    ; size of an FS entry
  1359.  
  1360. AntDat    ds    FcrLen    ; data file antname.ANT
  1361. AntDirX ds    FcrLen    ; directory copy antname.ANX
  1362. AntDirY ds    FcrLen    ; directory copy antname.ANY
  1363. AntSeq    ds    FcrLen    ; sequential file in/out
  1364.     cseg ; end of common
  1365.  
  1366.     dseg
  1367. msgIC4    db    'Integrity check #4.$'
  1368. msgIC5    db    'Integrity check #5.$'
  1369. msgIC6    db    'Integrity check #6.$'
  1370. msgIC7    db    'Integrity check #7.$'
  1371. msgIC8    db    'Integrity check #8.$'
  1372. screen: msgfile
  1373. save1    strconst 'Saving directory...'
  1374. save2    strconst 'done'
  1375.     cseg
  1376.  
  1377.     public    ANTSAV
  1378. ANTSAV:
  1379.     push    psw
  1380.     push    b
  1381.     push    d
  1382.     push    h
  1383.  
  1384.     fputstr screen,save1
  1385.     call    commit
  1386.     call    update
  1387.     fputline screen,save2
  1388.  
  1389.     pop    psw
  1390.     pop    b
  1391.     pop    d
  1392.     pop    h
  1393.     ret
  1394.  
  1395. ;===============================================================
  1396. ; Commit: sweep over the array R, doing these things:
  1397. ;
  1398. ;    1. convert conditional-free records (-1) to free (0)
  1399. ;       and add them to the Frecs count of free records.
  1400. ;
  1401. ;    2. count the free records and verify Frecs.
  1402. ;
  1403. ;    3. verify that un-free (nonzero) records contain valid
  1404. ;       file-pointers -- multiples of 16 and in the correct
  1405. ;       range -- which point to active files.
  1406. ;
  1407. ;    4. tally the records owned by each file in a temporary
  1408. ;       word in the file's FS entry.
  1409. ;
  1410. ;    5. convert record file-pointers to relative form.
  1411. ;
  1412. ; Then sweep over the array FS, doing these things:
  1413. ;
  1414. ;    1. count active (non-null) entries and verify AlFiles.
  1415. ;
  1416. ;    2. verify that each file's tally of records agrees with
  1417. ;       its size, and clean up the temporary count.
  1418. ;
  1419. ; Afterward the directory is known to be self-consistent and is
  1420. ; in condition to be written to disk.
  1421. ;
  1422. ; We need one word per file to tally the records that point to
  1423. ; each file.  The FS entry is laid out this way:
  1424. ;
  1425. ;    F I L E N A M E . T Y P 00 xx SS SS
  1426. ;
  1427. ; where SS SS is the size-word and xx is unused.  Since xx will
  1428. ; always be preceded by 00 ending the string, or by an unused
  1429. ; byte, we keep the tally in the "00 xx" bytes.  On the last
  1430. ; sweep we replace it with "00 00" to restore the terminal null
  1431. ; to any full-length string.
  1432.  
  1433. Commit:
  1434.  
  1435. ;    for j := 1 to MaxF do
  1436. ;       T[j] := 0
  1437. ;    end for
  1438.  
  1439.     lhld    TopF
  1440.     lxi    d,-4
  1441.     dad    d    ; HL->"T" field in top entry
  1442.     lxi    d,-17    ; DE = decrement value
  1443.     lbcd    BotF    ; BC = bottom limit for check
  1444.     xra    a    ; A = constant zero
  1445. C1loop:
  1446.     ora    a
  1447.     dsbc    b    ; while HL > BC
  1448.     jrc    C1loopz
  1449.     dad    b    ; (restore HL)
  1450.     mov    m,a
  1451.     inx    h
  1452.     mov    m,a    ;   T := 0000
  1453.     dad    d    ; HL->next lower entry's "T"
  1454.     jmp    C1loop
  1455. C1loopz:
  1456.  
  1457. ;    nfr := 0
  1458. ;    for j := 1 to MaxR do
  1459. ;        if        (R[j] = -1) then    {conditional free}
  1460. ;        R[j] := 0
  1461. ;        Frecs := Frecs+1
  1462. ;        nfr := nfr + 1
  1463. ;        else if (R[j] = 0) then    {actually free}
  1464. ;        nfr := nfr + 1
  1465. ;        else            {not free}
  1466. ;        f := R[j]
  1467. ;        if (f is valid) and (F[f] is active) then
  1468. ;            R[j] := TopF - f
  1469. ;            T[f] := T[f]+1
  1470. ;        else
  1471. ;            abort("Integrity Check #4")
  1472. ;        endif
  1473. ;        endif
  1474. ;    end for
  1475. ;    if (nfr <> Frecs) then abort("Integrity check #5")
  1476.  
  1477.     dseg
  1478. nfr    ds    2
  1479.     cseg
  1480.  
  1481.     lxi    h,0
  1482.     shld    nfr
  1483.     lhld    Base
  1484. C2loop:
  1485.     lbcd    TopR    ; while HL < TopR
  1486.     ora    a
  1487.     dsbc    b
  1488.     jnc    C2loopz
  1489.     dad    b
  1490.  
  1491.     mov    e,m
  1492.     inx    h
  1493.     mov    d,m    ; DE = R[j]
  1494.  
  1495.     mov a,d ! ora e
  1496.     jz    C2free    ; case of R[j]=0 is easy to spot
  1497.     inx    d    ; if DE+1 = 0, we have R[j]=-1
  1498.     mov a,d ! ora e
  1499.     dcx    d    ; assuming not, restore DE
  1500.     jnz    C2inuse
  1501.     dcx    h
  1502.     mov    m,a    ; (A now is 00)
  1503.     inx    h
  1504.     mov    m,a    ; now R[j] = 0
  1505.     lbcd    Frecs
  1506.     inx    b
  1507.     sbcd    Frecs    ; count the now-free slot
  1508. C2free: lbcd    nfr
  1509.     inx    b
  1510.     sbcd    nfr    ; count the free slot
  1511.     inx    h    ; HL->next slot
  1512.     jmp    C2loop    ; continue loop from here
  1513.  
  1514. C2inuse:
  1515.     push    d    ; save contents of R[j] = f
  1516.     push    h    ; save ->2nd byte of R[j]
  1517. ; that pointer f should be => BotF
  1518.     lhld    BotF
  1519.     dcx    h    ; f should be > HL = BotF-1
  1520.     ora    a
  1521.     dsbc    d    ; HL = (BotF-1) - f
  1522.     jnc    IC4
  1523. ; ..and less than TopF
  1524.     lhld    TopF
  1525.     ora    a
  1526.     dsbc    d    ; HL=TopF - f
  1527.     jc    IC4
  1528.     jz    IC4
  1529. ; ..and a multiple of 16
  1530.     mov    a,l
  1531.     ani    0fh
  1532.     jnz    IC4
  1533. ; R[j]=f is a valid pointer to an entry of FS and HL=TopF-f
  1534.     xchg        ; DE=TopF - f
  1535.     pop    h    ; HL->2nd byte of R[j]
  1536.     mov    m,d
  1537.     dcx    h
  1538.     mov    m,e    ; R[j] := TopF - f
  1539.     inx h ! inx h    ; HL->next slot
  1540.     xthl        ; HL->FS[f], ->next slot on stack
  1541.     mov    a,m    ; is F[f] active?
  1542.     ora    a    ; (not null string if so)
  1543.     jz    IC4
  1544.     lxi    d,FSsize-2
  1545.     dad    d    ; HL->T[f]
  1546.     inr    m    ; increment low byte
  1547.     jnz    C2pop    ; (no overflow to 2nd byte)
  1548.     inx    h
  1549.     inr    m    ; (propogate to 2nd byte)
  1550. C2pop:    pop    h    ; HL->next record slot
  1551.     jmp    C2loop
  1552.  
  1553. ; one of the checks on the value of R[j] failed.
  1554. IC4:    abort    ,msgIC4
  1555.  
  1556. C2loopz:
  1557.     lhld    nfr
  1558.     xchg
  1559.     lhld    Frecs
  1560.     ora    a
  1561.     dsbc    d
  1562.     abort    nz,msgIC5
  1563.  
  1564.     dseg
  1565. naf    equ    nfr    ; reuse the scratch word
  1566.     cseg
  1567.  
  1568. ;    naf := 0
  1569. ;    for j := 1 to MaxF do
  1570. ;        if (F[j] is not null) then
  1571. ;        naf := naf + 1
  1572. ;        if (T[j] <> S[j]) then
  1573. ;           abort("Integrity check #6")
  1574. ;        endif
  1575. ;    end for
  1576. ;    if (naf <> AlFiles) then abort("Integrity check #7")
  1577.  
  1578.     lxi    h,0
  1579.     shld    naf
  1580.     lhld    BotF    ; just for variety, go from low to hi
  1581. C3loop:
  1582.     lbcd    TopF
  1583.     ora    a    ; while BC > HL
  1584.     dsbc    b
  1585.     jnc    C3loopz
  1586.     dad    b
  1587.  
  1588.     mov    a,m    ; does HL->non-null string?
  1589.     ora    a
  1590.     jnz    C3inuse ; (yes)
  1591.     lxi    d,FSlen
  1592.     dad    d    ; no, advance to next
  1593.     jmp    C3loop    ; ..and iterate
  1594. C3inuse:
  1595.     lded    naf
  1596.     inx    d
  1597.     sded    naf    ; count active file
  1598.     lxi    d,FSsize-2
  1599.     dad    d    ; HL->T[j]
  1600.     xra    a
  1601.     mov    e,m
  1602.     mov    m,a    ; pick it up and zero it
  1603.     inx    h
  1604.     mov    d,m
  1605.     mov    m,a
  1606.     inx    h    ; HL->S[j], DE=T[j]
  1607.     mov    c,m
  1608.     inx    h
  1609.     mov    b,m    ; BC = S[j]
  1610.     inx    h    ; ..and HL->next entry
  1611.     xchg
  1612.     dsbc    b    ; compare S[j] :: T[j]
  1613.     xchg
  1614.     jz    C3loop
  1615.     abort    ,msgIC6
  1616. C3loopz:
  1617.     lhld    naf
  1618.     xchg
  1619.     lhld    AlFiles
  1620.     ora    a
  1621.     dsbc    d
  1622.     rz
  1623.     abort    ,msgIC7
  1624.  
  1625. ;===============================================================
  1626. ; update: the directory has been modified in storage, and Commit
  1627. ; has validated it and made file-addresses relocatable.  Now we
  1628. ; write it to disk updating the files .ANX and .ANY.  We write
  1629. ; from last record to first so that, if CP/M aborts us for a
  1630. ; full disk, it will do so before we change the existing files.
  1631.  
  1632.     dseg
  1633. recno    ds    2
  1634.     cseg
  1635.  
  1636. update:
  1637.  
  1638. ;    SizeR := TopR-Base
  1639. ;    if (SizeR < 0) then abort("Integrity check #8")
  1640. ;    SpanR := (SizeR+127)/128
  1641. ;
  1642. ;    SizeF := TopF-BotF
  1643. ;    if (SizeF < 0) then abort("Integrity check #8")
  1644. ;    SpanF := (SizeF+127)/128
  1645. ;    { number of records in directory is also recno of
  1646. ;      the last record, which will be the first written}
  1647. ;    recno := SpanR + SpanF + 1
  1648.  
  1649.     lhld    Base
  1650.     xchg
  1651.     lhld    TopR
  1652.     ora    a
  1653.     dsbc    d    ; HL = TopR-Base
  1654.     jm    IC8    ; (oops)
  1655.     shld    SizeR
  1656.     lxi    b,127
  1657.     dad    b    ; HL = SizeR+127
  1658.     dad    h    ; ..shifted left once
  1659.     mov    l,h
  1660.     mvi    h,0    ; ..shifted right 8 times
  1661.     shld    SpanR
  1662.  
  1663.     lhld    BotF
  1664.     xchg
  1665.     lhld    TopF
  1666.     ora    a
  1667.     dsbc    d    ; HL = TopF-BotF
  1668.     jm    IC8    ; (oops)
  1669.     shld    SizeF
  1670.     dad    b    ; ...+127
  1671.     dad    h    ; ..shift left
  1672.     mov    l,h
  1673.     mvi    h,0    ; ..and right by 8
  1674.     shld    SpanF
  1675.     xchg
  1676.     lhld    SpanR
  1677.     dad    d    ; HL = SpanF+SpanR
  1678.     inx    h    ; ..+1
  1679.     shld    recno    ; record number to write first/next
  1680.  
  1681. ;    j := SpanF
  1682. ;    ptr := TopF
  1683. ;    while ( j > 0 ) do
  1684. ;        ptr := ptr-128
  1685. ;        seek(ANX,recno)
  1686. ;        putblock(ANX,ptr,128)
  1687. ;        seek(ANY,recno)
  1688. ;        putblock(ANY,ptr,128)
  1689. ;        recno := recno-1
  1690. ;        j := j-1
  1691. ;    end while
  1692.  
  1693.     lda    SpanF    ; has to be less than 256
  1694.     mov    b,a    ; ..so    carry loop count in B
  1695.     lhld    TopF    ; set HL=byte above 1st record
  1696.     ora    a    ; any records in this segment?
  1697.     cnz    WRloop    ; ..if so, write B records from HL down
  1698.  
  1699. ;    j := SpanR
  1700. ;    ptr := Base+(SpanR*128)
  1701. ;    while ( j > 0 ) do
  1702. ;       {same loop as above}
  1703. ;    end while
  1704.  
  1705.     lda    SpanR
  1706.     mov    b,a
  1707.     ora    a    ; clear carry
  1708.     rar        ; 0 >> A >> carry
  1709.     mov    d,a    ; high 7 bits to D
  1710.     mvi    a,0
  1711.     rar        ; carry >> A
  1712.     mov    e,a    ; DE = SpanR * 128
  1713.     lhld    Base
  1714.     dad    d    ; HL = Base+(SpanR*128)
  1715.     mov    a,b    ; now, are there any records?
  1716.     ora    a
  1717.     cnz    WRloop    ; ..if so, write them
  1718.  
  1719. ;    frewind(ANX)
  1720. ;    putblock(ANX,significant numbers)
  1721. ;    fclose(ANX)
  1722. ;    frewind(ANY)
  1723. ;    putblock(ANY,significant numbers)
  1724. ;    fclose(ANY)
  1725. ;    fclose(ANT)
  1726.  
  1727.     lxi    h,AntHdr
  1728.     lxi    b,AntHdrLen
  1729.     lxi    d,AntDirX
  1730.     frewind @D
  1731.     fputblok @D,@H,@B
  1732.     fclose    @D
  1733.     lxi    d,AntDirY
  1734.     frewind @D
  1735.     fputblok @D,@H,@B
  1736.     fclose    @D
  1737.     lxi    d,AntDat
  1738.     fclose    @D
  1739.     ret
  1740.  
  1741. ; somehow, TopR is less than Base or TopF is less than BotF
  1742. IC8:    abort    ,msgIC8
  1743.  
  1744. ; the identical bodies of the above two loops, factored out
  1745.  
  1746. WRloop:
  1747.     lxi    d,-128
  1748.     dad    d    ; HL->next lower record to write
  1749.     lxi    d,AntDirX
  1750.     push    h    ; (save ptr)
  1751.     lhld    recno
  1752.     frecseek @D,@H
  1753.     pop    h
  1754.     fputblok @D,@H,128
  1755.     lxi    d,AntDirY
  1756.     push    h
  1757.     lhld    recno
  1758.     dcx    h    ; (insert recno := recno-1)
  1759.     shld    recno
  1760.     inx    h
  1761.     frecseek @D,@H
  1762.     pop    h
  1763.     fputblok @D,@H,128
  1764.     djnz    WRloop
  1765.     ret
  1766.  
  1767.     end
  1768.     name    'ANTMRK'
  1769. ; Copyright (C) 1985 M&T Publishing Co. all rights reserved
  1770. ;===============================================================
  1771. ;
  1772. ;    module    ANTMRK
  1773. ;
  1774. ; This module provides essential services to ANTGET, ANTDIR,
  1775. ; and ANTERA.  The ANTMRK routine takes an operand token,
  1776. ; assigns it to AntSeq, and marks every file in the directory
  1777. ; that matches that (possibly ambiguous) filespec.
  1778. ;
  1779. ; The ANTNMK (nextmark) returns the next marked directory entry
  1780. ; following the one it is passed.
  1781. ;
  1782. ; messages (aborts)
  1783. ;    FRUMMAGE is not a valid filespec
  1784. ;    Integrity check #10 (improper use of ANTNMK)
  1785. ;
  1786. ; History
  1787. ; initial code 8/4/84
  1788. ;===============================================================
  1789.     maclib    environ
  1790.  
  1791.     common    /ANTCOM/
  1792. ; This common area definition is included in all, or most
  1793. ; anthology programs.  It defines the directory in storage.
  1794. ; The filedefs are assembled in module ANTSUP.
  1795.  
  1796. AntHdr    equ    $    ; following words precede directory
  1797. SizeR    ds    2    ; size of array R (128-multiple)
  1798. SpanR    ds    2    ; # of 128-byte records over R
  1799. SizeF    ds    2    ; size of array FS (ditto)
  1800. SpanF    ds    2    ; # of 128-byte records over FS
  1801. AlFiles ds    2    ; count of allocated files
  1802. Frecs    ds    2    ; count of free records
  1803. AntHdrLen equ    $-AntHdr ; bytes written at head of file
  1804. Base    ds    2    ; ->base of dir. (array R)
  1805. TopR    ds    2    ; ->low free byte
  1806. BotF    ds    2    ; ->bottom byte of FS
  1807. TopF    ds    2    ; ->byte after directory
  1808.  
  1809. SizeDir equ    16384    ; in-core size of directory
  1810. FSsize    equ    14    ; offset to size in FS entry
  1811. FSlen    equ    16    ; size of an FS entry
  1812.  
  1813. AntDat    ds    FcrLen    ; data file antname.ANT
  1814. AntDirX ds    FcrLen    ; directory copy antname.ANX
  1815. AntDirY ds    FcrLen    ; directory copy antname.ANY
  1816. AntSeq    ds    FcrLen    ; sequential file in/out
  1817.     cseg ; end of common
  1818.  
  1819.     dseg
  1820. ngspec: db ' is not a valid filespec.$'
  1821. IC10:    db 'Integrity check #10.$'
  1822. msg    strspace 50
  1823.     cseg
  1824.  
  1825.     entersub
  1826.  
  1827. ;===============================================================
  1828. ; mark(DE->operand) returns HL=count
  1829. ;
  1830. ; Assign the operand to AntSeq; then extract its filename.typ
  1831. ; string.  Compare to every directory entry and mark the ones
  1832. ; that match.  The mark is to set the high bit in the first byte
  1833. ; of the filename (cleared in ANTNMK).
  1834.  
  1835.     public    ANTMRK
  1836. ANTMRK:
  1837.     push    psw
  1838.     push    b
  1839.     push    d
  1840.  
  1841.     xchg
  1842.     lxi    d,AntSeq
  1843.     fassign @D,@H
  1844.     jnz    okspec
  1845.     lxi    d,msg
  1846.     strcopy @D,@Hupdate
  1847.     lxi    h,ngspec
  1848.     strappnd @D,@Hupdate
  1849.     abort    ,@D
  1850.  
  1851. okspec:
  1852.     lxi    h,msg    ; string-space for filename.typ
  1853.     fgetspec @D,@H,0110b ; name, type not drive or pass
  1854.     lhld    TopF    ; work our way down from old to new
  1855.     lxi    b,0    ; BC counts matches
  1856.  
  1857. AMloop:
  1858.     lxi    d,-FSlen
  1859.     dad    d    ; HL->next file down
  1860.     lded    BotF
  1861.     ora    a
  1862.     dsbc    d    ; or is it off the end?
  1863.     jc    AMloopz ; (yes, done)
  1864.     dad    d    ; no, restore HL
  1865.     lxi    d,msg    ; DE->comparand
  1866.     call    compare
  1867.     jnz    AMloop
  1868.     mov    a,m
  1869.     ori    80h    ; mark the file
  1870.     mov    m,a
  1871.     inx    b    ; count match
  1872.     jmp    AMloop
  1873. AMloopz:
  1874.     mov h,b ! mov l,c
  1875.     pop    d
  1876.     pop    b
  1877.     pop    psw
  1878.     ret
  1879.  
  1880. ; Compare DE->"XYZ???.???" versus HL->filename string in F.
  1881. ; The rule is, "?" matches anything except dot and null.  When
  1882. ; we find a "?" versus a dot or null, we skip over the ?s
  1883. ; to a non-?.
  1884.  
  1885. Compare:
  1886.     push    d
  1887.     push    h
  1888.  
  1889.     mov a,m ! ora a ; a null directory entry matches nothing
  1890.     jnz    Comp2    ; (HL->live entry)
  1891.     inr    a    ; ..and this is null, set Z false
  1892.     jmp    Compdone
  1893.  
  1894. Comp2:    ldax d ! ora a    ; a null comparand matches everything
  1895.     jz    Compdone
  1896.  
  1897. Comploop:
  1898.     ldax    d    ; compare current bytes
  1899.     cmp    m
  1900.     jnz    CompNE    ; not equal, check for "?"
  1901.  
  1902. ; current bytes equal, are we at end of both strings?
  1903.     ora    a
  1904.     jz    Compdone ; yes, end with a match
  1905.  
  1906. ; current bytes are considered equal but are not at the end.
  1907. ; step to next bytes and try again.
  1908. CompStep:
  1909.     inx    d
  1910.     inx    h
  1911.     jmp    Comploop
  1912.  
  1913. ; current bytes are not equal.    If the comparand byte isn't
  1914. ; a "?" we have a definite mismatch.
  1915. CompNE:
  1916.     cpi    '?'
  1917.     jnz    Compdone
  1918.  
  1919. ; The comparand is "?" -- if the compared byte is neither a dot
  1920. ; nor the null at the end, consider them equal.
  1921.     mov    a,m
  1922.     ora    a
  1923.     jz    Compdelim
  1924.     cpi    '.'
  1925.     jnz    CompStep
  1926.  
  1927. ; We have "?..." versus a delimiter.  Step over the ?s to a
  1928. ; non-? and go back to compare it to the delimiter.
  1929. Compdelim:
  1930.     inx    d
  1931.     ldax    d
  1932.     cpi    '?'
  1933.     jrz    Compdelim
  1934.     jmp    Comploop
  1935.  
  1936. ; The comparison is over and the Z flag reflects the result.
  1937. Compdone:
  1938.     pop    h
  1939.     pop    d
  1940.     ret
  1941.  
  1942. ;===============================================================
  1943. ; nextmark(HL->F[f]) returns HL->F[f].    Scan down the directory
  1944. ; for the next marked entry, clear its mark, and return its
  1945. ; address.  We should not be called when there is no next mark.
  1946.  
  1947.     public    ANTNMK
  1948. ANTNMK:
  1949.  
  1950.     push    psw
  1951.     push    d
  1952.  
  1953. NMloop:
  1954.     lxi    d,-FSlen
  1955.     dad    d    ; HL->next file back
  1956.     lded    BotF
  1957.     ora    a
  1958.     dsbc    d    ; is there one?
  1959.     abort    c,IC10    ; (there better be)
  1960.     dad    d    ; yes, restore HL
  1961.     mov a,m ! ora a ; is this one marked?
  1962.     jp    NMloop    ; (no)
  1963.     ani    7Fh    ; yes, clear the mark
  1964.     mov    m,a
  1965.  
  1966.     pop    d
  1967.     pop    psw
  1968.     ret
  1969.  
  1970.     end
  1971.  ! ora a ; is this one marked?
  1972.     jp    NMloop    ; (no)
  1973.