[comp.sources.atari.st] v02i018: sort -- UNIX-style sort utility part02/02

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