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
/
RECORD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-14
|
8KB
|
293 lines
/*
Postman's Sort (R) Version 1.0
Copyright (c) Robert Ramey 1991. All Rights Reserved
*/
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <links.h>
#include "psort.h"
#include "key.h"
#include "record.h"
#include "arg.h"
STACK *d_stack;
RECORD *((*infunc)()) = rec_variable;
size_t record_size
= DEFAULT_RECORD_SIZE; /* max size of fixed or variable length record */
size_t data_size = 0; /* space required for fields, links etc. */
char *record_buffer = NULL; /* buffer to hold variable length record */
int delimiter = '\t'; /* field delimiter */
void *
need(STACK *, SEG_SIZE); /* defined in sort.c */
RECORD *
rec_get(char *, SEG_SIZE, FILE *);
void
rec_fill(RECORD *);
void
rec_windup(void);
/**********************************************************************
rec_init - get command line info for record functions
**********************************************************************/
void
rec_init(argc, argv)
int argc;
char *argv[];
{
RANGE range;
unsigned int i;
/* process key information */
key_init(argc, argv);
data_size = record_offset + sizeof(ADDRESS) + 1;
/* analize arguments in command line */
i = arg_find(argc, argv, "-d");
if(i == -1)
i = arg_find(argc, argv, "-D");
if(i != -1){
argv[i] = "";
if(++i >= argc
|| *argv[i] == '-'
|| *argv[i] == '0')
error("-d switch muse specify delimiter char in apostrophes");
arg_value(argv[++i], &delimiter);
argv[i] = "";
}
i = arg_find(argc, argv, "-s");
if(i == -1)
i == arg_find(argc, argv, "-S");
if(i != -1){
argv[i] = "";
if(++i >= argc
|| *argv[i] == '-'
|| *argv[i] == '0'){
error("-s switch must specify record width or range");
}
else{
arg_range(argv[i], &range);
argv[i] = "";
if(range.start == range.end){
record_size = range.start;
infunc = rec_fixed;
setmode(fileno(stdin), O_BINARY);
setmode(fileno(stdout), O_BINARY);
}
else{
record_size = range.end;
record_buffer = malloc(record_size + 1);
if(record_buffer == (char *)NULL)
error("Couldn't get space for record buffer");
}
}
}
if(record_buffer == (char *)NULL){
record_buffer = malloc(record_size + 1);
if(record_buffer == (char *)NULL)
error("Couldn't get space for record buffer");
}
if(record_buffer != (char *)NULL){
if(atexit(rec_windup))
error("Couldn't register record windup");
}
return;
}
/**********************************************************
rec_windup - return unused memory area
***********************************************************/
private void
rec_windup(){
if(record_buffer != (char *)NULL)
free(record_buffer);
}
/**********************************************************
rec_variable - get a variable size record from standard input
***********************************************************/
RECORD *
rec_variable()
{
RECORD *record_address; /* pointer to record */
size_t record_length;
/* make sure we don't fill the record buffer up */
if(rec_get(record_buffer, record_size , stdin)
== (char *)NULL)
return (RECORD *)NULL;
record_length = strlen(record_buffer);
record_address
= (RECORD *)mklinks(need(d_stack, data_size+record_length), 1);
memcpy(record_address->data+record_offset,
record_buffer, record_length + 1);
/* if record data doesn't fit within buffer */
if(record_address->data[record_offset + record_length - 1] != '\n')
error("Record too long");
record_address->field[0] = record_offset + record_length;
rec_fill(record_address);
return record_address;
}
/**********************************************************
rec_get - get a record from standard input
***********************************************************/
private
RECORD *
rec_get(ptr, size, fptr)
char *ptr;
SEG_SIZE size;
FILE *fptr;
{
if(fgets(ptr, (int)size, fptr) == (char *)NULL){
/* be sure its an end of file */
if(feof(fptr)){
/* if we're done, change future input source */
fclose(fptr);
/* and return NULL */
return (RECORD *)NULL;
}
else{
perror("I/O error in standard input");
exit(1);
}
}
}
/*********************************************************
rec_fixed - get a fixed size record from standard input
***********************************************************/
RECORD *
rec_fixed()
{
RECORD *record_address; /* pointer to record including links and fields */
int record_read;
SEG_SIZE size;
/* get space for input */
record_address
= (RECORD *)mklinks(need(d_stack, data_size + record_size), 1);
record_address->field[0] = record_offset + record_size;
/* get a line of text from standard input */
record_read =
fread(record_address->data+record_offset, record_size, 1, stdin);
/* add null terminator */
record_address->data[record_address->field[0]] = (char)NULL;
if(record_read == 0){
/* be sure its an end of file */
if(feof(stdin)){
/* if we're done, change future input source */
fclose(stdin);
/* and return NULL */
return (RECORD *)NULL;
}
else{
assert(ferror(stdin))
perror("I/O error in standard input");
exit(1);
}
}
rec_fill(record_address);
return record_address;
}
/*********************************************************************
rec_fill - give a record, fill in the field pointers
**********************************************************************/
private
void
rec_fill(record_address)
RECORD *record_address; /* pointer to record */
{
unsigned int
i, /* index into field sequence array */
fstart; /* start of numeric field */
static int
sign, /* +1 or -1 depending on sign of field */
offset, /* offset to record data */
noffset; /* offset to filled numeric data */
char *tptr, *eptr, c;
/* figure where data starts */
tptr = record_address->data + record_offset;
eptr = record_address->data + record_address->field[0];
/* find where fields start */
tab[0] = record_offset;
i = 1;
while(i < tab_count){
while(!isdelim(*tptr++)){
if(tptr >= eptr){
goto fini;
}
}
tab[i++] = tptr - record_address->data;
}
fini:
/* missing fields all point to null */
while(i < tab_count)
tab[i++] = record_address->field[0];
noffset = data_offset;
for(i = 0 ; i < key_count; ++i){
if(key[i].key_type == DEFAULT){
offset = tab[key[i].rfield+1] - tab[key[i].rfield];
offset = min(offset-1, key[i].disp) + tab[key[i].rfield];
assert(record_address);
record_address->field[i+1] = offset;
}
else{
/* Next 3 keys should be SIGN, NUMERIC, and FRACTION */
offset = tab[key[i].rfield+1] - tab[key[i].rfield];
offset = min(offset-1, key[i].disp) + tab[key[i].rfield];
/* skip leading spaces */
while(record_address->data[offset] == ' ')
++offset;
c = record_address->data[offset];
sign = 1;
if('+' == c)
++offset;
else
if('-' == c){
sign = -1;
++offset;
}
while(record_address->data[offset] == '0')
++offset;
fstart = offset;
while(key[i + 1].seq->value[record_address->data[offset]])
++offset;
assert(record_address);
record_address->data[noffset] = sign * (offset - fstart + 1);
record_address->field[i + 1] = noffset++;
record_address->field[i + 2] = fstart;
/* skip . or , if exists */
c = record_address->data[offset];
if(c == '.' || c == ',')
++offset;
record_address->field[i + 3] = offset;
i += 3;
}
}
rec_memflag(record_address) = FALSE;
return;
}
/*********************************************************************
rec_output - write one record to standard output
**********************************************************************/
void
rec_output(record_address)
RECORD *record_address;
{
efwrite(record_address->data + record_offset,
record_address->field[0] - record_offset,
1, stdout);
}