|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 4622 (0x120e) Types: TextFile Notes: UNIX file Names: »head.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─ ⟦this⟧ »cmd/head.c«
/* * The program head copys the head of a file to the standard output. * Its usage is: * head [{+-}n[{lbc}]] [file] * The initial `+' (or `-') indicate that `n' is relative to the * beggining (or ending respectively) of the file. * The optional `l', `b' or `c' (`l' default) is to indicate if `n' * is a number of lines, blocks or characters respectively. * If the entire position specifier is absent, then `+4l' is assumed. * If the optional `file' is absent, then the standard input is used. * In any case, head copys from the start of the file up to, and * includeing, the specified point onto the standard output. */ #include <stdio.h> #include <ctype.h> #include <mdata.h> #define bool char /* boolean type */ #define not ! /* logical negation operator */ #define and && /* logical conjunction */ #define or || /* logical disjunction */ #define TRUE (0 == 0) #define FALSE (not TRUE) #define EOS '\0' /* end-of-string char */ #define N 4 /* default number of lines */ struct blk { struct blk *next; int nlines; /* number of `\n' characters */ char blkb[BUFSIZ]; }; bool lflag = TRUE, /* lines (vs. chars) flag */ fflag = TRUE; /* + (vs. -) flag */ long n = N; /* number of lines or chars */ char obuf[BUFSIZ], /* stdout setbuf buffer */ nospace[] = "Window too large"; main(argc, argv) int argc; char *argv[]; { setbuf(stdout, obuf); options(argv); if (fflag) if (lflag) copyfl(); else copyfc(); else if (lflag) copybl(); else copybc(); return (0); } die(str) char *str; { fprintf(stderr, "%r\n", &str); exit(1); } usage() { die("usage: head [{+-}n[{lbc}]] [file]"); } options(argv) register char *argv[]; { register char *chp, ch; if (*++argv == NULL) return; chp = *argv; ch = *chp; if (ch == '-' || ch == '+') { fflag = (ch == '+'); n = 0; for (ch=*++chp; isascii(ch) && isdigit(ch); ch=*++chp) n = 10*n + ch-'0'; switch (ch) { case EOS: case 'l': break; case 'b': n *= BUFSIZ; /* fall thru */ case 'c': lflag = FALSE; break; default: usage(); } chp = *++argv; } if (chp == NULL) return; if (freopen(chp, "r", stdin) == NULL) die("Can't open %s", chp); } /* * Copyfl copys the first `n' lines of stdin to stdout. */ copyfl() { register int ch; while (--n >= 0) do { ch = getchar(); if (ch == EOF) return; putchar(ch); } while (ch != '\n'); } /* * Copyfc copys the first `n' characters of stdin to stdout. */ copyfc() { register int ch; for (ch=getchar(); --n >= 0 && ch != EOF; ch=getchar()) putchar(ch); } /* * Copybc copys all but the last `n' characters of stdin to stdout. */ copybc() { register char *buf, *chp, *limit; char ch; unsigned len; if (n > MAXUINT) die(nospace); len = n; buf = (char *)malloc(len); if (buf == NULL) die(nospace); len = fread(buf, sizeof *buf, len, stdin); if (len < n) { fwrite(buf, sizeof *buf, len, stdout); free(buf); return; } limit = buf + len; for (chp=buf; (ch=getchar()) != EOF;) { putchar(*chp); *chp++ = ch; if (chp == limit) chp = buf; } } /* * Copybl copys all but the last `n' lines of stdin to stdout. */ copybl() { register struct blk *bp; register char *chp; register int extra; int len; struct blk **tail, *head; if (n > MAXINT) die(nospace); extra = -n; for (tail=&head;;) { len = getblk(tail); bp = *tail; tail = &bp->next; extra += bp->nlines; for (bp=head; extra > bp->nlines; bp=bp->next) { extra -= bp->nlines; fwrite(bp->blkb, sizeof *bp->blkb, BUFSIZ, stdout); free(bp); } head = bp; if (len < BUFSIZ) break; } for (bp=head, chp=bp->blkb; extra > 0; --extra) while (*chp++ != '\n') ; fwrite(bp->blkb, sizeof *bp->blkb, chp-bp->blkb, stdout); } /* * Getblk allocates a blk, reads text into it and sets the nlines * field. It returns the number of characters read. It sets `bpp' * to point to the block. If the block could not be allocated, then * it dies with the appropriate error message. */ getblk(bpp) struct blk **bpp; { register struct blk *bp; register int len; bp = (struct blk *)malloc(sizeof *bp); if (bp == NULL) die(nospace); *bpp = bp; len = fread(bp->blkb, sizeof *bp->blkb, BUFSIZ, stdin); bp->nlines = cntlines(bp->blkb, len); return (len); } /* * Cntlines returns the number of '\n' characters in the char array * `chp' with length `len'. */ cntlines(chp, len) register char *chp; int len; { register char *limit; register int res; for (res=0, limit=&chp[len]; chp < limit;) if (*chp++ == '\n') ++res; return (res); }