?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE : Program Management : Object Code Utilities' ??
MODULE pmm$object_code_utilities;
?? RIGHT := 110 ??


?? NEWTITLE := '  Global declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc lle$loader_status_conditions
*copyc lle$load_map_diagnostics
*copyc lle$find_ep_diagnostics
*copyc llt$load_module
*copyc llt$object_module
*copyc llt$library_dictionary_pointers
*copyc lot$loader_type_definitions
*copyc oss$job_paged_literal
*copyc ost$caller_identifier
*copyc pme$execution_exceptions
*copyc pme$program_services_exceptions
*copyc pmt$object_library_address
?? POP ??
*copyc amp$get_file_attributes
*copyc amp$get_segment_pointer
*copyc clp$convert_string_to_file_ref
*copyc dbp$module_table_address
*copyc fsp$close_file
*copyc fsp$open_file
*copyc i#current_sequence_position
*copyc mmp$verify_access
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc pmp$establish_condition_handler
?? TITLE := '  [XDCL, #GATE] pmp$get_entry_point_dictionary', EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$get_entry_point_dictionary
    (    library: ^SEQ ( * );
     VAR entry_point_dictionary: ^llt$entry_point_dictionary;
     VAR status: ost$status);


    VAR
      i: 0 .. llc$max_dictionaries_on_library,
      object_library: ^SEQ ( * ),
      object_library_header: ^llt$object_library_header,
      object_library_hdr: ^llt$object_library_header_v1_0,
      object_library_dictionary: ^llt$object_library_dictionaries;


    status.normal := TRUE;
    entry_point_dictionary := NIL;

    object_library := library;
    RESET object_library;

    NEXT object_library_header IN object_library;
    IF object_library_header = NIL THEN
      osp$set_status_abnormal ('PM', pme$library_header_missing, '', status);
      RETURN; {----->
    IFEND;

    IF object_library_header^.version = llc$object_library_version THEN
      NEXT object_library_dictionary: [1 .. object_library_header^.number_of_dictionaries] IN object_library;
      IF object_library_dictionary = NIL THEN
        osp$set_status_abnormal ('PM', pme$library_header_missing, '', status);
        RETURN; {----->
      IFEND;

    /find_entry_point_dictionary/
      FOR i := LOWERBOUND (object_library_dictionary^) TO UPPERBOUND (object_library_dictionary^) DO
        IF (object_library_dictionary^ [i].kind = llc$entry_point_dictionary) THEN
          entry_point_dictionary := #PTR (object_library_dictionary^ [i].entry_point_dictionary,
                object_library^);
          EXIT /find_entry_point_dictionary/; {----->
        IFEND;
      FOREND /find_entry_point_dictionary/;

    ELSEIF object_library_header^.version = 'V1.0' THEN
      RESET object_library;
      NEXT object_library_hdr IN object_library;
      entry_point_dictionary := #PTR (object_library_hdr^.entry_point_dictionary, object_library^);

    ELSE
      osp$set_status_abnormal ('PM', pme$wrong_library_version, llc$object_library_version, status);
      RETURN; {----->

    IFEND;

    IF entry_point_dictionary = NIL THEN
      osp$set_status_abnormal ('PM', pme$bad_entry_dictionary_ptr, llc$object_library_version, status);
    IFEND;

  PROCEND pmp$get_entry_point_dictionary;
?? TITLE := '  [XDCL, #GATE] pmp$position_object_library', EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$position_object_library
    (VAR object_library: ^SEQ ( * );
         offset: ost$relative_pointer;
     VAR valid_position: boolean);

    VAR
      space: ^SEQ ( * );

    RESET object_library;

    IF offset <> 0 THEN
      NEXT space: [[REP offset OF cell]] IN object_library;
      valid_position := space <> NIL;
    ELSE
      valid_position := TRUE;
    IFEND;

  PROCEND pmp$position_object_library;
?? TITLE := '  [XDCL, #GATE] pmp$get_last_path_name', EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$get_last_path_name
    (    path: fst$file_reference;
     VAR last_name: ost$name;
     VAR status: ost$status);

    VAR
      parsed_file_reference: fst$parsed_file_reference;

    clp$convert_string_to_file_ref (path, parsed_file_reference, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    last_name := parsed_file_reference.path (parsed_file_reference.last_name.index,
          parsed_file_reference.last_name.size);

  PROCEND pmp$get_last_path_name;
?? TITLE := '[XDCL, #GATE] pmp$find_entry_point_in_library', EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$find_entry_point_in_library
    (    object_library: ^SEQ ( * );
         entry_point_name: pmt$program_name;
     VAR address: pmt$object_library_address;
     VAR status: ost$status);

*copyc pmh$find_entry_point_in_library

?? NEWTITLE := '    unaccessable_library', EJECT ??

    PROCEDURE unaccessable_library
      (    condition: pmt$condition;
           condition_descriptor: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      osp$set_status_from_condition ('PM', condition, save_area, status, handler_status);
      EXIT pmp$find_entry_point_in_library; {----->
    PROCEND unaccessable_library;

?? OLDTITLE, EJECT ??

    VAR
      access_fault: [STATIC, READ, oss$job_paged_literal] pmt$condition :=
            [pmc$system_conditions, $pmt$system_conditions [pmc$access_violation, pmc$invalid_segment_ring_0,
            pmc$address_specification], * ],
      access_fault_descriptor: pmt$established_handler,
      caller: ost$caller_identifier,
      entry_point_dictionary_item: llt$entry_point_dictionary_item,
      entry_point_found: boolean,
      ignore_status: ost$status,
      library: lot$load_file,
      module_header: ^llt$load_module_header,
      program_header: ^llt$library_member_header,
      scl_header: ^llt$library_member_header,
      verify_status: ost$status,
      version: string (4);

    #CALLER_ID (caller);

    status.normal := TRUE;
    pmp$establish_condition_handler (access_fault, ^unaccessable_library, ^access_fault_descriptor,
          ignore_status);

    pmp$verify_library (object_library, version, verify_status);
    IF verify_status.normal THEN
      entry_point_found := FALSE;
      find_entry_point_in_library (^entry_point_name, object_library, entry_point_found,
            entry_point_dictionary_item, verify_status);
      IF verify_status.normal THEN
        IF NOT entry_point_found THEN
          osp$set_status_abnormal ('PM', lle$entry_point_not_found, entry_point_name, status);
        ELSE
          CASE entry_point_dictionary_item.module_kind OF

          = llc$load_module =
            address.kind := llc$load_module;
            module_header := #PTR (entry_point_dictionary_item.module_header, object_library^);
            IF module_header <> NIL THEN
              library := object_library;
              get_load_module (^entry_point_name, module_header, library, address.load_module, status);
            ELSE
              osp$set_status_abnormal ('PM', lle$bad_load_header_ptr, '', status);
            IFEND;

          = llc$program_description =
            address.kind := llc$program_description;
            program_header := #PTR (entry_point_dictionary_item.program_header, object_library^);
            IF program_header <> NIL THEN
              address.program_description := #PTR (program_header^.member, object_library^);
              IF address.program_description <> NIL THEN
                RESET address.program_description;
              ELSE
                osp$set_status_abnormal ('PM', lle$bad_library_member_header, 'PROGRAM', status);
              IFEND;
            ELSE
              osp$set_status_abnormal ('PM', lle$bad_program_header_ptr, '', status);
            IFEND;

          = llc$command_procedure =
            address.kind := llc$command_procedure;
            scl_header := #PTR (entry_point_dictionary_item.command_header, object_library^);
            IF scl_header <> NIL THEN
              address.scl_procedure := #PTR (scl_header^.member, object_library^);
              IF address.scl_procedure <> NIL THEN
                RESET address.scl_procedure;
              ELSE
                osp$set_status_abnormal ('PM', lle$bad_library_member_header, 'SCL PROCEDURE', status);
              IFEND;
            ELSE
              osp$set_status_abnormal ('PM', lle$bad_scl_header_ptr, '', status);
            IFEND;
          ELSE
            ;
          CASEND;
        IFEND;
      ELSE
        status := verify_status;
      IFEND;
    ELSE
      status := verify_status;
    IFEND;


  PROCEND pmp$find_entry_point_in_library;
?? TITLE := '  find_entry_point_in_library', EJECT ??

  PROCEDURE find_entry_point_in_library
    (    name: {input} ^pmt$program_name;
         library_file: lot$load_file;
     VAR entry_point_found: boolean;
     VAR entry_point_dictionary_item: llt$entry_point_dictionary_item;
     VAR status: ost$status);

{  PURPOSE:
{    This procedure searches the entry_point dictionary of the specified library for name.
{    If the name is located, the corresponding entry_point dictionary item is returned.

?? NEWTITLE := '    search_entry_point_dictionary', EJECT ??

    PROCEDURE search_entry_point_dictionary
      (    name: {input} ^pmt$program_name;
           entry_point_dictionary: {input} ^llt$entry_point_dictionary;
       VAR entry_point_found {control} : boolean;
       VAR dictionary_index: 1 .. llc$max_entry_points_in_library);

      VAR
        temp: integer,
        lower: 1 .. llc$max_entry_points_in_library,
        upper: 0 .. llc$max_entry_points_in_library;

      lower := LOWERBOUND (entry_point_dictionary^);
      upper := UPPERBOUND (entry_point_dictionary^);
      entry_point_found := FALSE;

    /binary_search/
      WHILE (lower <= upper) AND (NOT entry_point_found) DO
        temp := lower + upper;
        dictionary_index := temp DIV 2;
        IF name^ = entry_point_dictionary^ [dictionary_index].name THEN
          entry_point_found := TRUE;
        ELSEIF name^ > entry_point_dictionary^ [dictionary_index].name THEN
          lower := dictionary_index + 1;
        ELSE
          upper := dictionary_index - 1;
        IFEND;
      WHILEND /binary_search/;
    PROCEND search_entry_point_dictionary;
?? OLDTITLE, EJECT ??

    VAR
      dictionary_index: 1 .. llc$max_entry_points_in_library,
      entry_point_dictionary: ^llt$entry_point_dictionary,
      i: 0 .. llc$max_dictionaries_on_library,
      library: lot$load_file,
      library_dictionary: ^llt$object_library_dictionaries,
      library_hdr: ^llt$object_library_header_v1_0,
      library_header: ^llt$object_library_header,
      number_of_entry_points: 0 .. llc$max_entry_points_in_library;

    status.normal := TRUE;
    entry_point_found := FALSE;

    library := library_file;
    RESET library;
    NEXT library_header IN library;

    IF library_header^.version = llc$object_library_version THEN
      NEXT library_dictionary: [1 .. library_header^.number_of_dictionaries] IN library;
      IF library_dictionary = NIL THEN
        osp$set_status_abnormal ('PM', lle$library_header_missing, '', status);
        RETURN; {----->
      IFEND;

      number_of_entry_points := 0;

    /find_entry_point_dictionary/
      FOR i := LOWERBOUND (library_dictionary^) TO UPPERBOUND (library_dictionary^) DO
        IF (library_dictionary^ [i].kind = llc$entry_point_dictionary) THEN
          entry_point_dictionary := #PTR (library_dictionary^ [i].entry_point_dictionary, library^);
          number_of_entry_points := UPPERBOUND (entry_point_dictionary^);
          EXIT /find_entry_point_dictionary/; {----->
        IFEND;
      FOREND /find_entry_point_dictionary/;

    ELSEIF library_header^.version = 'V1.0' THEN
      RESET library;
      NEXT library_hdr IN library;
      number_of_entry_points := library_hdr^.number_of_entry_points;
      entry_point_dictionary := #PTR (library_hdr^.entry_point_dictionary, library^);

    ELSE
      osp$set_status_abnormal ('PM', lle$wrong_library_version, llc$object_library_version, status);
      RETURN; {----->
    IFEND;

    IF number_of_entry_points > 0 THEN
      search_entry_point_dictionary (name, entry_point_dictionary, entry_point_found, dictionary_index);
      IF entry_point_found THEN
        entry_point_dictionary_item := entry_point_dictionary^ [dictionary_index];
      IFEND;
    IFEND;
  PROCEND find_entry_point_in_library;
?? TITLE := '  [XDCL, #GATE] pmp$verify_library', EJECT ??
*copy pmh$verify_library

  PROCEDURE [XDCL, #GATE] pmp$verify_library
    (    library_file: ^SEQ ( * );
     VAR version: string (4);
     VAR status: ost$status);

    VAR
      entry_dictionary: ^llt$entry_point_dictionary,
      i: 0 .. llc$max_dictionaries_on_library,
      lib: ^cell,
      library: lot$load_file,
      library_dictionary: ^llt$object_library_dictionaries,
      library_hdr: ^llt$object_library_header_v1_0,
      library_header: ^llt$object_library_header,
      module_dictionary: ^llt$module_dictionary,
      number_of_entry_points: 0 .. llc$max_entry_points_in_library,
      number_of_modules: 0 .. llc$max_modules_in_library;

    status.normal := TRUE;

    lib := library_file;
    IF (lib = NIL) OR NOT mmp$verify_access (^lib, mmc$va_read) THEN
      osp$set_status_condition (pme$invalid_sequence_pointer, status);
      RETURN; {----->
    IFEND;

    library := library_file;
    RESET library;

    NEXT library_header IN library;
    IF library_header = NIL THEN
      osp$set_status_abnormal ('PM', lle$library_header_missing, '', status);
      RETURN; {----->
    IFEND;

    version := library_header^.version;

    IF library_header^.version = llc$object_library_version THEN
      NEXT library_dictionary: [1 .. library_header^.number_of_dictionaries] IN library;
      IF library_dictionary = NIL THEN
        osp$set_status_abnormal ('PM', lle$library_header_missing, '', status);
        RETURN; {----->
      IFEND;

      number_of_modules := 0;
      number_of_entry_points := 0;

      FOR i := LOWERBOUND (library_dictionary^) TO UPPERBOUND (library_dictionary^) DO
        CASE library_dictionary^ [i].kind OF
        = llc$module_dictionary =
          module_dictionary := #PTR (library_dictionary^ [i].module_dictionary, library^);
          number_of_modules := UPPERBOUND (module_dictionary^);
        = llc$entry_point_dictionary =
          entry_dictionary := #PTR (library_dictionary^ [i].entry_point_dictionary, library^);
          number_of_entry_points := UPPERBOUND (entry_dictionary^);
        ELSE
        CASEND;
      FOREND;

    ELSEIF library_header^.version = 'V1.0' THEN
      RESET library;

      NEXT library_hdr IN library;
      IF library_hdr = NIL THEN
        osp$set_status_abnormal ('PM', lle$library_header_missing, '', status);
        RETURN; {----->
      IFEND;

      number_of_modules := library_hdr^.number_of_modules;
      module_dictionary := #PTR (library_hdr^.module_dictionary, library^);
      number_of_entry_points := library_hdr^.number_of_entry_points;
      entry_dictionary := #PTR (library_hdr^.entry_point_dictionary, library^);

    ELSE
      osp$set_status_abnormal ('PM', lle$wrong_library_version, llc$object_library_version, status);
      RETURN; {----->
    IFEND;

    IF number_of_modules = 0 THEN
      osp$set_status_abnormal ('PM', lle$empty_module_dictionary, '', status);
      RETURN; {----->
    IFEND;

    IF module_dictionary = NIL THEN
      osp$set_status_abnormal ('PM', lle$bad_module_dictionary_ptr, '', status);
      RETURN; {----->
    IFEND;

    IF number_of_entry_points <> 0 THEN
      IF entry_dictionary = NIL THEN
        osp$set_status_abnormal ('PM', lle$bad_entry_dictionary_ptr, '', status);
      IFEND;
    IFEND;

  PROCEND pmp$verify_library;
?? TITLE := '  [XDCL, #GATE] pmp$get_library_directories', EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$get_library_dictionaries
    (    library: ^SEQ ( * );
     VAR dictionaries: llt$library_dictionary_pointers;
     VAR status: ost$status);

*copyc pmh$get_library_dictionaries

    VAR
      i: 0 .. llc$max_dictionaries_on_library,
      library_dictionary: ^llt$object_library_dictionaries,
      local_library: ^SEQ ( * ),
      object_library_hdr: ^llt$object_library_header_v1_0,
      object_library_header: ^llt$object_library_header,
      version: string (4);

    status.normal := TRUE;

    pmp$verify_library (library, version, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    local_library := library;
    RESET local_library;
    NEXT object_library_header IN local_library;

    dictionaries.library_version := version;
    dictionaries.module_dictionary := NIL;
    dictionaries.entry_point_dictionary := NIL;
    dictionaries.command_dictionary := NIL;
    dictionaries.function_dictionary := NIL;
    dictionaries.help_module_dictionary := NIL;
    dictionaries.message_module_dictionary := NIL;
    dictionaries.panel_dictionary := NIL;

    IF version = llc$object_library_version THEN
      NEXT library_dictionary: [1 .. object_library_header^.number_of_dictionaries] IN local_library;

      FOR i := LOWERBOUND (library_dictionary^) TO UPPERBOUND (library_dictionary^) DO
        CASE library_dictionary^ [i].kind OF
        = llc$module_dictionary =
          dictionaries.module_dictionary := #PTR (library_dictionary^ [i].module_dictionary, local_library^);
        = llc$entry_point_dictionary =
          dictionaries.entry_point_dictionary := #PTR (library_dictionary^ [i].entry_point_dictionary,
                local_library^);
        = llc$command_dictionary =
          dictionaries.command_dictionary := #PTR (library_dictionary^ [i].command_dictionary,
                local_library^);
        = llc$function_dictionary =
          dictionaries.function_dictionary := #PTR (library_dictionary^ [i].function_dictionary,
                local_library^);
        = llc$help_module_dictionary =
          dictionaries.help_module_dictionary := #PTR (library_dictionary^ [i].help_module_dictionary,
                local_library^);
        = llc$message_module_dictionary =
          dictionaries.message_module_dictionary := #PTR (library_dictionary^ [i].message_module_dictionary,
                local_library^);
        = llc$panel_dictionary =
          dictionaries.panel_dictionary := #PTR (library_dictionary^ [i].panel_dictionary, local_library^);
        ELSE
          ;
        CASEND;
      FOREND;

    ELSEIF object_library_header^.version = 'V1.0' THEN
      RESET local_library;
      NEXT object_library_hdr IN local_library;
      dictionaries.module_dictionary := #PTR (object_library_hdr^.module_dictionary, local_library^);

      IF object_library_hdr^.number_of_entry_points <> 0 THEN
        dictionaries.entry_point_dictionary := #PTR (object_library_hdr^.entry_point_dictionary,
              local_library^);
      IFEND;
    IFEND;

  PROCEND pmp$get_library_dictionaries;
?? TITLE := '  [XDCL, #GATE] pmp$find_module_in_library', EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$find_module_in_library
    (    name: {input} pmt$program_name;
         object_library: ^SEQ ( * );
     VAR address: pmt$object_library_address;
     VAR status: ost$status);

*copyc pmh$find_module_in_library

?? NEWTITLE := '    unaccessible_library', EJECT ??

    PROCEDURE unaccessible_library
      (    condition: pmt$condition;
           condition_descriptor: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      osp$set_status_from_condition ('PM', condition, save_area, status, handler_status);
      EXIT pmp$find_module_in_library; {----->
    PROCEND unaccessible_library;
?? OLDTITLE, EJECT ??

    VAR
      command_header: ^llt$library_member_header,
      command_description_header: ^llt$library_member_header,
      dictionary_index: 1 .. llc$max_modules_in_library,
      function_header: ^llt$library_member_header,
      function_description_header: ^llt$library_member_header,
      i: 0 .. llc$max_dictionaries_on_library,
      library: lot$load_file,
      library_dictionary: ^llt$object_library_dictionaries,
      library_hdr: ^llt$object_library_header_v1_0,
      library_header: ^llt$object_library_header,
      message_header: ^llt$library_member_header,
      module_dictionary: ^llt$module_dictionary,
      module_found: boolean,
      module_header: ^llt$load_module_header,
      number_of_modules: 0 .. llc$max_modules_in_library,
      object_text_descriptor: ^llt$object_text_descriptor,
      panel_header: ^llt$library_member_header,
      program_header: ^llt$library_member_header,
      version: string (4);

    status.normal := TRUE;

    module_found := FALSE;
    library := object_library;
    RESET library;

    pmp$verify_library (library, version, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    RESET library;
    NEXT library_header IN library;

    IF version = llc$object_library_version THEN

      NEXT library_dictionary: [1 .. library_header^.number_of_dictionaries] IN library;
      IF library_dictionary = NIL THEN
        osp$set_status_abnormal ('PM', lle$library_header_missing, '', status);
        RETURN; {----->
      IFEND;

      number_of_modules := 0;

    /find_module_dictionary/
      FOR i := LOWERBOUND (library_dictionary^) TO UPPERBOUND (library_dictionary^) DO
        IF (library_dictionary^ [i].kind = llc$module_dictionary) THEN
          module_dictionary := #PTR (library_dictionary^ [i].module_dictionary, library^);
          number_of_modules := UPPERBOUND (module_dictionary^);
          EXIT /find_module_dictionary/; {----->
        IFEND;
      FOREND /find_module_dictionary/;

    ELSEIF library_header^.version = 'V1.0' THEN
      RESET library;
      NEXT library_hdr IN library;
      number_of_modules := library_hdr^.number_of_modules;
      module_dictionary := #PTR (library_hdr^.module_dictionary, library^);

    ELSE
      osp$set_status_abnormal ('PM', lle$wrong_library_version, llc$object_library_version, status);
      RETURN; {----->
    IFEND;

    IF number_of_modules = 0 THEN
      osp$set_status_abnormal ('PM', lle$empty_module_dictionary, '', status);
      RETURN; {----->
    IFEND;

    IF module_dictionary = NIL THEN
      osp$set_status_abnormal ('PM', lle$bad_module_dictionary_ptr, '', status);
      RETURN; {----->
    IFEND;

    search_for_module_in_dictionary (^name, module_dictionary, module_found, dictionary_index);

    IF module_found THEN
      CASE module_dictionary^ [dictionary_index].kind OF
      = llc$load_module =
        address.kind := llc$load_module;
        module_header := #PTR (module_dictionary^ [dictionary_index].module_header, library^);
        IF module_header <> NIL THEN
          get_load_module (^name, module_header, library, address.load_module, status);
        ELSE
          module_found := FALSE;
          osp$set_status_abnormal ('PM', lle$bad_load_header_ptr, '', status);
        IFEND;

      = llc$ppu_object_module =
        address.kind := llc$ppu_object_module;
        object_text_descriptor := #PTR (module_dictionary^ [dictionary_index].ppu_header, library^);
        IF (object_text_descriptor <> NIL) THEN
          get_ppu_module (^name, object_text_descriptor, library, address.ppu_object_module, status);
        ELSE
          module_found := FALSE;
          osp$set_status_abnormal ('PM', lle$bad_ppu_header_ptr, '', status);
        IFEND;

      = llc$program_description =
        address.kind := llc$program_description;
        program_header := #PTR (module_dictionary^ [dictionary_index].program_header, library^);
        IF program_header <> NIL THEN
          address.program_description := #PTR (program_header^.member, library^);
          IF address.program_description <> NIL THEN
            RESET address.program_description;
          ELSE
            module_found := FALSE;
            osp$set_status_abnormal ('PM', lle$bad_library_member_header, 'PROGRAM DESCRIPTION', status);
          IFEND;
        ELSE
          module_found := FALSE;
          osp$set_status_abnormal ('PM', lle$bad_program_header_ptr, '', status);
        IFEND;

      = llc$command_description =
        address.kind := llc$command_description;
        command_description_header := #PTR (module_dictionary^ [dictionary_index].command_description_header,
              library^);
        IF command_description_header <> NIL THEN
          address.command_description := #PTR (command_description_header^.member, library^);
          IF address.command_description <> NIL THEN
            RESET address.command_description;
          ELSE
            module_found := FALSE;
            osp$set_status_abnormal ('PM', lle$bad_library_member_header, 'COMMAND DESCRIPTION', status);
          IFEND;
        ELSE
          module_found := FALSE;
          osp$set_status_abnormal ('PM', lle$bad_program_header_ptr, '', status);
        IFEND;

      = llc$command_procedure =
        address.kind := llc$command_procedure;
        command_header := #PTR (module_dictionary^ [dictionary_index].command_header, library^);
        IF command_header <> NIL THEN
          address.scl_procedure := #PTR (command_header^.member, library^);
          IF address.scl_procedure <> NIL THEN
            RESET address.scl_procedure;
          ELSE
            module_found := FALSE;
            osp$set_status_abnormal ('PM', lle$bad_library_member_header, 'COMMAND PROCEDURE', status);
          IFEND;
        ELSE
          module_found := FALSE;
          osp$set_status_abnormal ('PM', lle$bad_scl_header_ptr, '', status);
        IFEND;

      = llc$function_procedure =
        address.kind := llc$function_procedure;
        function_header := #PTR (module_dictionary^ [dictionary_index].function_header, library^);
        IF function_header <> NIL THEN
          address.scl_procedure := #PTR (function_header^.member, library^);
          IF address.scl_procedure <> NIL THEN
            RESET address.scl_procedure;
          ELSE
            module_found := FALSE;
            osp$set_status_abnormal ('PM', lle$bad_library_member_header, 'FUNCTION PROCEDURE', status);
          IFEND;
        ELSE
          module_found := FALSE;
          osp$set_status_abnormal ('PM', lle$bad_scl_header_ptr, '', status);
        IFEND;

      = llc$function_description =
        address.kind := llc$function_description;
        function_description_header := #PTR (module_dictionary^ [dictionary_index].
              function_description_header, library^);
        IF function_description_header <> NIL THEN
          address.function_description := #PTR (function_description_header^.member, library^);
          IF address.function_description <> NIL THEN
            RESET address.function_description;
          ELSE
            module_found := FALSE;
            osp$set_status_abnormal ('PM', lle$bad_library_member_header, 'FUNCTION DESCRIPTION', status);
          IFEND;
        ELSE
          module_found := FALSE;
          osp$set_status_abnormal ('PM', lle$bad_program_header_ptr, '', status);
        IFEND;

      = llc$message_module =
        address.kind := llc$message_module;
        message_header := #PTR (module_dictionary^ [dictionary_index].message_header, library^);
        IF message_header <> NIL THEN
          address.message_module := #PTR (message_header^.member, library^);
          IF address.message_module <> NIL THEN
            RESET address.message_module;
          ELSE
            module_found := FALSE;
            osp$set_status_abnormal ('PM', lle$bad_library_member_header, 'MESSAGE MODULE', status);
          IFEND;
        ELSE
          module_found := FALSE;
          osp$set_status_abnormal ('PM', lle$bad_scl_header_ptr, '', status);
        IFEND;

      = llc$panel_module =
        address.kind := llc$panel_module;
        panel_header := #PTR (module_dictionary^ [dictionary_index].panel_header, library^);
        IF panel_header <> NIL THEN
          address.panel_module := #PTR (panel_header^.member, library^);
          IF address.panel_module <> NIL THEN
            RESET address.panel_module;
          ELSE
            module_found := FALSE;
            osp$set_status_abnormal ('PM', lle$bad_library_member_header, 'FORM MODULE', status);
          IFEND;
        ELSE
          module_found := FALSE;
          osp$set_status_abnormal ('PM', lle$bad_scl_header_ptr, '', status);
        IFEND;
      ELSE
        ;
      CASEND;

    ELSE
      osp$set_status_abnormal ('PM', lle$module_not_found, name, status);
    IFEND;

  PROCEND pmp$find_module_in_library;
?? TITLE := '  search_for_module_in_dictionary', EJECT ??

  PROCEDURE search_for_module_in_dictionary
    (    name: {input} ^pmt$program_name;
     VAR module_dictionary: {input} ^llt$module_dictionary;
     VAR module_found {control} : boolean;
     VAR dictionary_index: 1 .. llc$max_modules_in_library);

    VAR
      search_index: 1 .. llc$max_modules_in_library;


  /sequential_search/
    FOR search_index := 1 TO UPPERBOUND (module_dictionary^) DO
      IF name^ = module_dictionary^ [search_index].name THEN
        dictionary_index := search_index;
        module_found := TRUE;
        RETURN; {----->
      IFEND;
    FOREND /sequential_search/;
    module_found := FALSE;
  PROCEND search_for_module_in_dictionary;
?? TITLE := '  get_load_module', EJECT ??

  PROCEDURE get_load_module
    (    name: {input} ^pmt$program_name;
         module_header: ^llt$load_module_header;
     VAR library: lot$load_file;
     VAR load_module: ^llt$object_module;
     VAR status: ost$status);

    VAR
      object_text_descriptor_of_ident: ^llt$object_text_descriptor,
      object_text_descriptor_of_tra: ^llt$object_text_descriptor;

    status.normal := TRUE;

    object_text_descriptor_of_ident := #PTR (module_header^.interpretive_element, library^);
    object_text_descriptor_of_tra := #PTR (module_header^.interpretive_header.transfer_symbol, library^);

    RESET library TO object_text_descriptor_of_ident;
    NEXT load_module: [[REP (#OFFSET (object_text_descriptor_of_tra) + #SIZE (llt$object_text_descriptor) +
          #SIZE (llt$transfer_symbol) - #OFFSET (object_text_descriptor_of_ident)) OF cell]] IN library;
    IF load_module = NIL THEN
      osp$set_status_abnormal ('PM', lle$bad_module, name^, status);
      RETURN; {----->
    IFEND;

  PROCEND get_load_module;
?? TITLE := '  get_ppu_module', EJECT ??

  PROCEDURE get_ppu_module
    (    name: {input} ^pmt$program_name;
         object_text_descriptor: ^llt$object_text_descriptor;
     VAR library: ^SEQ ( * );
     VAR ppu_object_module: ^llt$object_module;
     VAR status: ost$status);

    VAR
      current_sequence_position: ost$segment_offset,
      new_identification_record: ^llt$identification,
      new_object_text_descriptor: ^llt$object_text_descriptor,
      ppu_absolute: ^llt$ppu_absolute;

    status.normal := TRUE;

    RESET library TO object_text_descriptor;
    NEXT new_object_text_descriptor IN library;
    IF new_object_text_descriptor = NIL THEN
      osp$set_status_abnormal ('PM', lle$bad_module, name^, status);
      RETURN; {----->
    IFEND;

    NEXT new_identification_record IN library;
    IF new_identification_record = NIL THEN
      osp$set_status_abnormal ('PM', lle$bad_module, name^, status);
      RETURN; {----->
    IFEND;

    NEXT new_object_text_descriptor IN library;
    IF new_object_text_descriptor = NIL THEN
      osp$set_status_abnormal ('PM', lle$bad_module, name^, status);
      RETURN; {----->
    IFEND;

    NEXT ppu_absolute: [0 .. new_object_text_descriptor^.number_of_words - 1] IN library;
    IF ppu_absolute = NIL THEN
      osp$set_status_abnormal ('PM', lle$bad_module, name^, status);
      RETURN; {----->
    IFEND;

    current_sequence_position := i#current_sequence_position (library);

    RESET library TO object_text_descriptor;
    NEXT ppu_object_module: [[REP (current_sequence_position - #OFFSET (object_text_descriptor)) OF cell]] IN
          library;
    IF ppu_object_module = NIL THEN
      osp$set_status_abnormal ('PM', lle$bad_module, name^, status);
    IFEND;
  PROCEND get_ppu_module;
?? TITLE := '  [XDCL, #GATE] pmp$open_object_library', EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$open_object_library
    (    file_name: amt$local_file_name;
     VAR file_identifier: amt$file_identifier;
     VAR object_library: ^SEQ ( * );
     VAR status: ost$status);

*copyc pmh$open_object_library

    VAR
      contains_data: boolean,
      current_attributes: array [1 .. 2] of amt$get_item,
      existing_file: boolean,
      local_file: boolean,
      read_attachment: [STATIC, READ, oss$job_paged_literal] array
            [1 .. 2] of fst$attachment_option := [[fsc$access_and_share_modes,
            [fsc$specific_access_modes, [fsc$read]], [fsc$determine_from_access_modes]],
            [fsc$create_file, FALSE]],
      required_attributes: [STATIC, READ, oss$job_paged_literal] array [1 .. 1] of
            fst$file_cycle_attribute := [[fsc$file_contents_and_processor, fsc$object_library,
            fsc$unknown_processor]],
      segment_pointer: amt$segment_pointer;

    status.normal := TRUE;

    current_attributes [1].key := amc$file_contents;
    current_attributes [2].key := amc$file_structure;
    amp$get_file_attributes (file_name, current_attributes, local_file, existing_file, contains_data, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    IF NOT contains_data THEN
      osp$set_status_abnormal ('PM', lle$empty_load_file, file_name, status);
      RETURN; {----->
    ELSEIF (current_attributes [1].file_contents <> amc$object) OR
          (current_attributes [2].file_structure <> amc$library) THEN
      osp$set_status_abnormal ('PM', lle$file_not_load_file, file_name, status);
      RETURN; {----->
    ELSE
      fsp$open_file (file_name, amc$segment, ^read_attachment, NIL, NIL, ^required_attributes, NIL,
            file_identifier, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;

      amp$get_segment_pointer (file_identifier, amc$sequence_pointer, segment_pointer, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;
    object_library := segment_pointer.sequence_pointer;
    RESET object_library;

  PROCEND pmp$open_object_library;

?? TITLE := '  [XDCL, #GATE] pmp$close_object_library', EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$close_object_library
    (    file_identifier: amt$file_identifier;
     VAR status: ost$status);

*copyc pmh$close_object_library

    fsp$close_file (file_identifier, status);

  PROCEND pmp$close_object_library;
?? TITLE := '  [XDCL, #GATE] pmp$get_application_information', EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$get_application_information
    (    application_address: ost$pva;
     VAR application_module_name: ost$name;
     VAR application_identifier: llt$application_identifier;
     VAR library_privilege: ost$name;
     VAR status: ost$status);

*copyc pmh$get_application_information

?? NEWTITLE := '    find_section_for_pva', EJECT ??

    PROCEDURE find_section_for_pva
      (    module_item: ^dbt$module_address_table_item;
           pva: ost$pva;
       VAR pva_found: boolean);

{  PURPOSE:
{    This procedure searches for a PVA in the section items of
{    a module address table item in DEBUG'S module address table.
{    The PVA is found when it points within one of the sections
{    in the module.

      VAR
        section_item_index: llt$section_ordinal;

      pva_found := FALSE;
      section_item_index := 0;
      WHILE (NOT pva_found) AND (section_item_index <= UPPERBOUND (module_item^.section_item)) DO
        pva_found := ((pva.ring = module_item^.section_item [section_item_index].address.ring) AND
              (pva.seg = module_item^.section_item [section_item_index].address.seg) AND
              ((pva.offset >= module_item^.section_item [section_item_index].address.offset) AND
              (pva.offset < module_item^.section_item [section_item_index].address.offset +
              module_item^.section_item [section_item_index].length)));
        section_item_index := section_item_index + 1;
      WHILEND;

    PROCEND find_section_for_pva;

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

    PROCEDURE find_module_table_for_pva
      (    pva: ost$pva;
       VAR module_item: ^dbt$module_address_table_item);

{  PURPOSE:
{    This procedure searches the DEBUG module address table
{    for a PVA.

      VAR
        pva_found: boolean;

      module_item := dbp$module_table_address ();

      pva_found := FALSE;
      WHILE (NOT pva_found) AND (module_item <> NIL) DO
        find_section_for_pva (module_item, pva, pva_found);
        IF NOT pva_found THEN
          module_item := module_item^.next_module;
        IFEND;

      WHILEND;

    PROCEND find_module_table_for_pva;

?? OLDTITLE, EJECT ??

    VAR
      invalid_pva: ^cell,
      module_item: ^dbt$module_address_table_item,
      pva_length: integer,
      pva_string: string (15);

    status.normal := TRUE;

    find_module_table_for_pva (application_address, module_item);
    IF module_item = NIL THEN
      invalid_pva := #ADDRESS (application_address.ring, application_address.seg, application_address.offset);
      STRINGREP (pva_string, pva_length, invalid_pva);
      osp$set_status_abnormal ('PM', pme$incorrect_applic_address, pva_string (1, pva_length), status);
      RETURN; {----->
    IFEND;

    application_module_name := module_item^.name;
    IF module_item^.application_identifier = NIL THEN
      application_identifier.name := osc$null_name;
    ELSE
      application_identifier.name := module_item^.application_identifier^.name;
    IFEND;

{
{  Library_privilege is hard coded to 'OBJECT' until it can be obtained from
{  the file registration attributes in 1.3.1.
{

    library_privilege := 'OBJECT';

  PROCEND pmp$get_application_information;
MODEND pmm$object_code_utilities
