home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d145
/
csh.lha
/
Csh
/
sets
/
sets.c
< prev
Wrap
C/C++ Source or Header
|
1988-05-26
|
5KB
|
243 lines
/*
* sets - performs set operations on two sets of arguments and
* prints the result on the standard output stream
*
* usage: sets [-p[aths]] e1 e2 ... en \-u[nion] e1 e2 ... en
* OR
* e1 e2 ... en \-d[ifference] e1 e2 ... en
* OR
* e1 e2 ... en \-i[ntersection] e1 e2 ... en
*
* This code may be freely distributed provided this comment
* is not removed or substantially altered. Please mail me any
* fixes, changes, or enhancements.
*
* Christopher Tweed, EdCAAD, University of Edinburgh, Scotland.
* chris@caad.ed.ac.uk
* ..mcvax!ukc!edcaad!chris
*
* 3 December 1987.
*
*/
#include <stdio.h>
#include <string.h>
#define MAXSET 256 /* maximum size of a set */
#define STREQ(s1, s2) (strcmp((s1), (s2)) == 0)
#define NOT(p) ((p) == FALSE)
#define NAME(s) ((ignorep == TRUE) ? nopath(s) : s)
typedef enum { FALSE=0, TRUE } BOOLEAN;
typedef enum { NULL_OP=0, UNION, DIFF, INTERSECT } OPERATOR;
extern int strcmp();
static void too_many();
static void usage();
static char *nopath();
static BOOLEAN member();
static BOOLEAN ignorep = TRUE;
main(argc, argv)
int argc;
char *argv[];
{
int i, j; /* general purpose */
BOOLEAN second = FALSE; /* flag set after operator */
char *set1[MAXSET]; /* the first set */
int n1 = 0; /* number of elements in first set */
char *set2[MAXSET]; /* the second set */
int n2 = 0; /* number of elements in second set */
int n; /* number in each set */
register OPERATOR op = NULL_OP; /* set operation to perform */
if (argc < 2) {
fprintf(stderr, "not enough arguments\n");
usage(argv[0]); /* EXITS */
}
n2 = n1 = 0;
/* collect sets */
while(--argc) {
if (argv[1][0] == '-') {
second = TRUE; /* found an operator */
switch (argv[1][1]) {
case 'u': /* set union */
op = UNION;
break;
case 'd': /* set difference */
op = DIFF;
break;
case 'i': /* set intersection */
op = INTERSECT;
break;
case 'p': /* don't ignore paths */
ignorep = FALSE;
break;
default:
fprintf(stderr, "illegal set operator %c\n",
argv[1][1]);
usage(argv[0]); /* EXITS */
}
} else {
if (second == TRUE) {
if (n2 == MAXSET)
too_many(); /* EXITS */
set2[n2++] = argv[1];
} else {
if (n1 == MAXSET)
too_many(); /* EXITS */
set1[n1++] = argv[1];
}
}
argv++;
}
if (op == NULL_OP) {
fprintf(stderr, "missing operator\n");
usage(argv[0]);
}
/* remove duplicates */
n1 = nodups(set1, n1);
n2 = nodups(set2, n2);
/*
* do set operation and print result
*
*/
n = (op == UNION) ? (n1 + n2) : n1;
for (i = 0; i < n; i++) {
switch(op) {
case UNION:
j = i - n1;
if (i < n1)
printf("%s ", set1[i]);
else if (NOT(member(set2[j], set1, n1)))
printf("%s ", set2[j]);
break;
case DIFF:
if (member(set1[i], set2, n2) == FALSE) {
printf("%s ", set1[i]);
}
break;
case INTERSECT:
if (member(set1[i], set2, n2) == TRUE) {
printf("%s ", set1[i]);
}
break;
}
}
printf("\n");
exit(0);
}
/*
* nodups(set, n)
*
* removes duplicates from set of n elements and returns number
* of remaining elements in the set
*
*/
int
nodups(set, n)
char *set[];
int n;
{
register int i;
register int j;
register int k;
register int nn = n;
/*
* start at the top of the list
*
*/
for(i=n-1; i>0; i--)
for(j=0; j<i; j++) {
if (set[i][0] == set[j][0] && STREQ(set[i], set[j])) {
set[i] = NULL; /* cancel the duplicate */
/*
* move everything above
* the duplicate down one
*
*/
for(k=i+1; k<nn; k++) {
set[k-1] = set[k];
set[k] = NULL;
}
nn--;
break;
}
}
return nn;
}
/*
* member(s, set, n)
*
* returns TRUE if string s is a member of set which has n members
* otherwise return FALSE
*
*/
static BOOLEAN
member(s, set, n)
register char *s, *set[];
register int n;
{
register int i;
for (i = 0; i < n; i++)
if (STREQ(NAME(s), NAME(set[i])))
return TRUE;
return FALSE;
}
/*
* nopath(s)
*
* Strips leading path from s if necessary; otherwise
* returns s.
*
*/
static char *
nopath(s)
char *s;
{
char *p;
#ifdef AMIGA
if ((p = strrchr(s, '/')) || (p = strrchr(s, ':')))
#else
if (p=strrchr(s, '/'))
#endif
return ++p;
else
return s;
}
static void
too_many()
{
fprintf(stderr, "too many members\n");
exit(1);
}
static void
usage(prog)
char *prog;
{
char *set = "e1 e2 ... en";
fprintf(stderr, "%s\t%s -u[nion] %s\n", prog, set, set);
fprintf(stderr, "\t%s -d[ifference] %s\n", set, set);
fprintf(stderr, "\t%s -i[ntersection] %s\n", set, set);
fprintf(stderr, "\t-p[aths]\t/* don't ignore leading paths */\n");
exit(1);
}