?? RIGHT := 110 ??
?? NEWTITLE := 'DEFINE_SUBPRODUCT Subutility: DEFINE_LIBRARY_MERGE Subcommand.' ??
MODULE ram$define_library_merge;

{ PURPOSE:
{   This module updates all fields necessary to define a library merge.
{
{ DESIGN:
{   The element list is searched for the correct file.  Then
{   all fields necessary to define a library merge are updated.
{   The compiled module resides in RAF$LIBRARY.
{
{ NOTES:
{

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc rae$package_software_cc
?? POP ??
*copyc clp$convert_file_ref_to_string
*copyc clp$get_fs_path_elements
*copyc clp$get_value
*copyc clp$scan_parameter_list
*copyc clp$trimmed_string_size
*copyc fsp$convert_fs_structure_to_pf
*copyc osp$append_status_file
*copyc osp$append_status_parameter
*copyc osp$generate_error_message
*copyc osp$set_status_abnormal
*copyc rap$get_file_path_and_ref
*copyc rap$locate_element
*copyc rav$subproduct_info_pointers
*copyc rav$pacs_catalog_p
*copyc rav$pacs_catalog_ref_p
*copyc rav$defs_scratch_segment

?? TITLE := 'Global Declarations Declared by This Module', EJECT ??


?? TITLE := '[XDCL] rap$define_library_merge', EJECT ??

{ PURPOSE:
{   This command interface sets the library_merge fields for a
{   file in the current subproduct.
{
{ DESIGN:
{   The library is validated as a legal file path.  If the installation
{   path has not been set in the attributes record, the file path cannot
{   totally validated at this time.  A warning message is outputed if
{   the library is not part of :$SYSTEM.$SYSTEM.
{   The file is validated as part of the current subproduct.
{   The file is located in the element_list and validated as type FILE.
{   All of the necessary fields are updated.
{
{ NOTES:
{
{

  PROCEDURE [XDCL] rap$define_library_merge
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);


{ pdt deflm_pdt (
{   file, f    : file = $required
{   library, l : file = $required
{   status     : var of status = $optional
{   )

?? PUSH (LISTEXT := ON) ??

    VAR
      deflm_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table :=
            [^deflm_pdt_names, ^deflm_pdt_params];

    VAR
      deflm_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 5] of
            clt$parameter_name_descriptor := [['FILE', 1], ['F', 1], ['LIBRARY', 2], ['L', 2], ['STATUS', 3]];

    VAR
      deflm_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 3] of clt$parameter_descriptor := [

{ FILE F }
      [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$file_value]],

{ LIBRARY L }
      [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$file_value]],

{ STATUS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$variable_reference, clc$array_not_allowed, clc$status_value]]];

?? POP ??

    VAR
      attributes_p: ^rat$subproduct_attributes,
      element_found: boolean,
      element_p: ^rat$element,
      file_path_index: integer,
      file_path_p: ^pft$path,
      file_path_ref_p: ^fst$file_reference,
      ignore_status: ost$status,
      installation_path_index: rat$path_container_index,
      library_path_p: ^pft$path,
      library_path_ref_p: ^fst$file_reference,
      length: integer,
      master_catalog: string (osc$max_name_size * 2 + 2),
      path_container_p: ^rat$path_container,
      subproduct_info_seq_p: ^rat$subproduct_info_sequence,
      value: clt$value;


    status.normal := TRUE;
    attributes_p := rav$subproduct_info_pointers.attributes_p;
    element_p := rav$subproduct_info_pointers.element_list_p;
    subproduct_info_seq_p := rav$subproduct_info_pointers.subproduct_info_seq_p;
    path_container_p := rav$subproduct_info_pointers.path_container_p;

    IF attributes_p^.first_level_element_count = 0 THEN
      osp$set_status_abnormal ('RA', rae$error_pacs_catalog_empty, '', status);
      RETURN;
    IFEND;

    clp$scan_parameter_list (parameter_list, deflm_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    RESET rav$defs_scratch_segment.sequence_p TO rav$defs_scratch_segment.reset_p;

    rap$get_file_path_and_ref ('LIBRARY', rav$defs_scratch_segment.sequence_p, library_path_p,
          library_path_ref_p, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF library_path_p^ [1] = '$LOCAL' THEN
      osp$set_status_abnormal ('RA', rae$cannot_use_local_catalog, 'the LIBRARY parameter', status);
      RETURN;
    IFEND;

    installation_path_index := attributes_p^.installation_path.path_container_index;

    IF installation_path_index = 0 THEN

      IF NOT ((library_path_p^ [1] = '$SYSTEM') AND (library_path_p^ [2] = '$SYSTEM')) THEN
        osp$set_status_abnormal ('RA', rae$unable_to_validate_lib_merg, '', status);
        osp$generate_error_message (status, ignore_status);
      IFEND;

    ELSE

      IF NOT (((library_path_p^ [1] = '$SYSTEM') AND (library_path_p^ [2] = '$SYSTEM')) OR
              ((library_path_p^ [1] = path_container_p^ [installation_path_index]) AND
            (library_path_p^ [2] = path_container_p^ [installation_path_index + 1]))) THEN

        STRINGREP (master_catalog, length, ':', path_container_p^ [installation_path_index] (1,
              clp$trimmed_string_size (path_container_p^ [installation_path_index])), '.',
              path_container_p^ [installation_path_index + 1]
              (1, clp$trimmed_string_size (path_container_p^ [installation_path_index + 1])));
        osp$set_status_abnormal ('RA', rae$bad_master_catalog_for_lib, '', status);
        osp$append_status_file (osc$status_parameter_delimiter, library_path_ref_p^, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, master_catalog (1, length), status);
        RETURN;

      IFEND;

    IFEND;

    rap$get_file_path_and_ref ('FILE', rav$defs_scratch_segment.sequence_p, file_path_p, file_path_ref_p,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF (#SIZE (file_path_ref_p^) < #SIZE (rav$pacs_catalog_ref_p^)) OR
          (rav$pacs_catalog_ref_p^ <> file_path_ref_p^ (1, #SIZE (rav$pacs_catalog_ref_p^))) THEN
      osp$set_status_abnormal ('RA', rae$not_in_pacs_catalog, '', status);
      osp$append_status_file (osc$status_parameter_delimiter, file_path_ref_p^, status);
      RETURN;
    IFEND;

    file_path_index := UPPERBOUND (rav$pacs_catalog_p^) + 1;

    rap$locate_element (file_path_p, file_path_index, subproduct_info_seq_p, element_p, element_found);

    IF NOT element_found THEN
      osp$set_status_abnormal ('RA', rae$not_in_pacs_catalog, '', status);
      osp$append_status_file (osc$status_parameter_delimiter, file_path_ref_p^, status);
      RETURN;
    IFEND;

    IF element_p^.element_type = rac$catalog THEN
      osp$set_status_abnormal ('RA', rae$expecting_file, '', status);
      osp$append_status_file (osc$status_parameter_delimiter, file_path_ref_p^, status);
      RETURN;
    IFEND;

    add_library_path_to_container (library_path_p^, element_p, rav$subproduct_info_pointers, status);

  PROCEND rap$define_library_merge;

?? TITLE := 'add_library_path_to_container', EJECT ??

{ PURPOSE:
{   This procedure sets:
{        the library_merge.path_container_index to the next available path container.
{        the library_merge.path_length to the file length of the element.
{        For example $SYSTEM.A.B.DDD.E has a length of 5.
{        the info_header_p.path_container_length to total length of all containers used.
{        the path_container_p^s are filled with the names of the library merge file.  In the example above
{        path_container_p^ [i] = $SYSTEM
{        path_container_p^ [i + 1] = A
{        path_container_p^ [i + 2] = B
{        path_container_p^ [i + 3] = DDD
{        path_container_p^ [i + 4] = E
{
{ DESIGN:
{   If the element already contains a library_merge.path_container_index check to see if the
{   new path is of the same length as the old path.  If they are the same length put the new path in the
{   same containers that the old path used.
{
{   Else set the library_merge.path_container_index to the next available index number.
{   The info_header_p^.path_container_index contains the value of the last used path container.
{   Set the value of the library_merge.path_length to the uppervalue of the array that contains the path.
{   See example above to understand how the length of a path is determined.
{   The info_header.path_container_length is updated to point to the last used path container.
{   If the path container has not been created, it is created with a size large enough to hold this path.
{   Else the path_containers size is set to the size indicated in info_header.path_container_length.
{   Then the path_containers are filled with the path.
{
{ NOTES:
{
  PROCEDURE add_library_path_to_container
    (    library_path: pft$path;
         element_p: ^rat$element;
     VAR subproduct_info_pointers: rat$subproduct_info_pointers;
     VAR status: ost$status);

    VAR
      i: rat$path_container_index,
      index: rat$path_container_index,
      info_header_p: ^rat$subproduct_info_header,
      path_container_p: ^rat$path_container,
      subproduct_info_seq_p: ^rat$subproduct_info_sequence;


    status.normal := TRUE;
    info_header_p := subproduct_info_pointers.info_header_p;
    subproduct_info_seq_p := subproduct_info_pointers.subproduct_info_seq_p;
    path_container_p := subproduct_info_pointers.path_container_p;

    IF (element_p^.library_merge.path_container_index <> 0) AND
          (element_p^.library_merge.path_length = UPPERBOUND (library_path)) THEN

      index := element_p^.library_merge.path_container_index;
      FOR i := 1 TO UPPERBOUND (library_path) DO
        path_container_p^ [index] := library_path [i];
        index := index + 1;
      FOREND;

    ELSE
      element_p^.library_merge.path_container_index := info_header_p^.path_container_length + 1;
      element_p^.library_merge.path_length := UPPERBOUND (library_path);
      info_header_p^.path_container_length := info_header_p^.path_container_length +
            UPPERBOUND (library_path);

      IF path_container_p = NIL THEN
        NEXT path_container_p: [1 .. info_header_p^.path_container_length] IN subproduct_info_seq_p;
        info_header_p^.path_container_p := #REL (path_container_p, subproduct_info_seq_p^);
      ELSE
        RESET subproduct_info_seq_p TO path_container_p;
        NEXT path_container_p: [1 .. info_header_p^.path_container_length] IN subproduct_info_seq_p;
      IFEND;

      index := element_p^.library_merge.path_container_index;
      FOR i := 1 TO UPPERBOUND (library_path) DO
        path_container_p^ [index] := library_path [i];
        index := index + 1;
      FOREND;

      subproduct_info_pointers.subproduct_info_seq_p := subproduct_info_seq_p;
      subproduct_info_pointers.path_container_p := path_container_p;
    IFEND;

  PROCEND add_library_path_to_container;

MODEND ram$define_library_merge;
