[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP OpenVMS Utility Routines Manual


Previous Contents Index

20.2.1 Arguments to SOR Routines

For a sort operation, the arguments to the SOR routines provide SORT with file specifications, key information, and instructions about the sorting process. For a merge operation, the arguments to the SOR routines provide MERGE with the number of input files, input and output file specifications, record information, key information, and input routine information. To perform sort or merge operations, you must pass key information (key_buffer argument) to either the SOR$BEGIN_SORT or SOR$BEGIN_MERGE routine. The key_buffer argument is passed as an array of words. The first word of the array contains the number of keys to be used in the sort or merge. Each block of four words that follows describes one key (multiple keys are listed in order of their priority):

  • The first word of each block describes the key data type.
  • The second word determines the sort or merge order (0 for ascending, 1 for descending).
  • The third word describes the relative offset of the key (beginning at position 0).
  • The fourth word describes the length of the key in bytes.

There are both mandatory and optional arguments. The mandatory arguments appear first in the argument list. You must specify all arguments in the order in which they are positioned in the argument list, separating each with a comma. Pass a zero by value to specify any optional arguments that you are omitting from within the list. You can end the argument list any time after specifying all the mandatory and desired optional arguments.

20.2.2 Interfaces to SOR Routines

You can submit data to the SOR routines as complete files or as single records. When your program submits one or more files to SORT or MERGE, which then creates one sorted or merged output file, you are using the file interface. When your program submits records one at a time and then receives the ordered records one at a time, you are using the record interface.

You can combine the file interface with the record interface by submitting files on input and receiving the ordered records on output or by releasing records on input and writing the ordered records to a file on output. Combining the two interfaces provides greater flexibility. If you use the record interface on input, you can process the records before they are sorted; if you use the record interface on output, you can process the records after they are sorted.

The SOR routines used and the order in which they are called depend on the type of interface used in a sorting or merging operation. The following sections detail the calling sequence for each of the interfaces.

20.2.2.1 Sort Operation Using File Interface

For a sort operation using the file interface, pass the input and output file specifications to SORT by calling SOR$PASS_FILES. You must call SOR$PASS_FILES for each input file specification. Pass the output file specification in the first call. If no input files are specified before the call to SOR$BEGIN_SORT, the record interface is used for input; if no output file is specified, the record interface is used for output.

Next, call SOR$BEGIN_SORT to pass instructions about keys and sort options. At this point, you must indicate whether you want to use your own key comparison routine. (This feature is not currently supported by the high-performance Sort/Merge utility.) SORT automatically generates a key comparison routine that is efficient for key data types; however, you might want to provide your own comparison routine to handle special sorting requirements. (For example, you might want names beginning with "Mc" and "Mac" to be placed together.) If you use your own key comparison routine, you must pass its address with the user_compare argument.

Call SOR$SORT_MERGE to execute the sort and direct the sorted records to the output file. Finally, call SOR$END_SORT to end the sort and release resources. The SOR$END_SORT routine can be called at any time to abort a sort or to merge and release all resources allocated to the sort or merge process.

20.2.2.2 Sort Operation Using Record Interface

For a sort operation using the record interface, first call SOR$BEGIN_SORT. As in the file interface, this routine sets up work areas and passes arguments that define keys and sort options. Note that, if you use the record interface, you must use a record-sorting process (not a tag, address, or index process).

Next, call SOR$RELEASE_REC to release a record to SORT. Call SOR$RELEASE_REC once for each record to be released. After all records have been passed to SORT, call SOR$SORT_MERGE to perform the sorting.

After the sort has been performed, call SOR$RETURN_REC to return a record from the sort operation. Call this routine once for each record to be returned. Finally, call the last routine, SOR$END_SORT, to complete the sort operation and release resources.

20.2.2.3 Merge Operation Using File Interface

For a merge operation using the file interface, pass the input and output file specifications to MERGE by calling SOR$PASS_FILES. You can merge up to 10 input files. (The high-performance Sort/Merge utility allows you to merge up to 12 input files.) by calling SOR$PASS_FILES once for each file. Pass the file specification for the merged output file in the first call. If no input files are specified before the call to SOR$BEGIN_MERGE, the record interface is used for input; if no output file is specified, the record interface is used for output.

Next, to execute the merge, call SOR$BEGIN_MERGE to pass key information and merge options. At this point, you must indicate whether you want to use your own key comparison routine tailored to your data. (This feature is not currently supported by the high-performance Sort/Merge utility.) Finally, call SOR$END_SORT to release resources.

20.2.2.4 Merge Operation Using Record Interface

For a merge operation using the record interface, first call SOR$BEGIN_MERGE. As in the file interface, this routine passes arguments that define keys and merge options. It also issues the first call to the input routine, which you must create, to begin releasing records to the merge.

Next, call SOR$RETURN_REC to return the merged records to your program. You must call this routine once for each record to be returned. SOR$RETURN_REC continues to call the input routine. MERGE, unlike SORT, does not need to hold all the records before it can begin returning them in the desired order. Releasing, merging, and returning records all take place in this phase of the merge.

Finally, after all the records have been returned, call the last routine, SOR$END_SORT, to clean up and release resources.

20.2.3 Reentrancy

The SOR routines are reentrant; that is, a number of sort or merge operations can be active at the same time. Thus, a program does not need to finish one sort or merge operation before beginning another. For example, reentrancy lets you perform multiple sorts on a file such as a mailing list and to create several output files, one with the records sorted by name, another sorted by state, another sorted by zip code, and so on.

The context argument, which can optionally be passed with any of the SOR routines, distinguishes among multiple sort or merge operations. When using multiple sort or merge operations, the context argument is required. On the first call, the context longword must be zero. It is then set (by SORT/MERGE) to a value identifying the sort or merge operation. Additional calls to the same sort or merge operation must pass the same context longword. The SOR$END_SORT routine clears the context longword.

20.3 Using the SOR Routines: Examples

This section provides examples of using the SOR routines for various operations including the following:
  • Example 20-1 is a HP Fortran program that demonstrates a merge operation using a record interface.
  • Example 20-2 is a HP Fortran program that demonstrates a sort operation using a file interface on input and a record interface on output.
  • Example 20-3 is a HP Pascal program that demonstrates a merge operation using a file interface.
  • Example 20-4 is a HP Pascal program that demonstrates a sort operation using a record interface.
  • Example 20-5 is a HP C program that demonstrates a sort operation using the STABLE option and two text keys.

Example 20-1 Using SOR Routines to Perform a Merge Using Record Interface in a HP Fortran Program

        Fortran Program 
C... 
C...    This program demonstrates the Fortran calling sequences 
C...    for the merge record interface. 
C... 
C 
C       THE INPUT FILES ARE LISTED BELOW. 
C 
C               INFILE1.DAT 
C 
C 1 BBBBBBBBBB REST OF DATA IN RECORD................................END OF RECORD 
C 2 UUUUUUUUUU REST OF DATA IN RECORD................................END OF RECORD 
C 
C               INFILE2.DAT 
C 
C 1 AAAAAAAAAA REST OF DATA IN RECORD................................END OF RECORD 
C 2 TTTTTTTTTT REST OF DATA IN RECORD................................END OF RECORD 
C 
C               INFILE3.DAT 
C 
C 1 TTTTTTTTTT REST OF DATA IN RECORD................................END OF RECORD 
C 2 BBBBBBBBBB REST OF DATA IN RECORD................................END OF RECORD 
C 
C               FOROUT.DAT 
C 
C 1 AAAAAAAAAA REST OF DATA IN RECORD................................END OF RECORD 
C 1 BBBBBBBBBB REST OF DATA IN RECORD................................END OF RECORD 
C 1 TTTTTTTTTT REST OF DATA IN RECORD................................END OF RECORD 
C 2 BBBBBBBBBB REST OF DATA IN RECORD................................END OF RECORD 
C 2 TTTTTTTTTT REST OF DATA IN RECORD................................END OF RECORD 
C 2 UUUUUUUUUU REST OF DATA IN RECORD................................END OF RECORD 
C 
C 
C................................................................................. 
C 
C 
 
        IMPLICIT INTEGER (A-Z) 
 
        CHARACTER*80 REC                        ! A record. 
 
        EXTERNAL READ_REC                       ! Routine to read a record. 
        EXTERNAL KOMPAR                         ! Routine to compare records. 
        EXTERNAL SS$_ENDOFFILE                  ! System end-of-file value 
 
        INTEGER*4 SOR$BEGIN_MERGE               ! SORT/MERGE function names 
        INTEGER*4 SOR$RETURN_REC 
        INTEGER*4 SOR$END_SORT 
        INTEGER*4 ISTAT                         ! storage for SORT/MERGE function value 
        INTEGER*4 LENGTH                        ! length of the returned record 
        INTEGER*2 LRL                           ! Longest Record Length (LRL) 
 
        LOGICAL*1 ORDER                         ! #files to merge (merge order) 
 
        DATA ORDER,LRL/3,80/                    ! Order of the merge=3,LRL=80 
C... 
C...    First open all the input files. 
C... 
        OPEN (UNIT=10, FILE='INFILE1.DAT',TYPE='OLD',READONLY, 
     *  FORM='FORMATTED') 
        OPEN (UNIT=11, FILE='INFILE2.DAT',TYPE='OLD',READONLY, 
     *  FORM='FORMATTED') 
        OPEN (UNIT=12, FILE='INFILE3.DAT',TYPE='OLD',READONLY, 
     *  FORM='FORMATTED') 
C 
C...    Open the output file. 
C 
        OPEN (UNIT=8, FILE='TEMP.TMP', TYPE='NEW') 
C... 
C...    Initialize the merge.  Pass the merge order, the largest 
C...    record length, the compare routine address, and the 
C...    input routine address. 
C... 
        ISTAT = SOR$BEGIN_MERGE (,LRL,,ORDER, 
     *  KOMPAR,,READ_REC) 
        IF (.NOT. ISTAT) GOTO 10        ! Check for error. 
 
 
 
C... 
C...    Now loop getting merged records.  SOR$RETURN_REC will 
C...    call READ_REC when it needs input. 
C... 
5       ISTAT = SOR$RETURN_REC (REC, LENGTH) 
        IF (ISTAT .EQ. %LOC(SS$_ENDOFFILE)) GO TO 30    ! Check for end of file. 
        IF (.NOT. ISTAT) GO TO 10       ! Check for error. 
 
        WRITE(8,200) REC                        ! Output the record. 
200     FORMAT(' ',A) 
        GOTO 5                                  ! And loop back. 
C... 
C...    Now tell SORT that we are all done. 
C... 
 
30      ISTAT = SOR$END_SORT() 
        IF (.NOT. ISTAT) GOTO 10        ! Check for error. 
        CALL EXIT 
 
C... 
C...    Here if an error occurred.  Write out the error status 
C...    and exit. 
C... 
10      WRITE(8,201)ISTAT 
201     FORMAT(' ?ERROR CODE', I20) 
        CALL EXIT 
        END 
 
 
        FUNCTION READ_REC (RECX, FILE, SIZE) 
C... 
C...    This routine reads a record from one of the input files 
C...    for merging.  It will be called by SOR$BEGIN_MERGE and by 
C...    SOR$RETURN_REC. 
C...    Parameters: 
C... 
C...            RECX.wcp.ds     character buffer to hold the record after 
C...                            it is read in. 
C... 
C...            FILE.rl.r       indicates which file the record is 
C...                            to be read from.  1 specifies the 
C...                            first file, 2 specifies the second 
C...                            etc. 
C... 
C...            LENGTH.wl.r     is the actual number of bytes in 
C...                            the record.  This is set by READ_REC. 
C... 
        IMPLICIT INTEGER (A-Z) 
 
        PARAMETER MAXFIL=10                     ! Max number of files. 
 
        EXTERNAL SS$_ENDOFFILE                  ! End of file status code. 
        EXTERNAL SS$_NORMAL                     ! Success status code. 
 
        LOGICAL*1 FILTAB(MAXFIL) 
        CHARACTER*(80) RECX                     ! MAX LRL =80 
 
        DATA FILTAB/10,11,12,13,14,15,16,17,18,19/ ! Table of I/O unit numbers. 
 
        READ_REC = %LOC(SS$_ENDOFFILE)         ! Give end of file return 
        IF (FILE .LT. 1 .OR. FILE .GT. MAXFIL) RETURN   !   if illegal call. 
 
        READ (FILTAB(FILE), 100, ERR=75, END=50) RECX   ! Read the record. 
100     FORMAT(A) 
 
        READ_REC = %LOC(SS$_NORMAL)             ! Return success code. 
        SIZE = LEN (RECX)                       ! Return size of record. 
        RETURN 
 
C...    Here if end of file. 
50      READ_REC = %LOC(SS$_ENDOFFILE)          ! Return "end of file" code. 
        RETURN 
 
C...    Here if error while reading 
75      READ_REC = 0 
        SIZE = 0 
        RETURN 
        END 
 
 
        FUNCTION KOMPAR (REC1,REC2) 
C... 
C...    This routine compares two records.  It returns -1 
C...    if the first record is smaller than the second, 
C...    0 if the records are equal, and 1 if the first record 
C...    is larger than the second. 
C... 
        PARAMETER KEYSIZ=10 
 
        IMPLICIT INTEGER (A-Z) 
 
        LOGICAL*1 REC1(KEYSIZ),REC2(KEYSIZ) 
 
        DO 20 I=1,KEYSIZ 
        KOMPAR = REC1(I) - REC2(I) 
        IF (KOMPAR .NE. 0) GOTO 50 
20      CONTINUE 
 
        RETURN 
 
50      KOMPAR = ISIGN (1, KOMPAR) 
        RETURN 
        END 

Example 20-2 is a HP Fortran program that demonstrates a sort operation using a file interface on input and a record interface on output.

Example 20-2 Using SOR Routines to Sort Using Mixed Interface in a HP Fortran Program

Program 
 
        PROGRAM CALLSORT 
C 
C 
C       This is a sample Fortran program that calls the SOR 
C       routines using the file interface for input and the 
C       record interface for output.  This program requests 
C       a record sort of the file 'R010SQ.DAT'  and  writes 
C       the records to SYS$OUTPUT.  The key is  an  80-byte 
C       character ascending  key starting in  position 1 of 
C       each record. 
C 
C       A short version of the input and output files follows: 
C 
C                       Input file R010SQ.DAT 
C 1 BBBBBBBBBB REST OF DATA IN RECORD................................END OF RECORD 
C 2 UUUUUUUUUU REST OF DATA IN RECORD................................END OF RECORD 
C 1 AAAAAAAAAA REST OF DATA IN RECORD................................END OF RECORD 
C 2 TTTTTTTTTT REST OF DATA IN RECORD................................END OF RECORD 
C 1 TTTTTTTTTT REST OF DATA IN RECORD................................END OF RECORD 
C 2 BBBBBBBBBB REST OF DATA IN RECORD................................END OF RECORD 
C 1 QQQQQQQQQQ REST OF DATA IN RECORD................................END OF RECORD 
C 2 AAAAAAAAAA REST OF DATA IN RECORD................................END OF RECORD 
C 1 UUUUUUUUUU REST OF DATA IN RECORD................................END OF RECORD 
C 2 QQQQQQQQQQ REST OF DATA IN RECORD................................END OF RECORD 
C 
C                       Output file SYS$OUTPUT 
C 
C 1 AAAAAAAAAA REST OF DATA IN RECORD...............................END OF RECORD 
C 1 BBBBBBBBBB REST OF DATA IN RECORD...............................END OF RECORD 
C 1 QQQQQQQQQQ REST OF DATA IN RECORD...............................END OF RECORD 
C 1 TTTTTTTTTT REST OF DATA IN RECORD...............................END OF RECORD 
C 1 UUUUUUUUUU REST OF DATA IN RECORD...............................END OF RECORD 
C 2 AAAAAAAAAA REST OF DATA IN RECORD...............................END OF RECORD 
C 2 BBBBBBBBBB REST OF DATA IN RECORD...............................END OF RECORD 
C 2 QQQQQQQQQQ REST OF DATA IN RECORD...............................END OF RECORD 
C 2 TTTTTTTTTT REST OF DATA IN RECORD...............................END OF RECORD 
C 2 UUUUUUUUUU REST OF DATA IN RECORD...............................END OF RECORD 
C 
C----------------------------------------------------------------------------- 
C 
C       Define external functions and data. 
C 
        CHARACTER*80 RECBUF 
        CHARACTER*10 INPUTNAME          !Input file name 
        INTEGER*2 KEYBUF(5)             !Key definition buffer 
        INTEGER*4 SOR$PASS_FILES        !SORT function names 
        INTEGER*4 SOR$BEGIN_SORT 
        INTEGER*4 SOR$SORT_MERGE 
        INTEGER*4 SOR$RETURN_REC 
        INTEGER*4 SOR$END_SORT 
        INTEGER*4 ISTATUS               !Storage for SORT function value 
        EXTERNAL SS$_ENDOFFILE 
        EXTERNAL DSC$K_DTYPE_T 
        EXTERNAL SOR$GK_RECORD 
        INTEGER*4 SRTTYPE 
 
C 
C       Initialize data -- first the file names, then the key buffer for 
C       one 80-byte character key starting in position 1, 3 work files, 
C       and a record sort process. 
C 
        DATA INPUTNAME/'R010SQ.DAT'/ 
        KEYBUF(1) = 1 
        KEYBUF(2) = %LOC(DSC$K_DTYPE_T) 
        KEYBUF(3) = 0 
        KEYBUF(4) = 0 
        KEYBUF(5) = 80 
        SRTTYPE = %LOC(SOR$GK_RECORD) 
 
C 
C       Call the SORT -- each call is a function. 
C 
C 
C       Pass SORT the file names. 
C 
        ISTATUS = SOR$PASS_FILES(INPUTNAME) 
        IF (.NOT. ISTATUS) GOTO 10 
C 
C       Initialize the work areas and keys. 
C 
        ISTATUS = SOR$BEGIN_SORT(KEYBUF,,,,,,SRTTYPE,%REF(3)) 
        IF (.NOT. ISTATUS) GOTO 10 
C 
C       Sort the records. 
C 
        ISTATUS = SOR$SORT_MERGE( ) 
        IF (.NOT. ISTATUS) GOTO 10 
C 
C       Now retrieve the individual records and display them. 
C 
5       ISTATUS = SOR$RETURN_REC(RECBUF) 
        IF (.NOT. ISTATUS) GOTO 6 
        ISTATUS = LIB$PUT_OUTPUT(RECBUF) 
        GOTO 5 
6       IF (ISTATUS .EQ. %LOC(SS$_ENDOFFILE)) GOTO 7 
        GOTO 10 
C 
C       Clean up the work areas and files. 
C 
7       ISTATUS = SOR$END_SORT() 
        IF (.NOT. ISTATUS) GOTO 10 
        STOP 'SORT SUCCESSFUL' 
10      STOP 'SORT UNSUCCESSFUL' 
        END 

Example 20-3 is a HP Pascal program that demonstrates a merge operation using a file interface.

Example 20-3 Using SOR Routines to Merge Three Input Files in a HP Pascal Program

Program 
 
 
(* This program merges three input files, (IN_FILE.DAT, 
 IN_FILE2.DAT IN_FILE3.DAT), and creates one merged output file.  *) 
 
 
program mergerecs( output, in_file1, in_file2, in_file3, out_file ); 
 
CONST 
   SS$_NORMAL = 1; 
   SS$_ENDOFFILE = %X870; 
   SOR$GK_RECORD = 1; 
   SOR$M_STABLE = 1; 
   SOR$M_SEQ_CHECK = 4; 
   SOR$M_SIGNAL = 8; 
   DSC$K_DTYPE_T = 14; 
 
TYPE 
   $UBYTE = [BYTE] 0..255; 
   $UWORD = [WORD] 0..65535; 
 
const 
    num_of_keys = 1; 
    merge_order = 3; 
    lrl         = 131; 
 
    ascending   = 0; 
    descending  = 1; 
 
 
type 
    key_buffer_block= 
        packed record 
        key_type:       $uword; 
        key_order:      $uword; 
        key_offset:     $uword; 
        key_length:     $uword; 
        end; 
 
   key_buffer_type= 
        packed record 
        key_count:      $uword; 
        blocks:         packed array[1..num_of_keys] of key_buffer_block; 
        end; 
 
   record_buffer =      packed array[1..lrl] of char; 
 
   record_buffer_descr = 
        packed record 
        length: $uword; 
        dummy:  $uword; 
        addr:   ^record_buffer; 
        end; 
 
var 
   in_file1, 
   in_file2, 
   in_file3, 
   out_file:    text; 
   key_buffer:  key_buffer_type; 
   rec_buffer:  record_buffer; 
   rec_length:  $uword; 
   status:      integer; 
   i:           integer; 
 
function sor$begin_merge( 
        var buffer:     key_buffer_type; 
        lrl:            $uword; 
        mrg_options:    integer; 
        merge_order:    $ubyte; 
        %immed cmp_rtn: integer := 0; 
        %immed eql_rtn: integer := 0; 
        %immed [unbound] function 
            read_record( 
                var rec:        record_buffer_descr; 
                var filenumber: integer; 
                var recordsize: $uword): integer 
        ): integer; extern; 
 
function sor$return_rec( 
        %stdescr rec:   record_buffer; 
        var rec_size:   $uword 
        ): integer; extern; 
 
function sor$end_sort: integer; extern; 
 
procedure sys$exit( %immed status : integer ); extern; 
 
function read_record( 
        var rec:        record_buffer_descr; 
        var filenumber: integer; 
        var recordsize: $uword 
        ): integer; 
 
procedure readone( var filename: text ); 
begin 
recordsize := 0; 
if eof(filename) 
then 
    read_record := ss$_endoffile 
else 
    begin 
    while not eoln(filename) and (recordsize < rec.length) do 
        begin 
        recordsize := recordsize + 1; 
        read(filename,rec.addr^[recordsize]); 
        end; 
    readln(filename); 
    end; 
end; 
 
begin 
read_record := ss$_normal; 
case filenumber of 
    1: readone(in_file1); 
    2: readone(in_file2); 
    3: readone(in_file3); 
    otherwise 
        read_record := ss$_endoffile; 
    end; 
end; 
 
procedure initfiles; 
begin 
open( in_file1, 'infile1.dat', old ); 
open( in_file2, 'infile2.dat', old ); 
open( in_file3, 'infile3.dat', old ); 
open( out_file, 'temp.tmp' ); 
reset( in_file1 ); 
reset( in_file2 ); 
reset( in_file3 ); 
rewrite( out_file ); 
end; 
 
procedure error( status : integer ); 
begin 
writeln( 'merge unsuccessful.  status=%x', status:8 hex ); 
sys$exit(status); 
end; 
begin 
 
with key_buffer do 
    begin 
    key_count := 1; 
    with blocks[1] do 
        begin 
        key_type := dsc$k_dtype_t; 
        key_order := ascending; 
        key_offset := 0; 
        key_length := 5; 
        end; 
    end; 
 
initfiles; 
 
status := sor$begin_merge( key_buffer, lrl, 
        sor$m_seq_check + sor$m_signal, 
        merge_order, 0, 0, read_record ); 
 
repeat 
    begin 
    rec_length := 0; 
    status := sor$return_rec( rec_buffer, rec_length ); 
    if odd(status) 
    then 
        begin 
        for i := 1 to rec_length do write(out_file, rec_buffer[i]); 
        writeln(out_file); 
        end; 
    end 
until not odd(status); 
 
if status <> ss$_endoffile then error(status); 
 
status := sor$end_sort; 
if not odd(status) then error(status); 
 
writeln( 'merge successful.' ); 
 
end. 

Example 20-4 is a HP Pascal program that demonstrates a sort operation using a record interface.

Example 20-4 Using SOR Routines to Sort Records from Two Input Files in a HP Pascal Program

Pascal Program 
 
PROGRAM FILETORECORDSORT (OUTPUT,SORTOUT); 
 
(*      This program calls SOR routines to read and sort records from 
        two input files, (PASINPUT1.DAT and PASINPUT2.DAT) and to return 
        sorted records to this program to be written to the output file, 
        (TEMP.TMP).  *) 
 
(*      Declarations for external status codes, and data structures, such as 
        the types $UBYTE (an unsigned byte) and $UWORD (an unsigned word). *) 
 
CONST 
   SS$_NORMAL = 1; 
   SS$_ENDOFFILE = %X870; 
   SOR$GK_RECORD = 1; 
   SOR$M_STABLE = 1; 
   SOR$M_SEQ_CHECK = 4; 
   SOR$M_SIGNAL = 8; 
   DSC$K_DTYPE_T = 14; 
 
TYPE 
   $UBYTE = [BYTE] 0..255; 
   $UWORD = [WORD] 0..65535; 
 
CONST 
   Numberofkeys = 1 ;   (* Number of keys for this sort *) 
   LRL = 131 ;          (* Longest Record Length for output records *) 
 
(* Key orders *) 
 
   Ascending = 0 ; 
   Descending = 1 ; 
 
 
TYPE 
   Keybufferblock= packed record 
                   Keytype : $UWORD ; 
                   Keyorder : $UWORD ; 
                   Keyoffset : $UWORD ; 
                   Keylength : $UWORD 
                   end ; 
 
(* The keybuffer. Note that the field buffer is a one-component array in 
   this program. This type definition would allow a multikeyed sort. *) 
 
   Keybuffer= packed record 
              Numkeys : $UWORD ; 
              Blocks : packed array[1..Numberofkeys] OF Keybufferblock 
              end ; 
 
(* The record buffer. This buffer will be used to hold the returned 
        records from SORT. *) 
 
   Recordbuffer = packed array[1..LRL] of char ; 
 
(* Name type for input and output files. A necessary fudge for %stdescr 
   mechanism.  *) 
 
   nametype= packed array[1..13] of char ; 
 
 
 
VAR 
   Sortout : text ;             (* the output file *) 
   Buffer : Keybuffer ;         (* the actual keybuffer *) 
   Sortoptions : integer ;      (* flag for sorting options *) 
   Sorttype : $UBYTE ;          (* sorting process *) 
   Numworkfiles : $UBYTE ;      (* number of work files *) 
   Status : integer ;           (* function return status code *) 
   Rec : Recordbuffer ;         (* a record buffer *) 
   Recordlength : $UWORD ;      (* the returned record length *) 
   Inputname:  nametype ;       (* input file name *) 
   i : integer ;                (* loop control variable *) 
 
 
 
(* function and procedure declarations *) 
 
(* Declarations of SORT functions *) 
(* Note that the following SORT routine declarations 
        do not use all of the possible routine parameters. *) 
(* The parameters used MUST have all preceding parameters specified, 
        however. *) 
 
FUNCTION SOR$PASS_FILES 
   (%STDESCR Inname : nametype ) 
   : INTEGER ; EXTERN ; 
 
FUNCTION SOR$BEGIN_SORT( 
    VAR Buffer : Keybuffer ; 
    Lrlen : $UWORD ; 
    VAR Sortoptions : INTEGER ; 
    %IMMED Filesize : INTEGER ; 
    %IMMED Usercompare : INTEGER ; 
    %IMMED Userequal : INTEGER ; 
    VAR Sorttype : $UBYTE ; 
    VAR Numworkfiles : $UBYTE ) 
    : INTEGER ; EXTERN ; 
 
FUNCTION SOR$SORT_MERGE 
   : INTEGER ; EXTERN ; 
 
FUNCTION SOR$RETURN_REC( 
   %STDESCR  Rec : Recordbuffer ; 
   VAR Recordsize : $UWORD ) 
   : INTEGER ; EXTERN ; 
 
FUNCTION SOR$END_SORT 
   : INTEGER ; EXTERN ; 
 
 
(* End of the SORT function declarations *) 
 
(* The CHECKSTATUS routine checks the return status for errors. *) 
(* If there is an error, write an error message and exit via sys$exit *) 
PROCEDURE CHECKSTATUS( var status : integer ) ; 
 
        procedure sys$exit( status : integer ) ; extern ; 
 
begin           (* begin checkstatus *) 
   if odd(status) then 
        begin 
        writeln( ' SORT unsuccessful. Error status = ', status:8 hex ) ; 
        SYS$EXIT( status ) ; 
        end ; 
end ;           (* end checkstatus *) 
 
(* end function and routine declarations *) 
 
 
BEGIN   (* begin the main routine *) 
 
(* Initialize data for one 8-byte character key, starting at record 
   offset 0, 3 work files, and the record sorting process *) 
 
Inputname := 'PASINPUT1.DAT' ; 
WITH Buffer DO 
   BEGIN 
   Numkeys := 1; 
   WITH Blocks[1] DO 
      BEGIN 
      Keytype := DSC$K_DTYPE_T ;        (* Use OpenVMS descriptor data types to 
                                                define SORT data types. *) 
      Keyorder := Ascending ; 
      Keyoffset := 0 ; 
      Keylength := 8 ; 
      END; 
   END; 
 
Sorttype := SOR$GK_RECORD ;             (* Use the global SORT constant to 
                                             define the sort process. *) 
Sortoptions := SOR$M_STABLE ;           (* Use the global SORT constant to 
                                             define the stable sort option. *) 
Numworkfiles := 3 ; 
 
(* call the sort routines as a series of functions *) 
 
(* pass the first filename to SORT *) 
Status := SOR$PASS_FILES( Inputname ) ; 
 
(* Check status for error. *) 
CHECKSTATUS( Status ) ; 
 
(* pass the second filename to SORT *) 
Inputname := 'PASINPUT2.DAT' ; 
 
Status := SOR$PASS_FILES( Inputname ) ; 
 
(* Check status for error. *) 
CHECKSTATUS( Status ) ; 
 
(* initialize work areas and keys *) 
Status := SOR$BEGIN_SORT( Buffer, 0, Sortoptions, 0, 0, 0, 
                                Sorttype, Numworkfiles ) ; 
 
(* Check status for error. *) 
CHECKSTATUS( Status ) ; 
 
(* sort the records *) 
Status := SOR$SORT_MERGE ; 
 
(* Check status for error. *) 
CHECKSTATUS( Status ) ; 
 
(* Ready output file for writing returned records from SORT. *) 
OPEN( SORTOUT, 'TEMP.TMP' ) ; 
REWRITE( SORTOUT ) ; 
 
(* Now get the sorted records from SORT. *) 
Recordlength := 0 ; 
REPEAT 
   Status := SOR$RETURN_REC( Rec, Recordlength ) ; 
 
   if odd( Status ) 
   then                 (* if successful, write record to output file. *) 
        begin 
        for i := 1 to Recordlength do 
           write( sortout, Rec[i] ) ;   (* write each character *) 
        writeln (sortout) ;                     (* end output line *) 
        end; 
UNTIL not odd( Status ) ; 
 
(* If there was just no more data to be returned (eof) continue, otherwise 
        exit with an error. *) 
if Status <> SS$_ENDOFFILE then 
   CHECKSTATUS( Status ) ; 
 
(* The sort has been successful to this point. *) 
 
(* Close the output file *) 
CLOSE( sortout ) ; 
 
(* clean up work areas and files *) 
Status := SOR$END_SORT ; 
 
(* Check status for error. *) 
CHECKSTATUS( Status ); 
 
WRITELN ('SORT SUCCESSFUL') ; 
 
END. 
 


Previous Next Contents Index