💾 Archived View for spam.works › mirrors › textfiles › apple › DOCUMENTATION › aplwrks.util.2 captured on 2023-06-16 at 21:14:18.

View Raw

More Information

-=-=-=-=-=-=-




     APPLEWORKS UTILITY TECH NOTE    CECIL FRETWELL     6-MAY-87    PAGE 1


                             AN APPLEWORKS UTILITY
                                       by
                                 Cecil Fretwell
                               2605 Highview Ave.
                              Waterloo, Iowa 50702
                                 (319) 236-0961

                                    6-May-87


                              --------------------
                              TECHNICAL DISCUSSION
                              --------------------

     Several technical aspects can be learned by studying the logic of this
     program.  Lines 240 to 300 install a special ampersand function  which
     allows one to delete an array  after it has been dimensioned and  used
     to the extent of its  useful life.  As  the discussion to follow  will
     show, the entries in  a subdirectory are  collected in an  appropriate
     array, sorted, and then  displayed or printed.   By deleting an  array
     after it has been used,  valuable variable storage and its  associated
     strings are  recovered.   Also,  using this  technique allows  one  to
     redimension an array in a program.   The power of this technique  will
     become more evident as this discussion progresses.

     The logic of  the ampersand  function is  reasonably simple.   In  the
     listing given below, Lines  37 to 42 insure  no syntax errors,  verify
     the specified array exists,  and sets up pointers  to the array  name.
     Lines 43 to 65 set up the  process to remove the specified array  from
     the array variable table.   Once these are  set up, the routine  exits
     through the  monitor routine  MOVE at  $FE2C with  the end  result  of
     having the array removed.

                     1    ***********************************
                     2    * AMPERSAND FUNCTION TO DELETE AN *
                     3    * ARRAY VARIABLE.  MODIFIED CODE  *
                     4    * OBTAINED FROM CALL A.P.P.L.E.   *
                     5    * ALL ABOUT APPLESOFT.            *
                     6    * SYNTAX IS                       *
                     7    *        & FRE XX$                *
                     8    ***********************************
                     9
                     10   *****************************
                     11   * PREPARED USING MERLIN PRO *
                     12   *****************************
                     13
                     14            ORG   $2F0
                     15
                     16   A1L      =     $3C        ;BOTTOM OF MOVE POINTER
                     17   A2L      =     $3E        ;TOP OF MOVE POINTER
                     18   A4L      =     $42        ;DESTINATION POINTER
                     19   STREND   =     $6D        ;END OF VAR POINTER
                     20   LOWTR    =     $9B        ;ARRAY ADDRESS POINTER
                     21   CHRGET   =     $B1        ;GET NEXT TOKEN



     APPLEWORKS UTILITY TECH NOTE    CECIL FRETWELL     6-MAY-87    PAGE 2


                     22   CHRGOT   =     $B7        ;GET CURRENT TOKEN
                     23   AMPERV   =     $3F5       ;AMPERSAND VECTOR
                     24   SYNERR   =     $DEC9      ;REPORT SYNTAX ERROR
                     25   GETARYPT =     $F7D9      ;GET ARRAY POINTER
                     26   MOVE     =     $FE2C      ;MOVE SUBROUTINE
                     27
     02F0: A2 02     28   INIT     LDX   #2         ;SET UP '&' VECTOR
     02F2: BD FD 02  29   :1       LDA   AMPJ,X
     02F5: 9D F5 03  30            STA   AMPERV,X
     02F8: CA        31            DEX
     02F9: 10 F7     32            BPL   :1
     02FB: 18        33            CLC
     02FC: 60        34            RTS
     02FD: 4C 00 03  35   AMPJ     JMP   FUNCS      ;'&' JMP INSTRUCTION
                     36
     0300: 20 B7 00  37   FUNCS    JSR   CHRGOT     ;GET CURRENT TOKEN
     0303: C9 D6     38            CMP   #$D6       ;FRE?
     0305: F0 03     39            BEQ   :1         ;IF YES, BRANCH
     0307: 4C C9 DE  40            JMP   SYNERR     ;ELSE SYNTAX ERROR
     030A: 20 B1 00  41   :1       JSR   CHRGET     ;GET NEXT TOKEN
     030D: 20 D9 F7  42            JSR   GETARYPT   ;FIND THE ARRAY
     0310: A0 02     43            LDY   #2         ;SET UP BOTTOM OF MOVE,
     0312: 18        44            CLC              ;TOP OF MOVE, AND THE
     0313: A5 9B     45            LDA   LOWTR      ;DEST ADDRESS FOR
     0315: 85 42     46            STA   A4L        ;USE BY MONITOR MOVE
     0317: 71 9B     47            ADC   (LOWTR),Y  ;ROUTINE
     0319: 85 3C     48            STA   A1L
     031B: A5 9C     49            LDA   LOWTR+1
     031D: 85 43     50            STA   A4L+1
     031F: C8        51            INY
     0320: 71 9B     52            ADC   (LOWTR),Y
     0322: 85 3D     53            STA   A1L+1
     0324: 38        54            SEC
     0325: A5 6D     55            LDA   STREND     ;ALSO CORRECT THE END
     0327: 85 3E     56            STA   A2L        ;OF VARIABLES POINTER
     0329: 88        57            DEY
     032A: F1 9B     58            SBC   (LOWTR),Y
     032C: 85 6D     59            STA   STREND
     032E: A5 6E     60            LDA   STREND+1
     0330: 85 3F     61            STA   A2L+1
     0332: C8        62            INY
     0333: F1 9B     63            SBC   (LOWTR),Y
     0335: 85 6E     64            STA   STREND+1
     0337: A0 00     65            LDY   #0
     0339: 4C 2C FE  66            JMP   MOVE       ;GO MOVE AND RETURN

     Lines 310 to 580 represent the code to provide the main menu  control.
     Once a function is performed, control always returns to Line 360.

     Lines 590 to 4120 provide  the logic to display  a catalog or print  a
     catalog.  Using a simple  flag in PF$, the same  code can be used  for
     both functions.  The  logic starts with the  necessary code to  prompt
     for a volume or subdirectory name and initialize the display or  print
     process.  This is performed in Lines 590 to 810.



     APPLEWORKS UTILITY TECH NOTE    CECIL FRETWELL     6-MAY-87    PAGE 3



     The logic in Lines 840 and 850 causes the DIM statement in Line 860 to
     reserve exactly  enough  space  for  the entries  in  the  first  root
     directory or sub  directory.   Line 840 uses  HIMEM to  locate the  1K
     buffer established for the OPENed directory file.  Based on  technical
     knowledge of file handling techniques used by BASIC.SYSTEM, the  logic
     of Line 850 then picks up the number of entries as stored in the first
     block describing the entires in the directory.

     The actual display or print of the desired catalog starts in Line 820.
     Notice the OPEN with the TDIR parameter in Line 820.  Under ProDOS,  a
     directory file may  be opened and  read just like  a sequential  file.
     What is returned by each INPUT statement is the same as that displayed
     by a  CATALOG command  with things  like file  name, file  type,  etc.
     returned in a fixed  format.  With  this in mind,  Line 870 reads  the
     volume or subdirectory name, ignores the following blank line, and the
     CATALOG header line.

     Lines 880 to 940 input and  collect each line in the CATALOG  display.
     This logic  uses the  BLOCKS FREE...  line as  an end  of file  marker
     instead of using ONERR processing to trap a true end of file.

     After a  line for  a  file is  read, the  input  is processed  by  the
     subroutine in Lines 1540  to 1780.  This  subroutine returns a  string
     whose contents are as follows:

          Position    Contents
          --------    --------
              1       File status.  "*" = locked.  " " = unlocked
            2-16      File name
           17-31      File type, e.g., SYSTEM PROGRAM
           32-41      Modification date dd-mmm-yy
           42-49      Right justified file length in terms of K
           50-...     Left justified file length in terms of K

     This string is then added to the array for the volume or  subdirectory
     entries.

     Lines 990  to 1100  sort the  array in  ascending order  by file  name
     and/or directory  name.   This  code is  a  modification of  the  code
     presented by Garry G. Kiziak in "The Compact Sorter", NIBBLE  Vol4/No.
     1.  It is a very fast  sort routine worthy repeating here in its  more
     general form.

          10 Z = 1
          20 Z = 3 * Z + 1 : IF Z < NUM THEN 20
          30 Z = (Z - 1)/3 : IF Z < 1 THEN RETURN
          40 FOR I = Z + L TO H : J = I - Z
          50 K = J + Z : IF A = (MID$(NA$(J),M,N)>
             MID$(NA$(K),M,N)) THEN TEMP$ = NA$(J):
             NA$(J) = NA$(K) : NA$(K) = TEMP$ :
             J = J - Z : IF J >= L THEN 50
          60 NEXT I : GOTO 30

     In this subroutine,



     APPLEWORKS UTILITY TECH NOTE    CECIL FRETWELL     6-MAY-87    PAGE 4


          NA$ = the array to be sorted.
            L = the starting subscript for the sort.
            H = the ending subscript for the sort.
            M = the column at which the sort begins.
            N = the number of columns to be sorted.
            A = the value 1 if an ascending sort is
                required, or the value 0 if a descending
                sort is required.

     To quote  Garry, "this  routine is  supposed to  be a  modified  SHELL
     METZNER sort.  It might be called  the SHELL SHUTTLE sort since it  is
     also a modified version of the SHUTTLE INTERCHANGE sort".  Based on my
     extensive use  of the  algorithm, I  have found  it to  be very  fast.
     Garry also presents a machine language form which really makes a  sort
     in BASIC fly.

     With the array sorted, Lines 1840 to 1950 display the contents of  the
     array.  Each line of the display starts at the left margin.  When  the
     array is completely displayed,  Lines 1960 to  2170 display the  final
     line showing space free,  space used, and total  space on the  volume.
     Control is then passed  back to the main  menu logic starting at  Line
     360.

     Going back to the display of the  array process, if Line 1940 finds  a
     directory entry in the  array, control passes to  Lines 2230 to  2680.
     Basically, this logic  reads the entries  for the subdirectory,  sorts
     them, and displays them.

     First note Lines 2230 and 2240.  The program could have been  designed
     to dimension  the subdirectory  arrays once  at the  beginning of  the
     program.  This has a couple of problems.  First, there is the  problem
     of how big to make the arrays.   Subdirectories are not limited to  51
     entries, therefore, too small a dimension might make the program  bomb
     with a subscript out of range error.  Too large a dimension might make
     the program  bomb with  an out  of  memory error.   To  minimize  this
     problem, Line 2230 results  in a D1 which  is the number of  directory
     blocks in  the subdirectory.   Each  block can  hold a  maximum of  13
     entries, therefore, Line 2240 dimensions  an array with a proper  size
     to accommodate the subdirectory entries.

     The second problem involves garbage  collection.  Even though I  force
     garbage collection at appropriate points in the logic, after an  array
     is used, its strings still exist in string storage.  When the array is
     used again, new strings  are built and,  based on experience,  without
     deleting the  array after  it has  been used,  the garbage  collection
     logic is invoked more often.

     To minimize  problems  with potential  out  of memory  conditions  and
     garbage collection, the array is deleted after it has been used.

     With this in mind, let's continue with the discussion of processing  a
     subdirectory under the root  of the volume.   Lines 2290 to 2380  read
     the subdirectory  entries  into  an  array  in  a  manner  exactly  as
     described for the root entries.  In Line 2410, if there are no entries



     APPLEWORKS UTILITY TECH NOTE    CECIL FRETWELL     6-MAY-87    PAGE 5


     in the subdirectory, control is passed  to Line 2660 in which the  D1$
     array is  deleted then  control is  passed to  Line 1950  to  continue
     processing of the root entries.

     If the subdirectory is  not empty, Lines 2420  to 2540 sort the  array
     using the  sort  algorithm described  earlier.   Lines  2550  to  2650
     display the entries in the  subdirectory with each line indented  over
     three spaces.   The final result  of the display  or print provides  a
     layout in which subdirectories can be quickly located.

     Once the subdirectory has been completely processed, Line 2660 deletes
     the array, garbage collection is forced, and control is passed to Line
     1950 to continue processing of the root entries.

     A subdirectory under  the root  can also contain  subdirectories.   If
     Line 2640 detects a  subdirectory, control is passed  to the logic  in
     Lines 2780 to 3220.  This logic is an exact duplicate of the logic  in
     Lines 2230 to 2680 with D1 replaced  by D2, R$ replaced with D1$,  and
     L1 replaced by L2.   Each displayed or  printed line is indented  over
     five  spaces  from  the  left  margin.    When  this  subdirectory  is
     completely processed, Line 3200 deletes the array, garbage  collection
     is forced, and control is passed  to Line 2650 to continue  processing
     in the first level subdirectory.

     A subdirectory under a  subdirectory can also contain  subdirectories.
     If Line 3180 detects a subdirectory, control is passed to the logic in
     Lines 3320 to 3750.   Again, logic is  duplicated with D2 replaced  by
     D3,  D1$ replaced by D2$, and L2 replaced by L3.

     The logic described here assumes  only three levels of  subdirectories
     under the  root.   Modifying the  logic to  include another  level  is
     relatively easy.   Add a Line  3715 to look  for a subdirectory  entry
     using say Line 3180 as a model.  Duplicate Lines 3320 to 3750 starting
     after the end of the program at Line 4870.  Now change each D2 to  D3,
     each D3 to D4, each D3$  to D4$, and each L3 to  L4.  Add a couple  of
     spaces to the copied Line 3640 and delete a couple of periods from the
     copied Line 3690.   Finally replace the GOTO  3190 in the copied  Line
     3750 to GOTO 3720.

     Lines 4180 to 4370 handle the LOCK  A FILE logic.  Lines 4430 to  4620
     handle the UNLOCK A FILE logic.   Lines 4680 to 4870 handle the  START
     UP APPLEWORKS logic.  The logic of these three functions is reasonably
     straightforward and require no technical discussion.

     This program should  be a  very useful addition  to any  library -  it
     certainly has  been  to mine.    It has  been  tested by  several  non
     technical types like  my wife  who rarely  work outside  the world  of
     Appleworks.