*copyc OSD$DEFAULT_PRAGMATS
MODULE iim$st_open;
?? TITLE := 'MODULE iim$st_open' ??

?? PUSH (LISTEXT := ON) ??
*copyc ame$open_validation_errors
*copyc amc$fap_request_codes
*copyc amp$access_method
*copyc amp$get_file_attributes
*copyc amp$set_file_instance_abnormal
*copyc amt$fap_declarations
*copyc amt$file_identifier
*copyc cle$ecc_lexical
*copyc clp$convert_integer_to_string
*copyc clp$validate_name
*copyc ife$error_codes
*copyc iip$search_connection_desc
*copyc iip$xlate_local_file_to_session
*copyc iik$keypoints
*copyc iip$clear_lock
*copyc iip$set_lock
*copyc iip$st_initialize_connection
*copyc iip$st_init_open_desc_atributes
*copyc iit$connection_description
*copyc iiv$connection_desc_ptr
*copyc iiv$interactive_terminated
*copyc iiv$int_task_open_file_count
*copyc nat$data_fragments
*copyc osc$timesharing_terminal_file
*copyc osp$set_status_abnormal
*copyc oss$job_paged_literal
*copyc oss$task_private
*copyc osv$job_pageable_heap
*copyc osv$task_private_heap
*copyc osv$task_shared_heap
*copyc rmp$get_device_class
*copyc iip$vt_open
?? POP ??

?? NEWTITLE := 'PROCEDURE iip$st_open', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$st_open (file_id: amt$file_identifier;
        open_file_desc_pointer: ^iit$st_open_file_description;
        file_name: amt$local_file_name;
        layer_number: amt$fap_layer_number;
    VAR status: ost$status);

    VAR
      call_block: amt$call_block,
      connection_desc_ptr: ^iit$connection_description,
      contains_data: boolean,
      device_assigned: boolean,
      device_class: rmt$device_class,
      fetch_file_contents_array: array [1 .. 1] of amt$fetch_item,
      file_attributes: [STATIC, READ, oss$job_paged_literal] array [1 .. 1] of amt$get_item :=
        [[amc$undefined_attribute, amc$null_attribute]],
      iiv$tbl_initialized: [STATIC, oss$task_private] boolean := FALSE,
      lfn: ost$name,
      local_file: boolean,
      local_status: ost$status,
      max_task_count_string: ost$string,
      old_file: boolean,
      terminal_file_name: amt$local_file_name,
      validated_name: ost$name,
      valid_name: boolean;

  /open_file/
    BEGIN


    { Put the file name into the open file description.

      clp$validate_name (file_name, validated_name, valid_name);
      IF NOT valid_name THEN
        osp$set_status_abnormal ('CL', cle$improper_name, file_name, status);
        EXIT /open_file/;
      IFEND;
      open_file_desc_pointer^.file_name := validated_name;

    { Initialize file access information.

      open_file_desc_pointer^.last_get_put_operation := amc$put_next_req;
      open_file_desc_pointer^.last_access_operation := amc$open_req;
      open_file_desc_pointer^.previous_record_length := 0;

    { Get the terminal file name associated with the file being opened.

      iip$xlate_local_file_to_session (file_name, terminal_file_name, status);
      IF NOT status.normal THEN
        EXIT /open_file/;
      IFEND;

    { Make sure the terminal file is actually assigned to a network device.

      rmp$get_device_class (terminal_file_name, device_assigned, device_class, status);
      IF NOT status.normal THEN
        EXIT /open_file/;
      IFEND;
      IF (device_class <> rmc$network_device) OR (NOT device_assigned) THEN
        osp$set_status_abnormal (ifc$interactive_facility_id, ife$file_is_not_network_file,
              '', status);
        EXIT /open_file/;
      IFEND;

      { The connection description was allocated at request_terminal time.  However, check
      { for its possible non-existence, as it could have been subsequently freed by closing
      { of all local files before opening of this one.

      iip$search_connection_desc (terminal_file_name, connection_desc_ptr);
      IF connection_desc_ptr = NIL THEN
        iip$st_initialize_connection (terminal_file_name, status);
        IF NOT status.normal THEN
          EXIT /open_file/;
        IFEND;
        iip$search_connection_desc (terminal_file_name, connection_desc_ptr);
      IFEND;
      connection_desc_ptr^.open_local_file_count := connection_desc_ptr^.open_local_file_count + 1;

      IF connection_desc_ptr^.output_buffer_entry_loc = NIL THEN
        ALLOCATE connection_desc_ptr^.output_buffer_entry_loc: [[REP 10000 OF cell]]
              in osv$job_pageable_heap^;
        RESET connection_desc_ptr^.output_buffer_entry_loc;
        connection_desc_ptr^.output_buffer_exit_loc := connection_desc_ptr^.output_buffer_entry_loc;
      IFEND;

    { Use session file name to point to the terminal connection table in the open file descriptor.

      open_file_desc_pointer^.session_layer_file_name := terminal_file_name;
      open_file_desc_pointer^.vtp_connection_id := connection_desc_ptr^.vtp_connection_id;
      iip$vt_open (terminal_file_name, open_file_desc_pointer^.vtp_file_id, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF iiv$int_task_open_file_count = 0 THEN

      { Increment interactive task count.

        iip$set_lock (iiv$interactive_task_count_lock, osc$wait, local_status);
        IF iiv$interactive_task_count >= 100000 THEN
          iip$clear_lock (iiv$interactive_task_count_lock, local_status);
          clp$convert_integer_to_string (100000, 10, FALSE,
                max_task_count_string, local_status);
          amp$set_file_instance_abnormal (file_id, ame$terminal_task_limit,
                amc$open_req, max_task_count_string.value, status);
          EXIT /open_file/;
        IFEND;
        iiv$interactive_task_count := iiv$interactive_task_count + 1;
        iip$clear_lock (iiv$interactive_task_count_lock, local_status);

      { Initialize the task break level to equal the current job break level.
      { This is a kludge which should be replaced by using task inherited
      { (from the parent) data if/when it is implemented.

        IF NOT iiv$tbl_initialized THEN
          {iiv$task_break_level := iiv$job_break_level;
          iiv$tbl_initialized := TRUE;
        IFEND;
      IFEND;  { IF iiv$int_task_open_file_count = 0 }

    { Initialize connection attributes in the open file descriptor.

      iip$st_init_open_desc_atributes (validated_name, open_file_desc_pointer, status);
      IF NOT status.normal THEN
        EXIT /open_file/;
      IFEND;
      open_file_desc_pointer^.terminal_mode := iic$line;
      fetch_file_contents_array [1].key := amc$file_contents;
      call_block.operation :=  amc$fetch_req;
      call_block.fetch.file_attributes := ^fetch_file_contents_array;
      amp$access_method (file_id,call_block,layer_number,status);
      open_file_desc_pointer^.format_effectors := (fetch_file_contents_array [1].file_contents = amc$list);

    { Increment task open interactive file count.

      iiv$int_task_open_file_count := iiv$int_task_open_file_count + 1;

      IF iiv$downline_data_block_ptr = NIL THEN

      { Allocate space to buffer task output from put partials.

        ALLOCATE iiv$downline_data_block_ptr IN osv$task_private_heap^;
      IFEND;

    END /open_file/;

  PROCEND iip$st_open;

MODEND iim$st_open;
