?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE : Loader : Task services definition matching' ??
MODULE lom$task_services_def_matching;

{  PURPOSE:
{    This module is responsible for satisfying externals from the TASK_SERVICES "library".  This module
{    must interface with System Generation components to obtain the definition of this library.
{    Satisfying externals from the TASK_SERVICES library is different from object library processing
{    in that no actual loading need be performed -- the pre-loaded task services entry points are
{    simply made known to the loaded program as needed.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc lot$loader_options
*copyc lot$loader_type_definitions
*copyc lot$task_services_entry_point
?? POP ??
*copyc lop$define_entry_point
*copyc lov$head_of_unsat_ref_list
*copyc lov$enable_source_type_checking
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??
  ?VAR
    inline_procs: boolean := TRUE?;

  VAR
    lov$task_services_entry_points: [XDCL] ^array [ * ] of lot$task_services_entry_point;

?? OLDTITLE ??
?? NEWTITLE := 'find_task_services_entry_point', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to find an entry point with the given name in the
{   array of task services entry points.

  PROCEDURE find_task_services_entry_point
    (    linkage_name: {input} ^pmt$program_name;
     VAR entry_point_found {control} : boolean;
     VAR dictionary_index: integer);

    VAR
      temp: integer,
      lower: integer,
      upper: integer;

    lower := LOWERBOUND (lov$task_services_entry_points^);
    upper := UPPERBOUND (lov$task_services_entry_points^);

  /binary_search/
    WHILE lower <= upper DO
      temp := lower + upper;
      dictionary_index := temp DIV 2;
      IF linkage_name^ = lov$task_services_entry_points^ [dictionary_index].name THEN
        entry_point_found := TRUE;
        RETURN
      ELSE
        IF linkage_name^ > lov$task_services_entry_points^ [dictionary_index].name THEN
          lower := dictionary_index + 1;
        ELSE
          upper := dictionary_index - 1;
        IFEND;
      IFEND;
    WHILEND /binary_search/;
    entry_point_found := FALSE;
  PROCEND find_task_services_entry_point;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] lop$satisfy_task_services_refs', EJECT ??

{  PURPOSE:
{    This procedure is responsible for determining if any unsatisfied external references can be
{    satisfied by task services entry points.  If a task service entry point can satisfy some
{    unsatisfied external reference, then the task service entry point is "defined" within the context
{    of the loaded program.
{  NOTE:
{    This procedure utilizes an external procedure (which understands the data structure used to store
{    unsatisfied references) to locate all unsatisfied references.  The external procedure is passed
{    a pointer to an internal procedure which is called to process individual unsatisfied references
{    as they are located by the external procedure.

  PROCEDURE [XDCL] lop$satisfy_task_services_refs
    (    control_options {control} : lot$control_options;
     VAR unsatisfied_reference: ^lot$unsatisfied_reference_list;
     VAR another_scan_required: boolean);

?? NEWTITLE := '    [INLINE] search_task_services_defs' ??

    ?IF inline_procs = TRUE THEN

      PROCEDURE [INLINE] search_task_services_defs;

    ?ELSE

      PROCEDURE search_task_services_defs;

    ?IFEND

    VAR
      duplicate_entry_point: boolean,
      linkage: ^lot$linkage_name_lists,
      references_list_head: ^^lot$unsatisfied_reference_group,
      reference_group: ^lot$unsatisfied_reference_group,
      reference_group_chain: ^lot$unsatisfied_reference_group,
      pseudo_entry_definition: llt$entry_definition,
      pseudo_module_descriptor: lot$module_descriptor,
      pseudo_allocated_sections: array [0 .. 1] of lot$section_allocation,
      pseudo_control_options: lot$control_options,
      i: integer,
      debug_entry_point: boolean,
      entry_point_found: boolean;

    linkage := unsatisfied_reference^.linkage_info;

    debug_entry_point := FALSE;
    find_task_services_entry_point (^linkage^.name, entry_point_found, i);
    references_list_head := ^linkage^.unsat_references_list^.references;
    reference_group := references_list_head^;

    IF entry_point_found THEN
      pseudo_entry_definition.section_ordinal := 0;
      pseudo_entry_definition.offset := 0;
      IF lov$task_services_entry_points^ [i].gated THEN
        pseudo_entry_definition.attributes := $llt$entry_point_attributes [llc$gated_entry_point];
      ELSE
        pseudo_entry_definition.attributes := $llt$entry_point_attributes [];
      IFEND;
      pseudo_entry_definition.name := lov$task_services_entry_points^ [i].name;
      pseudo_entry_definition.language := lov$task_services_entry_points^ [i].language;
      pseudo_entry_definition.declaration_matching_required :=
            lov$task_services_entry_points^ [i].declaration_matching_required;
      pseudo_entry_definition.declaration_matching := lov$task_services_entry_points^ [i].
            declaration_matching;
      pseudo_module_descriptor.name := 'TASK_SERVICES';

{!  When SYSTEM GENERATOR supports debug_procedure field.
{!          IF lov$task_services_entry_points^ [i].debug_procedure THEN

      IF (pseudo_entry_definition.name = 'DBP$BEGIN_DEBUG') OR (pseudo_entry_definition.name = 'DBP$DEBUG') OR
            (pseudo_entry_definition.name = 'DBP$END_DEBUG') THEN
        pseudo_module_descriptor.attributes.loaded_ring := lov$task_services_entry_points^ [i].r1;
        IF lov$task_services_entry_points^ [i].gated THEN
          pseudo_module_descriptor.attributes.call_bracket := lov$task_services_entry_points^ [i].r3;
        ELSE
          pseudo_module_descriptor.attributes.call_bracket := lov$task_services_entry_points^ [i].r2;
        IFEND;
        debug_entry_point := TRUE;
      IFEND;
      pseudo_module_descriptor.attributes.global_key_lock := lov$task_services_entry_points^ [i].global_lock;
      pseudo_module_descriptor.attributes.binding_section_address :=
            lov$task_services_entry_points^ [i].binding_section_address;
      pseudo_module_descriptor.attributes.vmid := lov$task_services_entry_points^ [i].vmid;
      pseudo_module_descriptor.attributes.source_declaration_matching := lov$enable_source_type_checking;
      pseudo_allocated_sections [0].kind := llc$code_section;
      pseudo_allocated_sections [0].address := lov$task_services_entry_points^ [i].address;
      pseudo_allocated_sections [0].binding_section_offset := 0;
      pseudo_allocated_sections [0].length := osc$maximum_offset;
      pseudo_allocated_sections [1].length := osc$maximum_offset;
      pseudo_control_options.map := control_options.map * $pmt$load_map_options [pmc$entry_point_xref];
      pseudo_control_options.debug_ring := control_options.debug_ring;
    IFEND;

  /scan_reference_group_list/
    WHILE reference_group <> NIL DO
      IF reference_group^.logically_satisfied THEN
        reference_group := reference_group^.nnext;
        CYCLE /scan_reference_group_list/
      IFEND;
      IF reference_group^.newly_created THEN
        reference_group^.newly_created := FALSE;
        reference_group_chain := reference_group^.nnext;
        WHILE reference_group_chain <> NIL DO
          reference_group_chain^.newly_created := FALSE;
          reference_group_chain := reference_group_chain^.nnext;
        WHILEND;
        reference_group := reference_group^.nnext;
        unsatisfied_reference^.library_searched := 0;
        another_scan_required := TRUE;
        CYCLE /scan_reference_group_list/
      IFEND;
      IF NOT entry_point_found THEN
        reference_group := reference_group^.nnext;
        CYCLE /scan_reference_group_list/
      IFEND;
      IF ((reference_group^.global_key = lov$task_services_entry_points^ [i].global_lock) OR
            (lov$task_services_entry_points^ [i].gated AND ((reference_group^.global_key = loc$master_key) OR
            (lov$task_services_entry_points^ [i].global_lock = loc$no_lock)))) AND
            ((reference_group^.ring >= lov$task_services_entry_points^ [i].r1) AND
            ((reference_group^.ring <= lov$task_services_entry_points^ [i].r2) OR
            (lov$task_services_entry_points^ [i].gated AND (reference_group^.ring <=
            lov$task_services_entry_points^ [i].r3)))) THEN
        IF NOT debug_entry_point THEN
          IF reference_group^.ring >= lov$task_services_entry_points^ [i].r2 THEN
            pseudo_module_descriptor.attributes.loaded_ring := lov$task_services_entry_points^ [i].r2;
            pseudo_module_descriptor.attributes.call_bracket := lov$task_services_entry_points^ [i].r3;
          ELSE
            pseudo_module_descriptor.attributes.loaded_ring := reference_group^.ring;
            pseudo_module_descriptor.attributes.call_bracket := reference_group^.ring;
          IFEND;
        IFEND;

        unsatisfied_reference := unsatisfied_reference^.b_link;

        lop$define_entry_point (^pseudo_entry_definition, ^pseudo_module_descriptor,
              ^pseudo_allocated_sections, pseudo_control_options, {load_file_number} 0,
              duplicate_entry_point);

        IF linkage^.unsat_references_list = NIL THEN
          RETURN;
        ELSEIF duplicate_entry_point THEN
          unsatisfied_reference := unsatisfied_reference^.f_link;
          RETURN;
        ELSE

          unsatisfied_reference := unsatisfied_reference^.f_link;

          reference_group := linkage^.unsat_references_list^.references;
        IFEND;

      ELSE
        reference_group := reference_group^.nnext;
      IFEND;
    WHILEND /scan_reference_group_list/;
  PROCEND search_task_services_defs;
?? OLDTITLE, EJECT ??


  WHILE unsatisfied_reference <> lov$head_of_unsat_ref_list DO
    search_task_services_defs;
    unsatisfied_reference := unsatisfied_reference^.f_link;
  WHILEND;
PROCEND lop$satisfy_task_services_refs;
?? OLDTITLE ??
MODEND lom$task_services_def_matching;
