home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / NEWPC_TP.ZIP / LU.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-01-03  |  19.2 KB  |  557 lines

  1. program LibraryUtility;   { written 10/09/84 by Steve Freeman
  2.  
  3.   This program was written to function as Gary Novosielski's LU.  As such it
  4.   will function as a utility to manipulate library members under any operating
  5.   system which will support TURBO Pascal.  Minor rewrites may be necessary for
  6.   other versions of Pascal.
  7.  
  8.   This program is placed into the Public Domain by the author and, as a Public
  9.   Domain program, may NOT be used for commercial purposes.
  10. }
  11.  
  12. const ProgramVersion = '1.00';
  13.       BufferSize = 127;      { maximum size of data buffer - 1 }
  14.       EntriesPerBuffer = 4;  { (BufferSize+1)/32 }
  15.       maxent = 128;          { maximum dir entries this program will take }
  16.  
  17. type TimeType = integer;
  18.      FileNameType = array[1..11] of char;
  19.      LibFileType = file;
  20.  
  21.      EntryType = record
  22.                    status: byte;
  23.                    name: array[1..8] of char;
  24.                    ext:  array[1..3] of char;
  25.                    index: integer;
  26.                    length: integer;
  27.                    CRC: integer;
  28.                    CreationDate: integer;
  29.                    LastChangeDate: integer;
  30.                    CreationTime: TimeType;
  31.                    LastChangeTime: TimeType;
  32.                    PadCount: byte;
  33.                    filler: array[27..31] of byte;
  34.                  end;
  35.      EntryPtr = ^EntryType;
  36.  
  37.      hexstr = string[4];
  38.      maxstr = string[255];
  39.      filename = string[12];
  40.  
  41. var buffer: array[0..BufferSize] of byte;
  42.     library, file2: file;
  43.     SizeFile: file of byte;
  44.     DirectoryChanged: boolean;
  45.     LibName, fname: filename;
  46.     LibSize, NumEntries: integer;
  47.     LibEntry: EntryType;
  48.     Dir: array[0..maxent] of EntryPtr;
  49.     active, unused, deleted: integer;
  50. {.cp7}
  51.   procedure WaitKey;
  52.     var c: char;
  53.     begin
  54.       write(^M^J,'Press any key to continue...');
  55.       repeat until keypressed;
  56.       read(kbd,c);
  57.     end;
  58. {.cp13}
  59.   function Confirm: boolean;
  60.     var c: char;
  61.     begin
  62.       write('Confirm operation (Y/N): ');
  63.       repeat
  64.           read(kbd,c);
  65.           c := upcase(c);
  66.         until (c in ['Y','N']);
  67.       writeln(c);
  68.       if c = 'Y'
  69.         then Confirm := true
  70.         else Confirm := false
  71.     end;
  72. {.cp9}
  73.   function CommandLine: maxstr;
  74.     var len, i: integer;
  75.         str: maxstr;
  76.     begin
  77.       str := '';
  78.       len := mem[cseg:$80];
  79.       if len>1
  80.         then for i:=2 to len do str := str + chr(mem[cseg:$80+i]);
  81.       CommandLine := str;
  82.     end;
  83. {.cp13}
  84.   function hex(num: integer): hexstr;
  85.     var i, j: integer;
  86.         h: string[16];
  87.         str: hexstr;
  88.     begin
  89.       str := '0000';   h := '0123456789ABCDEF';   j := num;
  90.       for i:=4 downto 1
  91.         do begin
  92.              str[i] := h[(j and 15)+1];
  93.              j := j shr 4;
  94.            end;
  95.       hex := str;
  96.     end;
  97. {.cp14}
  98.   procedure MakeName(f: filename; var name: FileNameType);
  99.     var dotpos, endname, i: integer;
  100.     begin
  101.       for i:=1 to 11 do name[i] := ' ';
  102.       dotpos := pos('.',f);
  103.       if dotpos > 0
  104.         then endname := dotpos-1
  105.         else endname := length(f);
  106.       for i:=1 to length(f) do f[i] := upcase(f[i]);
  107.       if dotpos > 0
  108.         then for i:=1 to 3 do if f[dotpos+i]<>' '
  109.                                 then name[8+i] := f[dotpos+i];
  110.       for i:=1 to endname do name[i] := f[i];
  111.     end;
  112. {.cp8}
  113.   procedure PutName(f: filename; n: integer);
  114.     var i: integer;
  115.         name: FileNameType;
  116.     begin
  117.       MakeName(f,name);
  118.       for i:=1 to 8 do Dir[n]^.name[i] := name[i];
  119.       for i:=1 to 3 do Dir[n]^.ext[i]  := name[i+8];
  120.     end;
  121. {.cp29}
  122.   function FindMember(f: filename): integer;
  123.     var member, dotpos, endname, i, k: integer;
  124.         lookup: FileNameType;
  125.         found: boolean;
  126.  
  127.     function NamesMatch(entry: integer): boolean;
  128.       var match: boolean;
  129.       begin
  130.         NamesMatch := true;
  131.         with Dir[entry]^
  132.           do begin
  133.                if status <> 0 then NamesMatch := false;
  134.                for k:=1 to 8 do if name[k]<>lookup[k] then NamesMatch := false;
  135.                for k:=1 to 3 do if ext[k]<>lookup[8+k] then NamesMatch := false;
  136.              end;
  137.       end;
  138.  
  139.     begin
  140.       MakeName(f,lookup);
  141.       found := false;   i := 1;
  142.       while not(found) and (i<NumEntries)
  143.         do if NamesMatch(i)
  144.              then found := true
  145.              else i := i + 1;
  146.  
  147.       if (active=1) or not(found)
  148.         then FindMember := 0
  149.         else FindMember := i
  150.     end;
  151. {.cp9}
  152.   function Parse(f: filename): filename;
  153.     var i: integer;
  154.     begin
  155.       for i:=1 to length(f) do f[i]:=upcase(f[i]);
  156.       i := pos('.',f);
  157.       if i>0 then f:=copy(f,1,i-1);
  158.       f := f + '.LBR';
  159.       Parse := f;
  160.     end;
  161. {.cp13}
  162.   procedure WriteDirectoryToDisk(var lib: LibFileType);
  163.     var member, i: integer;
  164.     begin
  165.       reset(lib);
  166.       member := 0;
  167.       while member < NumEntries
  168.         do begin
  169.              for i:=0 to EntriesPerBuffer-1 do move(Dir[member+i]^,buffer[32*i],32);
  170.              blockwrite(lib,buffer,1);
  171.              member := member + 4
  172.            end;
  173.       DirectoryChanged := false
  174.     end;
  175. {.cp6}
  176.   procedure ZeroEntry(n: integer);
  177.     begin
  178.       fillchar(Dir[n]^,32,chr(0));      {clear the record}
  179.       fillchar(Dir[n]^.name[1],11,' '); {clear file name}
  180.       Dir[n]^.status := -1;             {mark unused}
  181.     end;
  182. {.cp38}
  183.   procedure SortDir;
  184.     var i, j: integer;
  185.  
  186.     function larger(a, b: integer): boolean;
  187.       var ok, x: integer;
  188.           c1, c2: char;
  189.       begin
  190.         ok := 0;   x := 1;
  191.         if (Dir[a]^.status <> 0) and (Dir[b]^.status <> 0) then ok := 2;
  192.         if (Dir[a]^.status <> 0) and (ok = 0) then ok := 1;
  193.         if (Dir[b]^.status <> 0) and (ok = 0) then ok := 2;
  194.         while (x < 12) and (ok=0)
  195.           do begin
  196.                c1 := Dir[a]^.name[x];   c2 := Dir[b]^.name[x];
  197.                if c1 > c2 then ok := 1;
  198.                if c1 < c2 then ok := 2;
  199.                x := x + 1
  200.              end;
  201.         if ok=1
  202.           then larger := true
  203.           else larger := false
  204.       end;
  205.  
  206.     procedure swap(x, y: integer);
  207.       var temp: EntryPtr;
  208.       begin
  209.         temp   := Dir[x];
  210.         Dir[x] := Dir[y];
  211.         Dir[y] := temp
  212.       end;
  213.  
  214.     begin
  215.       for i:=1 to NumEntries-1
  216.         do if Dir[i]^.status <> 0 then ZeroEntry(i);
  217.       for i:=1 to NumEntries-2
  218.         do begin
  219.              for j:=i+1 to NumEntries-1
  220.                do if larger(i,j) then swap(i,j);
  221.            end;
  222.     end;
  223. {.cp22}
  224.   procedure CreateDirectory;
  225.     var i: integer;
  226.     begin
  227.       rewrite(library);
  228.  
  229.       clrscr;  writeln('Creating a new library.  Name = ',LibName);
  230.       write('How many entries? ');  readln(i);
  231.       NumEntries := i + 1; {add 1 for Directory entry}
  232.       i := NumEntries MOD 4;
  233.       if i<>0 then NumEntries := NumEntries + (4 - i);
  234.  
  235.       for i:=0 to NumEntries-1
  236.         do begin
  237.              new(Dir[i]);
  238.              ZeroEntry(i);
  239.            end;
  240.  
  241.       Dir[0]^.status := 0; {directory entry is always used}
  242.       Dir[0]^.length := NumEntries DIV 4;
  243.       active := 1;   unused := NumEntries - 1;   deleted := 0;
  244.       WriteDirectoryToDisk(library);
  245.     end;
  246. {.cp26}
  247.   procedure GetDirectory;
  248.     var i, offset: integer;
  249.     begin
  250.       offset := 0;   DirectoryChanged := false;
  251.       LibSize := (1 + filesize(library)) DIV 8;  {in kilobytes}
  252.       blockread(library,buffer,1);
  253.       new(Dir[0]);                 {make space for directory header}
  254.       move(buffer[0],Dir[0]^,32);  {move header entry}
  255.       NumEntries := (128 * Dir[0]^.length) DIV 32;
  256.       for i:=1 to NumEntries-1
  257.         do begin
  258.              if (i MOD EntriesPerBuffer) = 0
  259.                then begin {read next block}
  260.                       blockread(library,buffer,1);
  261.                       offset := offset + EntriesPerBuffer;
  262.                     end;
  263.              new(Dir[i]);
  264.              move(buffer[32*(i-offset)],Dir[i]^,32);
  265.            end;
  266.       active := 1;   unused := 0;   deleted := 0;
  267.       for i:=1 to NumEntries-1
  268.         do if Dir[i]^.status=0
  269.              then active := active + 1
  270.              else if Dir[i]^.status=$FE
  271.                     then deleted := deleted + 1
  272.                     else unused := unused + 1;
  273.     end;
  274. {.cp8}
  275.   procedure OpenLibrary;
  276.     begin
  277.       assign(library,LibName);
  278.       {$I-} reset(library) {$I+};
  279.       if IOresult=0
  280.         then GetDirectory
  281.         else CreateDirectory;
  282.     end;
  283. {.cp23}
  284.   procedure Directory;
  285.     var i, j: integer;
  286.     begin
  287.       clrscr;
  288.       writeln('Library ',LibName,' is ',LibSize,'K',^M^J);
  289.       writeln('  name          index  length    CRC');
  290.       writeln('------------------------------------');
  291.       for i:=1 to NumEntries-1
  292.         do with Dir[i]^
  293.              do begin
  294.                   if status<>$FF
  295.                     then begin
  296.                            for j:=1 to 8 do write(name[j]);
  297.                            write('.');
  298.                            for j:=1 to 3 do write(ext[j]);
  299.                            write(' ',index:8,length:8,'   ',hex(CRC));
  300.                            if status=$FE then write('   deleted');
  301.                            writeln;
  302.                          end;
  303.                 end;
  304.       writeln(^M^J,active,' active, ',unused,' unused, ',deleted,' deleted: ',active+unused+deleted,' total entries.');
  305.       WaitKey;
  306.     end;
  307. {.pa}
  308.   procedure Extract;
  309.     var fname2: filename;
  310.         i, blocknum, bytenum: integer;
  311.     begin
  312.       clrscr;   write('Enter filename to extract: ');  readln(fname2);
  313.       if length(fname2)>0
  314.         then begin
  315.                i := FindMember(fname2);
  316.                if i>0
  317.                  then begin
  318.                         assign(file2,fname2);
  319.                         rewrite(file2);
  320.                         with Dir[i]^
  321.                           do begin
  322.                                seek(library,index);
  323.                                blocknum := 1;   bytenum := 0;
  324.                                while blocknum <= length
  325.                                  do begin
  326.                                       blockread(library,buffer,1);
  327.                                       if blocknum<length
  328.                                         then blockwrite(file2,buffer,1)
  329.                                         else begin
  330.                                                close(file2); {save disk info}
  331.                                                assign(SizeFile,fname2);
  332.                                                reset(SizeFile);
  333.                                                seek(SizeFile,filesize(SizeFile));
  334.                                                while bytenum < ((128 - PadCount) MOD 128)
  335.                                                  do begin
  336.                                                       write(SizeFile,buffer[bytenum]);
  337.                                                       bytenum := bytenum + 1
  338.                                                     end;
  339.                                                close(SizeFile);
  340.                                                reset(file2); {for later close}
  341.                                              end;
  342.                                       blocknum := blocknum + 1
  343.                                     end;
  344.                              end;
  345.                         close(file2);
  346.                       end
  347.                  else writeln('member was not found!!');
  348.              end;
  349.       WaitKey;
  350.     end;
  351. {.cp27}
  352.   procedure Delete;
  353.     var fname2: filename;
  354.         i: integer;
  355.         ok: boolean;
  356.     begin
  357.       clrscr;   write('Enter member to delete: ');  readln(fname2);
  358.       if length(fname2)>0
  359.          then begin
  360.                 i := FindMember(fname2);
  361.                 if i>0
  362.                   then begin
  363.                          ok := Confirm;
  364.                          write('Member ',fname2);
  365.                          if ok
  366.                            then begin
  367.                                   Dir[i]^.status := $FE;
  368.                                   deleted := deleted + 1;
  369.                                   active := active - 1;
  370.                                   writeln(' was deleted.');
  371.                                   DirectoryChanged := true;
  372.                                 end
  373.                            else writeln(' was NOT deleted.')
  374.                        end
  375.                   else writeln(fname2,' does not exist.');
  376.                 WaitKey;
  377.               end;
  378.     end;
  379. {.cp21}
  380.   procedure Undelete;
  381.     var fname2: filename;
  382.         i: integer;
  383.         ok: boolean;
  384.     begin
  385.       clrscr;   write('Enter member to undelete: ');  readln(fname2);
  386.       if length(fname2)>0
  387.          then begin
  388.                 i := FindMember(fname2);
  389.                 if i>0
  390.                   then begin
  391.                          Dir[i]^.status := 0;
  392.                          deleted := deleted - 1;
  393.                          active := active + 1;
  394.                          writeln(fname2,' was undeleted.');
  395.                          DirectoryChanged := true;
  396.                        end
  397.                   else writeln(fname2,' does not exist.');
  398.                 WaitKey;
  399.               end;
  400.     end;
  401. {.pa}
  402.   procedure Add;
  403.     var fname2: filename;
  404.         EntryLength, EntryIndex, SizeOfFile, number, i: integer;
  405.     begin
  406.       number := 0;   i := 1;
  407.       while (number = 0) and (i < NumEntries)
  408.         do begin
  409.              if (Dir[i]^.status=$FF) and (number=0)
  410.                then number := i
  411.                else i := i + 1;
  412.            end;
  413.       clrscr;
  414.       if number > 0
  415.         then begin
  416.                write('Enter member to add: ');  readln(fname2);
  417.                if length(fname2)>0
  418.                  then begin
  419.                         if FindMember(fname2) = 0
  420.                           then begin
  421.                                  assign(SizeFile,fname2);
  422.                                  {$I-} reset(SizeFile) {$I+};
  423.                                  if IOresult=0
  424.                                    then begin
  425.                                           SizeOfFile := filesize(SizeFile);
  426.                                           close(SizeFile);
  427.  
  428.                                           assign(file2,fname2);
  429.                                           reset(file2);
  430.                                           EntryIndex  := filesize(library);
  431.                                           EntryLength := filesize(file2);
  432.                                           seek(library,EntryIndex);
  433.                                           while not(eof(file2))
  434.                                             do begin
  435.                                                  blockread(file2,buffer,1);
  436.                                                  blockwrite(library,buffer,1)
  437.                                                end;
  438.                                           close(file2);
  439.  
  440.                                           fillchar(Dir[number]^,32,chr(0)); {status:=0}
  441.                                           Dir[number]^.index  := EntryIndex;
  442.                                           Dir[number]^.length := EntryLength;
  443.                                           Dir[number]^.PadCount := (128 - (SizeOfFile MOD 128)) and $7F;
  444.                                           PutName(fname2,number);
  445.                                           unused := unused - 1;
  446.                                           active := active + 1;
  447.                                           write('Member ',fname2,' was added.');
  448.                                           DirectoryChanged := true;
  449.                                         end
  450.                                    else writeln('File ',fname2,' was not found.');
  451.                                end
  452.                           else writeln(fname2,' is already a member.');
  453.                       end;
  454.              end
  455.         else writeln('There are no available places to put this entry.');
  456.       WaitKey;
  457.     end;
  458. {.pa}
  459.   procedure Reorganize;
  460.     var i, j: integer;
  461.     begin
  462.       SortDir;
  463.       assign(file2,'WORK-$$$.LBR');
  464.       reset(library);   rewrite(file2);
  465.       WriteDirectoryToDisk(file2);
  466.       for i:=1 to NumEntries-1
  467.         do with Dir[i]^
  468.              do begin
  469.                   if (status = 0) and (length > 0)
  470.                     then begin
  471.                            writeln('Copying: ',name,'.',ext,'  ',filepos(file2));
  472.                            seek(library,index);
  473.                            index := filepos(file2);
  474.                            for j:=1 to length
  475.                              do begin
  476.                                   blockread (library,buffer,1);
  477.                                   blockwrite(file2,  buffer,1)
  478.                                 end
  479.                          end
  480.                 end;
  481.       WriteDirectoryToDisk(file2);
  482.       close(file2);     close(library);
  483.       erase(library);   rename(file2,LibName);
  484.       reset(library);
  485.     end;
  486. {.cp8}
  487.   procedure HelpCmdLine;
  488.     begin
  489.       clrscr;
  490.       writeln(^M^J,'You must enter a file name:');
  491.       writeln(^M^J,'LU <filename>[.LBR]');
  492.       writeln(^M^J,'NOTE: the .LBR suffix is optional.');
  493.       WaitKey;
  494.     end;
  495. {.cp14}
  496.   procedure Help;
  497.     begin
  498.       clrscr;
  499.       writeln('Library Utility Commands:',^M^J);
  500.       writeln('Add       - add a new member, can''t be duplicate');
  501.       writeln('Directory - gives the listing of this library''s directory');
  502.       writeln('Extract   - copy a member out to its own file');
  503.       writeln('Kill      - delete a member from the library');
  504.       writeln('Undelete  - reverses the effects of a delete');
  505.       writeln('Reorganize- compresses blank space in library');
  506.       writeln('eXit      - terminate this program');
  507.       writeln('Help      - gives this screen');
  508.       WaitKey;
  509.     end;
  510. {.pa}
  511.   procedure Menu;
  512.     var selection: char;
  513.     begin
  514.       OpenLibrary;
  515.       repeat
  516.           clrscr;
  517.           gotoxy(30,2);  write('Library Utility Menu');
  518.           gotoxy(35,3);  write('version ',ProgramVersion);
  519.           gotoxy(40-length(LibName) DIV 2,5);  write(LibName);
  520.           gotoxy(10,07); write('D - directory');
  521.           gotoxy(10,08); write('E - extract member');
  522.           gotoxy(10,09); write('A - add member');
  523.           gotoxy(10,10); write('K - delete member');
  524.           gotoxy(10,11); write('U - undelete member');
  525.           gotoxy(10,12); write('R - reorganize library');
  526.           gotoxy(10,13); write('X - exit');
  527.           gotoxy(10,14); write('? - help');
  528.           gotoxy(20,20); write('choose one: ');
  529.           repeat
  530.               repeat until keypressed;
  531.               read(kbd,selection);
  532.               selection := upcase(selection);
  533.             until (selection in ['A','D','E','K','R','U','X','?']);
  534.           writeln(selection);
  535.           case selection of
  536.             'A': Add;
  537.             'D': Directory;
  538.             'E': Extract;
  539.             '?': Help;
  540.             'K': Delete;
  541.             'R': Reorganize;
  542.             'U': Undelete;
  543.           end;
  544.         until selection='X';
  545.       if DirectoryChanged then WriteDirectoryToDisk(library);
  546.       close(library);
  547.     end;
  548. {.cp8}
  549. begin {Main}
  550.  
  551.   LibName := Parse('source' {CommandLine});
  552.   if length(LibName)=0
  553.     then HelpCmdLine
  554.     else Menu;
  555.  
  556. end.
  557.