C
c gordon liddy
2 different cats.
I've been going through chp 8 of K&R and wanted to write a standard cat
function with a little more functionality than existing solns: I want to
code behavior for the -v switch. It occurs to me that there "should" be
source out there for this and googled for "cat.c unix source" . The second
hit I got was this:
/*
* Concatenate files.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
char stdbuf[BUFSIZ];
main(argc, argv)
char **argv;
{
int fflg = 0;
register FILE *fi;
register c;
int dev, ino = -1;
struct stat statb;
setbuf(stdout, stdbuf);
for( ; argc>1 && argv[1][0]=='-'; argc--,argv++) {
switch(argv[1][1]) {
Holy smokes! This must count as archeology for unix systems. Funky-looking
main call and register as a type as opposed to storage specifier. This gave
me a pretty good idea what I wasn't looking for.
I then hit on:
http://www.openbsd.org/cgi-bin/cvsweb/src/bin/cat/cat.c?rev=1.14&content-type=text/plain
The first thing a person notices is the stack of non-standard headers.
Their inclusion is the usual reason for lack of topicality of unix
questions. My platform and my target consist of my non-unix machine; not
only do I not know what's in those headers, I don't have them.
Past that is the main control:
while ((ch = getopt(argc, argv, "benstuv")) != -1)
switch (ch) {
case 'b':
bflag = nflag = 1; /* -b implies -n */
break;
case 'e':
eflag = vflag = 1; /* -e implies -v */
break;
case 'n':
nflag = 1;
break;
case 's':
sflag = 1;
break;
case 't':
tflag = vflag = 1; /* -t implies -v */
break;
case 'u':
setbuf(stdout, NULL);
break;
case 'v':
vflag = 1;
break;
default:
(void)fprintf(stderr,
"usage: %s [-benstuv] [-] [file ...]\n", __progname);
exit(1);
/* NOTREACHED */
}
argv += optind;
The only case I'm to consider is 'v', so I won't need all of this. getopt
will be something that I have to code from scratch. Out of curiosity, what
header is it defined in?
Moving along is:
if (bflag || eflag || nflag || sflag || tflag || vflag)
cook_args(argv);
, so if any flag gets set we cook the args. Maybe instead, we cook with the
args. In this process we traverse through:
} else if (vflag)
{ if (!isascii(ch))
{ if (putchar('M') == EOF || putchar('-') == EOF)
break;
ch = toascii(ch);
}
if (iscntrl(ch)) {
if (putchar('^') == EOF ||
putchar(ch == '\177' ? '?' :
ch | 0100) == EOF)
break;
continue;
}
I did my best to get this on the screen. The parts I don't understand here
follow the double pipe, which I read as "inclusive or." In the first if
clause, it would appear that 'M' is substituted for non-ascii chars. What
does
|| putchar('-') == EOF)
do beyond this?
Similarly, I'm out of my depth with what follows the double pipe in the
second if clause.
|| putchar(ch == '\177' ? '?' : ch | 0100) == EOF)
Wouldn't \177 be a tri-graph? A perfectly-acceptable explanation might be
that it's beyond the scope of my present endeavor and can be omitted.
Grateful for your thoughtful comment.
I've been going through chp 8 of K&R and wanted to write a standard cat
function with a little more functionality than existing solns: I want to
code behavior for the -v switch. It occurs to me that there "should" be
source out there for this and googled for "cat.c unix source" . The second
hit I got was this:
/*
* Concatenate files.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
char stdbuf[BUFSIZ];
main(argc, argv)
char **argv;
{
int fflg = 0;
register FILE *fi;
register c;
int dev, ino = -1;
struct stat statb;
setbuf(stdout, stdbuf);
for( ; argc>1 && argv[1][0]=='-'; argc--,argv++) {
switch(argv[1][1]) {
Holy smokes! This must count as archeology for unix systems. Funky-looking
main call and register as a type as opposed to storage specifier. This gave
me a pretty good idea what I wasn't looking for.
I then hit on:
http://www.openbsd.org/cgi-bin/cvsweb/src/bin/cat/cat.c?rev=1.14&content-type=text/plain
The first thing a person notices is the stack of non-standard headers.
Their inclusion is the usual reason for lack of topicality of unix
questions. My platform and my target consist of my non-unix machine; not
only do I not know what's in those headers, I don't have them.
Past that is the main control:
while ((ch = getopt(argc, argv, "benstuv")) != -1)
switch (ch) {
case 'b':
bflag = nflag = 1; /* -b implies -n */
break;
case 'e':
eflag = vflag = 1; /* -e implies -v */
break;
case 'n':
nflag = 1;
break;
case 's':
sflag = 1;
break;
case 't':
tflag = vflag = 1; /* -t implies -v */
break;
case 'u':
setbuf(stdout, NULL);
break;
case 'v':
vflag = 1;
break;
default:
(void)fprintf(stderr,
"usage: %s [-benstuv] [-] [file ...]\n", __progname);
exit(1);
/* NOTREACHED */
}
argv += optind;
The only case I'm to consider is 'v', so I won't need all of this. getopt
will be something that I have to code from scratch. Out of curiosity, what
header is it defined in?
Moving along is:
if (bflag || eflag || nflag || sflag || tflag || vflag)
cook_args(argv);
, so if any flag gets set we cook the args. Maybe instead, we cook with the
args. In this process we traverse through:
} else if (vflag)
{ if (!isascii(ch))
{ if (putchar('M') == EOF || putchar('-') == EOF)
break;
ch = toascii(ch);
}
if (iscntrl(ch)) {
if (putchar('^') == EOF ||
putchar(ch == '\177' ? '?' :
ch | 0100) == EOF)
break;
continue;
}
I did my best to get this on the screen. The parts I don't understand here
follow the double pipe, which I read as "inclusive or." In the first if
clause, it would appear that 'M' is substituted for non-ascii chars. What
does
|| putchar('-') == EOF)
do beyond this?
Similarly, I'm out of my depth with what follows the double pipe in the
second if clause.
|| putchar(ch == '\177' ? '?' : ch | 0100) == EOF)
Wouldn't \177 be a tri-graph? A perfectly-acceptable explanation might be
that it's beyond the scope of my present endeavor and can be omitted.
Grateful for your thoughtful comment.