754 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			754 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*   
 | 
						|
@(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));
 | 
						|
}
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------*/
 |