|
|
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 - metrics - 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);
}