home *** CD-ROM | disk | FTP | other *** search
- unit loader;
-
- interface
-
- uses util,dump,globals,head;
-
- type
- hash_ptr = ^hash_rec;
- hash_rec = record
- byte_len : word;
- table : word_array;
- end;
-
- list_ptr = ^list_rec;
- list_rec = record
- offset : word;
- hash : word;
- next : list_ptr;
- end;
-
- unit_ptr = ^unit_rec;
- unit_rec = record
- target:word;
- checksum:word;
- prev_unit,next_unit : word;
- end;
-
- unit_list_ptr = ^unit_list_rec;
- unit_list_rec = record
- name : string;
- path : string;
- obj_list : list_ptr;
- own_record : word;
- checksum : word;
- buffer : byte_array_ptr;
- has_symbols : boolean;
- end;
-
- obj_ptr = ^obj_rec;
- obj_rec = record
- next_obj: word; { in case of a hash collision }
- obj_type : byte;
- name: string;
- end;
-
- var
- hash_table : hash_ptr;
-
- unit_list : array[1..255] of unit_list_ptr;
- num_known : word;
-
- procedure build_list(var obj_list:list_ptr;
- buffer:byte_array_ptr;
- hash_table:hash_ptr);
-
- procedure add_unit(var objname:string;info:unit_ptr);
- function get_unit(unit_ofs:word):unit_list_ptr;
- function get_unit_by_name(var name:string):unit_list_ptr;
- function get_unit_num(var name:string):word;
-
- implementation
-
- procedure build_list(var obj_list:list_ptr;
- buffer:byte_array_ptr;
- hash_table:hash_ptr);
- var
- i,j,t:word;
- current,new_entry : list_ptr;
- obj : obj_ptr;
- begin
- new(obj_list);
- with obj_list^ do
- begin
- offset := $ffff; { set up a sentinel record }
- next := nil;
- end;
-
- with hash_table^ do
- for i := 0 to byte_len div 2 do
- if table[i] <> 0 then
- begin
- t := table[i];
- repeat
- current := obj_list;
- while t > current^.offset do
- current := current^.next;
- new(new_entry);
- new_entry^ := current^;
- current^.offset := t;
- current^.hash := i;
- current^.next := new_entry;
- obj := add_offset(buffer,t);
- { get the next object... }
- t := obj^.next_obj;
- until t = 0;
- end;
- end;
-
- procedure add_unit(var objname:string;info : unit_ptr);
- var
- size,total:word;
- header:^header_rec;
- unit_obj:obj_ptr;
- junk : pointer;
-
- procedure load_buffer;
- begin
- with unit_list[num_known]^ do
- begin
- path := objname+'.tpu';
- read_file(path,pointer(header),0,sizeof(header^));
- if header = nil then
- begin
- path := uses_path+path;
- read_file(path,pointer(header),0,sizeof(header^));
- end;
- if header <> nil then
- begin
- if header^.file_id <> 'TPU9' then
- begin
- writeln('Error: file ',path,' is not a TP 6.0 .TPU file!');
- writeln('Halting.');
- halt;
- end;
- read_file(path,pointer(buffer),0,header^.sym_size);
- if buffer <> nil then
- has_symbols := true;
- exit;
- end;
- path := '';
- if got_tpl then
- begin
- header := pointer(tpl_buffer);
- total := 0;
- repeat
- if header^.file_id <> 'TPU9' then
- begin
- writeln('Error searching ',tpl_name,'. It is not a TP library!');
- writeln('Halting.');
- halt;
- end;
- unit_obj := add_offset(header,header^.ofs_this_unit);
- if unit_obj^.name = objname then
- begin
- buffer := pointer(header);
- has_symbols := true;
- exit;
- end;
- size := roundup(header^.sym_size,16)
- +roundup(header^.code_size,16)
- +roundup(header^.reloc_size,16)
- +roundup(header^.const_size,16)
- +roundup(header^.vmt_size,16);
- total := total+size;
- header := add_offset(header,size);
- until (total >= tpl_size) or (size = 0);
- end;
- writeln('Warning: Can''t find unit ',objname);
- end;
- end;
-
- var
- existing : unit_list_ptr;
- begin
- existing := get_unit_by_name(objname);
- if existing <> nil then
- with existing^ do
- begin
- if (info <> nil)
- and (existing^.buffer <> nil)
- and (checksum <> info^.checksum) then
- begin
- writeln('Warning: checksum for unit ',name,' is ',hexword(checksum),' in ',
- path);
- has_symbols := false;
- freemem(buffer,header^.sym_size);
- buffer := nil;
- end;
- exit;
- end;
-
- inc(num_known);
- new(unit_list[num_known]);
- with unit_list[num_known]^ do
- begin
- name := objname;
- obj_list := nil;
- buffer := nil;
- has_symbols := false;
- getmem(junk,16-ofs(heapptr^) and $F); { make it load at a paragraph }
- load_buffer;
- if has_symbols then
- begin
- own_record := header_ptr(buffer)^.ofs_this_unit;
- inc(own_record,
- 4+length(obj_rec(add_offset(buffer,own_record)^).name));
- checksum := unit_ptr(add_offset(buffer,own_record))^.checksum;
- end;
- end;
- end;
-
- function get_unit(unit_ofs:word):unit_list_ptr;
- var
- the_unit : unit_ptr;
- begin
- if unit_ofs > unit_list[1]^.own_record then
- begin
- the_unit := add_offset(buffer,unit_ofs);
- get_unit := unit_list[the_unit^.target];
- end
- else
- get_unit := unit_list[1];
- end;
-
- function get_unit_by_name(var name:string):unit_list_ptr;
- var
- i : word;
- begin
- i := get_unit_num(name);
- if i <> 0 then
- get_unit_by_name := unit_list[i]
- else
- get_unit_by_name := nil;
- end;
-
- function get_unit_num(var name:string):word;
- var
- i : word;
- begin
- for i:=1 to num_known do
- if unit_list[i]^.name = name then
- begin
- get_unit_num := i;
- exit;
- end;
- get_unit_num := 0;
- end;
- end.