?? RIGHT := 110 ??
?? NEWTITLE := 'INSTALL_SOFTWARE Utility: RAP$ASSIGN_INSTALL_IDENTIFIER Interface.' ??
MODULE ram$assign_install_identifier;

{ PURPOSE:
{   This module contains the interface and procedure that assigns the
{   installation identifier.
{
{ DESIGN:
{   The compiled module resides in RAF$LIBRARY.
{
{ NOTES:
{

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc rae$install_software_cc
*copyc rat$installation_control_record
?? POP ??
*copyc clp$put_job_command_response
*copyc clp$trimmed_string_size
*copyc pfp$convert_fs_path_to_pf_path
*copyc pfp$convert_string_to_fs_path
*copyc pfp$define_catalog
*copyc pmp$get_compact_date_time
*copyc clp$convert_date_time_to_string
*copyc rav$installation_command_abbrv
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

?? OLDTITLE ??
?? NEWTITLE := '[XDCL] rap$assign_install_identifier', EJECT ??

{ PURPOSE:
{   This interface creates the installation identifier catalog and returns
{   the installation identifier for the installation event.
{
{ DESIGN:
{   The procedure first makes sure the Installation Logs catalog exits.
{   This is done by attempting to create each subcatalog along the the path
{   while ignoring status.  The interface called to create subcatalogs
{   requires the path format be converted from FS to PF format.  In an
{   attempt to simplify the dividing of the path into subcatalogs, the PF
{   path array containing the entire path is created in a sequence.  This
{   will protect the values of the entire PF path array while subsets of
{   the array are used to create the subcatalogs in order of occurance.  In
{   this way assignment to the PF path array is only done once.
{
{   Once the Installation Logs catalog is believed to exist the installation
{   identifier catalog is created under it.  An installation identifier is
{   assigned for this installation event.  The installation identifier is
{   used as the name of the installation identifier catalog.
{
{   The identifier is created using the format:  command abbreviation // '_'
{   // user referenece // '_' // suffix.  The user reference is determined
{   by the value of the packing list name.  When the packing list name is
{   the null name, the current date is used (format:  Y4_M2_D2).  Otherwise,
{   the packing list name passed in is taken as the user reference.
{
{   Determining what suffix to use is done by trial and error.  The suffix
{   starts as 'A' through 'Z', then 'AA' through 'AZ' up to 'ZZ'.  A suffix
{   is generated and appended to the installation identifer, then the
{   installation identifier catalog's creation is attempted.  A status
{   condition is returned when the identifier is already being used.  The
{   process is continued until a unused identifier is formed and the
{   catalog is successfully created or some other status condition is
{   encountered.
{
{ NOTES:
{

  PROCEDURE [XDCL] rap$assign_install_identifier
    (    installation_command: rat$installation_commands;
         installation_logs: rat$path;
         packing_list_name: ost$name;
     VAR installation_identifier: rat$installation_identifier;
     VAR status: ost$status);


    CONST
      first_subcatalog = 1,
      family_user_catalogs = 2; { The first 2 path elements are the family and user catalogs. }


    VAR
      defined: boolean,
      fs_path: string (fsc$max_path_size),
      identifier_length: integer,
      ignore_cycle_reference: fst$cycle_reference,
      ignore_cycle_selector: clt$cycle_selector,
      ignore_open_position: fst$open_position,
      ignore_status: ost$status,
      length: integer,
      line: string (osc$max_string_size),
      number_of_path_elements: fst$number_of_path_elements,
      number_of_subcatalogs: fst$number_of_path_elements,
      path_p: ^pft$path,
      path_sequence_p: ^SEQ ( * ),
      subcatalogs: integer,
      suffix: string (2),
      user_reference: ost$string;


    status.normal := TRUE;

    { Determine the number of subcatalogs in the installation logs catalog
    { path.

    pfp$convert_string_to_fs_path (installation_logs.path (1, installation_logs.size), fs_path,
          number_of_path_elements, ignore_cycle_reference, ignore_open_position, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    { Convert the installation logs catalog path, which is in file reference
    { format to PF format.  Create a sequence to contain the path plus
    { additional entry for the installation identifier.

    PUSH path_sequence_p: [[REP ((number_of_path_elements + 1) * #SIZE (pft$name)) OF cell]];
    RESET path_sequence_p;
    NEXT path_p: [1 .. number_of_path_elements] IN path_sequence_p;
    pfp$convert_fs_path_to_pf_path (fs_path, path_p, ignore_cycle_reference, ignore_cycle_selector, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    { Attempt to create each subcatalog in the installation logs catalog path
    { while ignoring status.

    number_of_subcatalogs := number_of_path_elements - family_user_catalogs;

    FOR subcatalogs := first_subcatalog TO number_of_subcatalogs DO

      RESET path_sequence_p;
      NEXT path_p: [1 .. family_user_catalogs + subcatalogs] IN path_sequence_p;

      pfp$define_catalog (path_p^, ignore_status);

    FOREND;

    { Determine the installation identifier.

    get_user_reference (packing_list_name, user_reference, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    RESET path_sequence_p;
    NEXT path_p: [1 .. number_of_path_elements + 1] IN path_sequence_p;

    defined := FALSE;
    suffix := '';

    REPEAT

      get_identifier_suffix (suffix);

      STRINGREP (installation_identifier, identifier_length,
            rav$installation_command_abbrv [installation_command],
            '_', user_reference.value (1, user_reference.size),
            '_', suffix (1, clp$trimmed_string_size (suffix)));

      path_p^ [number_of_path_elements + 1] (1, * ) := installation_identifier (1, identifier_length);

      pfp$define_catalog (path_p^, status);
      IF NOT status.normal THEN
        IF (status.condition = pfe$name_already_subcatalog) OR
              (status.condition = pfe$name_already_permanent_file) THEN
          status.normal := TRUE;
        ELSE
          RETURN;
        IFEND;
      ELSE
        defined := TRUE;
      IFEND;

    UNTIL defined;

    { Display the installation identifier to $RESPONSE.

    STRINGREP (line, length, '0The installation identifier assigned to this job is ',
          installation_identifier (1, identifier_length), '.');
    clp$put_job_command_response (line (1, length), status);

  PROCEND rap$assign_install_identifier;

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

{ PURPOSE:
{   This procedure returns the next installation identifier suffix.
{
{ DESIGN:
{   The previous suffix is passed in and incremented to create the next
{   suffix.  The suffix is assummed to be initialized to the null string on
{   the first call.  The suffix starts as 'A' through 'Z', then 'AA' through
{   'AZ' up to 'ZZ'.
{
{ NOTES:
{

  PROCEDURE get_identifier_suffix
    (VAR suffix {input, output} : string (2));


    VAR
      char_1: string (1),
      char_2: string (1);


    char_1 := suffix (1, 1);
    char_2 := suffix (2, 1);

    IF char_1 = '' THEN

      char_1 := 'A';

    ELSEIF char_2 = '' THEN

      IF char_1 = 'Z' THEN
        char_1 := 'A';
        char_2 := 'A';
      ELSE
        char_1 := $CHAR ($INTEGER (char_1) + 1);
      IFEND;

    ELSE {both characters are being used}

      IF char_2 = 'Z' THEN
        char_2 := 'A';
        IF char_1 = 'Z' THEN
          char_1 := 'A';
        ELSE
          char_1 := $CHAR ($INTEGER (char_1) + 1);
        IFEND;
      ELSE
        char_2 := $CHAR ($INTEGER (char_2) + 1);
      IFEND;

    IFEND;

    suffix (1, 1) := char_1;
    suffix (2, 1) := char_2;

  PROCEND get_identifier_suffix;

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

{ PURPOSE:
{   This procedure returns the user reference.
{
{ DESIGN:
{   The user reference is determined by the value of the packing list name.
{   When the packing list name is the null name, the current date is used
{   (format:  Y4_M2_D2).  Otherwise, the packing list name passed in is
{   taken as the user reference.
{
{ NOTES:
{

  PROCEDURE get_user_reference
    (    packing_list_name: ost$name;
     VAR user_reference: ost$string;
     VAR status: ost$status);


    VAR
      date_time: clt$date_time;


    status.normal := TRUE;

    IF packing_list_name = osc$null_name THEN

      pmp$get_compact_date_time (date_time.value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      date_time.date_specified := TRUE;
      date_time.time_specified := TRUE;

      clp$convert_date_time_to_string (date_time, 'Y4 M2 D2', user_reference, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      { Convert the user reference to a name by replacing the blank delimiters with underscores.
      { The size field is not affected.

      user_reference.value (5, 1) := '_';
      user_reference.value (8, 1) := '_';

    ELSE {packing list name is used}

      user_reference.size := clp$trimmed_string_size (packing_list_name);
      user_reference.value (1, * ) := packing_list_name;
    IFEND;

  PROCEND get_user_reference;
MODEND ram$assign_install_identifier;
