PROCEDURE (ram$lisci) list_command_information, lisci (
  entry, entries, e: list of any of
      key
        all
        (control_statements, control_statement, cs)
        (first, f)
        $system
      keyend
      name
      file
    anyend = first
  output, o: file = $output
  display_options, display_option, do: list of key
      all
      (all_names, all_name, an)
      (source, s)
      (brief_help, bh)
      (full_help, fh)
      (compact_parameter_descriptions, compact_parameter_description, cpd)
      (parameter_descriptions, parameter_description, pd)
      (parameter_help, ph)
      (advanced_usage, au)
    keyend = osd$disci_display_options, (compact_parameter_descriptions, advanced_usage)
  list_options, list_option, lo: list of key
      all
      (commands_only, co)
      (functions_only, fo)
    keyend = all
  page_width, pw: (BY_NAME, ADVANCED) integer 60..132 = 80
  page_length, pl: (BY_NAME, ADVANCED) integer 16..6000 = 60
  index_when_pages_equal, iwpe: (BY_NAME, ADVANCED) integer 1..$max_integer = 4
  status)

" PURPOSE:
"   List all command and function names and parameters from one or several command list entries.
" DESIGN:
"   Use display_command_list_entry to produce a list of command and function names. Read this list of command
"   and function names, and execute the display_command_information or display_function_information command
"   to produce a list of parameter descriptions.
" NOTES:
"   Excessive pagination is avoided while retaining parameter descriptions on the same page on which they
"   started. An index is produced only when the index_when_pages_equal value is exceeded. Both the
"   primary output and index are forced to an even number of pages for two-sided listing purposes.

"$format=no
  VAR
    all_commands: file = $unique(:$local)
    commands_found: boolean
    command_list: list 0 .. page_length/4 of string = ()
    command_list_entry: string
    command_names: list 0 .. $max_list of string
    disci_path: string = ''
    entry_is_a_file: boolean
    functions_found: boolean
    ignore: status
    index: file = $unique(:$local)
    instant: file = $unique(:$local)
    lines_written: integer = page_length
    page_number: integer = 1
    parameter_list: list 0 .. $max_list of string
    parameters: file = $unique(:$local)
    previous_command: string
    sorted_index: file = $unique(:$local)
    title: string = $justify('1'//$processor(model, 0)//'/'//$processor(serial, 0)//'  '//$job(os_version)//..
'  '//$date(iso)//'  '//$time(hms), page_width-10, left)
  VAREND
"$format=yes

" Delete all procedure created files upon procedure termination.
  WHEN exit DO
    $system.delete_file file=all_commands status=ignore
    $system.delete_file file=instant status=ignore
    $system.delete_file file=index status=ignore
    $system.delete_file file=parameters status=ignore
    $system.delete_file file=sorted_index status=ignore
  WHENEND

" Establish file connections and file attributes for temporary files.
  PUSH file_connections
  $system.create_file_connection standard_file=$errors file=parameters
  $system.set_file_attributes file=parameters page_format=continuous open_position=$asis pw=page_width-4
  $system.set_file_attributes file=instant file_content=list page_format=continuous pw=page_width
  $system.set_file_attributes file=all_commands file_content=legible page_format=continuous pw=$max_string

  IF list_option = commands_only THEN
    display_command_list_entry entry=entry display_option=(commands all_names) output=all_commands
  ELSEIF list_option = functions_only THEN
    display_command_list_entry entry=entry display_option=(functions all_names) output=all_commands
  ELSE
    display_command_list_entry entry=entry display_option=list_option output=all_commands
  IFEND

  get_lines variable=command_names input=all_commands

" Process each command and function name in the specified command list entries
  FOR EACH command_name IN $select(command_names, x<>' ') DO
    CYCLE WHEN $substring(command_name, 1, 2) = '--'
    IF $substring(command_name, 1, 5) = 'ENTRY' THEN
" Found the beginning of a command list entry, prepare to process the entry contents.
      CYCLE WHEN command_list_entry = command_name(7, all)
      command_list_entry = command_name(7, all)
      put_line line=' Processing entry: '//command_list_entry output=$response
      commands_found = no
      functions_found = no
      lines_written = page_length
      entry_is_a_file = no
      include_command 'entry_is_a_file = $file($fname(command_list_entry), assigned)' status=ignore
      IF entry_is_a_file THEN
        disci_path = command_list_entry // '.'
      ELSEIF $scan_string('$system', command_name)<> 0 THEN
        disci_path = '$system.'
      ELSE
        disci_path = ''
      IFEND
      CYCLE WHEN $size(command_list)> page_length/4
      command_list = $add($justify(command_list_entry, page_width-10, left)//'Page '//page_number, ..
            command_list)
      CYCLE
    ELSEIF $substring(command_name, 1, 8) = 'Commands' THEN
" Found the beginning of a list of command names and aliases.
      commands_found = yes
      functions_found = no
      lines_written = page_length
      CYCLE
    ELSEIF $substring(command_name, 1, 9) = 'Functions' THEN
" Found the beginning of a list of parameter names and aliases.
      commands_found = no
      functions_found = yes
      lines_written = page_length
      CYCLE
    ELSEIF $substring(command_name, 1, 16) = 'Control Commands' THEN
" Found the beginning of the list of SCL control commands.
      command_list_entry = ' '//command_name
      put_line line=' Processing commands from entry: '//command_list_entry output=$response
      commands_found = yes
      functions_found = no
      lines_written = page_length
      disci_path = ''
      CYCLE WHEN $size(command_list)> page_length/4
      command_list = $add($justify(command_list_entry, page_width-10, left)//'Page '//page_number, ..
            command_list)
      CYCLE
    ELSEIF $substring(command_name, 1, 25) = 'System Supplied Functions' THEN
" Found the beginning of the list of SYSTEM functions.
      command_list_entry = ' '//command_name
      put_line line=' Processing functions from entry: '//command_list_entry output=$response
      commands_found = no
      functions_found = yes
      lines_written = page_length
      CYCLE WHEN $size(command_list)> page_length/4
      command_list = $add($justify(command_list_entry, page_width-10, left)//'Page '//page_number, ..
            command_list)
      CYCLE
    IFEND
    CYCLE WHEN NOT (commands_found OR functions_found)
" Display parameter information and/or loader errors (via $ERRORS connection) to the parameters file.
    put_line line=' ' output=parameters.$boi
    $system.rewind_file file=parameters
    IF functions_found THEN
      put_line line='     -- FUNCTION -- '//$trim($substring(command_name, 1, 31)) output=$response
      display_function_information $name($substring(command_name, 1, 31)) display_option=display_option ..
            output=parameters status=ignore
    ELSE
      put_line line='     -- COMMAND  -- '//$trim($substring(command_name, 1, 31)) output=$response
      include_command command='display_command_information '//disci_path//..
$substring(command_name, 1, 31)//' display_option=display_option output=parameters status=ignore'
    IFEND
    IF NOT ignore.normal THEN
      display_value ignore output=parameters
    IFEND
    $system.change_file_attributes file=parameters ring_attributes=($ring $ring $ring) "Needed within EDIPC
    $system.rewind_file file=parameters
    get_lines variable=parameter_list input=parameters
" Remove unwanted lines from beginning of parameter_list
    FOR EACH parameter IN parameter_list DO
      IF (parameter = ' ') OR ($scan_string('Parameters:', parameter)<> 0) THEN
        parameter_list = $rest(parameter_list)
      ELSE
        EXIT
      IFEND
    FOREND
" Check whether to continue on the current page.
    IF (lines_written > page_length-6) AND ($size(parameter_list)> 4) THEN "start a new page"
      lines_written = page_length
    IFEND
    IF (lines_written >= page_length) THEN " start command display on new page"
      put_lines lines=(title//'Page '//page_number, ' ENTRY: '//command_list_entry, ' ') output=instant.$eoi
      lines_written = 3
      page_number = page_number + 1
    IFEND
" Write the command/function and alias names first, followed by the parameter information.
    display_value value=command_name//' ' output=instant.$eoi
    lines_written = lines_written + $size(' '//command_name//' ')/page_width + 1
    put_line line=command_name output=index.$eoi
    FOR EACH parameter IN parameter_list DO
      IF $mod(lines_written, (page_length)) = 0 THEN " start parameter display on new page"
        put_lines lines=(title//'Page '//page_number, ' ENTRY: '//command_list_entry, ' ') output=instant.$eoi
        lines_written = 3
        page_number = page_number + 1
      IFEND
      display_value value='  '//parameter output=instant.$eoi
      lines_written = lines_written + $size('   '//parameter)/page_width + 1
    FOREND
" If room remains on current page, insert a blank line to separate this command from the next one.
    IF (page_length - lines_written)> 2 THEN
      put_line line=' ' output=instant.$eoi
      lines_written = lines_written + 1
    ELSE
      lines_written = page_length
    IFEND
  FOREND

" Write the existing information to the output file.
  $system.copy_file input=instant output=output status=ignore
  IF $mod(page_number, 2) = 0 THEN
    put_line line='1' output=output.$eoi "Blank line for two-page"
  IFEND

" When enough pages of information have been created, produce an index. Exit the procedure otherwise.
  EXIT_PROC WHEN page_number < index_when_pages_equal
  put_line line=' Generating command index' output=$response

" Split the alias names onto lines separate from the primary command name.
  TASK " Start new task to guarantee only one editor session per current task
    $system.edit_file file=index output=$null prolog=$null
    "$command=EDIT_FILE
      REPEAT
        IF $size($line_text)> 32 THEN
          break_text line=current column=33
          position_forward number=1
          replace_text text=' ' new_text='' number=all line=current status=ignore
          position_cursor column=1 line=current
          REPEAT
            position_cursor text=',' line=current number=1 status=ignore
            IF ignore.normal THEN
              break_text line=current column=current
              position_forward number=1
              replace_text text=',' new_text='' number=1 line=current
            IFEND
          UNTIL NOT ignore.normal
        IFEND
        position_forward number=1 status=ignore
      UNTIL NOT ignore.normal
    QUIT write_file=yes
  TASKEND

" Find the page number on which every command/function name or alias is referenced.
  TASK
    $system.edit_file file=instant output=$null prolog=$null
    "$command=EDIT_FILE
      get_line variable=command_names input=index
      $system.delete_file file=index status=ignore
      FOR EACH command_name IN command_names DO
        position_cursor text=command_name number=1 line=current..last status=ignore
        IF ignore.normal THEN
          position_cursor text=title direction=backward number=1 status=ignore
          put_line line=$justify($justify(command_name//' ', page_width-28, left, '.'), page_width-24, ..
                right)//$substring($line_text, page_width-10, 10) output=index.$eoi
        IFEND
      FOREND
    QUIT write_file=no
  TASKEND

  put_line line=' Sorting index by command name' output=$response
  $system.sort from=index to=sorted_index key=1..60 list=$null error=$null
  put_line line=' Writing command index' output=$response
  command_list = $reverse(command_list)

" Add page numbers to the index.
  TASK
    $system.edit_file file=sorted_index output=$null prolog=$null
    "$command=EDIT_FILE
      lines_written = page_length
      page_number = 1
      REPEAT
        IF lines_written >= page_length THEN
          put_lines lines=(title//'Index '//page_number, ' ') output=output.$eoi
          put_line line=$apply(command_list, x) output=output.$eoi
          put_line line=' ' output=output.$eoi
          lines_written = $size(command_list) + 3
          page_number = page_number + 1
        IFEND
        IF previous_command = $substring($line_text, 6, 31) THEN
          put_line line=$line_text//' <== Duplicate' output=output.$eoi
        ELSE
          put_line line=$line_text output=output.$eoi
        IFEND
        previous_command = $substring($line_text, 6, 31)
        lines_written = lines_written + 1
        position_forward number=1 status=ignore
      UNTIL NOT ignore.normal
    QUIT write_file=no
  TASKEND

  IF $mod(page_number, 2) = 0 THEN
    put_line line='1' output=output.$eoi "Blank line for two-page"
  IFEND

PROCEND list_command_information
