|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 8832 (0x2280) Types: TextFile Names: »SORT.C«
└─⟦b35f94715⟧ Bits:30003295 BDS C version 1.50 arbejdsdiskette til RC703 Piccolo └─⟦b35f94715⟧ Bits:30005324 BDS C version 1.50 arbejdsdiskette til RC703 Piccolo └─ ⟦this⟧ »SORT.C«
/* Sort/Merge from Software Tools Last Modified : 6 October 1982 Converted from Software Tools RATFOR to BDS C by Leor Zolman Sep 2, 1982 Usage: sort <infile> <outfile> Main variables have been made external; this is pretty much in line with the RATFOR call-by-name convention anyway. Requires lots of disk space, up to around three times the length of the file file being sorted. This program is intended for files bigger than memory; simpler, faster sorts can be implemented for really short files (like ALPH.C) -leor Compile & Link: A>cc sort.c -e2800 -o A>l2 sort (or...) A>cc sort.c -e2900 -o A>clink sort */ #include <bdscio.h> #define VERBOSE 1 /* give running account of file activity */ #define MAXLINE 200 /* longest line we want to deal with */ #define NBUFS 7 /* Max number of open buffered files */ #define MAXPTR 3000 /* Max number of lines (set for dict) */ #define MERGEORDER (NBUFS-1) /* Max # of intermediate files to merge */ #define NAMESIZE 20 /* Max Filename size */ #define LOGPTR 13 /* smallest value >= log (base 2) of MAXPTR */ #define EOS 'Ø0' /* string termination character */ #define FILE struct _buf #define stderr 4 #define fputc putc char nameÆNAMESIZEÅ, name2ÆNAMESIZE + 10Å; FILE buffersÆNBUFS + 1Å; /* up to NBUFS general-purp. buffered files */ FILE *infilÆMERGEORDER + 1Å; /* tmp file ptrs for sort operation */ unsigned linptrÆMAXPTR + 1Å, nlines; int temp; unsigned maxtext; /* max # of chars in main text buffer */ char *linbuf; /* text area starts after this variable */ main(argc,argv) char **argv; æ FILE *infile, *outfile; /* main input and output streams */ FILE *tmpfile; int makfil(), min(), gopen(), gremov(); int gtext(); unsigned high, lim, low, t; linbuf = endext(); /* start of text buffer area */ maxtext = topofmem() - endext() - 500; tmpfile = buffersÆ0Å; if (argc != 3) exit(puts("Usage: sort <infile> <outfile>Øn")); infile = buffersÆ1Å; if (fopen(argvÆ1Å, infile) == ERROR) æ puts("Can't open "); puts(argvÆ1Å); exit(-1); å #if VERBOSE fputs("Beginning initial formation runØn",stderr); #endif high = 0; /* Initial formation of runs: */ do æ t = gtext(infile); quick(nlines); high++; makfil(high,tmpfile); ptext(tmpfile); fclout(tmpfile); å while (t != NULL); fclose(infile); /* free up the input file buffer */ #if VERBOSE fputs("Beginning merge operationØn",stderr); #endif for (low = 1; low < high; low += MERGEORDER) /* merge */ æ lim = min(low + MERGEORDER - 1, high); gopen(low, lim); /* open files */ high++; makfil(high, tmpfile); merge(lim - low + 1, tmpfile); fclout(tmpfile); /* terminate, flush and close file */ gremov(low, lim); å /* Now write the sorted output file: */ fputs("Merge complete.Øn",stderr); gname(high, name); /* create name of result file */ infile = buffersÆ0Å; unlink(argvÆ2Å); /* remove any old copy of result file */ if (rename(name,argvÆ2Å) == ERROR) æ puts("An error occurred in renaming the output file from "); puts(name); puts(" to "); puts(argvÆ2Å); å å fclout(obuf) FILE *obuf; æ putc(CPMEOF,obuf); fflush(obuf); fclose(obuf); å /* * Quick: Quicksort for character lines */ quick(nlines) unsigned nlines; æ unsigned i,j, lvÆLOGPTR + 1Å, p, pivlin, uvÆLOGPTR + 1Å; int compar(); lvÆ1Å = 1; uvÆ1Å = nlines; p = 1; while (p > 0) if (lvÆpÅ >= uvÆpÅ) /* only 1 element in this subset */ p--; /* pop stack */ else æ i = lvÆpÅ - 1; j = uvÆpÅ; pivlin = linptrÆjÅ; /* pivot line */ while (i < j) æ for (i++; compar(linptrÆiÅ,pivlin) < 0; i++) ; for (j--; j > i; j--) if (compar(linptrÆjÅ, pivlin) <= 0) break; if (i < j) /* out of order pair */ æ temp = linptrÆiÅ; linptrÆiÅ = linptrÆjÅ; linptrÆjÅ = temp; å å j = uvÆpÅ; /* move pivot to position 1 */ temp = linptrÆiÅ; linptrÆiÅ = linptrÆjÅ; linptrÆjÅ = temp; if ( (i - lvÆpÅ) < (uvÆpÅ - i)) æ lvÆp + 1Å = lvÆpÅ; uvÆp + 1Å = i - 1; lvÆpÅ = i + 1; å else æ lvÆp + 1Å = i + 1; uvÆp + 1Å = uvÆpÅ; uvÆpÅ = i - 1; å p++; å return; å /* * Compar: Compare two strings; return 0 if equal, -1 if first is * lexically smaller, or 1 if first is bigger */ int compar(lp1, lp2) unsigned lp1, lp2; æ unsigned i, j; for (i = lp1, j = lp2; linbufÆiÅ == linbufÆjÅ; i++,j++) æ if (linbufÆiÅ == EOS) return 0; å return (linbufÆiÅ < linbufÆjÅ) ? -1 : 1; å /* * Ptext: output text lines from linbuf onto the buffered output file given */ ptext(outfil) FILE *outfil; æ int i; for (i = 1; i <= nlines; i++) æ if (fputs(&linbufÆlinptrÆiÅÅ, outfil) == ERROR) æ fputs("Error writing output file..disk full?Øn", stderr); exit(-1); å å return 0; å /* * Gtext: Get text lines from the buffered input file provided, and * place them into linbuf */ int gtext(infile) FILE *infile; æ unsigned lbp, len; nlines = 0; lbp = 1; do æ if ( (len = fgets(&linbufÆlbpÅ, infile)) == NULL) break; len = strlen(&linbufÆlbpÅ); nlines++; linptrÆnlinesÅ = lbp; lbp += len + 1; å while ( lbp < (maxtext - MAXLINE) && nlines < MAXPTR); return len; /* return 0 if done with file */ å /* * Makfil: Make a temporary file having suffix 'n' and open it for * output via the supplied buffer */ FILE *makfil(n,obuf) /* make temp file having suffix 'n' */ int n; FILE *obuf; æ FILE *fp; char nameÆ20Å; gname(n,name); if (fcreat(name,obuf) == ERROR) æ puts("Can't create "); puts(name); exit(-1); å return 0; å /* * Gname: Make temporary filename having suffix 'n' */ char *gname(n,name) char *name; int n; æ char tmptextÆ10Å; strcpy(name,"TEMP"); /* create "TEMPn.$$$" */ strcat(name,itoa(tmptext,n)); strcat(name,".$$$"); return name; /* return a pointer to it */ å /* * Itoa: convert integer value n into ASCII representation at strptr, * and return a pointer to it */ char *itoa(strptr,n) char *strptr; int n; æ int length; if (n < 0) æ *strptr++ = '-'; strptr++; n = -n; å if (n < 10) æ *strptr++ = (n + '0'); *strptr = 'Ø0'; return strptr - 1; å else æ length = strlen(itoa(strptr, n/10)); itoa(&strptrÆlengthÅ, n % 10); return strptr; å å /* * Gopen: open group of files low...lim */ gopen(low, lim) int lim, low; æ int i; #if VERBOSE fprintf(stderr,"Opening temp files %d-%dØn",low,lim); #endif for (i = 1; i <= (lim - low + 1); i++) æ gname(low + i - 1, name); if (fopen(name, buffersÆiÅ) == ERROR) æ puts("Can't open: "); puts(name); exit(-1);; å infilÆiÅ = &buffersÆiÅ; å å /* * Remove group of files low...lim * (should use "close" instead of "fabort" for MP/M II) */ gremov(low, lim) int lim, low; æ int i; #if VERBOSE fprintf(stderr,"Removing temp files %d-%dØn",low,lim); #endif for (i = 1; i <= (lim - low + 1); i++) æ fabort(infilÆiÅ->_fd); /* forget about the file */ gname(low + i - 1, name); unlink(name); /* and physically remove it */ å å /* * Fputs: special version that aborts on output error: */ fputs(s,iobuf) char *s; FILE *iobuf; æ char c; while (c = *s++) æ if (c == 'Øn') putc('Ør',iobuf); if (putc(c,iobuf) == ERROR) æ fputs("Error on file outputØn",stderr); exit(ERROR); å å return OK; å /* * Merge: merge infilÆ1Å...infilÆnfilesÅ onto outfil */ merge(nfiles, outfil) FILE *outfil; æ char *fgets(); int i, inf, lbp, lp1, nf; lbp = 1; nf = 0; for (i = 1; i <= nfiles; i++) /* get one line from each file */ if (fgets(&linbufÆlbpÅ, infilÆiÅ) != NULL) æ nf++; linptrÆnfÅ = lbp; lbp += MAXLINE; /* leave room for largest line */ å quick(nf); /* make initial heap */ while (nf > 0) æ lp1 = linptrÆ1Å; fputs(&linbufÆlp1Å, outfil); inf = lp1 / MAXLINE + 1; /* compute file index */ if (fgets(&linbufÆlp1Å,infilÆinfÅ) == NULL) æ linptrÆ1Å = linptrÆnfÅ; nf--; å reheap(nf); å return; å /* * Reheap: propogate linbufÆlinptrÆ1ÅÅ to proper place in heap */ reheap(nf) unsigned nf; æ unsigned i,j; for (i = 1; (i + i) <= nf; i = j) æ j = i + i; if (j < nf && compar(linptrÆjÅ, linptrÆj + 1Å) > 0) j++; if (compar(linptrÆiÅ, linptrÆjÅ) <= 0) break; temp = linptrÆiÅ; linptrÆiÅ = linptrÆjÅ; linptrÆjÅ = temp; å return; å «eof»