home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_10_08
/
ramey.exe
/
KEY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-14
|
7KB
|
243 lines
/*
Copyright (c) Robert Ramey 1991. All Rights Reserved
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "psort.h"
#include "arg.h"
#include "key.h"
#define MAX_KEYS 32
#define NSIZE 16
unsigned int key_count = 0; /* number of keys specified by command line */
KEY key[MAX_KEYS]; /* table of keys specified in command line */
size_t
tab_count = 0, /* number of fields to count in input record */
data_offset = 0, /* start additional data used for sorting */
*tab = (size_t)NULL, /* array of pointers to fields */
record_offset = 1; /* start of original record data */
SEQ *n_seq = (SEQ *)NULL;
SEQ *seq;
void
key_create(unsigned int, unsigned int, SEQ *, unsigned int,
unsigned int, BOOLEAN);
void
key_table();
/*********************************************************************
structure for accumulating on keys from information from command line
**********************************************************************/
struct {
struct {
BOOLEAN specified;
int
start,
size;
} field, /* field specification */
disp; /* character displacement specification */
BOOLEAN iflag; /* inverted sequence flag for this field */
BOOLEAN nflag; /* key field is a numeric value */
SEQ *seq; /* pointer to sequence table */
} key_spec;
/*********************************************************************
key_init - initialize information on keys from command line
**********************************************************************/
void
key_init(argc, argv)
unsigned int argc;
char *argv[];
{
RANGE range;
unsigned int i, j, l, seq_value, pseq_value;
int k;
/* set up defaults */
key_spec.field.specified = FALSE;
key_spec.field.start = 0;
key_spec.field.size = 0;
key_spec.disp.specified = FALSE;
key_spec.disp.start = 0;
key_spec.disp.size = UINT_MAX;
key_spec.seq = (SEQ *)NULL;
key_spec.nflag = FALSE;
key_spec.iflag = FALSE;
/* set up default collating sequence */
/* which consists of printable characters */
key_spec.seq = (SEQ *)malloc(sizeof(SEQ));
if(key_spec.seq == (SEQ *)NULL)
error("Couldn't get space for default collating sequence");
for(i = 0; i < 256; ++i)
key_spec.seq->value[i] = 0;
j = 0;
for(i = ' '; i <= '~'; ++i)
key_spec.seq->value[i] = ++j;
key_spec.seq->order = j;
/* analize arguments in command line */
for(i = 0; ++i < argc;){
if(argv[i][0] != '-' || argv[i][2] != '\0'){
continue;
}
switch(argv[i][1]){
default:
continue;
case 'f': case 'F':
argv[i] = "";
if(key_spec.field.specified)
key_table();
key_spec.field.specified = TRUE;
key_spec.disp.start = 0;
key_spec.disp.size = UINT_MAX;
arg_range(argv[++i], &range);
key_spec.field.start = range.start;
key_spec.field.size = range.end - range.start;
break;
case 'c': case 'C':
argv[i] = "";
if(key_spec.disp.specified)
key_table();
key_spec.disp.specified = TRUE;
arg_range(argv[++i], &range);
if(range.end > range.start)
error("Invalid character displacement range");
key_spec.disp.start = range.start;
key_spec.disp.size = range.end - range.start + 1;
break;
case 'n': case 'N':
key_spec.nflag = TRUE;
++record_offset;
if(n_seq == (SEQ *)NULL){
n_seq = (SEQ *)malloc(sizeof(SEQ));
if(n_seq == (SEQ *)NULL)
error("Couldn't get space for sign sequence");
/* set up collating sequence for - sign */
for(j = 0;j < 256;++j)
n_seq->value[j++] = 0;
j = 0;
for(k = -NSIZE; k < 0; ++k)
n_seq->value[k & 0xff] = ++j;
for(k = 1; k <= NSIZE; ++k)
n_seq->value[k & 0xff] = ++j;
n_seq->order = j;
}
break;
case 'i': case 'I':
key_spec.iflag = TRUE;
break;
case 'k': case 'K':
if(i + 1 == argc)
break;
key_spec.iflag = FALSE;
key_spec.nflag = FALSE;
key_spec.seq = (SEQ *)malloc(sizeof(SEQ));
if(key_spec.seq == (SEQ *)NULL)
error("Couldn't get space for collating sequence");
for(j = 0; j < 256 ;++j)
key_spec.seq->value[j] = 0;
key_spec.seq->order = 0;
if(key_spec.seq == (SEQ *)NULL)
error("Couldn't get memory for a sequence table");
pseq_value = 0;
case 'r': case 'R':
argv[i++] = "";
seq_value = pseq_value;
while(i < argc && argv[i][0] != NULL && argv[i][0] != '-'){
pseq_value = seq_value;
arg_range(argv[i], &range);
k = range.start < range.end ? +1 : -1;
for(j = range.start;;j += k){
key_spec.seq->value[j] = ++seq_value;
if(j == range.end)
break;
}
argv[i++] = "";
}
key_spec.seq->order = seq_value;
--i;
continue;
}
argv[i] = "";
}
/* every sort must have at least one key */
if(key_count == 0)
key_table();
tab_count += 2;
tab = malloc(tab_count * sizeof(int));
if(tab == (size_t *)NULL)
error("Couldn't get memory for tab array");
data_offset = sizeof(unsigned int) * (key_count + 1);
record_offset += data_offset;
return;
}
/*********************************************************************
key_table - create key table entries from command line information
**********************************************************************/
private
void
key_table()
{
unsigned int i, j;
int k;
i = key_spec.field.start;
j = i + key_spec.field.size;
k = key_spec.field.size < 0 ? -1 : 1 ;
tab_count = max(tab_count, i);
tab_count = max(tab_count, j);
for(;;){
if(!key_spec.nflag){
key_create(key_spec.disp.start, key_spec.disp.size,
key_spec.seq, i, DEFAULT, key_spec.iflag);
}
else{
key_create(key_spec.disp.start, 1,
n_seq, i, SIGN, key_spec.iflag);
key_create(key_spec.disp.start, UINT_MAX,
key_spec.seq, i, NUMERIC, key_spec.iflag);
key_create(key_spec.disp.start, UINT_MAX,
key_spec.seq, i, FRACTION, key_spec.iflag);
}
if(i == j)
break;
else
i += k;
}
return;
}
/*********************************************************************
key_create - add a key structure to the table
**********************************************************************/
private
void
key_create(disp, size, seq, rfield, key_type, iflag)
unsigned int
disp, size, rfield, key_type;
BOOLEAN iflag;
SEQ *seq;
{
KEY *key_ptr;
if(MAX_KEYS == key_count)
error("Too many key fields used");
key_ptr = &key[key_count++];
key_ptr->disp = disp;
key_ptr->size = size;
key_ptr->rfield = rfield;
key_ptr->key_type = key_type;
key_ptr->inverted = iflag;
key_ptr->seq = seq;
return;
}