koreth@ssyx.ucsc.edu (Steven Grimm) (02/25/89)
Submitted-by: leo@philmds.dts.philips.nl (Leo de Wit) Posting-number: Volume 2, Issue 18 Archive-name: sort/part02 #!/bin/sh # this is part 2 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file sortcomp.c continued # CurArch=2 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 sed 's/^X//' << 'SHAR_EOF' >> sortcomp.c X } else { X --bs; /* Effectively skip *bt */ X } X } else if (isdict(*bt)) { X --bt; /* Effectively skip *bs */ X } /* (else: skip both) */ X } X } X for ( ; bs < es; ) { /* Skip any more */ X if (isdict(*++bs)) { /* non-dict chars in bs */ X --bs; X break; X } X } X for ( ; bt < et; ) { /* Skip any more */ X if (isdict(*++bt)) { /* non-dict chars in bt */ X --bt; X break; X } X } X X return (et - bt) - (es - bs); X} X Xint c_if(bs,bt,es,et) /* Normalized/Fold */ Xregister char *bs, *bt; Xregister char *es, *et; X{ X --bs; --bt; --es; --et; X for ( ; bs < es && bt < et; ) { X if (fold[*++bs] != fold[*++bt]) { /* Increment & compare */ X if (isnorm(*bs)) { X if (isnorm(*bt)) { X return fold[*bs] - fold[*bt]; X } else { X --bs; /* Effectively skip *bt */ X } X } else if (isnorm(*bt)) { X --bt; /* Effectively skip *bs */ X } /* (else: skip both) */ X } X } X for ( ; bs < es; ) { /* Skip any more */ X if (isnorm(*++bs)) { /* non-norm chars in bs */ X --bs; X break; X } X } X for ( ; bt < et; ) { /* Skip any more */ X if (isnorm(*++bt)) { /* non-norm chars in bt */ X --bt; X break; X } X } X X return (et - bt) - (es - bs); X} X Xint c_i(bs,bt,es,et) /* Normalized order */ Xregister char *bs, *bt; Xregister char *es, *et; X{ X --bs; --bt; --es; --et; X for ( ; bs < es && bt < et; ) { X if (*++bs != *++bt) { /* Increment & compare */ X if (isnorm(*bs)) { X if (isnorm(*bt)) { X return fold[*bs] - fold[*bt]; X } else { X --bs; /* Effectively skip *bt */ X } X } else if (isnorm(*bt)) { X --bt; /* Effectively skip *bs */ X } /* (else: skip both) */ X } X } X for ( ; bs < es; ) { /* Skip any more */ X if (isnorm(*++bs)) { /* non-norm chars in bs */ X --bs; X break; X } X } X for ( ; bt < et; ) { /* Skip any more */ X if (isnorm(*++bt)) { /* non-norm chars in bt */ X --bt; X break; X } X } X X return (et - bt) - (es - bs); X} X Xint c_af(bs,bt,es,et) /* Fold */ Xregister char *bs, *bt; Xregister char *es, *et; X{ X register short minlen; X X minlen = ((es - bs) <= (et - bt)) ? (es - bs) : (et - bt); X if (minlen == 0) { X return (es - bs) - (et - bt); X } X X if (fold[*bs] == fold[*bt]) { X for ( ; --minlen != 0 && fold[*++bs] == fold[*++bt]; ) ; X if (minlen == 0) { X return 0; X } X } X X return fold[*bs] - fold[*bt]; X} X Xint c_dfu(bs,bt) /* Dictionary/Fold */ Xregister char *bs, *bt; X{ X register char *fld = fold; X X --bs; --bt; X do { X while (fld[*++bs] == fld[*++bt] && *bt) ; /* Skip equal ones */ X if (!*bt || !*bs) break; /* Stop on '\0' */ X if (isdict(*bs)) { X if (isdict(*bt)) { X break; /* Difference found */ X } else { X --bs; /* Effectively skip *bt */ X } X } else { X if (isdict(*bt)) { X --bt; /* Effectively skip *bs */ X } X } /* (else: skip both) */ X } while (1); X X return fld[*bs] - fld[*bt]; X} X Xint c_du(bs,bt) /* Dictionary */ Xregister char *bs, *bt; X{ X --bs; --bt; X do { X while (*++bs == *++bt && *bt) ; /* Skip equal ones */ X if (!*bt || !*bs) break; /* Stop on '\0' */ X if (isdict(*bs)) { X if (isdict(*bt)) { X break; /* Difference found */ X } else { X --bs; /* Effectively skip *bt */ X } X } else { X if (isdict(*bt)) { X --bt; /* Effectively skip *bs */ X } X } /* (else: skip both) */ X } while (1); X X return *bs - *bt; X} X Xint c_ifu(bs,bt) /* Normalized/Fold */ Xregister char *bs, *bt; X{ X register char *fld = fold; X X --bs; --bt; X do { X while (fld[*++bs] == fld[*++bt] && *bt) ; /* Skip equal ones */ X if (!*bt || !*bs) break; /* Stop on '\0' */ X if (isnorm(*bs)) { X if (isnorm(*bt)) { X break; /* Difference found */ X } else { X --bs; /* Effectively skip *bt */ X } X } else { X if (isnorm(*bt)) { X --bt; /* Effectively skip *bs */ X } X } /* (else: skip both) */ X } while (1); X X return fld[*bs] - fld[*bt]; X} X Xint c_iu(bs,bt) /* Normalized */ Xregister char *bs, *bt; X{ X --bs; --bt; X do { X while (*++bs == *++bt && *bt) ; /* Skip equal ones */ X if (!*bt || !*bs) break; /* Stop on '\0' */ X if (isnorm(*bs)) { X if (isnorm(*bt)) { X break; /* Difference found */ X } else { X --bs; /* Effectively skip *bt */ X } X } else { X if (isnorm(*bt)) { X --bt; /* Effectively skip *bs */ X } X } /* (else: skip both) */ X } while (1); X X return *bs - *bt; X} X Xint c_afu(bs,bt) /* Fold */ Xregister char *bs, *bt; X{ X register char *fld = fold; X X if (fld[*bs] == fld[*bt] && *bt) { X for ( ; fld[*++bs] == fld[*++bt] && *bt; ) ; X } X X return fld[*bs] - fld[*bt]; X} X X#ifndef M68000 X/* using asm if 68000 */ X Xint c_dbfr(bs,bt,es,et) /* Dict/Blank/Fold/Reverse */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_df(bt,bs,et,es); X} X Xint c_dbf(bs,bt,es,et) /* Dictionary/Blank/Fold */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_df(bs,bt,es,et); X} X Xint c_dbr(bs,bt,es,et) /* Dictionary/Blank/Reverse */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_d(bt,bs,et,es); X} X Xint c_db(bs,bt,es,et) /* Dictionary/Blank */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_d(bs,bt,es,et); X} X Xint c_dfr(bs,bt,es,et) /* Dictionary/Fold/Reverse */ Xchar *bs, *bt; Xchar *es, *et; X{ X return c_df(bt,bs,et,es); X} X Xint c_dr(bs,bt,es,et) /* Dictionary/Reversed */ Xchar *bs, *bt; Xchar *es, *et; X{ X return c_d(bt,bs,et,es); X} X Xint c_ibfr(bs,bt,es,et) /* Norm/Blank/Fold/Reverse */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_if(bt,bs,et,es); X} X Xint c_ibf(bs,bt,es,et) /* Normalized/Blank/Fold */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_if(bs,bt,es,et); X} X Xint c_ibr(bs,bt,es,et) /* Normalized/Blank/Reverse */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_i(bt,bs,et,es); X} X Xint c_ib(bs,bt,es,et) /* Normalized/Blank */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_i(bs,bt,es,et); X} X Xint c_ifr(bs,bt,es,et) /* Normalized/Fold/Reverse */ Xchar *bs, *bt; Xchar *es, *et; X{ X return c_if(bt,bs,et,es); X} X Xint c_ir(bs,bt,es,et) /* Normalized/Reversed */ Xchar *bs, *bt; Xchar *es, *et; X{ X return c_i(bt,bs,et,es); X} X Xint c_abfr(bs,bt,es,et) /* Blank/Fold/Reverse */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_af(bt,bs,et,es); X} X Xint c_abf(bs,bt,es,et) /* Blank/Fold */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_af(bs,bt,es,et); X} X Xint c_abr(bs,bt,es,et) /* Blank/Reverse */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_a(bt,bs,et,es); X} X Xint c_ab(bs,bt,es,et) /* Blank */ Xregister char *bs, *bt; Xchar *es, *et; X{ X SKIPSPACE(bs,bt); X return c_a(bs,bt,es,et); X} X Xint c_afr(bs,bt,es,et) /* Fold/Reverse */ Xchar *bs, *bt; Xchar *es, *et; X{ X return c_af(bt,bs,et,es); X} X Xint c_ar(bs,bt,es,et) /* Reverse */ Xchar *bs, *bt; Xchar *es, *et; X{ X return c_a(bt,bs,et,es); X} X X/* Unbounded comparisions start here */ X Xint c_dbfru(bs,bt) /* Dict/Blank/Fold/Reverse */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_dfu(bt,bs); X} X Xint c_dbfu(bs,bt) /* Dictionary/Blank/Fold */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_dfu(bs,bt); X} X Xint c_dbru(bs,bt) /* Dictionary/Blank/Reverse */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_du(bt,bs); X} X Xint c_dbu(bs,bt) /* Dictionary/Blank */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_du(bs,bt); X} X Xint c_dfru(bs,bt) /* Dictionary/Fold/Reverse */ Xchar *bs, *bt; X{ X return c_dfu(bt,bs); X} X Xint c_dru(bs,bt) /* Dictionary/Reverse */ Xchar *bs, *bt; X{ X return c_du(bt,bs); X} X Xint c_ibfru(bs,bt) /* Norm/Blank/Fold/Reverse */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_ifu(bt,bs); X} X Xint c_ibfu(bs,bt) /* Normalized/Blank/Fold */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_ifu(bs,bt); X} X Xint c_ibru(bs,bt) /* Normalized/Blank/Reverse */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_iu(bt,bs); X} X Xint c_ibu(bs,bt) /* Normalized/Blank */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_iu(bs,bt); X} X Xint c_ifru(bs,bt) /* Normalized/Fold/Reverse */ Xchar *bs, *bt; X{ X return c_ifu(bt,bs); X} X Xint c_iru(bs,bt) /* Normalized/Reverse */ Xchar *bs, *bt; X{ X return c_iu(bt,bs); X} X Xint c_abfru(bs,bt) /* Blank/Fold/Reverse */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_afu(bt,bs); X} X Xint c_abfu(bs,bt) /* Blank/Fold */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_afu(bs,bt); X} X Xint c_abru(bs,bt) /* Blank/Reverse */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_au(bt,bs); X} X Xint c_abu(bs,bt) /* Blank */ Xregister char *bs, *bt; X{ X SKIPSPACE(bs,bt); X return c_au(bs,bt); X} X Xint c_afru(bs,bt) /* Fold/Reverse */ Xregister char *bs, *bt; X{ X register char *fld = fold; X X if (fld[*bs] == fld[*bt] && *bt) { X for ( ; fld[*++bs] == fld[*++bt] && *bt; ) ; X } X X return fld[*bt] - fld[*bs]; X} X Xint c_aru(bs,bt) /* Reverse */ Xregister char *bs, *bt; X{ X if (*bs == *bt && *bt) { X for ( ; *++bs == *++bt && *bt; ) ; X } X X return *bt - *bs; X} X Xint c_au(bs,bt) /* Ordinary sort */ Xregister char *bs, *bt; X{ X if (*bs == *bt && *bs) { /* Compare & skip eq. chars */ X while (*++bs == *++bt && *bs) ; /* Compare & skip eq. chars */ X } X X return *bs - *bt; X} X Xint c_a(bs,bt,es,et) /* Ordinary sort */ Xregister char *bs, *bt; Xregister char *es, *et; X{ X register short minlen; X X minlen = ((es - bs) <= (et - bt)) ? (es - bs) : (et - bt); X if (minlen == 0) { X return (es - bs) - (et - bt); X } X X if (*bs == *bt) { X for ( ; --minlen != 0 && *++bs == *++bt; ) ; X if (minlen == 0) { X return 0; X } X } X X return *bs - *bt; X} X#endif not MC68000 SHAR_EOF chmod 0600 sortcomp.c || echo "restore of sortcomp.c fails" sed 's/^X//' << 'SHAR_EOF' > sortcomp.h && X/****************************************************************************** X * * X * sortcomp.h version 1.0 of 22 Januari 1989 (C) L.J.M. de Wit 1989 * X * * X * This software may be used and distributed freely if not used commercially * X * and the originator (me) is mentioned in the source (just leave this 9 line * X * header intact). * X * * X ****************************************************************************** X * X * sortcomp.h: header for sortcomp.c's external definitions X */ X Xextern int c_nr(), c_n(), /* the various compare funcs*/ X c_dbfr(), c_dbf(), c_dbr(), c_db(), X c_dfr(), c_df(), c_dr(), c_d(), X c_ibfr(), c_ibf(), c_ibr(), c_ib(), X c_ifr(), c_if(), c_ir(), c_i(), X c_abfr(), c_abf(), c_abr(), c_ab(), X c_afr(), c_af(), c_ar(), c_a(), X c_dbfru(), c_dbfu(), c_dbru(), c_dbu(), X c_dfru(), c_dfu(), c_dru(), c_du(), X c_ibfru(), c_ibfu(), c_ibru(), c_ibu(), X c_ifru(), c_ifu(), c_iru(), c_iu(), X c_abfru(), c_abfu(), c_abru(), c_abu(), X c_afru(), c_afu(), c_aru(), c_au(); X Xextern void initlookup(); /* Initialize lookup tables */ SHAR_EOF chmod 0600 sortcomp.h || echo "restore of sortcomp.h fails" sed 's/^X//' << 'SHAR_EOF' > sortfile.c && X/****************************************************************************** X * * X * sortfile.c version 1.0 of 1 Januari 1989 (C) L.J.M. de Wit 1989 * X * * X * This software may be used and distributed freely if not used commercially * X * and the originator (me) is mentioned in the source (just leave this 9 line * X * header intact). * X * * X ****************************************************************************** X * X * sortfile.c: stdio replacement for Atari ST X * X * This replacement is added both to speed up the normal stdio offered by X * Lattice C, and to repair a bug with open() (fopen() ?) that is in the X * standard library (version 3.03: try opening & closing 20 files, your X * program bombs when you try to open a new file, even though the old ones X * have been closed). X * X * Note that this package is not complete (no flushbuf, filbuf, printf etc.) X * but this wasn't the intent anyway; furthermore, the allocation of buffers X * takes place when a file is opened, rather than when it is first read/written X * (as in a standard stdio package). X */ X X#include <stdio.h> X#include <osbind.h> X#include <fcntl.h> X#include "sortmain.h" X#include "sortfile.h" X X#undef Fwrite X#define Fwrite fixwrite /* Fix for Fwrite bug */ X Xstatic int buflen; /* Default buffer length */ X Xstatic int lopen(); Xstatic int fixwrite(); X X#ifdef BESTIO X Xvoid bestio(size) /* Initializes stdin/stdout */ Xint size; X{ X char *iobuffer[2]; /* stdin/stdout buffer ptrs */ X X buflen = size; X iobuffer[0] = (char *)Malloc(buflen); X iobuffer[1] = (char *)Malloc(buflen); X if (iobuffer[0] == (char *)-1 || iobuffer[1] == (char *)-1) { X error("memory allocation failed\n",(char *)0); X } X stdin->_ptr = stdin->_base = iobuffer[0]; X stdin->_rcnt = buflen; X stdin->_flag = _IOREAD; X stdin->_file = 0; X stdin->_size = buflen; X X stdout->_ptr = stdout->_base = iobuffer[1]; X stdout->_wcnt = buflen; X stdout->_flag = _IOWRT; X stdout->_file = 1; X stdout->_size = buflen; X} X Xvoid exit(code) /* Replaces standard exit */ Xint code; X{ X int i; X X for (i = 0; i < _NFILE; i++) { X if (_iob[i]._flag != 0) { /* Stclose any open files */ X stclose(_iob+i); X } X } X _exit(code); /* and _exit */ X} X X#else NOT BESTIO X Xint _fmode = 0x8000; /* No translation, for speed*/ X X#endif BESTIO X XFILE *stopen(filename,mode) /* Replaces fopen() */ Xchar *filename, *mode; X{ X FILE *fp; X int desc; X int flag; X int i; X X for (i = 0; i < _NFILE; i++) { /* Find first free entry */ X if (_iob[i]._flag == 0) { X break; X } X } X if (i < _NFILE) { X fp = _iob + i; /* First free */ X } else { X return (FILE *)0; /* All occupied */ X } X X if (!strcmp(mode,"w")) { /* Mode "w": write */ X desc = lopen(filename,O_WRONLY|O_CREAT|O_TRUNC); X flag = _IOWRT; X } else if (!strcmp(mode,"r")) { /* Mode "r": read */ X desc = lopen(filename,O_RDONLY); X flag = _IOREAD; X } else { /* Unknown mode */ X return (FILE *)0; X } X X if (desc < 0) { X return (FILE *)0; /* Lopen failed */ X } else { X fp->_rcnt = fp->_wcnt = fp->_size = 0; X fp->_ptr = fp->_base = (char *)0; X fp->_file = desc; X fp->_flag = flag; X } X X return fp; X} X Xint stclose(fp) /* Replaces fclose() */ XFILE *fp; X{ X int retco; X X if (fp->_flag & (_IORW|_IOWRT)) { X stflush(fp); /* Flush an output stream */ X } X retco = Fclose(fp->_file); /* Close file */ X if (fp->_base != (char *)0) { X retco |= Mfree(fp->_base); /* Free allocated buffer */ X } X fp->_base = (char *)0; X fp->_flag = 0; /* Indicate entry is free */ X X return retco; X} X Xint stflush(fp) XFILE *fp; X{ X if (fp->_size > fp->_wcnt) { /* Any data to be flushed ? */ X Fwrite(fp->_file,fp->_size-fp->_wcnt,fp->_base); /* Write it */ X fp->_ptr = fp->_base; /* re-init ptr */ X fp->_wcnt = fp->_size; /* and _wcnt */ X } X} X Xvoid stbuffer(fp,buf,size) XFILE *fp; Xchar *buf; Xint size; X{ X fp->_ptr = fp->_base = buf; X fp->_size = size; X fp->_wcnt = size; X fp->_rcnt = 0; X} X Xchar *stgets(inbuf,size,fp) /* Replaces fgets() */ Xchar *inbuf; Xregister int size; Xregister FILE *fp; X{ X register int todo, i, ntoread; X register char *s, *t; X X if (fp->_base == (char *)0) { X s = (char *)Malloc(buflen); /* Allocate buffer */ X stbuffer(fp,s,buflen); X } X if (size-- <= 0 || feof(fp)) { /* One for the '\0' */ X return (char *)0; X } X X t = inbuf; X s = fp->_ptr; X ntoread = fp->_rcnt; X X for ( ; ; ) { X todo = min(size,ntoread); X for (i = 0; i < todo; i++) { X if ((*t++ = *s++) == '\n') { /* Had a newline */ X i++; X *t = '\0'; /* 0-terminate line */ X fp->_ptr = s; X fp->_rcnt = ntoread - i; X return inbuf; X } X } X if ((size -= todo) <= 0) { /* All read */ X break; X } X ntoread = Fread(fp->_file,fp->_size,fp->_base); /* Read a buffer */ X s = fp->_base; /* Re-init ptr */ X if (ntoread <= 0) { X fp->_flag |= _IOEOF; X return (char *)0; /* End-of-file */ X } X } X fp->_rcnt = ntoread - todo; X fp->_ptr = s; X *t = '\0'; X return inbuf; X} X Xvoid stputs(inbuf,fp) /* Replaces fputs() */ Xchar *inbuf; Xregister FILE *fp; X{ X register int i, ntowrite; X register char *s, *t; X X if (fp->_base == (char *)0) { X s = (char *)Malloc(buflen); /* Allocate buffer */ X stbuffer(fp,s,buflen); X } X s = inbuf; X t = fp->_ptr; X ntowrite = fp->_wcnt; X X for ( ; ; ) { X for (i = 0; i < ntowrite; i++) { X if (*s == '\0') { /* Found 0 terminator */ X break; X } X *t++ = *s++; X } X if (*s == '\0') { X fp->_wcnt = ntowrite - i; X fp->_ptr = t; X return; X } X Fwrite(fp->_file,t - fp->_base,fp->_base); /* Write a buffer */ X ntowrite = fp->_size; X t = fp->_base; /* Re-init ptr */ X } X} X Xstatic int lopen(filename,mode) /* Simple open() replacement*/ Xchar *filename; Xint mode; X{ X int fd; X X if (!(mode & O_TRUNC)) { X fd = Fopen(filename,mode & (O_WRONLY|O_RDWR)); /* Open file */ X } X X if ((mode & O_TRUNC) || ((fd < 0) && (mode & O_CREAT))) { X fd = Fcreate(filename,!(mode & (O_WRONLY|O_RDWR))); /* Create file */ X } X X return fd; X} X Xstatic int fixwrite(fd,len,buf) Xint fd, len; Xchar *buf; X{ X int total, piece = 0; X char *top; X X if (fd != 1) { X return gemdos(0x40,fd,len,buf); X } X for (total = 0, top = buf + len; len > 0; buf += piece, len -= piece) { X if ((piece = len) > 32767) { X piece = 32256; X } X total += gemdos(0x40,fd,piece,buf); X } X return total; X} SHAR_EOF chmod 0600 sortfile.c || echo "restore of sortfile.c fails" sed 's/^X//' << 'SHAR_EOF' > sortfile.h && X/****************************************************************************** X * * X * sortfile.h version 1.0 of 22 Januari 1989 (C) L.J.M. de Wit 1989 * X * * X * This software may be used and distributed freely if not used commercially * X * and the originator (me) is mentioned in the source (just leave this 9 line * X * header intact). * X * * X ****************************************************************************** X * X * sortfile.h: external definitions for the sortfile stdio package. X * X * To enable the speeded up std I/O routines, the BESTIO symbol must be X * #define'd (with -dBESTIO in the LC1 compilation phase when using Lattice C) X * and sortfile used when linking. X * To use the standard stdio package, don't define BESTIO and don't link with X * sortfile. X */ X X#ifdef BESTIO X X#define fopen stopen X#define fgets stgets X#define fputs stputs X#define fclose stclose X#define setbuffer stbuffer X Xextern FILE *stopen(); Xextern char *stgets(); Xextern void stputs(); Xextern void stbuffer(); Xextern int stclose(); Xextern void bestio(); Xextern void exit(); X X#else not BESTIO X X#define bestio(s) X X#endif BESTIO SHAR_EOF chmod 0600 sortfile.h || echo "restore of sortfile.h fails" sed 's/^X//' << 'SHAR_EOF' > sortmain.c && X/****************************************************************************** X * * X * sortmain.c version 1.0 of 22 Januari 1989 (C) L.J.M. de Wit 1989 * X * * X * This software may be used and distributed freely if not used commercially * X * and the originator (me) is mentioned in the source (just leave this 9 line * X * header intact). * X * * X ****************************************************************************** X * X * sortmain.c: main module for sort X */ X X#include <stdio.h> X#include <ctype.h> X#include "sortmain.h" X#include "sortcomp.h" X#include "sortfile.h" X Xtypedef struct key { /* Sort key structure */ X int (*cmp)(); /* Comparision routine */ X int bfld; /* Begin field no. */ X int bchar; /* Begin char no. */ X int echar; /* End char no. */ X int flds; /* # of fields (efld-bfld) */ X int bis0; /* bfld == bchar == 0 */ X int eis0; /* efld == echar == 0 */ X struct key *next; /* Next sort key ptr. */ X} key; X Xint options = 0; /* Global sort type flag */ Xlong _mneed = 40000; /* Memory occupied by prog */ X Xstatic char sepchar = ' '; /* Field separator char */ Xstatic key firstkey; /* First key used */ X Xstatic int compar(); /* Standard compare routine */ Xstatic int compb0(), compe0(), compbe(); /* Special cases of compar()*/ Xstatic int bdfinr(); /* Get 'bdfinr' options */ Xstatic char *(*fieldfunc)(); Xstatic char *getsepfld(), *getspafld(); /* Search field + offset */ Xstatic int (*getcmp())(); Xextern void allsort(); X Xmain(argc,argv) Xint argc; Xchar **argv; X{ X int i, qualif; X char *s; X char *outfile = (char *)0; /* Result file (stdout) */ X key *keyp, *keyn; X int (*compfunc)(); /* Routine used to compare */ X int nkeys = 0; /* No. of keys to be used */ X X settemp("\\tmp"); /* Set default temp dir */ X X initlookup(); /* Initialize lookup arrays */ X X for (i = 1; i < argc && (*argv[i] == '-' || X *argv[i] == '+'); i++) { /* Handle commandline flags */ X s = argv[i]; X if (*s++ == '-') { X if (*s == '\0') { /* '-' denotes std input */ X break; X } X for ( ; *s != '\0'; ) { X if (qualif = bdfinr(*s)) { /* *s in (b,d,f,i,n,r) */ X options |= qualif; /* Add it to options */ X s++; X } else { X switch (*s++) { X case 't': /* Field separator char */ X sepchar = *s++; X break; X case 'c': /* Don't sort, only check */ X options |= CHECKONLY; X break; X case 'm': /* Merge the sorted input */ X options |= MERGEONLY; X break; X case 'o': /* Output file */ X options |= OUTFILE; X s += strlen(s); X outfile = argv[++i]; X break; X case 'T': /* Directory for temp files */ X options |= SEPARATOR; X s += strlen(s); X settemp(argv[++i]); X break; X case 'u': /* Remove duplicate lines */ X options |= UNIQUE; X break; X default: /* Invalid option */ X *s = '\0'; /* Null terminate */ X error("invalid option %s\n",--s); X break; X } X } X } X } else { /* '+' sort key flag */ X int keyflags = 0, efld = 0; X X if (nkeys++ == 0) { X keyp = &firstkey; X } else { X keyp = (key *)malloc(sizeof(key));/* Create the (next) key */ X if (keyp == (key *)0) { X error("memory allocation failed\n",(char *)0); X } X for (keyn = &firstkey; keyn->next != (key *)0; X keyn = keyn->next) ; X keyn->next = keyp; X } X keyp->next = (key *)0; X keyp->bfld = atoi(s); /* Get key's start field no.*/ X for ( ; isdigit(*s); s++) ; X if (*s == '.') { X keyp->bchar = atoi(++s); /* Get char offset for field*/ X for ( ; isdigit(*s); s++) ; X } else { X keyp->bchar = 0; /* 0 is default */ X } X for ( ; *s != '\0'; s++) { /* 'bdfinr' flags for key */ X if (qualif = bdfinr(*s)) { X keyflags |= qualif; /* Add flag */ X } else { X s[1] = '\0'; X error("invalid option %s\n",s); X } X } X if (i + 1 < argc && argv[i+1][0] == '-' /* End field specified */ X && (argv[i+1][1] == '.' || isdigit(argv[i+1][1]))) { X s = argv[++i] + 1; X efld = atoi(s); /* Get key's end field no. */ X for ( ; isdigit(*s); s++) ; X if (*s == '.') { X keyp->echar = atoi(++s); /* Get char offset for field*/ X for ( ; isdigit(*s); s++) ; X } else { X keyp->echar = 0; /* 0 is default */ X } X for ( ; *s != '\0'; s++) { /* 'bdfinr' flags for key */ X if (qualif = bdfinr(*s)) { X keyflags |= qualif; /* add flag */ X } else { X s[1] = '\0'; X error("invalid option %s\n",s); X } X } X } else { X efld = keyp->echar = 0; X } X if (keyflags == 0) { /* If no field flags */ X keyflags = options; /* Take global ones */ X } X keyp->flds = efld - keyp->bfld; X keyp->bis0 = keyp->bfld == 0 && keyp->bchar == 0; X keyp->eis0 = efld == 0 && keyp->echar == 0; X keyp->cmp = getcmp(keyflags,keyp->eis0); X } X } X X bestio(2048); /* Possibly initiate bestio */ X X if (nkeys == 0) { /* No key specified */ X nkeys++; X firstkey.next = (key *)0; X firstkey.cmp = getcmp(options,1); X firstkey.bfld = 0; X firstkey.bchar = 0; X firstkey.echar = 0; X firstkey.flds = 0; X firstkey.bis0 = 1; X firstkey.eis0 = 1; X } X X fieldfunc = (options & SEPARATOR) ? getsepfld : getspafld; X X if (nkeys == 1) { /* One key only */ X if (firstkey.bis0) { X if (firstkey.eis0) { X compfunc = firstkey.cmp; X } else { X compfunc = compb0; X } X } else { X if (firstkey.eis0) { X compfunc = compe0; X } else { X compfunc = compbe; X } X } X } else { X compfunc = compar; X } X allsort(argv+i,outfile, compfunc); X} X Xstatic int (*getcmp(flags, unbounded))() Xint flags, unbounded; X{ X /* DICTORDER, IGNBLANK, FOLDUPPER, REVERSE, unbounded */ X static int (*cmparr[])() = { /* All 48 other cases */ X c_a, c_au, c_ar, c_aru, X c_af, c_afu, c_afr, c_afru, X c_ab, c_abu, c_abr, c_abru, X c_abf, c_abfu, c_abfr, c_abfru, X c_d, c_du, c_dr, c_dru, X c_df, c_dfu, c_dfr, c_dfru, X c_db, c_dbu, c_dbr, c_dbru, X c_dbf, c_dbfu, c_dbfr, c_dbfru, X c_i, c_iu, c_ir, c_iru, X c_if, c_ifu, c_ifr, c_ifru, X c_ib, c_ibu, c_ibr, c_ibru, X c_ibf, c_ibfu, c_ibfr, c_ibfru, X }; X X if (flags & NUMERIC) { /* Numeric sort */ X return (flags & REVERSE) ? c_nr : c_n; X } X X return cmparr[unbounded + X ((flags & REVERSE) ? 2 : 0) + X ((flags & FOLDUPPER) ? 4 : 0) + X ((flags & IGNBLANK) ? 8 : 0) + X ((flags & DICTORDER) ? 16 : X (flags & IGNONPRINT) ? 32 : 0)]; X} X Xstatic int bdfinr(c) /* Get 'bdfinr' options */ Xchar c; X{ X switch (c) { X case 'b': /* Ignore leading blanks */ X return IGNBLANK; X case 'd': /* Dictionary order */ X return DICTORDER; X case 'f': /* Fold ucase to lcase */ X return FOLDUPPER; X case 'i': /* Ignore nonprinting chars */ X return IGNONPRINT; X case 'n': /* Numeric sort */ X return NUMERIC; X case 'r': /* Reverse comparision */ X return REVERSE; X default: /* Other flags */ X return 0; X } X} X Xstatic int compar(s,t) /* Gen.compare for all keys */ Xchar *s, *t; /* Strings to be compared */ X{ X register key *keyp = &firstkey; /* Start with key firstkey */ X register int result; /* Result of comparision */ X register char *bs, *bt; /* Begin pos within strings */ X X do { X if (keyp->bis0) { /* Avoid function call */ X bs = s; X bt = t; X } else { X bs = (*fieldfunc)(s,keyp->bfld,keyp->bchar); X bt = (*fieldfunc)(t,keyp->bfld,keyp->bchar); X } X if (keyp->eis0) { /* Unbounded end; */ X result = (*keyp->cmp)(bs,bt); /* Avoid end calculation */ X } else { X result = (*keyp->cmp)(bs,bt, X (*bs == '\0') ? bs : X (*fieldfunc)(bs-keyp->bchar,keyp->flds,keyp->echar), X (*bt == '\0') ? bt : X (*fieldfunc)(bt-keyp->bchar,keyp->flds,keyp->echar)); X } X } while (result == 0 /* Strings compare equal */ X && (keyp = keyp->next) != (key *)0) ; /* and more keys to consider*/ X X return result; X} X Xstatic int compb0(bs,bt) /* Compare for 1 bis0 key */ Xregister char *bs, *bt; /* Strings to be compared */ X{ X register key *keyp = &firstkey; /* For efficiency only */ X X return (*keyp->cmp)(bs,bt, X (*fieldfunc)(bs,keyp->flds,keyp->echar), X (*fieldfunc)(bt,keyp->flds,keyp->echar)); X} X Xstatic int compe0(bs,bt) /* Compare for 1 eis0 key */ Xregister char *bs, *bt; /* Strings to be compared */ X{ X register key *keyp = &firstkey; /* For efficiency only */ X X return (*keyp->cmp)((*fieldfunc)(bs,keyp->bfld,keyp->bchar), X (*fieldfunc)(bt,keyp->bfld,keyp->bchar)); X} X Xstatic int compbe(bs,bt) /* Compare for 1 bounded key*/ Xregister char *bs, *bt; /* Strings to be compared */ X{ X register key *keyp = &firstkey; /* For efficiency only */ X X bs = (*fieldfunc)(bs,keyp->bfld,keyp->bchar); X bt = (*fieldfunc)(bt,keyp->bfld,keyp->bchar); X return (*keyp->cmp)(bs,bt, X (*bs == '\0') ? bs : X (*fieldfunc)(bs-keyp->bchar,keyp->flds,keyp->echar), X (*bt == '\0') ? bt : X (*fieldfunc)(bt-keyp->bchar,keyp->flds,keyp->echar)); X} X Xstatic char *getsepfld(s,field,ch) /* Get position of field */ Xregister char *s; /* String to consider */ Xregister int field, ch; /* Field no. and offset cnt */ X{ /* Separator was specified */ X register char sc = sepchar; X X if (field > 0) { X for ( ; *s != '\0'; ) { X if (*s++ == sc && --field == 0) { /* Count 'field' separators */ X break; X } X } X } X for ( ; ch-- != 0; ) { /* Go ch characters further */ X if (*s++ == '\0') { X return --s; /* but not past '\0' */ X } X } X return s; X} X Xstatic char *getspafld(s,field,ch) /* Get position of field */ Xregister char *s; /* String to consider */ Xregister int field, ch; /* Field no. and offset cnt */ X{ /* No separator; is blanks */ X if (field > 0) { X for ( ; *s != '\0'; s++) { X if (wspace(*s)) { X do { X s++; X } while (wspace(*s)) ; X if (--field == 0) { X break; X } X } X } X } X for ( ; ch-- != 0; ) { /* Go ch characters further */ X if (*s++ == '\0') { X return --s; /* But not past '\0' */ X } X } X return s; X} X Xvoid error(format,arg) /* Display a formatted */ Xchar *format, *arg; /* error message and exit */ X{ X fprintf(stderr,"sort: "); X fprintf(stderr,format,arg); X exit(1); X} SHAR_EOF chmod 0600 sortmain.c || echo "restore of sortmain.c fails" sed 's/^X//' << 'SHAR_EOF' > sortmain.h && X/****************************************************************************** X * * X * sortmain.h version 1.0 of 22 Januari 1989 (C) L.J.M. de Wit 1989 * X * * X * This software may be used and distributed freely if not used commercially * X * and the originator (me) is mentioned in the source (just leave this 9 line * X * header intact). * X * * X ****************************************************************************** X * X * sortmain.h: external definitions & symbols for sortmain X */ X X#define IGNBLANK 0x001 /* Ignore leading blanks */ X#define DICTORDER 0x002 /* Dictionary order */ X#define FOLDUPPER 0x004 /* Fold ucase to lcase */ X#define IGNONPRINT 0x008 /* Ignore non-printing chars*/ X#define NUMERIC 0x010 /* Interpret as numeric */ X#define REVERSE 0x020 /* Reverse result */ X X#define CHECKONLY 0x040 /* Don't sort; check only */ X#define MERGEONLY 0x080 /* Merge; input is sorted */ X#define OUTFILE 0x100 /* Output was specified */ X#define UNIQUE 0x200 /* Remove identical lines */ X#define SEPARATOR 0x400 /* Separator was specified */ X X#define wspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') X Xextern int options; /* Global sort flags */ X Xextern void error(); /* Display error msg & exit */ SHAR_EOF chmod 0600 sortmain.h || echo "restore of sortmain.h fails" rm -f s2_seq_.tmp echo "You have unpacked the last part" exit 0