Spostato csort
git-svn-id: svn://10.65.10.50/trunk@854 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
8e00232883
commit
a1a7b2c36a
753
include/csort.c
Executable file
753
include/csort.c
Executable file
@ -0,0 +1,753 @@
|
||||
/*
|
||||
@(SH) Funzioni per l'esecuzione di sort
|
||||
@(VG$) PRIVATE
|
||||
datisort : copia struttura del sort attivo
|
||||
nsortfield : Numero campi definiti dal sort
|
||||
sp : struttura dei parametri sort
|
||||
totrcd : numero totale di record ordinati
|
||||
no_seq : contatore sequenze
|
||||
no_seq1 : contatore sequenze
|
||||
bspace : spazio disponibile nel buffer
|
||||
nrcds : numero di records nel buffer di sort
|
||||
nrcds1 : numero di records nel buffer di sort
|
||||
bf, bf1 : puntatori al buffer di sort
|
||||
inbf : records variabili nel buffer di sort
|
||||
sptr : puntatore al vettore dei puntatori ai buffer
|
||||
init_sptr : puntatore al buffer appropriato
|
||||
rcds_seq : sequenza record nel buffer di merge
|
||||
fp1, fp2 : puntatori a file di lavoro per il sort
|
||||
fdname : nome di lavoro del sort
|
||||
f2name : nome di lavoro del sort
|
||||
-------------------------------------------------------------------------------
|
||||
@(H) 2.3.00.112 23/11/91 Bonazzi Corretta fine sort
|
||||
@(H) 2.3.01.245 08/03/94 Soragna Corretto sort_op per 386
|
||||
*/
|
||||
|
||||
#include "csort.h"
|
||||
#include <memory.h>
|
||||
|
||||
/*----------------------- STATIC PER PRIMA PARTE ----------------------------*/
|
||||
|
||||
static struct s_prm datisort;
|
||||
static int nsortfield;
|
||||
|
||||
/*----------------------- STATIC PER SECONDA PARTE --------------------------*/
|
||||
|
||||
static struct s_prm *sp;
|
||||
/* @(!) 2.3.00.112 */
|
||||
static unsigned long totrcd;
|
||||
static unsigned no_seq;
|
||||
static unsigned no_seq1;
|
||||
/* @(:) 2.3.00.112 */
|
||||
static unsigned bspace;
|
||||
/* @(!) 2.3.00.112 */
|
||||
static unsigned nrcds;
|
||||
static unsigned nrcds1;
|
||||
/* @(:) 2.3.00.112 */
|
||||
static char *bf, *bf1;
|
||||
/* @(!) 2.3.00.112 */
|
||||
static unsigned inbf;
|
||||
/* @(:) 2.3.00.112 */
|
||||
static char **sptr;
|
||||
static char *init_sptr;
|
||||
/* @(!) 2.3.00.112 */
|
||||
static unsigned rcds_seq;
|
||||
/* @(:) 2.3.00.112 */
|
||||
static FILE *fp1, *fp2;
|
||||
static char fdname [42];
|
||||
static char f2name [42];
|
||||
|
||||
static int sortcomp(char **, char **);
|
||||
static char *appr_mem(unsigned *);
|
||||
/* @(!) 2.3.00.112 */
|
||||
static FILE *wopen(char *);
|
||||
/* @(:) 2.3.00.112 */
|
||||
static void dumpbuff(void);
|
||||
static void merge(void);
|
||||
static void prep_merge(void);
|
||||
/* @(!) 2.3.01.245 */
|
||||
void dummy(void);
|
||||
/* @(:) 2.3.01.245 */
|
||||
|
||||
/*----------------------- PRIMA PARTE ---------------------------------------*/
|
||||
|
||||
/*
|
||||
@(#) init_sort SORT
|
||||
|
||||
@(ID)
|
||||
Inizializza le variabili globali per il sort.
|
||||
@(FD)
|
||||
*/
|
||||
|
||||
int init_sort(prms)
|
||||
struct s_prm *prms; /* struttura di descrizione del sort */
|
||||
{
|
||||
sp = prms;
|
||||
if ((bf = appr_mem(&bspace)) != NULL) {
|
||||
nrcds1 = nrcds = bspace / (sp->rc_len + sizeof(char *));
|
||||
init_sptr = bf;
|
||||
sptr = (char **) bf;
|
||||
bf += nrcds * sizeof(char *);
|
||||
fp1 = fp2 = NULL;
|
||||
totrcd = no_seq = inbf = 0;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@(#) sort SORT
|
||||
|
||||
@(ID)
|
||||
Funzione per l'input dei record da ordinare.
|
||||
@(FD)
|
||||
|
||||
@(IN)
|
||||
La chiamata sort(char *) NULL) chiude la fase di input dei record.
|
||||
@(FN)
|
||||
*/
|
||||
|
||||
void sort(s_rcd)
|
||||
char *s_rcd; /* buffer contenente il record da ordinare */
|
||||
|
||||
{
|
||||
/* @(!) 2.3.00.112 */
|
||||
if (inbf == nrcds) { /* if the sort buffer is full */
|
||||
/* @(:) 2.3.00.112 */
|
||||
qsort(init_sptr, inbf, sizeof (char *), sortcomp);
|
||||
if (s_rcd) { /* if there are more records to sort */
|
||||
dumpbuff(); /* dump the buffer to a sort work file*/
|
||||
no_seq++; /* count the sorted sequences */
|
||||
}
|
||||
}
|
||||
if (s_rcd !=NULL) {
|
||||
/* --- this is a record to sort --- */
|
||||
totrcd++;
|
||||
/* --- put the rcd addr in the pointer array --- */
|
||||
*sptr = bf + inbf * sp->rc_len;
|
||||
inbf++;
|
||||
/* --- move the rcd to the buffer --- */
|
||||
memcpy(*sptr, s_rcd, sp->rc_len);
|
||||
sptr++; /* point to next array entry*/
|
||||
}
|
||||
else { /* null pointer means no more rcds */
|
||||
if (inbf) { /* any records in the buffer? */
|
||||
qsort(init_sptr, inbf, sizeof (char *), sortcomp);
|
||||
if (no_seq) /* if this isn't the only sequence*/
|
||||
dumpbuff(); /* dump the buffer to a work file */
|
||||
no_seq++; /* count the sequence */
|
||||
}
|
||||
no_seq1 = no_seq;
|
||||
if (no_seq > 1) /* if there is more than 1 sequence */
|
||||
prep_merge(); /* prepare for the merge */
|
||||
}
|
||||
}
|
||||
/*
|
||||
@($) prep_merge SORT
|
||||
|
||||
@(ID)
|
||||
Funzione per la preparazione del Merge.
|
||||
@(FD)
|
||||
|
||||
@(ISV)
|
||||
i = contatore.
|
||||
|
||||
rr = puntatore ad una struttura di sequenza (di lavoro).
|
||||
|
||||
n_bfsz = ampiezza in byte del merge buffer.
|
||||
|
||||
@(FSV)
|
||||
*/
|
||||
|
||||
static void prep_merge()
|
||||
{
|
||||
int i;
|
||||
struct bp *rr;
|
||||
unsigned n_bfsz;
|
||||
|
||||
memset(init_sptr, '\0', bspace);
|
||||
/* -------- merge buffer size ------ */
|
||||
n_bfsz = bspace - no_seq * sizeof(struct bp);
|
||||
/* ------ # rcds/seq in merge buffer ------- */
|
||||
rcds_seq = n_bfsz / no_seq / sp->rc_len;
|
||||
if (rcds_seq < 2) {
|
||||
/* ---- more sequence blocks than will fit in buffer,
|
||||
merge down ---- */
|
||||
while (rcds_seq < 2) {
|
||||
FILE *hd;
|
||||
/* @(!) 2.3.00.112 */
|
||||
char wname[42]; /* sort work name */
|
||||
|
||||
fp2 = wopen(f2name); /* open a sort work file */
|
||||
/* @(:) 2.3.00.112 */
|
||||
merge(); /* binary merge */
|
||||
hd = fp1; /* swap fds */
|
||||
fp1 = fp2;
|
||||
fp2 = hd;
|
||||
/* @(!) 2.3.00.112 */
|
||||
strcpy(wname, fdname);
|
||||
strcpy(fdname, f2name);
|
||||
strcpy(f2name, wname);
|
||||
fclose(fp2);
|
||||
unlink(f2name);
|
||||
fp2 = NULL;
|
||||
/* @(:) 2.3.00.112 */
|
||||
nrcds *= 2;
|
||||
/* ------ adjust number of sequence ------ */
|
||||
no_seq = (no_seq + 1) / 2;
|
||||
n_bfsz = bspace - no_seq * sizeof(struct bp);
|
||||
rcds_seq = n_bfsz / no_seq / sp->rc_len;
|
||||
}
|
||||
}
|
||||
bf1 = init_sptr;
|
||||
rr = (struct bp *) init_sptr;
|
||||
bf1 += no_seq * sizeof(struct bp);
|
||||
bf = bf1;
|
||||
|
||||
/* fill the merge buffer with records from all sequences */
|
||||
|
||||
for (i = 0; i < no_seq; i++) {
|
||||
fseek(fp1, (long) i * ((long) nrcds * sp->rc_len), 0);
|
||||
/* ------ read them all at once ------ */
|
||||
/* @(!) 2.3.00.112 modificata fread(bf1, rcds_seq * sp->rc_len, 1, fp1); */
|
||||
fread(bf1, sp->rc_len, rcds_seq, fp1);
|
||||
/* @(:) 2.3.00.112 */
|
||||
rr->rc = bf1;
|
||||
/* --- the last seq has fewer rcds than the rest --- */
|
||||
if (i == no_seq-1) {
|
||||
if (totrcd % nrcds > rcds_seq) {
|
||||
rr->rbuf = rcds_seq;
|
||||
/* @(!) 2.3.00.112 */
|
||||
rr->rdsk = (unsigned) (totrcd % nrcds) - rcds_seq;
|
||||
/* @(:) 2.3.00.112 */
|
||||
}
|
||||
else {
|
||||
/* @(!) 2.3.00.112 */
|
||||
rr->rbuf = (unsigned) (totrcd % nrcds);
|
||||
/* @(:) 2.3.00.112 */
|
||||
rr->rdsk = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rr->rbuf = rcds_seq;
|
||||
rr->rdsk = nrcds - rcds_seq;
|
||||
}
|
||||
rr++;
|
||||
bf1 += rcds_seq * sp->rc_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* @(!) 2.3.01.245 */
|
||||
/* Funzione che non fa assolutamente nulla, ma e' estremamente
|
||||
utile all'interno di sort_op, quando si supera una certa mole di
|
||||
dati immessi nel buffer di sort; e' necessaria solo per la
|
||||
compilazione di eseguibili per 386. Questa funzione inserita tra
|
||||
le righe rtn= k+..... e memcpy(..) evita il fastidioso memory
|
||||
fault che si ottiene utilizzando strutture molto ampie o molto
|
||||
numerose. Probabilmente evita, in fase di compilazione, che vengano
|
||||
creati indirizzi strani, oppure in fase di esecuzione, che vengano
|
||||
reperite zone di memoria che non c'entrano per nulla.
|
||||
*/
|
||||
void dummy()
|
||||
{
|
||||
}
|
||||
/* @(:) 2.3.01.245 */
|
||||
|
||||
|
||||
/*
|
||||
@($) merge SORT
|
||||
|
||||
@(ID)
|
||||
Effettua un merge.
|
||||
E' un merge binario di records dalla sequenza fp1 in fp2.
|
||||
@(FD
|
||||
|
||||
@(ISV)
|
||||
i = contatore.
|
||||
|
||||
needy,needx = se true necessita un record da (x/y).
|
||||
|
||||
xcnt,ycnt = numero di records lasciati in ogni sequenza.
|
||||
|
||||
x,y = contatori per le sequenze.
|
||||
|
||||
adx,ady = indirizzi sul disco delle sequenze di record.
|
||||
|
||||
ysptr = stringa di lavoro.
|
||||
@(FSV)
|
||||
*/
|
||||
|
||||
static void merge()
|
||||
{
|
||||
int i;
|
||||
int needy, needx; /* true = need a rcd from (x/y) */
|
||||
/* @(!) 2.3.00.112 */
|
||||
unsigned xcnt, ycnt; /* # rcds left each sequence */
|
||||
/* @(:) 2.3.00.112 */
|
||||
int x, y; /* sequence counters */
|
||||
long adx, ady; /* sequence record disk addresses */
|
||||
/* @(!) 2.3.00.112 */
|
||||
char *ysptr = init_sptr + sp->rc_len;
|
||||
/* @(:) 2.3.00.112 */
|
||||
|
||||
/* --- the two sets of sequences are x and y ----- */
|
||||
fseek (fp2, 0L, 0);
|
||||
for (i = 0; i < no_seq; i += 2) {
|
||||
x = y = i;
|
||||
y++;
|
||||
ycnt =
|
||||
y == no_seq ? 0 : y == no_seq - 1 ?
|
||||
/* @(!) 2.3.00.112 */
|
||||
(unsigned) (totrcd % nrcds) : nrcds;
|
||||
xcnt = y == no_seq ? (unsigned) (totrcd % nrcds) : nrcds;
|
||||
/* @(:) 2.3.00.112 */
|
||||
adx = (long) x * (long) nrcds * sp->rc_len;
|
||||
ady = adx + (long) nrcds * sp ->rc_len;
|
||||
needy = needx = 1;
|
||||
while (xcnt || ycnt) {
|
||||
if (needx && xcnt) { /* need a rcd from x? */
|
||||
fseek(fp1, adx, 0);
|
||||
adx += (long) sp->rc_len;
|
||||
fread(init_sptr, sp->rc_len, 1, fp1);
|
||||
needx = 0;
|
||||
}
|
||||
if (needy && ycnt) { /* need a rcd from y? */
|
||||
fseek(fp1, ady, 0);
|
||||
ady += sp->rc_len;
|
||||
/* @(!) 2.3.00.112 modificata fread(init_sptr+sp->rc_len, sp->rc_len, 1, fp1); */
|
||||
fread(ysptr, sp->rc_len, 1, fp1);
|
||||
/* @(:) 2.3.00.112 */
|
||||
needy = 0;
|
||||
}
|
||||
if (xcnt || ycnt) { /* if anything is left */
|
||||
/* ---- compare the two sequences --- */
|
||||
/* @(!) 2.3.00.112 modificata if (!ycnt || (xcnt && (sortcomp(&init_sptr, &init_sptr + sp->rc_len)) < 0)) { */
|
||||
if (!ycnt || (xcnt && (sortcomp(&init_sptr, &ysptr)) < 0)) {
|
||||
/* @(:) 2.3.00.112 */
|
||||
/* ----- record from x is lower ---- */
|
||||
fwrite(init_sptr, sp->rc_len, 1, fp2);
|
||||
--xcnt;
|
||||
needx = 1;
|
||||
}
|
||||
else if (ycnt) { /* record from y is lower */
|
||||
/* @(!) 2.3.00.112 */
|
||||
fwrite(ysptr, sp->rc_len, 1, fp2);
|
||||
/* @(:) 2.3.00.112 */
|
||||
--ycnt;
|
||||
needy = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
@($) dumpbuff SORT
|
||||
|
||||
@(ID)
|
||||
Copia il buffer di sort nel file di lavoro.
|
||||
@(FD)
|
||||
|
||||
@(ISV)
|
||||
i = contatore.
|
||||
@(FSV)
|
||||
*/
|
||||
|
||||
static void dumpbuff()
|
||||
{
|
||||
/* @(!) 2.3.00.112 */
|
||||
unsigned i;
|
||||
/* @(:) 2.3.00.112 */
|
||||
|
||||
if (fp1 == NULL)
|
||||
/* @(!) 2.3.00.112 */
|
||||
fp1 = wopen(fdname);
|
||||
/* @(:) 2.3.00.112 */
|
||||
sptr = (char **) init_sptr;
|
||||
for (i = 0; i < inbf; i++) {
|
||||
fwrite(*(sptr + i), sp->rc_len, 1, fp1);
|
||||
/* @(!) 2.3.00.112 */
|
||||
*(sptr + i) = 0;
|
||||
/* @(:) 2.3.00.112 */
|
||||
}
|
||||
inbf = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@($) wopen SORT
|
||||
|
||||
@(ID)
|
||||
Apre un file di lavoro temporaneo (per il sort).
|
||||
@(FD)
|
||||
|
||||
@(ISV)
|
||||
fp = puntatore al file temporaneo.
|
||||
|
||||
s = stringa di formato.
|
||||
|
||||
n = numero del file.
|
||||
|
||||
@(FSV)
|
||||
*/
|
||||
|
||||
/* @(!) 2.3.00.112 */
|
||||
static FILE *wopen(name)
|
||||
char *name; /* nome del file temporaneo */
|
||||
/* @(:) 2.3.00.112 */
|
||||
{
|
||||
FILE *fp;
|
||||
char s[42];
|
||||
/* @(!) 2.3.00.112 */
|
||||
static int n = 0;
|
||||
/* @(:) 2.3.00.112 */
|
||||
|
||||
sprintf(s, "srt%03d", ++n);
|
||||
TMPFNAME(name,s);
|
||||
#ifdef DOS
|
||||
if ((fp = fopen(name, "wb+")) == NULL) {
|
||||
#else
|
||||
if ((fp = fopen(name, "w+")) == NULL) {
|
||||
#endif
|
||||
|
||||
#ifndef XVT_OS
|
||||
printf("\nFile error");
|
||||
exit(1);
|
||||
#else
|
||||
fatal_box("Can't open SORT file");
|
||||
#endif
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
/*
|
||||
@(#) sort_op SORT
|
||||
|
||||
@(ID)
|
||||
Ritorna il puntatore al primo record non ancora elaborato nella sequenza ordinata.
|
||||
@(FD)
|
||||
|
||||
@(ISV)
|
||||
j = e' true se una qualche sequenza contiene ancora dei records.
|
||||
|
||||
i = contatore.
|
||||
|
||||
k,nrd,l = variabili di lavoro.
|
||||
|
||||
rr = variabile di lavoro.
|
||||
|
||||
r1 = variabile di lavoro.
|
||||
|
||||
rtn = indirizzo del buffer da ritornare.
|
||||
|
||||
ad,tr = variabili di lavoro.
|
||||
@(FSV)
|
||||
|
||||
@(FN)
|
||||
Se la funzione sort_op ritorna NULL non ci sono piu' records nella sequenza ordinata.
|
||||
@(FN)
|
||||
*/
|
||||
|
||||
|
||||
char *sort_op()
|
||||
{
|
||||
int j = 0;
|
||||
/* @(!) 2.3.00.112 */
|
||||
unsigned i, k, nrd, l;
|
||||
/* @(:) 2.3.00.112 */
|
||||
struct bp *rr;
|
||||
/* @(!) 2.3.00.112 */
|
||||
static unsigned r1 = 0;
|
||||
/* @(:) 2.3.00.112 */
|
||||
char *rtn;
|
||||
long ad, tr;
|
||||
|
||||
if (init_sptr == NULL) return NULL;
|
||||
|
||||
sptr = (char **) init_sptr;
|
||||
if (no_seq < 2) {
|
||||
/* -- with only 1 sequence, mo merge has been done -- */
|
||||
/* @(!) 2.3.00.112 */
|
||||
if (r1 == (unsigned) totrcd) {
|
||||
/* @(:) 2.3.00.112 */
|
||||
if (init_sptr != NULL) free(init_sptr);
|
||||
/* @(!) 2.3.00.112 */
|
||||
init_sptr = NULL;
|
||||
/* @(:) 2.3.00.112 */
|
||||
fp1 = fp2 = NULL;
|
||||
r1 = 0;
|
||||
return NULL;
|
||||
}
|
||||
return *(sptr + r1++);
|
||||
}
|
||||
|
||||
|
||||
rr = (struct bp *) init_sptr;
|
||||
for (i = 0; i < no_seq; i++)
|
||||
/* @(!) 2.3.00.112 */
|
||||
j |= (int) (rr + i)->rbuf | (rr + i)->rdsk;
|
||||
/* @(:) 2.3.00.112 */
|
||||
|
||||
/* -- j will be true if any sequence still has records - */
|
||||
if (!j)
|
||||
{
|
||||
fclose(fp1); /* none left */
|
||||
unlink(fdname);
|
||||
/* @(!) 2.3.00.112 eliminata if (fp2) */
|
||||
/* @(!) 2.3.00.112 eliminata { */
|
||||
/* @(!) 2.3.00.112 eliminata fclose(fp2); */
|
||||
/* @(!) 2.3.00.112 eliminata unlink(f2name); */
|
||||
/* @(!) 2.3.00.112 eliminata } */
|
||||
/* @(:) 2.3.00.112 */
|
||||
if (init_sptr != NULL) free(init_sptr);
|
||||
/* @(!) 2.3.00.112 */
|
||||
init_sptr = NULL;
|
||||
/* @(:) 2.3.00.112 */
|
||||
fp1 = fp2 = NULL;
|
||||
r1 = 0;
|
||||
return NULL;
|
||||
}
|
||||
k = 0;
|
||||
|
||||
/* --- find the sequence in the merge buffer
|
||||
with the lowest record --- */
|
||||
for (i = 0; i < no_seq; i++)
|
||||
k = ((sortcomp( &(rr + k)->rc, &(rr + i)->rc) < 0) ? k : i);
|
||||
|
||||
|
||||
/* --- k is an integer sequence number that offsets to the
|
||||
sequence with the lowest record ---- */
|
||||
|
||||
(rr + k)->rbuf--; /* decrement the rcd counter */
|
||||
rtn = (rr + k)->rc; /* set the return pointer */
|
||||
(rr + k)->rc += sp->rc_len;
|
||||
if ((rr + k)->rbuf == 0) {
|
||||
/* ---- the sequence got empty ---- */
|
||||
/* --- so get some more if there are any --- */
|
||||
rtn = bf + k * rcds_seq * sp->rc_len;
|
||||
/* @(!) 2.3.01.245 */
|
||||
dummy();
|
||||
/* @(:) 2.3.01.245 */
|
||||
memcpy(rtn, (rr + k)->rc - sp->rc_len, sp->rc_len);
|
||||
(rr + k)->rc = rtn + sp->rc_len;
|
||||
if ((rr + k)->rdsk != 0) {
|
||||
l = ((rcds_seq-1) < (rr+k)->rdsk) ? rcds_seq-1 : (rr+k)->rdsk;
|
||||
/* @(!) 2.3.00.112 */
|
||||
nrd = k == no_seq - 1 ? (unsigned) (totrcd % nrcds) : nrcds;
|
||||
/* @(:) 2.3.00.112 */
|
||||
tr = (long) ((k * nrcds + (nrd - (rr + k)->rdsk)));
|
||||
ad = tr * sp->rc_len;
|
||||
fseek(fp1, ad, 0);
|
||||
/* @(!) 2.3.00.112 modificata fread(rtn + sp->rc_len, l * sp->rc_len, 1, fp1); */
|
||||
fread(rtn + sp->rc_len, sp->rc_len, l, fp1);
|
||||
/* @(:) 2.3.00.112 */
|
||||
(rr + k)->rbuf = l;
|
||||
(rr + k)->rdsk -= l;
|
||||
}
|
||||
else
|
||||
memset((rr + k)->rc, 127, sp->rc_len);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/*
|
||||
@(#) sort_stats SORT
|
||||
|
||||
@(ID)
|
||||
Visualizza la statistica sul sort.
|
||||
@(FD)
|
||||
*/
|
||||
|
||||
void sort_stats()
|
||||
{
|
||||
#ifndef XVT_OS
|
||||
printf("\n\r\n\r\n\rRecord Length = %d",sp->rc_len);
|
||||
/* @(!) 2.3.00.112 */
|
||||
printf("\n\r%u records sorted",totrcd);
|
||||
printf("\n\r%u sequence",no_seq);
|
||||
/* @(:) 2.3.00.112 */
|
||||
if (no_seq1 != 1) putchar('s');
|
||||
printf("\n\r%u characters of sort buffer", bspace);
|
||||
/* @(!) 2.3.00.112 */
|
||||
printf("\n\r%u records per buffer\n\n",nrcds);
|
||||
/* @(:) 2.3.00.112 */
|
||||
#else
|
||||
message_box(
|
||||
"Record length = %d\n"
|
||||
"%u records sorted\n"
|
||||
"%u sequences\n"
|
||||
"%u bytes of sort buffer\n"
|
||||
"%u records per buffer",
|
||||
sp->rc_len, totrcd, no_seq, bspace, nrcds
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@($) appr_mem SORT
|
||||
|
||||
@(ID)
|
||||
Alloca memoria per un buffer.
|
||||
@(FD)
|
||||
|
||||
@(ISV)
|
||||
buff = buffer di memoria allocato.
|
||||
@(FSV)
|
||||
|
||||
@(IN)
|
||||
Se puo' alloca MOSTMEM altrimenti ne alloca quanto puo',
|
||||
non scendendo mai sotto il minimo LEASTMEM
|
||||
@(FN)
|
||||
*/
|
||||
|
||||
static char *appr_mem(h)
|
||||
unsigned *h; /* puntatore alla quantita' di byte allocati */
|
||||
{
|
||||
char *buff = NULL;
|
||||
|
||||
*h = (unsigned) MOSTMEM + 1024;
|
||||
while (buff == NULL && *h > LEASTMEM) {
|
||||
*h -= 1024;
|
||||
buff = malloc(*h);
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
/*
|
||||
@($) sortcomp SORT
|
||||
|
||||
@(ID)
|
||||
Esegue i confronti per il sort ed il merge.
|
||||
@(FD)
|
||||
|
||||
@(ISV)
|
||||
i = contatore.
|
||||
|
||||
k = risultato della comparazione.
|
||||
@(FSV)
|
||||
|
||||
@(IN)
|
||||
Ritorna un intero < 0 se a < b
|
||||
0 se a = b
|
||||
> 0 se a > b
|
||||
@(FN)
|
||||
*/
|
||||
|
||||
static int sortcomp(a,b)
|
||||
char **a; char **b; /* puntatori ai puntatori ai record da confrontare */
|
||||
{
|
||||
int i, k;
|
||||
|
||||
if (**a == 127 || **b == 127)
|
||||
return (int) **a - (int) **b;
|
||||
for (i = 0; i < NOFLDS; i++)
|
||||
{
|
||||
if (sp->s_fld[i].f_pos == 0) break;
|
||||
if (sp->s_fld[i].f_len >= 0) /* string compare */
|
||||
{
|
||||
if ( ( k=strncmp ( (*a)+sp->s_fld[i].f_pos-1,
|
||||
(*b)+sp->s_fld[i].f_pos-1,
|
||||
sp->s_fld[i].f_len
|
||||
) ) != 0)
|
||||
return (sp->s_fld[i].ad == 'd')?-k:k;
|
||||
}
|
||||
|
||||
if (sp->s_fld[i].f_len == -1) /* integer compare */
|
||||
{
|
||||
if ( (*( (int*) (*a)+sp->s_fld[i].f_pos-1 )) !=
|
||||
(*( (int*) (*b)+sp->s_fld[i].f_pos-1 )) )
|
||||
{
|
||||
k=(*( (int*) (*a)+sp->s_fld[i].f_pos-1 )) - (*( (int*) (*b)+sp->s_fld[i].f_pos-1 ));
|
||||
return (sp->s_fld[i].ad == 'd')?-k:k;
|
||||
}
|
||||
}
|
||||
|
||||
if (sp->s_fld[i].f_len == -2) /* BOOLEAN compare */
|
||||
{
|
||||
if ( (*( (BOOLEAN*) (*a)+sp->s_fld[i].f_pos-1 )) !=
|
||||
(*( (BOOLEAN*) (*b)+sp->s_fld[i].f_pos-1 )) )
|
||||
{
|
||||
k=(int) ( (*( (BOOLEAN*) (*a)+sp->s_fld[i].f_pos-1 )) - (*( (BOOLEAN*) (*b)+sp->s_fld[i].f_pos-1 )) );
|
||||
return (sp->s_fld[i].ad == 'd')?-k:k;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------- SECONDA PARTE --------------------------------*/
|
||||
|
||||
/*
|
||||
@(#) initsortfield SORT
|
||||
|
||||
@(ID)
|
||||
Definizione di sort per un record ISAM.
|
||||
@(FD)
|
||||
*/
|
||||
|
||||
void initsortfield ()
|
||||
{
|
||||
nsortfield = datisort.s_fld[0].f_pos = 0; /* sort su nessun campo */
|
||||
}
|
||||
|
||||
/*
|
||||
@(#) addsortfield SORT
|
||||
|
||||
@(ID)
|
||||
Aggiunge campi alla descrizione.
|
||||
@(FD)
|
||||
|
||||
@(ISV)
|
||||
i = variablie di lavoro.
|
||||
|
||||
n = variablie di lavoro.
|
||||
@(FSV)
|
||||
*/
|
||||
|
||||
int addsortfield (isfd,ncampo,da,a,ad)
|
||||
isfdptr isfd; /* puntatore al descrittore del file ISAM */
|
||||
FieldName ncampo; /* nome campo */
|
||||
int da; /* carattere da cui considerare il campo per il sort */
|
||||
int a; /* carattere fino al quale considerare il campo per il sort */
|
||||
char ad; /* ordine crescente o decrescente */
|
||||
|
||||
{
|
||||
int i,n;
|
||||
|
||||
if (((n = findfld(isfd->r, ncampo)) != -1) && (nsortfield < NOFLDS))
|
||||
{
|
||||
/* sostituito i con n in Fd[_].RecOff e Fd[_].len */
|
||||
/* @(!) 2.3.01.temp */
|
||||
datisort.s_fld[nsortfield].f_pos = (da==0) ? (isfd->r->Fd[n].RecOff + 1) : (isfd->r->Fd[n].RecOff+da);
|
||||
datisort.s_fld[nsortfield].f_len = (a==0) ? (isfd->r->Fd[n].Len) : (a-da+1); /* carica FLDLEN */
|
||||
datisort.s_fld[nsortfield].ad = ad; /* carica AD */
|
||||
nsortfield++;
|
||||
/* @(:) 2.3.01.temp */
|
||||
return 0;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@(#) finesortfield SORT
|
||||
|
||||
@(ID)
|
||||
Chiude la descrizione del sort per i record ISAM.
|
||||
@(FD)
|
||||
|
||||
@(IN)
|
||||
Attenzione : questa funzione inizializza anche il sort.
|
||||
@(FN)
|
||||
*/
|
||||
|
||||
int finesortfield (isfd)
|
||||
isfdptr isfd; /* puntatore al descrittore del file ISAM */
|
||||
{
|
||||
datisort.rc_len=isfd->d->LenR;
|
||||
/* @(!) 2.3.01.temp */
|
||||
if (nsortfield < NOFLDS)
|
||||
datisort.s_fld[nsortfield].f_pos = 0; /* chiude l'elenco campi */
|
||||
/* @(:) 2.3.01.temp */
|
||||
return (init_sort (&datisort));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
148
include/csort.h
Executable file
148
include/csort.h
Executable file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
@(SH) Header
|
||||
|
||||
@(C#) PUBBLICHE
|
||||
NOFLDS : massimo numero di chiavi da ordinare
|
||||
|
||||
@(C$) PRIVATE
|
||||
MOSTMEM : numero massimo di bytes di memoria per il buffer di sort
|
||||
LEASTMEM : numero minimo di bytes di memoria per il buffer di sort
|
||||
@(VG#) PUBBLICHE
|
||||
s_prm : struttura di un sort
|
||||
s_prm.rc_len : lunghezza del record
|
||||
s_prm.s_fld : vettore della struttura dei campi di sort
|
||||
s_prm.s_fld[].f_pos : prima posizione del campo (contando da 1)
|
||||
s_prm.s_fld[].f_len : lunghezza del campo e tipo del campo; se f_len > 0 e' una stringa; se f_len = -1 e' un intero; se f_len = -2 e' un boolean
|
||||
s_prm.s_fld[].ad : a = crescente; d = decrescente
|
||||
|
||||
@(VG$) PRIVATE
|
||||
bp : struttura di una sequenza in un buffer di merge
|
||||
bp.rc : puntatore al record nel merge buffer
|
||||
bp.rbuf : record rimasti nel buffer in questa sequenza di sort
|
||||
bp.rdsk : record rimasti nel disco in questa sequenza di sort
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __CSORT_H
|
||||
#define __CSORT_H
|
||||
|
||||
#ifndef __CCOMMON_H
|
||||
#include "ccommon.h"
|
||||
#endif
|
||||
#ifndef __CCUSTIO_H
|
||||
#include "ccustio.h"
|
||||
#endif
|
||||
#include "/usr/include/isam.h"
|
||||
|
||||
#define NOFLDS 10
|
||||
#define MOSTMEM 51200
|
||||
#define LEASTMEM 10240
|
||||
#define MaxFields 100
|
||||
#define MKFields 10
|
||||
#define MaxKeys 8
|
||||
#define MAXKEYS 8
|
||||
|
||||
typedef char FieldName[12] ;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char SysName[42] __PACKED__ ;
|
||||
RecNoType EOD __PACKED__ ;
|
||||
RecNoType EOX __PACKED__ ;
|
||||
unsigned short LenR __PACKED__ ;
|
||||
RecNoType Flags __PACKED__ ;
|
||||
char Des[42] __PACKED__ ;
|
||||
char FCalc[32] __PACKED__ ;
|
||||
char GenPrompt[32] __PACKED__ ;
|
||||
} FileDes;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FieldName Name __PACKED__ ;
|
||||
byte TypeF __PACKED__;
|
||||
byte Len __PACKED__ ;
|
||||
byte Dec __PACKED__ ;
|
||||
#ifdef __PACK_1__
|
||||
byte junk __PACKED__ ;
|
||||
#endif
|
||||
unsigned short RecOff __PACKED__ ;
|
||||
} RecFieldDes ;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
word DupKeys __ALIGNED__ ;
|
||||
byte NkFields __ALIGNED__ ;
|
||||
byte FieldSeq[MKFields] __PACKED__ ;
|
||||
byte FromCh[MKFields] __PACKED__ ;
|
||||
byte ToCh[MKFields] __PACKED__ ;
|
||||
} KeyDes ;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short NFields __PACKED__ ;
|
||||
RecFieldDes Fd[MaxFields] __PACKED__ ;
|
||||
byte SortFd[MaxFields] __PACKED__ ;
|
||||
short NKeys __PACKED__ ;
|
||||
KeyDes Ky[MaxKeys] __PACKED__ ;
|
||||
} RecDes ;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int i;
|
||||
FileDes *d;
|
||||
RecDes *r;
|
||||
RecNoType RecNo;
|
||||
short ln;
|
||||
short ft;
|
||||
short knum;
|
||||
short newkey;
|
||||
int mode;
|
||||
struct keydesc k[MAXKEYS + 1];
|
||||
} isdef ;
|
||||
|
||||
|
||||
typedef isdef* isfdptr;
|
||||
struct s_prm {
|
||||
int rc_len;
|
||||
struct {
|
||||
int f_pos;
|
||||
int f_len;
|
||||
char ad;
|
||||
|
||||
} s_fld [NOFLDS];
|
||||
};
|
||||
struct bp {
|
||||
char *rc;
|
||||
/* @(!) 2.3.00.112 */
|
||||
unsigned rbuf;
|
||||
unsigned rdsk;
|
||||
/* @(:) 2.3.00.112 */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
/*----------------------- FUNZIONI VISIBILI PRIMA PARTE ---------------------*/
|
||||
|
||||
int init_sort(struct s_prm *); /* Initialize the sort */
|
||||
void sort(char *); /* Pass records to Sort */
|
||||
char *sort_op(void); /* Retrieve sorted records */
|
||||
void sort_stats(void); /* Display sort statistics */
|
||||
|
||||
/*----------------------- FUNZIONI VISIBILI SECONDA PARTE -------------------*/
|
||||
|
||||
void initsortfield (void);
|
||||
int addsortfield (isfdptr, FieldName, int, int, char);
|
||||
int finesortfield (isfdptr);
|
||||
|
||||
/* azzera l'elenco dei campi in base a cui eseguire il sort */
|
||||
/* ritorna 0 se tutto ok, -1 se chiamata piu' di NOFLDS volte dopo l'ultimo initsortfield */
|
||||
/* ritorna 0 se tutto ok, -1 se non c'e' sufficiente memoria per procedere */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __CSORT_H */
|
@ -59,7 +59,7 @@ I56=$(IP)config.h $(I55) $(I13)
|
||||
I57=$(IP)confapp.h $(I56) $(I24)
|
||||
I58=$(IP)text.h $(I10) $(I13) $(I32)
|
||||
I59=$(IP)viswin.h $(I13) $(I32) $(I10) $(I58)
|
||||
I60=$(IP)printwin.h $(I32)
|
||||
I60=$(IP)printwin.h $(I32) $(I58)
|
||||
|
||||
U1=$(IP)default.url $(I43)
|
||||
#U2=$(IP)pr_menu.h $(I43) # Guai a chi la usa!
|
||||
|
@ -114,7 +114,9 @@ $(LIB)(isreorg.o): $(C1) $(C2) $(C3) $(C9) $(C11) $(C12) $(H1) $(IP)isreorg.c
|
||||
|
||||
$(LIB)(isbuild.o): $(C1) $(C2) $(C3) $(C9) $(C11) $(C12) $(H1) $(CLIB)isbuild.c
|
||||
|
||||
$(LIB)(csort.o): $(C1) $(C2) $(C3) $(C11) $(C12) $(C19) $(CLIB)csort.c
|
||||
$(LIB)(csort.o): $(C1) $(C2) $(C3) $(C11) $(C12) $(C19) $(IP)csort.c
|
||||
$(CCOMP) $(CFLAGS) $(IP)csort $*
|
||||
$(LIBINSERT) $*.o
|
||||
|
||||
$(LIB)(mshell.o): $(CLIB)mshell.h $(CLIB)mshell.c
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user