home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / PASCAL / INTRFC62.ZIP / LOADER.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1991-05-02  |  6.0 KB  |  239 lines

  1. unit loader;
  2.  
  3. interface
  4.  
  5.   uses util,dump,globals,head;
  6.  
  7. type
  8.   hash_ptr = ^hash_rec;
  9.   hash_rec = record
  10.     byte_len : word;
  11.     table    : word_array;
  12.   end;
  13.  
  14.   list_ptr = ^list_rec;
  15.   list_rec = record
  16.     offset : word;
  17.     hash : word;
  18.     next : list_ptr;
  19.   end;
  20.  
  21.   unit_ptr = ^unit_rec;
  22.   unit_rec = record
  23.     target:word;
  24.     checksum:word;
  25.     prev_unit,next_unit : word;
  26.   end;
  27.  
  28.   unit_list_ptr = ^unit_list_rec;
  29.   unit_list_rec = record
  30.     name : string;
  31.     path : string;
  32.     obj_list : list_ptr;
  33.     own_record : word;
  34.     checksum : word;
  35.     buffer     : byte_array_ptr;
  36.     has_symbols : boolean;
  37.   end;
  38.  
  39.   obj_ptr = ^obj_rec;
  40.   obj_rec = record
  41.     next_obj: word;  { in case of a hash collision }
  42.     obj_type : byte;
  43.     name: string;
  44.   end;
  45.  
  46. var
  47.   hash_table : hash_ptr;
  48.  
  49.   unit_list : array[1..255] of unit_list_ptr;
  50.   num_known : word;
  51.  
  52.   procedure build_list(var obj_list:list_ptr;
  53.                          buffer:byte_array_ptr;
  54.                          hash_table:hash_ptr);
  55.  
  56.   procedure add_unit(var objname:string;info:unit_ptr);
  57.   function  get_unit(unit_ofs:word):unit_list_ptr;
  58.   function  get_unit_by_name(var name:string):unit_list_ptr;
  59.   function  get_unit_num(var name:string):word;
  60.  
  61. implementation
  62.  
  63.   procedure build_list(var obj_list:list_ptr;
  64.                          buffer:byte_array_ptr;
  65.                          hash_table:hash_ptr);
  66.   var
  67.     i,j,t:word;
  68.     current,new_entry : list_ptr;
  69.     obj : obj_ptr;
  70.   begin
  71.     new(obj_list);
  72.     with obj_list^ do
  73.     begin
  74.       offset := $ffff;     { set up a sentinel record }
  75.       next := nil;
  76.     end;
  77.  
  78.     with hash_table^ do
  79.       for i := 0 to byte_len div 2 do
  80.         if table[i] <> 0 then
  81.         begin
  82.           t := table[i];
  83.           repeat
  84.             current := obj_list;
  85.             while t > current^.offset do
  86.               current := current^.next;
  87.             new(new_entry);
  88.             new_entry^ := current^;
  89.             current^.offset := t;
  90.             current^.hash := i;
  91.             current^.next := new_entry;
  92.              obj := add_offset(buffer,t);
  93.              { get the next object... }
  94.             t := obj^.next_obj;
  95.           until t = 0;
  96.         end;
  97.   end;
  98.  
  99.   procedure add_unit(var objname:string;info : unit_ptr);
  100.   var
  101.     size,total:word;
  102.     header:^header_rec;
  103.     unit_obj:obj_ptr;
  104.     junk : pointer;
  105.  
  106.   procedure load_buffer;
  107.   begin
  108.     with unit_list[num_known]^ do
  109.     begin
  110.       path := objname+'.tpu';
  111.       read_file(path,pointer(header),0,sizeof(header^));
  112.       if header = nil then
  113.       begin
  114.         path := uses_path+path;
  115.         read_file(path,pointer(header),0,sizeof(header^));
  116.       end;
  117.       if header <> nil then
  118.       begin
  119.         if header^.file_id <> 'TPU9' then
  120.         begin
  121.           writeln('Error:  file ',path,' is not a TP 6.0 .TPU file!');
  122.           writeln('Halting.');
  123.           halt;
  124.         end;
  125.         read_file(path,pointer(buffer),0,header^.sym_size);
  126.         if buffer <> nil then
  127.           has_symbols := true;
  128.         exit;
  129.       end;
  130.       path := '';
  131.       if got_tpl then
  132.       begin
  133.         header := pointer(tpl_buffer);
  134.         total := 0;
  135.         repeat
  136.           if header^.file_id <> 'TPU9' then
  137.           begin
  138.             writeln('Error searching ',tpl_name,'.  It is not a TP library!');
  139.             writeln('Halting.');
  140.             halt;
  141.           end;
  142.           unit_obj := add_offset(header,header^.ofs_this_unit);
  143.           if unit_obj^.name = objname then
  144.           begin
  145.             buffer := pointer(header);
  146.             has_symbols := true;
  147.             exit;
  148.           end;
  149.           size := roundup(header^.sym_size,16)
  150.                  +roundup(header^.code_size,16)
  151.                  +roundup(header^.reloc_size,16)
  152.                  +roundup(header^.const_size,16)
  153.                  +roundup(header^.vmt_size,16);
  154.           total := total+size;
  155.           header := add_offset(header,size);
  156.         until (total >= tpl_size) or (size = 0);
  157.       end;
  158.       writeln('Warning:  Can''t find unit ',objname);
  159.     end;
  160.   end;
  161.  
  162.   var
  163.     existing : unit_list_ptr;
  164.   begin
  165.     existing := get_unit_by_name(objname);
  166.     if existing <> nil then
  167.       with existing^ do
  168.       begin
  169.         if   (info <> nil)
  170.          and (existing^.buffer <> nil)
  171.          and (checksum <> info^.checksum) then
  172.         begin
  173.           writeln('Warning:  checksum for unit ',name,' is ',hexword(checksum),' in ',
  174.                   path);
  175.           has_symbols := false;
  176.           freemem(buffer,header^.sym_size);
  177.           buffer := nil;
  178.         end;
  179.         exit;
  180.       end;
  181.  
  182.     inc(num_known);
  183.     new(unit_list[num_known]);
  184.     with unit_list[num_known]^ do
  185.     begin
  186.       name := objname;
  187.       obj_list := nil;
  188.       buffer := nil;
  189.       has_symbols := false;
  190.       getmem(junk,16-ofs(heapptr^) and $F);  { make it load at a paragraph }
  191.       load_buffer;
  192.       if has_symbols then
  193.       begin
  194.         own_record := header_ptr(buffer)^.ofs_this_unit;
  195.         inc(own_record,
  196.             4+length(obj_rec(add_offset(buffer,own_record)^).name));
  197.         checksum := unit_ptr(add_offset(buffer,own_record))^.checksum;
  198.       end;
  199.     end;
  200.   end;
  201.  
  202.   function get_unit(unit_ofs:word):unit_list_ptr;
  203.   var
  204.     the_unit : unit_ptr;
  205.   begin
  206.     if unit_ofs > unit_list[1]^.own_record then
  207.     begin
  208.       the_unit := add_offset(buffer,unit_ofs);
  209.       get_unit := unit_list[the_unit^.target];
  210.     end
  211.     else
  212.       get_unit := unit_list[1];
  213.   end;
  214.  
  215.   function get_unit_by_name(var name:string):unit_list_ptr;
  216.   var
  217.     i : word;
  218.   begin
  219.     i := get_unit_num(name);
  220.     if i <> 0 then
  221.       get_unit_by_name := unit_list[i]
  222.     else
  223.       get_unit_by_name := nil;
  224.   end;
  225.  
  226.   function get_unit_num(var name:string):word;
  227.   var
  228.     i : word;
  229.   begin
  230.     for i:=1 to num_known do
  231.       if unit_list[i]^.name = name then
  232.       begin
  233.         get_unit_num := i;
  234.         exit;
  235.       end;
  236.     get_unit_num := 0;
  237.   end;
  238. end.
  239.