Previous | Contents | Index |
Example 20-5 is a HP C program that demonstrates a sort operation using the STABLE option and two test keys.
Example 20-5 Using SOR Routines to Sort Records Using the STABLE Option and Two Text Keys in a HP C Program |
---|
/* C Program Example This program demonstrates the use of the STABLE option with 2 ascending text keys to sort a file of names. The names are sorted by the first 6 characters of the last name and the first 6 characters of the first name. The contents of the input file and resulting output file are listed below. The associated C program code listing follows. ................................................................... Input file: example.in JONES DAVID WARNER LIZZY SMITTS JAMES SMITH RANDY BROWN TONY GRANT JOSEPH BROWN JAMES JONES DAVID BAKER PAMELA SMART SHERYL RUSSO JOSEPH JONES DONALD BROWN GORDON ................................................................... Output file: example.out BAKER PAMELA BROWN GORDON BROWN JAMES BROWN TONY GRANT JOSEPH JONES DAVID JONES DAVID JONES DONALD RUSSO JOSEPH SMART SHERYL SMITH RANDY SMITTS JAMES WARNER LIZZY ................................................................... */ /* **================================================================= ** ** EXAMPLE.C code: ** ** Abstract: Example of using sort with the STABLE option and ** 2 text keys (both ascending). ** ** ** Input file: example.in ** Output file: example.out ** **================================================================= */ /* ---------------------------------------------------------------------------- ** Include files: */ # include <stdlib.h> # include <stdio.h> # include <string.h> # include <descrip.h> # include <ssdef.h> # include <sor$routines.h> /* ---------------------------------------------------------------------------- ** Local macro definitions: */ # define MAX_REC_LEN 150 # define MAX_NUM_KEYS 10 /* ---------------------------------------------------------------------------- ** Local structure definitions. */ /* Define the description for each key. */ typedef struct { unsigned short type; /* Data type of key */ unsigned short order; /* Order of key */ unsigned short offset; /* Offset of key */ unsigned short len; /* Length of key */ } key_info; struct { unsigned short num; /* number of keys */ key_info key[MAX_NUM_KEYS]; } key_buffer; /* ---------------------------------------------------------------------------- ** External literals. */ globalvalue int SOR$M_STABLE; /* ---------------------------------------------------------------------------- ** Main entry point. */ main (int argc, char *argv[]) { int i; unsigned int options; /* Sort options */ unsigned int num_records_in; unsigned int num_records_out; unsigned int lrl; /* longest record length */ unsigned short size; /* record size from return_rec */ unsigned int status; unsigned long int return_status; FILE *infile; /* input file */ FILE *outfile; /* output file */ char record [MAX_REC_LEN]; $DESCRIPTOR (record_desc, record); lrl = sizeof(record); key_buffer.num = 2; key_buffer.key[0].type = DSC$K_DTYPE_T; key_buffer.key[0].order = 0; /* ascending */ key_buffer.key[0].offset = 0; key_buffer.key[0].len = 6; key_buffer.key[1].type = DSC$K_DTYPE_T; key_buffer.key[1].order = 0; /* ascending */ key_buffer.key[1].offset = 7; key_buffer.key[1].len = 6; /* Open input and output files. */ if (argc != 3) { printf("Usage: example inputfile outputfile\n"); exit(-1); } infile = fopen(argv[1], "r"); if (infile == (FILE *) NULL) { printf("Can't open input file %s\n",argv[1]); exit(-1); } outfile = fopen(argv[2], "w"); if (outfile == (FILE *) NULL) { printf("Can't create output file %s\n",argv[2]); exit(-1); } /* Specify options. Initialize the sort and check for errors. */ options = SOR$M_STABLE; return_status = SOR$BEGIN_SORT(&key_buffer, &lrl, &options, 0,0,0,0,0,0); if (return_status != SS$_NORMAL) { printf ("Status from SOR$BEGIN_SORT: 0x%x\n", return_status); exit(return_status); } /* Within a loop, get all the records from the input file. */ /* Exit if an error occurs. */ num_records_in = 0; while (fgets( record, lrl, infile) != NULL) { record_desc.dsc$w_length = strlen(record)-1; num_records_in++; return_status = SOR$RELEASE_REC(&record_desc,0); if (return_status != SS$_NORMAL) { printf ("Status from SOR$RELEASE_REC: 0x%x\n", return_status); exit(return_status); } } /* Sort all of the input records. */ /* Exit if an error occurs. */ return_status = SOR$SORT_MERGE(0); if (return_status != SS$_NORMAL) { printf ("Status from SOR$SORT_MERGE: 0x%x\n", return_status); exit(return_status); } /* Within a loop, write the sorted records to the output file. */ /* Exit if an error occurs, other than end-of-file. */ record_desc.dsc$w_length = lrl; num_records_out = 0; do { return_status = SOR$RETURN_REC(&record_desc,&size,0); if (return_status == SS$_NORMAL) { num_records_out++; status = fprintf (outfile,"%.*s\n", size, record); if (status < 0 ) { printf ("Error writing to output file, status = %d\n", status); exit(status); } } else if (return_status != SS$_ENDOFFILE) { printf ("Status from SOR$RETURN_REC: 0x%x\n", return_status); exit(return_status); }; } while (return_status != SS$_ENDOFFILE); /* Sanity check - assure number of input and output records match. */ if (num_records_out != num_records_in) { printf("Number of records out is not correct. # in = %d, # out = %d\n", num_records_out, num_records_in); exit(status); } /* Successful completion. Close input and output files. End program. */ return_status = SOR$END_SORT(0); if (return_status != SS$_NORMAL) { printf ("Status from SOR$END_SORT: 0x%x\n", return_status); exit(return_status); } fclose (infile); fclose (outfile); } |
This section describes the individual SOR routines.
The SOR$BEGIN_MERGE routine initializes the merge operation by opening the input and output files and by providing the number of input files, the key specifications, and the merge options.
SOR$BEGIN_MERGE [key-buffer] [,lrl] [,options] [,merge_order] [,user_compare] [,user_equal] [,user_input] [,context]
OpenVMS usage: cond_value type: longword (unsigned) access: write only mechanism: by value
Longword condition value. Most Sort/Merge utility routines return a condition value in R0. Condition values that this routine can return are listed under Condition Values Returned.
key_buffer
OpenVMS usage: vector_word_unsigned type: word (unsigned) access: read only mechanism: by reference
Array of words describing the keys on which you plan to merge. The key_buffer argument is the address of an array containing the key descriptions.The first word of this array contains the number of keys described (up to 255). Following the first word, each key is described (in order of priority) in blocks of four words. The four words specify the key's data type, order, offset, and length, respectively.
The first word of the block specifies the key's data type. The following data types are accepted:
DSC$K_DTYPE_Z Unspecified (uninfluenced by collating sequence) DSC$K_DTYPE_B Byte integer (signed) DSC$K_DTYPE_BU Byte (unsigned) DSC$K_DTYPE_W Word integer (signed) DSC$K_DTYPE_WU Word (unsigned) DSC$K_DTYPE_L Longword integer (signed) DSC$K_DTYPE_LU Longword (unsigned) DSC$K_DTYPE_Q Quadword integer (signed) DSC$K_DTYPE_QU Quadword (unsigned) DSC$K_DTYPE_O+ Octaword integer (signed) DSC$K_DTYPE_OU+ Octaword (unsigned) DSC$K_DTYPE_F Single-precision floating DSC$K_DTYPE_D Double-precision floating DSC$K_DTYPE_G G-format floating DSC$K_DTYPE_H+ H-format floating DSC$K_DTYPE_FS++ IEEE single-precision S floating DSC$K_DTYPE_FT++ IEEE double-precision T floating DSC$K_DTYPE_T Text (may be influenced by collating sequence) DSC$K_DTYPE_NU Numeric string, unsigned DSC$K_DTYPE_NL Numeric string, left separate sign DSC$K_DTYPE_NLO Numeric string, left overpunched sign DSC$K_DTYPE_NR Numeric string, right separate sign DSC$K_DTYPE_NRO Numeric string, right overpunched sign DSC$K_DTYPE_NZ+ Numeric string, zoned sign DSC$K_DTYPE_P Packed decimal string
The HP OpenVMS Programming Concepts Manual manual describes each of these data types.
The second word of the block specifies the key order: 0 for ascending order, 1 for descending order. The third word of the block specifies the relative offset of the key in the record. (Note that the first byte in the record is at position 0.) The fourth word of the block specifies the key length in bytes (in digits for packed decimal---DSC$K_DTYPE_P).
If you do not specify the key_buffer argument, you must pass either a key comparison routine or use a specification file to define the key.
OpenVMS usage: | word_unsigned |
type: | word (unsigned) |
access: | read only |
mechanism: | by reference |
OpenVMS usage: | mask_longword |
type: | longword (unsigned) |
access: | read only |
mechanism: | by reference |
The following table lists and describes the bit mask values available:
Flag | Description |
---|---|
SOR$M_STABLE | Keeps records with equal keys in the same order as they appeared on input. |
SOR$M_EBCDIC | Orders ASCII character keys according to EBCDIC collating sequence. No translation takes place. |
SOR$M_MULTI | Orders character keys according to the multinational collating sequence, which collates the international character set. |
SOR$M_NOSIGNAL | Returns a status code instead of signaling errors. |
SOR$M_NODUPS | Omits records with duplicate keys. You cannot use this option if you specify your own equal-key routine. |
SOR$M_SEQ_CHECK | Requests an "out of order" error return if an input file is not already in sequence. By default, this check is not done. You must request sequence checking if you specify an equal-key routine. |
All other bits in the longword are reserved and must be zero.
OpenVMS usage: | byte_unsigned |
type: | byte (unsigned) |
access: | read only |
mechanism: | by reference |
OpenVMS usage: | procedure |
type: | procedure value |
access: | function call |
mechanism: | by reference |
MERGE calls the comparison routine with five reference arguments---ADRS1, ADRS2, LENG1, LENG2, CNTX---corresponding to the addresses of the two records to be compared, the lengths of these two records, and the context longword.
The comparison routine must return a 32-bit integer value:
OpenVMS usage: | procedure |
type: | procedure value |
access: | function call |
mechanism: | by reference |
MERGE calls the duplicate key routine with five reference arguments---ADRS1, ADRS2, LENG1, LENG2, CNTX---corresponding to the addresses of the two records that compare equally, the lengths of the two records that compare equally, and the context longword.
The routine must return one of the following 32-bit condition codes:
Code | Description |
---|---|
SOR$_DELETE1 | Delete the first record from the merge. |
SOR$_DELETE2 | Delete the second record from the merge. |
SOR$_DELBOTH | Delete both records from the merge. |
SS$_NORMAL | Keep both records in the merge. |
Any other failure value causes the error to be signaled or returned. Any other success value causes an undefined result.
OpenVMS usage: | procedure |
type: | procedure value |
access: | function call |
mechanism: | by reference |
This input routine must read (or construct) a record, place it in a record buffer, store its length in an output argument, and then return control to MERGE.
The input routine must accept the following four arguments:
The input routine must also return one of the following status values:
OpenVMS usage: | context |
type: | longword (unsigned) |
access: | modify |
mechanism: | by reference |
The SOR$BEGIN_MERGE routine initializes the merge process by passing arguments that provide the number of input streams, the key specifications, and any merge options.You must define the key by passing either the key buffer address argument or your own comparison routine address. (You can also define the key in a specification file and call the SOR$SPEC_FILE routine.)
The SOR$BEGIN_MERGE routine initializes the merge process in the file, record, and mixed interfaces. For record interface on input, you must also pass the merge order, the input routine address, and the longest record length. For files not on disk, you must pass the longest record length.
Some of the following condition values are used with different severities, depending on whether SORT/MERGE can recover. Thus, you should use LIB$MATCH_COND if you want to check for a specific status.
SS$_NORMAL Success. SOR$_BADDTYPE Invalid or unsupported CDD data type. SOR$_BADLENOFF Length and offset must be multiples of 8 bits. SOR$_BADLOGIC Internal logic error detected. SOR$_BADOCCURS Invalid OCCURS clause. SOR$_BADOVRLAY Invalid overlay structure. SOR$_BADPROTCL Node is an invalid CDD object. SOR$_BAD_KEY Invalid key specification. SOR$_BAD_LRL Record length n greater than specified longest record length. SOR$_BAD_MERGE Number of input files must be between 0 and 10. (For the high-performance Sort/Merge utility, the maximum number is 12.) SOR$_BAD_ORDER Merge input is out of order. SOR$_BAD_SRL Record length n is too short to contain keys. SOR$_BAD_TYPE Invalid sort process specified. SOR$_CDDERROR CDD error at node name. SOR$_CLOSEIN Error closing file as input. SOR$_CLOSEOUT Error closing file. SOR$_COL_CHAR Invalid character definition. SOR$_COL_CMPLX Collating sequence is too complex. SOR$_COL_PAD Invalid pad character. SOR$_COL_THREE Cannot define 3-byte collating values. SOR$_ENDDIAGS Completed with diagnostics. SOR$_ILLBASE Nondecimal base is invalid. SOR$_ILLLITERL Record containing symbolic literals is unsupported. SOR$_ILLSCALE Nonzero scale invalid for floating-point data item. SOR$_INCDIGITS Number of digits is not consistent with the type or length of item. SOR$_INCNODATA Include specification references no data, at line n. SOR$_INCNOKEY Include specification references no keys, at line n. SOR$_IND_OVR Indexed output file must already exist. SOR$_KEYAMBINC Key specification is ambiguous or inconsistent. SOR$_KEYED Mismatch between SORT/MERGE keys and primary file key. SOR$_KEY_LEN Invalid key length, key number n, length n. SOR$_LRL_MISS Longest record length must be specified. SOR$_MISLENOFF Length and offset required. SOR$_MISS_PARAM A required subroutine argument is missing. SOR$_MULTIDIM Invalid multidimensional OCCURS. SOR$_NODUPEXC Equal-key routine and no-duplicates option cannot both be specified. SOR$_NOTRECORD Node name is a name, not a record definition. SOR$_NUM_KEY Too many keys specified. SOR$_NYI Not yet implemented. SOR$_OPENIN Error opening file as input. SOR$_OPENOUT Error opening file as output. SOR$_READERR Error reading file. SOR$_RTNERROR Unexpected error status from user-written routine. SOR$_SIGNCOMPQ Absolute Date and Time data type represented in 1-second units. SOR$_SORT_ON Sort or merge routines called in incorrect order. SOR$_SPCIVC Invalid collating sequence specification at line n. SOR$_SPCIVD Invalid data type at line n. SOR$_SPCIVF Invalid field specification at line n. SOR$_SPCIVI Invalid include or omit specification at line n. SOR$_SPCIVK Invalid key or data specification at line n. SOR$_SPCIVP Invalid sort process at line n. SOR$_SPCIVS Invalid specification at line n. SOR$_SPCIVX Invalid condition specification at line n. SOR$_SPCMIS Invalid merge specification at line n. SOR$_SPCOVR Overridden specification at line n. SOR$_SPCSIS Invalid sort specification at line n. SOR$_SRTIWA Insufficient space. The specification file is too complex. SOR$_STABLEEX Equal-key routine and stable option cannot both be specified. SOR$_SYSERROR System service error. SOR$_UNDOPTION Undefined option flag was set. SOR$_UNSUPLEVL Unsupported core level for record name. SOR$_WRITEERR Error writing file.
Previous | Next | Contents | Index |