meillo@14: # meillo@14: /* cut : cut and paste columns of a table (projection of a relation) (GWRL) */ meillo@14: /* Release 1.5; handles single backspaces as produced by nroff */ meillo@14: # include /* make: cc cut.c */ meillo@14: # define NFIELDS 512 /* max no of fields or resulting line length */ meillo@14: # define BACKSPACE 8 meillo@14: main(argc, argv) meillo@14: int argc; char **argv; meillo@14: { meillo@14: int del = '\t'; meillo@14: int i, j, count, poscnt, r, s, t; meillo@14: int endflag, supflag, cflag, fflag, backflag, filenr; meillo@14: int sel[NFIELDS]; meillo@14: register int c; meillo@14: register char *p1; meillo@14: char *p2, outbuf[NFIELDS]; meillo@14: FILE *inptr; meillo@14: meillo@14: meillo@14: while (argc > 1 && argv[1][0] == '-'){ meillo@14: for (i = 1; (c = argv[1][i]) != '\0'; i++) { meillo@14: switch(c) { meillo@14: case 'd' : del = argv[1][++i]; meillo@14: if (del == '\0') diag("no delimiter\n"); meillo@14: break; meillo@14: case 's': supflag++ ; meillo@14: break; meillo@14: case 'c': cflag++ ; meillo@14: break; meillo@14: case 'f': fflag++ ; meillo@14: break; meillo@14: default : diag("Usage: cut [-s] [-d] {-c | -f} file ...\n"); meillo@14: break; meillo@14: } meillo@14: if (!endflag && (cflag || fflag)) { meillo@14: endflag = 1; meillo@14: r = s = t = 0; meillo@14: do { c = argv[1][++i]; meillo@14: switch(c) { meillo@14: case '-' : if (r) diagl(); meillo@14: r = 1; meillo@14: if (t == 0) s = 1; meillo@14: else {s = t; t = 0;} meillo@14: continue; meillo@14: case '\0' : meillo@14: case ',' : if (t >= NFIELDS) diagl(); meillo@14: if (r) { if (t == 0) t = NFIELDS - 1; meillo@14: if (t 0 ? 1 : 0); meillo@14: r = s = t = 0; meillo@14: if (c == '\0') {i--; break;} meillo@14: continue; meillo@14: default : meillo@14: if (c< '0' || c> '9') diagl(); meillo@14: t = 10*t + c - '0'; meillo@14: continue; meillo@14: } meillo@14: for (j = t = 0; j < NFIELDS; j++) t += sel[j]; meillo@14: if (t == 0) diag("no fields\n"); meillo@14: } while (c != '\0'); meillo@14: } meillo@14: } meillo@14: --argc; meillo@14: ++argv; meillo@14: } /* end options */ meillo@14: if (!(cflag || fflag)) diagl(); meillo@14: meillo@14: --argc; meillo@14: filenr = 1; meillo@14: do { /* for all input files */ meillo@14: if (argc > 0) inptr = fopen(argv[filenr], "r"); meillo@14: else inptr = stdin; meillo@14: meillo@14: if (inptr == NULL) { meillo@14: write(2,"Cannot open :",14); meillo@14: diag(argv[filenr]); meillo@14: } meillo@14: endflag = 0; meillo@14: do { /* for all lines of a file */ meillo@14: count = poscnt = backflag = 0; meillo@14: p1 = &outbuf[0] - 1 ; meillo@14: p2 = p1; meillo@14: do { /* for all char of the line */ meillo@14: c = fgetc(inptr); meillo@14: if (c == EOF) { meillo@14: endflag = 1; meillo@14: break; meillo@14: } meillo@14: if (count == NFIELDS - 1) diag("line too long\n"); meillo@14: if (c != '\n') *++p1 = c; meillo@14: if (cflag && (c == BACKSPACE)) backflag++ ; else meillo@14: { if ( !backflag ) poscnt += 1 ; else backflag-- ;} meillo@14: if ( backflag > 1 ) diag("cannot handle multiple adjacent backspaces\n"); meillo@14: if ( ((c == '\n') && count > 0) || c == del || cflag) { meillo@14: count += 1; meillo@14: if (fflag) poscnt = count ; meillo@14: if (sel[poscnt]) p2 = p1; else p1 = p2; meillo@14: } meillo@14: }while (c != '\n'); meillo@14: if ( !endflag && (count > 0 || !supflag)) { meillo@14: if (*p1 == del) *p1 = '\0'; meillo@14: else *++p1 = '\0'; /*suppress trailing delimiter*/ meillo@14: puts(outbuf); meillo@14: } meillo@14: } while (!endflag) ; meillo@14: fclose(inptr); meillo@14: } while(++filenr <= argc); meillo@14: } meillo@14: meillo@14: diag(s) meillo@14: char *s; meillo@14: { meillo@14: write(2, "cut : ", 6); meillo@14: while(*s) meillo@14: write(2,s++,1); meillo@14: exit(2); meillo@14: } meillo@14: diagl() meillo@14: { meillo@14: diag("bad list for c/f option\n"); meillo@14: }