|
|
1.1 ! root 1: /* ! 2: * c.c ! 3: * 9/23/91 ! 4: * Usage: c [ -lN ] [ -wN ] [ -012 ] ! 5: * Columnize from stdin to stdout. ! 6: */ ! 7: ! 8: #include <stdio.h> ! 9: ! 10: #define VERSION "1.3" ! 11: ! 12: extern char *getenv(); ! 13: ! 14: #define NAV 6 /* max # environmental args */ ! 15: ! 16: typedef struct line { ! 17: struct line *l_next; ! 18: char *l_line; ! 19: } LINE; ! 20: ! 21: /* Forward. */ ! 22: char *item(); ! 23: char *sel0(); ! 24: char *sel1(); ! 25: char *sel2(); ! 26: void nomem(); ! 27: void fatal(); ! 28: ! 29: /* Globals. */ ! 30: int fieldmax; /* # columns of widest field */ ! 31: int length; /* # lines down page */ ! 32: LINE *lhead; /* head of LINE list */ ! 33: LINE *ltail; /* tail of LINE list */ ! 34: int nacross; /* # fields across page */ ! 35: int ndown; /* # fields down page */ ! 36: int nfields; /* # fields read from input */ ! 37: int npp; /* # fields per page */ ! 38: char *(*select)() = sel1; /* selector function */ ! 39: char *usage = "\nUsage: c [ -lN ] [ -wN ] [ -012 ]"; ! 40: int width = 80; /* # columns across page */ ! 41: ! 42: main(argc, argv) int argc; char *argv[]; ! 43: { ! 44: char obuf[BUFSIZ], av[NAV]; ! 45: ! 46: envargs(av); ! 47: setflags(av); ! 48: setflags(&argv[1]); ! 49: setbuf(stdout, obuf); ! 50: input(); ! 51: output(); ! 52: exit(0); ! 53: } ! 54: ! 55: setflags(av) register char **av; ! 56: { ! 57: ! 58: for (; *av; ++av) { ! 59: if (av[0][0] != '-') ! 60: fatal("%s is not an option%s", av[0], usage); ! 61: switch (av[0][1]) { ! 62: case '0': ! 63: select = sel0; ! 64: break; ! 65: case '1': ! 66: select = sel1; ! 67: break; ! 68: case '2': ! 69: select = sel2; ! 70: break; ! 71: case 'w': ! 72: width = atoi(&av[0][2]); ! 73: break; ! 74: case 'l': ! 75: length = atoi(&av[0][2]); ! 76: break; ! 77: case 'V': ! 78: fprintf(stderr, "c: V%s\n", VERSION); ! 79: break; ! 80: default: ! 81: fatal("bad option %s%s", av[0], usage); ! 82: } ! 83: } ! 84: } ! 85: ! 86: input() ! 87: { ! 88: register LINE *lp; ! 89: register i; ! 90: char lbuf[BUFSIZ]; ! 91: ! 92: while ((i=getline(lbuf)) >= 0) { ! 93: lp = malloc(sizeof *lp); ! 94: if (lp == NULL) ! 95: nomem(); ! 96: if (lhead) ! 97: ltail->l_next = lp; ! 98: else ! 99: lhead = lp; ! 100: ltail = lp; ! 101: lp->l_next = NULL; ! 102: if (i) { ! 103: lp->l_line = malloc(i+1); ! 104: if (lp->l_line == NULL) ! 105: nomem(); ! 106: strcpy(lp->l_line, lbuf); ! 107: } ! 108: else ! 109: lp->l_line = NULL; ! 110: ++nfields; ! 111: } ! 112: ! 113: ++fieldmax; ! 114: } ! 115: ! 116: output() ! 117: { ! 118: register int i, j; ! 119: ! 120: nacross = (width+1) / fieldmax; ! 121: if (nacross <= 0) ! 122: nacross = 1; ! 123: if (length != 0) ! 124: npp = length * nacross; ! 125: ndown = (nfields + nacross - 1) / nacross; ! 126: for (i = 0; i < ndown; ++i) { ! 127: for (j = 0; j < nacross; ++j) ! 128: putline((*select)(i, j)); ! 129: putline((char *)0); ! 130: } ! 131: ! 132: fclose(stdout); ! 133: } ! 134: ! 135: ! 136: getline(lbuf) char lbuf[]; ! 137: { ! 138: register char *p; ! 139: register int col, xcol; ! 140: int c; ! 141: ! 142: p = lbuf; ! 143: col = 0; ! 144: xcol = 0; ! 145: ! 146: for (; ;) { ! 147: switch (c = getchar()) { ! 148: case EOF: ! 149: return (-1); ! 150: case '\n': ! 151: break; ! 152: case ' ': ! 153: ++xcol; ! 154: continue; ! 155: case '\t': ! 156: xcol = (xcol|7) + 1; ! 157: continue; ! 158: case '\b': ! 159: if (xcol > col) ! 160: --xcol; ! 161: else if (col) { ! 162: --col; ! 163: --xcol; ! 164: *p++ = c; ! 165: } ! 166: continue; ! 167: default: ! 168: while (col < xcol) { ! 169: *p++ = ' '; ! 170: ++col; ! 171: } ! 172: *p++ = c; ! 173: ++col; ! 174: ++xcol; ! 175: continue; ! 176: } ! 177: break; ! 178: } ! 179: ! 180: if (col > fieldmax) ! 181: fieldmax = col; ! 182: *p = '\0'; ! 183: return (p - lbuf); ! 184: } ! 185: ! 186: putline(lbuf) char *lbuf; ! 187: { ! 188: register c; ! 189: register char *p; ! 190: static col, ! 191: xcol; ! 192: ! 193: p = lbuf; ! 194: if (p == NULL) { ! 195: col = 0; ! 196: xcol = 0; ! 197: putchar('\n'); ! 198: return; ! 199: } ! 200: ! 201: while (c = *p++) ! 202: switch (c) { ! 203: case ' ': ! 204: ++xcol; ! 205: break; ! 206: case '\b': ! 207: --col; ! 208: --xcol; ! 209: putchar(c); ! 210: break; ! 211: default: ! 212: while ((col|7)+1 <= xcol) { ! 213: putchar('\t'); ! 214: col = (col|7) + 1; ! 215: } ! 216: while (col < xcol) { ! 217: putchar(' '); ! 218: ++col; ! 219: } ! 220: putchar(c); ! 221: ++col; ! 222: ++xcol; ! 223: break; ! 224: } ! 225: ! 226: xcol += fieldmax - xcol%fieldmax; ! 227: } ! 228: ! 229: char * ! 230: item(n) int n; ! 231: { ! 232: register LINE *lp; ! 233: register int m; ! 234: ! 235: for (m = 0, lp = lhead; lp; lp = lp->l_next) ! 236: if (++m > n) ! 237: return (lp->l_line ? lp->l_line : ""); ! 238: return ""; ! 239: } ! 240: ! 241: /* ! 242: * Across each row, then on to next row. ! 243: */ ! 244: char * ! 245: sel0(i, j) int i, j; ! 246: { ! 247: return item(i*nacross + j); ! 248: } ! 249: ! 250: /* ! 251: * Down each column, then on to next column. ! 252: * Leave spaces in last column. ! 253: */ ! 254: char * ! 255: sel1(i, j) int i, j; ! 256: { ! 257: register int page, rows, line; ! 258: ! 259: if (length == 0) ! 260: return item(i + j*ndown); ! 261: page = i / length; /* page number */ ! 262: line = i % length; /* line on page */ ! 263: if (page == (ndown-1)/length) ! 264: rows = ((ndown-1)%length) + 1; /* rows on last page */ ! 265: else ! 266: rows = length; /* rows on full page */ ! 267: return item(page * npp + line + j * rows); ! 268: } ! 269: ! 270: /* ! 271: * Down each column, then on to next column. ! 272: * Leave spaces in last row. ! 273: */ ! 274: char * ! 275: sel2(i, j) int i, j; ! 276: { ! 277: register int ncols, page, line, adjust; ! 278: ! 279: if (i * nacross + j >= nfields) ! 280: return ""; ! 281: ncols = nfields % nacross; /* columns in incomplete last line */ ! 282: adjust = (j > ncols) ? ncols : j; /* last line adjust */ ! 283: if (length == 0) ! 284: return item(i /* n on prev. lines this col. */ ! 285: + j*(ndown-1) /* n on prev. cols. */ ! 286: + adjust); /* n on last line */ ! 287: page = i / length; /* page number */ ! 288: line = i % length; /* line on page */ ! 289: if (page != (ndown-1)/length) /* not last page */ ! 290: return item(page * npp + line + j * length); ! 291: else /* last page */ ! 292: return item(page * npp /* n on prev. pages. */ ! 293: + line /* n on prev. lines this col. */ ! 294: + j*((ndown-1)%length) /* n on prev. cols. */ ! 295: + adjust); /* n on last line */ ! 296: } ! 297: ! 298: envargs(av) char **av; ! 299: { ! 300: register fl; ! 301: register char *p; ! 302: register char **ap; ! 303: ! 304: ap = av; ! 305: *ap = NULL; ! 306: if ((p=getenv("C")) == NULL) ! 307: return; ! 308: ! 309: fl = 0; ! 310: while (*p) ! 311: switch (*p++) { ! 312: case '\t': ! 313: case '\n': ! 314: case ' ': ! 315: fl = 0; ! 316: p[-1] = '\0'; ! 317: break; ! 318: default: ! 319: if (fl) ! 320: break; ! 321: if (ap >= &av[NAV-1]) ! 322: fatal("too many environmental arguments"); ! 323: *ap++ = &p[-1]; ! 324: ++fl; ! 325: break; ! 326: } ! 327: ! 328: *ap = NULL; ! 329: } ! 330: ! 331: void ! 332: nomem() ! 333: { ! 334: ! 335: fatal("out of memory"); ! 336: } ! 337: ! 338: void ! 339: fatal(arg0) ! 340: char *arg0; ! 341: { ! 342: ! 343: fflush(stdout); ! 344: fprintf(stderr, "c: %r\n", &arg0); ! 345: exit(1); ! 346: } ! 347: ! 348: /* end of c.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.