home *** CD-ROM | disk | FTP | other *** search
/ norge.freeshell.org (192.94.73.8) / 192.94.73.8.tar / 192.94.73.8 / pub / computers / cpm / alphatronic / DRIPAK.ZIP / CPM_3-0 / SOURCES / INITDIR.PLI < prev    next >
Text File  |  1982-12-31  |  41KB  |  1,163 lines

  1. initdir: procedure options(main);
  2.  
  3. declare
  4.     cpm3                char(2) static initial('30');
  5.  
  6. /* fixed bug in clearout, buildnew, and reconstruction 11/12/82 */
  7.  
  8. /*
  9.             copyright(c) 1982
  10.             digital research
  11.             box 579
  12.             pacific grove, ca
  13.             93950
  14.   */
  15.  
  16. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  17.  
  18.  
  19.                   * * *  DISK INTERFACE * * *
  20.  
  21.  
  22.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  23.  
  24.         %include 'diomod.dcl';
  25.  
  26.         %include 'plibios.dcl';
  27.  
  28.         %replace
  29.            TRUE           by '1'b,
  30.            FALSE          by '0'b;
  31.  
  32.                                         /* directory array 4K */
  33.         declare
  34.                 1 dir_fcb(0:127),
  35.                  3 user          bit(8),
  36.                  3 rest(31)      char(1),
  37.  
  38.                 1 outbuf(0:127),
  39.                  2 user         fixed(7),
  40.                  2 rest(31)     char(1),
  41.  
  42.                 1 buffer2(0:127),
  43.                  2 user         bit(8),
  44.                  2 rest(31)     bit(8),
  45.  
  46.                 1 outb(0:127)   based(outptr),
  47.                  2 rest         char(32),
  48.  
  49.                 1 outb2(0:127)  based(outptr),
  50.                  2 user         bit(8),
  51.                  2 rest(31)     char(1),
  52.  
  53.                 1 outb3(0:127)  based(outptr),
  54.                  2 user         fixed(7),
  55.                  2 rest(31)     bit(8),
  56.  
  57.                 1 outb4(0:127)  based(outptr),
  58.                  2 sfcbm        char(1),
  59.                  2 sfcb(3),
  60.                   3 stamps      char(8),
  61.                   3 mode        bit(8),
  62.                   3 rest        char(1),
  63.                  2 frest        char(1),
  64.  
  65.                 1 infcb(0:127)  based(dirptr),
  66.                  2 rest         char(32),
  67.  
  68.                 1 infcb2(0:127) based(dirptr),
  69.                  2 user         char(1),
  70.                  2 name         char(11),
  71.                  2 pmode        bit(8),
  72.                  2 junk1        char(11),
  73.                  2 stamp        char(8),
  74.  
  75.                1 clearbuf(0:127) based(clearptr),
  76.                  2 rest         char(32),
  77.  
  78.                 zeroes(31)      bit(8) static init((31)'00000000'b);
  79.  
  80.                                         /* directory array mask */
  81.         declare
  82.            1 dirm(0:127)      based(dirptr),
  83.              3 user          fixed(7),
  84.              3 fname         char(8),
  85.              3 ftype         char(3),
  86.              3 fext          bin fixed(7),
  87.              3 fs1           bit(8),
  88.              3 fs2           bit(8),
  89.              3 frc           fixed(7),
  90.              3 diskpass(8)   char(1),
  91.              3 rest          char(8);
  92.  
  93.         declare                         /* disk parameter header mask */
  94.                 dphp            ptr,
  95.                 1 dph_mask      based(dphp),
  96.                  2 xlt1         ptr,
  97.                  2 space(9)     bit(8),
  98.                  2 mediaf       bit(8),
  99.                  2 dpbptr       ptr,
  100.                  2 csvptr       ptr,
  101.                  2 alvptr       ptr,
  102.                  2 dirbcb       ptr,
  103.                  2 dtabcb       ptr,
  104.                  2 hash         ptr,
  105.                  2 hbank        ptr,
  106.  
  107.         xlt             ptr;    /* save the xlt ptr because of F10 buffer */
  108.  
  109.         declare                 /* disk parameter block mask */
  110.            dpbp        ptr ext,
  111.            1 dpb_mask  based(dpbp),
  112.              2 spt     fixed(15),
  113.              2 blkshft fixed(7),
  114.              2 blkmsk  fixed(7),
  115.              2 extmsk  fixed(7),
  116.              2 dsksiz  fixed(15),
  117.              2 dirmax  fixed(15),
  118.              2 diralv  bit(16),
  119.              2 checked fixed(15),
  120.              2 offset  fixed(15),
  121.              2 physhf  fixed(7),
  122.              2 phymsk  fixed(7),
  123.  
  124.                 dspt    decimal(7,0),
  125.                 dblk    decimal(7,0);
  126.  
  127.         declare
  128.            dir_blks(32)   bit(8),
  129.            errorcode      bit(16);
  130.  
  131.         declare
  132.                 MAXSAVE         bin fixed(15),
  133.                 enddcnt         bin fixed(15),
  134.                 nxfcb           bin fixed(15),
  135.                 notsaved        bin fixed(15),
  136.                 xptr            pointer,
  137.  
  138.                 1 XFCBs(1)      based(xptr),
  139.                  2 user         bin fixed(7),
  140.                  2 name         char(11),
  141.                  2 pmode        bit(8),
  142.                  2 stamp        char(8);
  143.  
  144.  
  145. declare
  146.                 INITMSG         char(54) static initial
  147.                    ('INITDIR WILL ACTIVATE TIME STAMPS FOR SPECIFIED DRIVE.'),
  148.                 CONFIRM         char(60) varying static initial
  149.                    ('Do you want to re-format the directory on drive: '),
  150.  
  151.                 ASKCLEAR        char(44) static initial
  152.                    ('Do you want the existing time stamps cleared'),
  153.                 RECOVER         char(50) varying static init
  154.                    ('Do you want to recover time/date directory space'),
  155.                 YN              char(10) static initial('  (Y/N)?  '),
  156.                 YES             char(1) static initial('Y'),
  157.                 lyes            char(1) static initial('y'),
  158.                 yesno           char(1),
  159.  
  160.                 UPPERCASE       char(26) static initial
  161.                                          ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
  162.                 LOWERCASE       char(26) static initial
  163.                                          ('abcdefghijklmnopqrstuvwxyz'),
  164.  
  165.                 pass1           char(20) static initial
  166.                                          ('End of PASS 1.'),
  167.                 ERRORM          char(7) static initial('ERROR: '),
  168.                 TERM            char(30) static initial('INITDIR TERMINATED.'),
  169.                 errvers         char(30) static initial
  170.                                 ('Requires CP/M 3.0 or higher.'),
  171.                 errnotnew       char(31) static initial
  172.                                 ('Directory already re-formatted.'),
  173.                 errtoobig       char(30) static initial
  174.                                 ('Not enough room in directory.'),
  175.                 errpass         char(15) static initial('Wrong password.'),
  176.                 errSTRIP        char(30) varying static initial
  177.                                 ('No time stamps present.'),
  178.                 errMEM          char(30) varying static initial
  179.                                 ('Not enough available memory.'),
  180.                 errRO           char(20) varying static initial
  181.                                 ('Disk is READ ONLY.'),
  182.                 errWHAT         char(30) varying static initial
  183.                                 ('Cannot find last XFCB.'),
  184.                 errRSX          char(60) varying static initial
  185.                 ('Cannot re-format the directory with RSXs in memory.'),
  186.                 errunrec        char(19) static initial ('Unrecognized drive.'),
  187.  
  188.                 errBIOS         char(20) static initial('Cannot select drive.');
  189.  
  190.         declare
  191.                 outptr          pointer,
  192.                 bufptr1         pointer,
  193.                 bufptr2         pointer,
  194.                 dirptr          pointer,
  195.                 drivptr         pointer,
  196.                 clearptr        pointer,
  197.  
  198.                 nempty          bin fixed(15),
  199.                 (nfcbs,nfcbs1)  bin fixed(15),
  200.                 lastsfcb        bin fixed(15),
  201.                 lastdcnt        bin fixed(15),
  202.                 (lasti,lastx)   bin fixed(15),
  203.                 lastsect        bin fixed(15),
  204.                 cleardcnt       bin fixed(15),
  205.                 (gsec,gtrk)     bin fixed(15),
  206.                 (dcnt,sect)     bin fixed(15),
  207.                 outdcnt         bin fixed(15),
  208.                 newdcnt         bin fixed(15),
  209.                 outidx          bin fixed(7),
  210.                 curdisk         bin fixed(7),
  211.                 newlasti        bin fixed(7),
  212.                 (sfcbidx,sfcboffs)  bin fixed(15),
  213.                 usernum         fixed(7),
  214.                 SFCBmark        fixed(7) static initial(33),
  215.                 Dlabel          bin fixed(7) static initial (32),
  216.  
  217.                 Redo            bit(1),
  218.                 bad             bit(1),
  219.                 writeflag       bit(1),
  220.                 CLEARSECT       bit(1),
  221.                 CLEARSFCB       bit(1),
  222.                 labdone         bit(1) static initial(false),
  223.                 cversion        bit(16),
  224.                 READonly        bit(16),
  225.  
  226.                 ptreos          pointer,
  227.                 EOS             bit(8) static initial('00'b4),
  228.                 CEOS            char(1) based (ptreos),
  229.  
  230.                 fcb(32)         char(1),
  231.                 fcb0(50)        char(1) based (drivptr),
  232.                 dr0             fixed(7) based(drivptr),
  233.                 disks           char(16) static initial
  234.                                 ('ABCDEFGHIJKLMNOP'),
  235.                 drive           bin fixed(7),
  236.                 cdrive          char(1);
  237.  
  238. declare
  239.                 1 SCB,
  240.                  2 soffs        fixed(7),
  241.                  2 seter        fixed(7),
  242.                  2 value        char(2),
  243.  
  244.                 ccppage         bit(8);
  245.  
  246. /*************************************************************************
  247.  
  248.  
  249.                         ***  MAIN PROGRAM  ***
  250.  
  251.  
  252. **************************************************************************/
  253.  
  254.         declare i       bin fixed(7);
  255.  
  256.         cversion = vers();
  257.         if substr(cversion,9,8) < '31'b4 then call errprint((errvers));
  258.  
  259.         soffs = 23;
  260.         seter = 0;
  261.         ccppage = sgscb(addr(SCB));             /* if RSX present then stop */
  262.         if substr(ccppage,7,1) = '1'b then call errprint(errRSX);
  263.  
  264.         drivptr = dfcb0();                      /* get drive */
  265.         drive = dr0;
  266.         if dr0 > 16  then drive = 0;
  267.  
  268.         do while(drive = 0);                    /* none recognized */
  269.                 call wrongdisk(i,drive);
  270.                 call getdisk(i,drive);
  271.         end;
  272.  
  273.         cdrive = substr(disks,drive,1);
  274.  
  275.         curdisk = curdsk();                     /* restore BIOS to this */
  276.  
  277.         put edit(INITMSG,confirm,cdrive,YN)(skip(2),a,skip,a,a,a);
  278.         get list(yesno);
  279.         if yesno ~= YES & yesno ~= lyes then call reboot;
  280.  
  281.         READonly = rovec();                     /* is the drive RO ? */
  282.         if substr(READonly,(17-drive),1) = '1'b then
  283.            call errprint(errRO);
  284.  
  285.         call dselect(drive);
  286.         nfcbs = ((phymsk + 1)*4) - 1;           /* # fcbs/physical rcd - 1 */
  287.         nfcbs1 = nfcbs + 1;
  288.  
  289.         dirptr = addr(dir_fcb(0));
  290.         dcnt = 0;
  291.         call read_sector(dcnt,dirptr);
  292.  
  293.         call init;
  294.  
  295.         call restore;
  296.  
  297. /********************************************************************/
  298.  
  299.  
  300. wrongdisk: procedure(i,drive);
  301.         declare (i,j,drive)     bin fixed(7);
  302.  
  303.         put list(ERRORM,errunrec);
  304.         put skip list('DRIVE: ');
  305.                                                 /* print errant string */
  306.         j = i;
  307.         ptreos = addr(EOS);
  308.         do while(fcb0(j) ~= ' ' & fcb0(j) ~= CEOS);
  309.                 put edit(fcb0(j))(a);
  310.                 j = j + 1;
  311.         end;
  312.         put skip;
  313.  
  314. end wrongdisk;
  315.  
  316. getdisk: procedure(i,drive);
  317.         declare (i,drive)       bin fixed(7);
  318.  
  319.         put skip list('Enter Drive: ');
  320.         get list(fcb0(i));
  321.         fcb0(i) = translate(fcb0(i),UPPERCASE,LOWERCASE);
  322.         fcb0(i+1) = ':';
  323.  
  324.         drive = index(disks,fcb0(i));
  325.  
  326. end getdisk;
  327.  
  328.  
  329. /**************************************************************************/
  330.  
  331.  
  332. init: procedure;
  333.  
  334.         declare
  335.                 (i,j,k,l)       bin fixed(15);
  336.  
  337.         call allxfcb;                   /* allocate XFCB data space */
  338.         call countdir;
  339.  
  340.         lastx = nxfcb;
  341.         sect = sect - 1;
  342.         dcnt = dcnt - 1;                        /* reset to good dcnt */
  343.  
  344.         if Redo then do;
  345.                 newdcnt = lastdcnt;
  346.                 newlasti = lasti;
  347.         end;
  348.         else do;
  349.                 newdcnt = lastdcnt + lastsfcb + (2 - mod(lastdcnt,3));
  350.                 if (newdcnt + 1) > dirmax then do;
  351.                         lastdcnt = lastdcnt - nempty;
  352.                         lastsfcb = lastdcnt/3 + 1;
  353.                         newdcnt = lastdcnt + lastsfcb + (2 - mod(lastdcnt,3));
  354.  
  355.                         if (newdcnt + 1) > dirmax then 
  356.                            call errprint(errtoobig);
  357.  
  358.                         call collapse;           /* remove all empties by
  359.                                                     collapsing dir from top */
  360.                         lastsfcb = lastdcnt/3 + 1;
  361.                         newdcnt = lastdcnt + lastsfcb + (2 - mod(lastdcnt,3));
  362.                 end;
  363.                 newlasti = mod(newdcnt,nfcbs1) - 3 + mod(lastdcnt,3);
  364.         end;
  365.  
  366.         outptr = addr(buffer2(0));              /* want to clear last read
  367.                                                    sector...buffer2 only used
  368.                                                    in collapse so it is free */
  369.         call clearout;
  370.         clearptr = outptr;
  371.         outptr = addr(outbuf(0));
  372.         call clearout;                          /* zero output buffer */
  373.  
  374.  
  375. /***********************************************************************/
  376.  
  377.  
  378.         do while(lastsect < sect );             /* clear from end of dir */
  379.                 call write_sector(dcnt,outptr);
  380.                 dcnt = dcnt - nfcbs1;
  381.                 sect = sect - 1;
  382.         end;
  383.  
  384.         if (nempty - 1) ~= dirmax then do;      /* if there are files on dir */
  385.  
  386.                                                 /* bottom of directory is
  387.                                                    now all E5 and 21...
  388.                                                    it is positioned to the
  389.                                                    last good sector of the old
  390.                                                    directory.  */
  391.            dcnt = lastdcnt;
  392.            enddcnt = newdcnt;
  393.            call read_sector(dcnt,dirptr);       /* read last good sector */
  394.  
  395.            outidx = newlasti;                   /* index into out buffer */
  396.            call buildnew(lasti);                /* fill in outbuff from the
  397.                                                    bottom up...need this call
  398.                                                    because lasti may be in 
  399.                                                    middle of read buffer */
  400.            do while(dcnt >= 0);
  401.                                                 /* as soon as we are finished
  402.                                                    with reading old sector,
  403.                                                    then go clear it.  This
  404.                                                    should limit possibility
  405.                                                    that duplicate FCB's occur.
  406.                                                 */
  407.                 call read_sector(dcnt,dirptr);
  408.                 call buildnew(nfcbs);
  409.            end;
  410.  
  411.         end;                                    /* virgin dir */
  412.  
  413.         else call write_sector(0,outptr);       /* write last sector */
  414.  
  415.         do while(notsaved > 0);
  416.                 call moreXFCB;
  417.         end;
  418.  
  419. end init;
  420.  
  421. /************************************************************************/
  422.  
  423.  
  424. strip: procedure;
  425.  
  426.                                 /* remove all SFCB from directory by jamming
  427.                                    E5 into user field.  Also turn off time/date
  428.                                    stamping in DIR LABEL.  */
  429.  
  430.         declare (i,j)           bin fixed(7),
  431.                 1 direct(0:127) based(dirptr),
  432.                  2 junk1        char(12),
  433.                  2 ext          bit(8),
  434.                  2 rest         char(19),
  435.  
  436.                 olddcnt         bin fixed(15);
  437.  
  438.  
  439.         dcnt = 0;
  440.  
  441.         do while(dcnt <= dirmax);
  442.  
  443.                 call read_sector(dcnt,dirptr);
  444.  
  445.                 olddcnt = dcnt;
  446.                 do i = 0 to nfcbs while(dcnt <= dirmax);
  447.  
  448.                         if ~labdone then
  449.                             if dirm(i).user = Dlabel then do;
  450.                                 call getpass(i);
  451.                                 direct(i).ext = direct(i).ext & '10000001'b;
  452.                                 labdone = true;
  453.                             end;
  454.  
  455.                         if dirm(i).user = SFCBmark then 
  456.                             dir_fcb(i).user = 'E5'b4;
  457.  
  458.                         dcnt = dcnt + 1;
  459.                 end;
  460.  
  461.                 call write_sector(olddcnt,dirptr);
  462.         end;
  463.  
  464. end strip;
  465.  
  466.  
  467. /*****************************************************************************/
  468.  
  469.  
  470.  
  471. countdir: procedure;
  472.         declare i       bin fixed(7);
  473.  
  474.                                         /* there are 5 valid sets of codes in 
  475.                                            the user field:
  476.  
  477.                                                 E5      - empty
  478.                                                 0-15    - user numbers
  479.                                                 32      - Directory label
  480.                                                 33      - SFCB marker
  481.                                                 16-31   - XFCB marker
  482.  
  483.                                            This routine counts the # of used
  484.                                            directory slots ignoring E5.
  485.                                            NOTE: if SFCB present then last
  486.                                                  slot = SFCB */
  487.  
  488.         Redo = false;
  489.         nempty = 0;
  490.         sect = 0;
  491.         nxfcb = 0;
  492.         notsaved = 0;
  493.         bad = true;
  494.                                         /* If dir is already time stamped then 
  495.                                            SFCBs should appear in every sector,
  496.                                            notably the first sector. Thus,
  497.                                            test first sector.  If first sector
  498.                                            has SFCB then all do.  If none in
  499.                                            first & they appear later then
  500.                                            INITDIR was probably interrupted.
  501.                                            In that case, zap the found SFCB's
  502.                                            and treat dir as virgin.  */
  503.  
  504.         if dirm(3).user = SFCBmark then bad = false;
  505.  
  506.         do while(dcnt <= dirmax);
  507.                 do i = 0 to nfcbs while(dcnt <= dirmax);
  508.                         if dir_fcb(i).user ~= 'E5'b4 then do;
  509.                                 usernum = dirm(i).user;
  510.  
  511.                                 if ~Redo & usernum = 33 then call query;
  512.  
  513.                                 if usernum > 15 & usernum < 32 then
  514.                                    call getXFCB(i);
  515.  
  516.                                         /* if LABEL then check for password...
  517.                                            may terminate in getpass */
  518.  
  519.                                 else if usernum = Dlabel then call getpass(i);
  520.  
  521.                                 if (usernum < 33) | (~bad & usernum = 33) then
  522.                                         do;
  523.  
  524.                                         lasti = i;
  525.                                         lastsect = sect;
  526.                                         lastdcnt = dcnt;
  527.                                 end;                 /* bad...*/
  528.                                 else if usernum = 33 then nempty = nempty + 1;
  529.  
  530.                         end;                    /* E5 ... */
  531.                         else nempty = nempty + 1;
  532.                         dcnt = dcnt + 1;
  533.                 end;
  534.  
  535.                 sect = sect + 1;
  536.                 call read_sector(dcnt,dirptr);
  537.         end;
  538.  
  539.         if ~Redo then lastsfcb = lastdcnt/3 + 1;
  540.  
  541. end countdir;
  542.  
  543. getXFCB: procedure(i);
  544.         declare i       bin fixed(7);
  545.  
  546.          if nxfcb <= MAXSAVE then do;
  547.                 nxfcb = nxfcb + 1;
  548.                 XFCBs(nxfcb).user = usernum - 16;
  549.                 XFCBs(nxfcb).name = infcb2(i).name;
  550.                 XFCBs(nxfcb).pmode = infcb2(i).pmode;
  551.                 XFCBs(nxfcb).stamp = infcb2(i).stamp;
  552.          end;
  553.          else notsaved = notsaved + 1;
  554.  
  555. end getXFCB;
  556.  
  557.  
  558. allxfcb: procedure;
  559.  
  560.                                 /* allocates largest available block of space
  561.                                    to be used in storing XFCB info.
  562.                                         maxwds & allwds use word units */
  563.  
  564.         declare maxwds          entry returns(fixed(15)),
  565.                 allwds          entry(fixed(15)) returns(pointer),
  566.                 size            bin fixed(15);
  567.  
  568.         size = maxwds();                /* get largest block in free space */
  569.         if size <= 10 then call errprint(errMEM);
  570.  
  571.         xptr = allwds(size);            /* reserve it */
  572.         MAXSAVE = (2*size)/21;          /* # XFCBs that can be saved */
  573.  
  574. end allxfcb;
  575.  
  576.  
  577. query: procedure;
  578.  
  579.         if bad then return;
  580.  
  581.         put skip(2) list(errnotnew);
  582.  
  583.                                                 /* check to see if user wants
  584.                                                    to strip SFCB's */
  585.         if ~asker(RECOVER) then do;
  586.                 Redo = true;
  587.                 CLEARSFCB = false;
  588.                 if asker(ASKCLEAR) then do;
  589.                         CLEARSFCB = true;
  590.                         return;
  591.                 end;
  592.         end;
  593.         else call strip;                        /* this will end down here
  594.                                                    after stripping */
  595.  
  596.         call restore;                           /* dir is already formattted &
  597.                                                    user does not want to clear
  598.                                                    old SFCB's....just stop */
  599.  
  600. end query;              
  601.  
  602. buildnew: procedure(endidx);
  603.         declare (i,j,k,endidx)          bin fixed(15);
  604.  
  605. declare 1 ot(0:127)     based(outptr),
  606.          2 user         fixed(7),
  607.          2 fname        char(8),
  608.          2 ftype        char(3),
  609.          2 rest         char(20);
  610.  
  611.                                       /* build output buffer from
  612.                                            input(end) to input(0).
  613.                                            k => refers to input */
  614.         k = endidx;
  615.         do while(k >= 0);
  616.                 usernum = dirm(k).user;
  617.  
  618.                 outb(outidx).rest = infcb(k).rest;
  619.  
  620.                 if usernum = SFCBmark then do;
  621.                         if bad then outb2(outidx).user = 'E5'b4;
  622.                         else if CLEARSFCB then outb3(outidx).rest = zeroes;
  623.                 end;
  624.  
  625.                 if usernum < 16 then do;
  626.                    if nxfcb > 0 then            /* if fcb is ex=0 and XFCB
  627.                                                    exists then check for
  628.                                                    possible SFCB update */
  629.                         call putXFCB(k);
  630.                 end;
  631.  
  632.                 if ~Redo & mod(outidx,4) = 0 then outidx = outidx - 2;
  633.                 else outidx = outidx - 1;
  634.  
  635.                 k = k - 1;
  636.                 dcnt = dcnt - 1;
  637.  
  638.                 if outidx < 0 then do;
  639.                         if dcnt > 14 then 
  640.                            if mod(dcnt + 1,nfcbs1) = 0 then
  641.                                 call write_sector(dcnt + 1,clearptr);
  642.                         call write_sector(newdcnt,outptr);
  643.                         newdcnt = newdcnt - nfcbs1;
  644.                         outidx = nfcbs - 1;
  645.                         if Redo then outidx = outidx + 1;
  646.                 end;
  647.         end;
  648.  
  649. end buildnew;
  650.  
  651.  
  652. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  653.  
  654.  
  655. compare: procedure(k) returns(fixed(7));
  656.  
  657.         declare (i,j,k)         bin fixed(7),
  658.                 1 direc(0:127)  based(dirptr),
  659.                  2 user         fixed(7),
  660.                  2 name(11)     char(1),
  661.                  2 rest         char(20),
  662.  
  663.                 1 XFCB2(1)      based(xptr),
  664.                  2 user         char(1),
  665.                  2 name(11)     char(1),
  666.                  2 rest         char(9);
  667.  
  668.                                                 /* compare fcb with XFCB list;
  669.                                                    return position in list if
  670.                                                    found, 0 otherwise.
  671.                                                    Nullify usernum field in 
  672.                                                    XFCB list (=99) if found.
  673.                                                    Decrement #xfcb as well.*/
  674.         do i = 1 to nxfcb;
  675.                 if XFCBs(i).user ~= 99 then do;
  676.                         if XFCBs(i).user = direc(k).user then do;
  677.  
  678.                                 do j = 1 to 11;
  679.                                    if direc(k).name(j) ~= XFCB2(i).name(j)
  680.                                       then go to outx;
  681.                                 end;
  682.  
  683.                                                 /* found a match */
  684.                                 XFCBs(i).user = 99;
  685.                                 nxfcb = nxfcb - 1;
  686.                                 return(i);
  687.  
  688. outx:                   end;
  689.                 end;
  690.         end;
  691.  
  692.         return(0);
  693.  
  694. end compare;
  695.  
  696. moreXFCB: procedure;
  697.                                 /* we could not store all the xfcb's in memory
  698.                                    available, so now must make another pass &
  699.                                    store as many XFCB as possible.
  700.                                    'notsaved' > 0 ==> we may have to
  701.                                                       do this again.  */
  702.         declare (i,k)   bin fixed(7);
  703.  
  704.         dcnt = enddcnt;                 /* go to end of directory */
  705.         if ~findXFCB(k) then            /* work backwards trying to find
  706.                                            last known XFCB...if not found
  707.                                            then something very strange has
  708.                                            happened;
  709.             call errprint(errWHAT);
  710.  
  711.         notsaved = 0;                   /* now in last sector where last XFCB
  712.                                            occurs...look for other XFCB that
  713.                                            we know is there.  */
  714.         nxfcb = 0;
  715.  
  716.         dcnt = dcnt + 1;
  717.         lastdcnt = dcnt;                /* save position of last XFCB + 1 */
  718.         lasti = k + 1;                  /* index in sector */
  719.         do while(dcnt <= enddcnt);
  720.                 do i = k+1 to nfcbs while(dcnt <= enddcnt);
  721.                         usernum = dirm(i).user;
  722.                         if usernum > 15 & usernum < 32 then call getXFCB(i);
  723.                         dcnt = dcnt + 1;
  724.                 end;
  725.                 k = 0;
  726.                 call read_sector(dcnt,dirptr);
  727.         end;
  728.  
  729.         dcnt = 0;                               /* go to start of dir */
  730.         do while(dcnt <= enddcnt);
  731.                 call read_sector(dcnt,dirptr);
  732.                 outdcnt = dcnt;
  733.                 writeflag = false;              /* putXFCB sets when it finds a
  734.                                                    match */
  735.  
  736.                 do k = 0 to nfcbs while(dcnt <= enddcnt);
  737.                         outidx = k;
  738.                         if dirm(k).user < 16 then call putXFCB(k);
  739.                         dcnt = dcnt + 1;
  740.                 end;
  741.                 if writeflag then call write_sector(outdcnt,dirptr);
  742.         end;
  743.  
  744. end moreXFCB;
  745.  
  746. findXFCB: procedure(idx) returns(bit(1));
  747.  
  748.                                 /* find the last known XFCB...starts from the
  749.                                    last written sector in the dir and goes
  750.                                    backwards...hopefully that's faster */
  751.         declare idx     fixed(7);
  752.  
  753.         do while(dcnt > 0);
  754.                 call read_sector(dcnt,dirptr);
  755.                 do idx = 0 to nfcbs while(dcnt > 0);
  756.                         usernum = dirm(idx).user;
  757.                         if usernum > 15 & usernum < 32 then
  758.                                 if XFCBs(lastx).name = infcb2(idx).name then
  759.                                         return(true);
  760.                         dcnt = dcnt + 1;
  761.                 end;
  762.         end;
  763.  
  764.         return(false);          /* big trouble...*/
  765.  
  766. end findXFCB;
  767.  
  768.  
  769. putXFCB: procedure(k);
  770.                                 /* if this is extent 0 fold and names match
  771.                                    then update SFCB from XFCB */
  772.         declare (k,j)   fixed(7);
  773.  
  774.                         if dirm(k).fext <= dpb_mask.extmsk then do;
  775.                            j = compare(k);
  776.                            if j ~= 0 then do;
  777.  
  778.                                                 /* fcb matches XFCB...
  779.                                                    update the SFCB */
  780.                              sfcboffs = mod(outidx+1,4);
  781.                              sfcbidx = outidx + (4 - sfcboffs);
  782.                              outb4(sfcbidx).sfcb(sfcboffs).stamps =
  783.                                                                 XFCBs(j).stamp;
  784.                              outb4(sfcbidx).sfcb(sfcboffs).mode =
  785.                                                                 XFCBs(j).pmode;
  786.                              writeflag = true;
  787.                            end;
  788.                         end;                    /* extent 0 ? */
  789.  
  790. end putXFCB;
  791.  
  792.  
  793. errprint: procedure(msg);
  794.         declare
  795.                 msg             char(60) varying;
  796.  
  797.         put edit(ERRORM,msg,TERM)(skip(2),a,a,skip,a);
  798.         put skip(2);
  799.  
  800.         call restore;
  801.  
  802. end errprint;
  803.  
  804.  
  805. asker: procedure(msg) returns(bit(1));
  806.  
  807.         declare msg             char(60) varying;
  808.  
  809.         put skip list(msg,YN);
  810.         get list(yesno);
  811.  
  812.         if yesno ~= YES & yesno ~= lyes then return(false);
  813.  
  814.         return(true);
  815.  
  816. end asker;
  817.  
  818.  
  819. clearout: procedure;
  820.         declare
  821.                 (i,j)   bin fixed(7);
  822.  
  823.         do i = 0 to nfcbs;
  824.                 if mod(i+1,4) ~= 0 then outb2(i).user = 'E5'b4;
  825.                 else outb3(i).user = SFCBmark;
  826.  
  827.                 do j = 1 to 31;
  828.                         outb3(i).rest(j) = '00000000'b;
  829.                 end;
  830.         end;
  831.  
  832. end clearout;
  833.  
  834. getpass: procedure(fcbx);
  835.                                         /* Drive may be password protected...
  836.                                            Get passw from user and compare
  837.                                            with Password in label.
  838.                                            Label password is encoded by first
  839.                                            reversing each char nibble and then
  840.                                            XOR'ing with the sum of the pass.
  841.                                            S2 in label = that sum.  */
  842.  
  843.         declare
  844.                 passwd(8)       bit(8) based(passptr),
  845.  
  846.                 passptr         pointer,
  847.                 convptr         pointer,
  848.                 pchar(8)        bit(8),
  849.                 cvpass(8)       char(1) based(convptr),
  850.                 inpass          char(8),
  851.                 (i,j,fcbx)      bin fixed(7);
  852.  
  853.         labdone = true;
  854.  
  855.         passptr = addr(dirm(fcbx).diskpass);
  856.         convptr = addr(pchar(1));
  857.  
  858.         do i = 1 to 8;                  /* XOR each character  */
  859.                 pchar(i) = bool(passwd(i),dirm(fcbx).fs1,'0110'b);
  860.         end;
  861.  
  862.         if cvpass(8) <= ' ' then return; /* no password */
  863.  
  864.         put skip(2) list('Directory is password protected.');
  865.         put skip list('Password, please.  >');
  866.         get list(inpass);
  867.         inpass = translate(inpass,UPPERCASE,LOWERCASE);
  868.  
  869.         j = 8;
  870.         do i = 1 to 8;
  871.                 if substr(inpass,i,1) ~= cvpass(j) then call errprint(errpass);
  872.                 j = j - 1;
  873.         end;
  874.  
  875. end getpass;
  876.  
  877. collapse: procedure;
  878.  
  879.         declare whichbuf        bin fixed(7),
  880.                 enddcnt         bin fixed(15),
  881.                 (i,nout1,nout2) bin fixed(7);
  882.  
  883.         dcnt = 0;
  884.         sect = 0;
  885.         outdcnt = 0;
  886.         whichbuf = 0;
  887.         nout1 = 0;
  888.         nout2 = 0;
  889.         lastsect = 0;
  890.         enddcnt = lastdcnt + nempty;
  891.         lastdcnt = 0;
  892.         bufptr1 = addr(outbuf(0));
  893.         bufptr2 = addr(buffer2(0));
  894.  
  895.         do while(dcnt <= enddcnt);               /* read up to last dcnt */
  896.  
  897.                 call read_sector(dcnt,dirptr);
  898.  
  899.                 do i = 0 to nfcbs while(dcnt <= enddcnt);
  900.                         if dir_fcb(i).user ~= 'E5'b4 &
  901.                            dirm(i).user ~= SFCBmark then do;
  902.  
  903.                                if whichbuf = 0 then 
  904.                                         call fill(bufptr1,i,nout1,whichbuf);
  905.                                 else call fill(bufptr2,i,nout2,whichbuf);
  906.                         end;
  907.                         dcnt = dcnt + 1;
  908.                 end;
  909.  
  910.                 sect = sect + 1;
  911.                 if nout1 = nfcbs1 then call flush_write(nout1,bufptr1);
  912.                 else if nout2 = nfcbs1 then call flush_write(nout2,bufptr2);
  913.         end;
  914.  
  915.         dcnt = dcnt - 1;                        /* fill unused slots in buffer
  916.                                                    with empty...scratch rest of
  917.                                                    dir */
  918.         if whichbuf = 0 then call fill2(bufptr1,nout1);
  919.         else call fill2(bufptr2,nout2);
  920.  
  921. end collapse;
  922.  
  923. fill: proc(bufptr,i,nout,whichbuf);
  924.         declare bufptr          pointer,
  925.                 (i,j,nout)      bin fixed(7),
  926.                 whichbuf        bin fixed(7),
  927.  
  928.                 1 buffer(0:127) based(bufptr),
  929.                  2 out          char(32);
  930.  
  931.         buffer(nout).out = infcb(i).rest;
  932.  
  933.         lastdcnt = lastdcnt + 1;
  934.         nout = nout + 1;
  935.         if nout = nfcbs1 then whichbuf = mod((whichbuf + 1),2);
  936.  
  937. end fill;
  938.  
  939. flush_write: proc(nout,bufptr);
  940.         declare nout            bin fixed(7),
  941.                 bufptr          pointer;
  942.  
  943.                                         /* always behind the read...thus don't
  944.                                            need to test to see if read sector =
  945.                                            write sector. */
  946.         call write_sector(outdcnt,bufptr);
  947.         outdcnt = outdcnt + nfcbs1;
  948.         nout = 0;
  949.         lastsect = lastsect + 1;
  950.  
  951. end flush_write;
  952.  
  953. fill2: proc(bufptr,nout);
  954.  
  955.         declare (i,j,nout)      bin fixed(7),
  956.                 bufptr          pointer,
  957.                 1 buffer(0:127) based(bufptr),
  958.                  2 user         bit(8),
  959.                  2 rest(31)     bit(8);
  960.  
  961.         do i = nout to nfcbs;
  962.                 buffer(i).user = 'E5'b4;
  963.                 do j = 1 to 31;
  964.                         buffer(i).rest(j) = '00000000'b;
  965.                 end;
  966.         end;
  967.  
  968.         lastdcnt = lastdcnt - 1;
  969.         lasti = nout - 1;
  970.         call flush_write(nout,bufptr);
  971.  
  972.         do i = 0 to nfcbs;                      /* prepare empty sector */
  973.                 buffer(i).user = 'E5'b4;
  974.                 do j = 1 to 31;
  975.                         buffer(i).rest(j) = '00000000'b;
  976.                 end;
  977.         end;
  978.  
  979.                                                 /* clear rest of directory */
  980.         do while (outdcnt < dcnt);
  981.                 call write_sector(outdcnt,bufptr);
  982.                 outdcnt = outdcnt + nfcbs1;
  983.         end;
  984.  
  985. end fill2;
  986.  
  987. restore: procedure;
  988.  
  989.         dphp = seldsk(curdisk);         /* restore drive */
  990.         call reset();                   /* reset disk system */
  991.         errorcode = select(curdisk);
  992.  
  993.         call reboot;
  994.  
  995. end restore;
  996.  
  997.                                 /* read logical record # to dma address */
  998. read_sector: procedure(lrcd,dmaaddr);
  999.         dcl 
  1000.            lrcd      bin fixed(15),
  1001.            prcd      decimal(7,0),
  1002.            dmaaddr   pointer;                   /* dma address */
  1003.  
  1004.         prcd = lrcd/nfcbs1;
  1005.         gtrk = track(prcd);
  1006.         call settrk(gtrk);
  1007.         gsec = sector(prcd);
  1008.         call setsec(gsec);
  1009.  
  1010.         call bstdma(dmaaddr);
  1011.         if rdsec() ~= 0 then signal error(71);
  1012.  
  1013. end read_sector;
  1014.  
  1015.  
  1016.                                 /* write logical record # from dma address */
  1017. write_sector: procedure(lrcd,dmaaddr);
  1018.         dcl 
  1019.            lrcd         bin fixed(15),
  1020.            dmaaddr      pointer,                /* dma address */
  1021.            prcd         decimal(7,0);
  1022.  
  1023.         prcd = lrcd/nfcbs1;                     /* #fcbs/phys rec */
  1024.         gtrk = track(prcd);
  1025.         call settrk(gtrk);
  1026.         gsec = sector(prcd);
  1027.         call setsec(gsec);
  1028.  
  1029.         call bstdma(dmaaddr);
  1030.         if wrsec(1) ~= 0 then signal error(91);
  1031.  
  1032. end write_sector;
  1033.  
  1034.  
  1035.                                 /* select disk drive */
  1036. dselect: procedure((d));
  1037.         dcl
  1038.             p              ptr,
  1039.             wdalv(16)      fixed(15) based(p),
  1040.             btalv(16)      fixed(7)  based(p),
  1041.             all            bit(16),
  1042.             d              fixed(7);
  1043.  
  1044.  
  1045.         dcl
  1046.                 1 dpb based (dpbp),
  1047.                   2 sec bit(16),
  1048.                   2 bsh bit(8),
  1049.                   2 blm bit(8),
  1050.                   2 exm bit(8),
  1051.                   2 dsm bit(16),
  1052.                   2 drm bit(16),
  1053.                   2 al0 bit(8),
  1054.                   2 al1 bit(8),
  1055.                   2 cks bit(16),
  1056.                   2 off bit(8);
  1057.  
  1058.         if d = 0 then d = curdsk();
  1059.         else d = d - 1;
  1060.  
  1061.         errorcode = select(d);                  /* sync BIOS & BDOS */
  1062.         dphp = seldsk(d);
  1063.         if dphp = null then call errprint(errBIOS);/* can't select disk */
  1064.  
  1065.         xlt = xlt1;
  1066.         dpbp = dpbptr;
  1067.  
  1068.         dspt = decimal(spt/(phymsk + 1));
  1069.         dblk = decimal(conv(blkmsk) + 1);
  1070.                                         /* get directory blocks */
  1071.         p = addr(dir_blks(1));
  1072.         all = al0;
  1073.         substr(all,9) = al1;
  1074.  
  1075.         do d = 1 to 16;
  1076.             wdalv(d) = 0;       /* clears dir_blks to 0s */
  1077.             if substr(all,d,1) then 
  1078.                 if dsksiz < 255 then
  1079.                     btalv(d) = d - 1;
  1080.                 else
  1081.                     wdalv(d) = d - 1;
  1082.         end;
  1083.  
  1084. end dselect;
  1085.  
  1086.  
  1087.                                 /* convert logical rcd # to physical sector */
  1088. sector: procedure(i) returns(fixed(15));
  1089.         dcl 
  1090.             i    decimal(7,0);
  1091.  
  1092.         return(sectrn(binary(mod(i,dspt),15),xlt));
  1093.  
  1094. end sector;
  1095.  
  1096.  
  1097.                                 /* logical record # to physical track */
  1098. track: procedure(i) returns(fixed(15));
  1099.         dcl 
  1100.             i    decimal(7,0);
  1101.  
  1102.         return(offset + binary(i/dspt,15));
  1103.  
  1104. end track;
  1105.  
  1106.  
  1107.                                 /* logical record # to physical block */
  1108. block: procedure(i) returns(fixed(15));
  1109.         dcl 
  1110.             i decimal(7,0);
  1111.  
  1112.         return(binary(i/dblk,15));
  1113.  
  1114. end block;
  1115.  
  1116.                                 /* block to logical sector */
  1117. bsec: procedure(i) returns(decimal(7,0));
  1118.         dcl 
  1119.             i     fixed(15);
  1120.  
  1121.         if i > dsksiz then signal error(83);
  1122.  
  1123.         return(decimal(i) * dblk);
  1124.  
  1125. end bsec;
  1126.  
  1127.                         /* convert fixed(7) to fixed(15) w/o sign extension */
  1128. conv: procedure(i) returns(fixed(15));
  1129.         dcl
  1130.             i       fixed(7),
  1131.             j       fixed(15),
  1132.             p       ptr,
  1133.             n       fixed(7) based(p);
  1134.  
  1135.         p = addr(j);
  1136.         j = 0;
  1137.         n = i;
  1138.         return(j);
  1139. end conv;
  1140.  
  1141.                                 /* test for console break */
  1142. break_test: procedure ext;
  1143.  
  1144.         if con_break() then signal error(85);
  1145.  
  1146. end break_test;
  1147.  
  1148.  
  1149.                                 /* test for console break */
  1150. con_break: procedure returns(bit(1));
  1151.         dcl
  1152.             c char(1);
  1153.  
  1154.         if break() then do;
  1155.             c = rdcon();
  1156.             if c ~= '^S' then return(TRUE);
  1157.         end;
  1158.         return(FALSE);
  1159.  
  1160. end con_break;
  1161.  
  1162. end initdir;
  1163.