/* * 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 #include #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