/* * SORTLEX.C * * Sort a file by lines. * Ignore case and punctuation in comparison. * Optionally skip leading chars in comparison. * * This is a modification of the ALPH program written by Leor Zolman * * The sort is alphameric, ignoring case and punctuation. * * The "-l" parameter is for the maximum number of lines of text * to be sorted (default = MAXLINES). This allocates an array of * pointers to text. * * The "-s" parameter is to specify a number of LEADING characters * in each line to be ignored in determining order in the sort. * * Usage: * * sortlex [-l] [-s] * * Written to use BDS C by H.Moran * Last Update: 10/9/83 (hrm) */ #include "bdscio.h" #define REV_DATE "10/9/83" #define PROC int /* PROCedure i.e. function returning no value */ #define TRIAD int /* -1, 0, or +1 */ #define NATURAL unsigned /* Natural or counting numbers */ #define MAXLINES 500 /* default max number of lines */ /* * forward declared functions */ TRIAD cmpstr(); /* * cmpstr() locals made global for speed */ char *s1, *t1; int i; /* * Globals */ FILE iobuf; /* used for both input and output file */ char **ltab; int lcount; char *allocp; NATURAL maxlines; NATURAL skipchars; PROC main(argc, argv) char **argv; { char linbuf[300]; int maxwidth, width, wideline; int i; skipchars = maxwidth = 0; maxlines = MAXLINES; if ( argc < 3 || argc >5 ) abort("incorrect number of arguments"); if ( fopen(argv[1], &iobuf) == ERROR ) { printf("Can't open %s\n", argv[1]); exit(1); } for ( i = 3; i < argc; ++i ) { /* decode options */ if ( argv[i][0] != '-' ) abort("expecting '-' option"); else { /* option flag detected */ if ( tolower(argv[i][1]) == 'l' ) maxlines = atoi(&argv[i][2]); else if ( tolower(argv[i][1]) == 's' ) skipchars = atoi(&argv[i][2]); else /* invalid option */ abort("unrecognized option"); } } if ( (ltab = sbrk(2*(maxlines+1))) == ERROR ) { printf("Can't allocate space for <%d> lines\n", maxlines); exit(1); } lcount = 0; for ( i = 0; i < maxlines; i++ ) { if ( ! fgets(linbuf, &iobuf) ) break; if ( (width = strlen(linbuf)) > maxwidth ) { maxwidth = width; wideline = i; } if ( (allocp = sbrk(width + 1)) == ERROR ) { puts("Out of allocation space\n"); exit(1); } ltab[lcount++] = allocp; strcpy(allocp, linbuf); } fclose(&iobuf); if ( i == maxlines ) { puts("Too many lines. Change MAXLINES or use -L option\n"); exit(1); } printf("%d lines of a possible %d were used\n", i, maxlines); printf("Line %d is the longest line (%d characters)\n", wideline, maxwidth); qsort(ltab, lcount, 2, &cmpstr); if ( fcreat(argv[2], &iobuf) == ERROR ) { printf("Can't create %s\n", argv[2]); exit(1); } for ( i = 0; i < lcount; i++ ) fputs(ltab[i], &iobuf); putc(CPMEOF, &iobuf); fflush(&iobuf); fclose(&iobuf); puts("All done.\n"); } /* * compare two strings via double deep pointers * ignore case and scan past blanks and punctuation in the comparison * i.e. the beginnings of a lexicographic compare */ TRIAD cmpstr(s, t) char **s, **t; { /* char *s1, *t1; ------ Made global for speed */ /* int i; */ s1 = *s; for ( i = 0; i < skipchars; ++i, ++s1 ) if ( *s1 == '\0' ) break; t1 = *t; for ( i = 0; i < skipchars; ++i, ++t1 ) if ( *t1 == '\0' ) break; while ( *s1 && *t1 ) { /* not at the end of either string */ if ( *s1 && ! ( isspace(*s1) || isalpha(*s1) || isdigit(*s1)) ) ++s1; else if ( *t1 && ! ( isspace(*t1) || isalpha(*t1) || isdigit(*t1)) ) ++t1; else if ( *s1 != *t1 ) break; else { /* identical matching non-blanks */ ++s1; ++t1; } } if ( i = (tolower(*s1) - tolower(*t1)) ) /* case independent compare */ return (i); else /* unless they match */ return (*s1 - *t1); } /* * abort with error message */ PROC abort(s) char *s; { printf("%s\n\n", s); printf("Usage:\n\n"); printf("sortlex [-l] [-s]\n"); printf("DEFAULTS: =%d, =0\n", MAXLINES); printf("\nLast Revision Date: %s\n", REV_DATE); exit(1); }