Skip to content

Instantly share code, notes, and snippets.

@ClarkThan
Forked from sinclairtarget/1-cat-pdp7.s
Last active September 27, 2024 05:42
Show Gist options
  • Save ClarkThan/35de1f7839ccea398ff5a08df8280533 to your computer and use it in GitHub Desktop.
Save ClarkThan/35de1f7839ccea398ff5a08df8280533 to your computer and use it in GitHub Desktop.

Revisions

  1. @sinclairtarget sinclairtarget revised this gist Nov 12, 2018. 1 changed file with 9 additions and 9 deletions.
    18 changes: 9 additions & 9 deletions 1-cat-pdp7.s
    Original file line number Diff line number Diff line change
    @@ -74,12 +74,12 @@ getc: 0
    lac ipt " Load pointer to next word in buffer
    sad eipt " Is pointer at end of input buffer?
    jmp 1f " Yes, jump forward to 1, we need to read more
    dac 2f "
    add o400000
    dac ipt
    ral
    lac 2f i
    szl
    dac 2f " Not
    add o400000 " so
    dac ipt " sure
    ral " about
    lac 2f i " all
    szl " this
    lrss 9
    and o177
    sna
    @@ -99,7 +99,7 @@ getc: 0
    lac o4 " No chars left, return 4 (EOF?)
    jmp getc i " Return

    putc: 0
    putc: 0 " Also not sure I understand what is going on here
    and o177
    dac 2f+1
    lac opt
    @@ -133,11 +133,11 @@ eipt: 0 " Input buffer end pointer
    iipt: .+1; .=.+64 " Input buffer base pointer and input buffer
    fi: 0
    opt: .+2
    iopt: .+1; .=.+64
    iopt: .+1; .=.+64 " Output buffer base pointer and output buffer
    noc: 0 " num chars queued to write
    fo: 1

    d1: 1
    d1: 1 " Octal and decimal constants?
    o4:d4: 4
    d8: 8
    o400000: 0400000
  2. @sinclairtarget sinclairtarget revised this gist Nov 12, 2018. 1 changed file with 179 additions and 171 deletions.
    350 changes: 179 additions & 171 deletions 5-cat-net2.c
    Original file line number Diff line number Diff line change
    @@ -15,8 +15,8 @@
    * documentation and/or other materials provided with the distribution.
    * 3. All advertising materials mentioning features or use of this software
    * must display the following acknowledgement:
    * This product includes software developed by the University of
    * California, Berkeley and its contributors.
    * This product includes software developed by the University of
    * California, Berkeley and its contributors.
    * 4. Neither the name of the University nor the names of its contributors
    * may be used to endorse or promote products derived from this software
    * without specific prior written permission.
    @@ -41,7 +41,7 @@ char copyright[] =
    #endif /* not lint */

    #ifndef lint
    static char sccsid[] = "@(#)cat.c 5.15 (Berkeley) 5/23/91";
    static char sccsid[] = "@(#)cat.c 5.15 (Berkeley) 5/23/91";
    #endif /* not lint */

    #include <sys/param.h>
    @@ -54,197 +54,205 @@ static char sccsid[] = "@(#)cat.c 5.15 (Berkeley) 5/23/91";
    #include <string.h>
    #include <ctype.h>

    /* Most comments after this one not in the original */
    int bflag, eflag, nflag, sflag, tflag, vflag;
    int rval;
    int rval; /* Program exit code */
    char *filename;

    void cook_args(), cook_buf(), raw_args(), raw_cat();
    void err __P((int, const char *, ...));

    main(argc, argv)
    int argc;
    char **argv;
    int argc;
    char **argv;
    {
    extern int optind;
    int ch;
    extern int optind; /* Set by getopt() to number of options passed */
    int ch; /* Command-line flag character */

    while ((ch = getopt(argc, argv, "benstuv")) != EOF)
    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, (char *)NULL);
    break;
    case 'v':
    vflag = 1;
    break;
    case '?':
    (void)fprintf(stderr,
    "usage: cat [-benstuv] [-] [file ...]\n");
    exit(1);
    }
    argv += optind;
    while ((ch = getopt(argc, argv, "benstuv")) != EOF)
    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, (char *)NULL);
    break;
    case 'v':
    vflag = 1;
    break;
    case '?':
    (void)fprintf(stderr,
    "usage: cat [-benstuv] [-] [file ...]\n");
    exit(1);
    }
    argv += optind; /* Increment past all options */

    if (bflag || eflag || nflag || sflag || tflag || vflag)
    cook_args(argv);
    else
    raw_args(argv);
    if (fclose(stdout))
    err(1, "stdout: %s", strerror(errno));
    exit(rval);
    if (bflag || eflag || nflag || sflag || tflag || vflag)
    cook_args(argv);
    else
    raw_args(argv);
    if (fclose(stdout))
    err(1, "stdout: %s", strerror(errno));
    exit(rval);
    }

    /* Process file arguments and feed to "cooked" mode of cat */
    void
    cook_args(argv)
    char **argv;
    char **argv;
    {
    register FILE *fp;
    register FILE *fp;

    fp = stdin;
    filename = "stdin";
    do {
    if (*argv) {
    if (!strcmp(*argv, "-"))
    fp = stdin;
    else if (!(fp = fopen(*argv, "r"))) {
    err(0, "%s: %s", *argv, strerror(errno));
    ++argv;
    continue;
    }
    filename = *argv++;
    }
    cook_buf(fp);
    if (fp != stdin)
    (void)fclose(fp);
    } while (*argv);
    fp = stdin;
    filename = "stdin";
    do {
    if (*argv) {
    if (!strcmp(*argv, "-"))
    fp = stdin;
    else if (!(fp = fopen(*argv, "r"))) {
    err(0, "%s: %s", *argv, strerror(errno));
    ++argv;
    continue;
    }
    filename = *argv++;
    }
    cook_buf(fp);
    if (fp != stdin)
    (void)fclose(fp);
    } while (*argv);
    }

    /* "Cooked" mode of cat, i.e. prepared and seasoned. Have to handle all the
    * different combinations of command-line flags */
    void
    cook_buf(fp)
    register FILE *fp;
    register FILE *fp;
    {
    register int ch, gobble, line, prev;
    register int ch, gobble, line, prev;

    line = gobble = 0;
    for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
    if (prev == '\n') {
    if (ch == '\n') {
    if (sflag) {
    if (!gobble && putchar(ch) == EOF)
    break;
    gobble = 1;
    continue;
    }
    if (nflag && !bflag) {
    (void)fprintf(stdout, "%6d\t", ++line);
    if (ferror(stdout))
    break;
    }
    } else if (nflag) {
    (void)fprintf(stdout, "%6d\t", ++line);
    if (ferror(stdout))
    break;
    }
    }
    gobble = 0;
    if (ch == '\n') {
    if (eflag)
    if (putchar('$') == EOF)
    break;
    } else if (ch == '\t') {
    if (tflag) {
    if (putchar('^') == EOF || putchar('I') == EOF)
    break;
    continue;
    }
    } 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;
    }
    }
    if (putchar(ch) == EOF)
    break;
    }
    if (ferror(fp)) {
    err(0, "%s: %s", strerror(errno));
    clearerr(fp);
    }
    if (ferror(stdout))
    err(1, "stdout: %s", strerror(errno));
    line = gobble = 0;
    for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
    if (prev == '\n') {
    if (ch == '\n') {
    if (sflag) {
    if (!gobble && putchar(ch) == EOF)
    break;
    gobble = 1;
    continue;
    }
    if (nflag && !bflag) {
    (void)fprintf(stdout, "%6d\t", ++line);
    if (ferror(stdout))
    break;
    }
    } else if (nflag) {
    (void)fprintf(stdout, "%6d\t", ++line);
    if (ferror(stdout))
    break;
    }
    }
    gobble = 0;
    if (ch == '\n') {
    if (eflag)
    if (putchar('$') == EOF)
    break;
    } else if (ch == '\t') {
    if (tflag) {
    if (putchar('^') == EOF || putchar('I') == EOF)
    break;
    continue;
    }
    } 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;
    }
    }
    if (putchar(ch) == EOF)
    break;
    }
    if (ferror(fp)) {
    err(0, "%s: %s", strerror(errno));
    clearerr(fp);
    }
    if (ferror(stdout))
    err(1, "stdout: %s", strerror(errno));
    }

    /* Process file arguments and feed to "raw" mode of cat */
    void
    raw_args(argv)
    char **argv;
    char **argv;
    {
    register int fd;
    register int fd;

    fd = fileno(stdin);
    filename = "stdin";
    do {
    if (*argv) {
    if (!strcmp(*argv, "-"))
    fd = fileno(stdin);
    else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
    err(0, "%s: %s", *argv, strerror(errno));
    ++argv;
    continue;
    }
    filename = *argv++;
    }
    raw_cat(fd);
    if (fd != fileno(stdin))
    (void)close(fd);
    } while (*argv);
    fd = fileno(stdin);
    filename = "stdin";
    do {
    if (*argv) {
    if (!strcmp(*argv, "-"))
    fd = fileno(stdin);
    else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
    err(0, "%s: %s", *argv, strerror(errno));
    ++argv;
    continue;
    }
    filename = *argv++;
    }
    raw_cat(fd);
    if (fd != fileno(stdin))
    (void)close(fd);
    } while (*argv);
    }

    /* "Raw" mode cat -- no special handling, just print char for char */
    void
    raw_cat(rfd)
    register int rfd;
    register int rfd;
    {
    register int nr, nw, off, wfd;
    static int bsize;
    static char *buf;
    struct stat sbuf;
    register int nr, nw, off, wfd;
    static int bsize;
    static char *buf;
    struct stat sbuf;

    wfd = fileno(stdout);
    if (!buf) {
    if (fstat(wfd, &sbuf))
    err(1, "%s: %s", filename, strerror(errno));
    bsize = MAX(sbuf.st_blksize, 1024);
    if (!(buf = malloc((u_int)bsize)))
    err(1, "%s", strerror(errno));
    }
    while ((nr = read(rfd, buf, bsize)) > 0)
    for (off = 0; off < nr; nr -= nw, off += nw)
    if ((nw = write(wfd, buf + off, nr)) < 0)
    err(1, "stdout");
    if (nr < 0)
    err(0, "%s: %s", filename, strerror(errno));
    wfd = fileno(stdout);
    if (!buf) {
    if (fstat(wfd, &sbuf))
    err(1, "%s: %s", filename, strerror(errno));
    bsize = MAX(sbuf.st_blksize, 1024);
    if (!(buf = malloc((u_int)bsize)))
    err(1, "%s", strerror(errno));
    }
    while ((nr = read(rfd, buf, bsize)) > 0)
    for (off = 0; off < nr; nr -= nw, off += nw)
    if ((nw = write(wfd, buf + off, nr)) < 0)
    err(1, "stdout");
    if (nr < 0)
    err(0, "%s: %s", filename, strerror(errno));
    }

    /* Error handling function err(), with some conditional compilation based on
    * available libraries, it looks like */
    #if __STDC__
    #include <stdarg.h>
    #else
    @@ -256,22 +264,22 @@ void
    err(int ex, const char *fmt, ...)
    #else
    err(ex, fmt, va_alist)
    int ex;
    char *fmt;
    int ex;
    char *fmt;
    va_dcl
    #endif
    {
    va_list ap;
    va_list ap;
    #if __STDC__
    va_start(ap, fmt);
    va_start(ap, fmt);
    #else
    va_start(ap);
    va_start(ap);
    #endif
    (void)fprintf(stderr, "cat: ");
    (void)vfprintf(stderr, fmt, ap);
    va_end(ap);
    (void)fprintf(stderr, "\n");
    if (ex)
    exit(1);
    rval = 1;
    }
    (void)fprintf(stderr, "cat: ");
    (void)vfprintf(stderr, fmt, ap);
    va_end(ap);
    (void)fprintf(stderr, "\n");
    if (ex)
    exit(1);
    rval = 1;
    }
  3. @sinclairtarget sinclairtarget revised this gist Nov 12, 2018. 1 changed file with 8 additions and 7 deletions.
    15 changes: 8 additions & 7 deletions 4-cat-bsd4.c
    Original file line number Diff line number Diff line change
    @@ -7,6 +7,7 @@ static char *Sccsid = "@(#)cat.c 4.2 (Berkeley) 10/9/80";
    #include <sys/types.h>
    #include <sys/stat.h>

    /* All comments below this one not in the original file. */
    char stdbuf[BUFSIZ];
    int bflg, eflg, nflg, sflg, tflg, vflg;
    int spaced, col, lno, inline;
    @@ -26,27 +27,27 @@ char **argv;
    switch(argv[1][1]) {
    case 0:
    break;
    case 'u':
    case 'u': /* Don't buffer */
    setbuf(stdout, (char *)NULL);
    continue;
    case 'n':
    case 'n': /* Print with line numbers */
    nflg++;
    continue;
    case 'b':
    case 'b': /* Omit line numbers from blank lines */
    bflg++;
    nflg++;
    continue;
    case 'v':
    case 'v': /* Print control characters */
    vflg++;
    continue;
    case 's':
    case 's': /* Collapse multiple adjacent blank lines */
    sflg++;
    continue;
    case 'e':
    case 'e': /* Print '$' after lines */
    eflg++;
    vflg++;
    continue;
    case 't':
    case 't': /* Print tabs as '^I' */
    tflg++;
    vflg++;
    continue;
  4. @sinclairtarget sinclairtarget revised this gist Nov 12, 2018. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions 3-cat-v7.c
    Original file line number Diff line number Diff line change
    @@ -6,6 +6,7 @@
    #include <sys/types.h>
    #include <sys/stat.h>

    /* All comments below this one not in the original file. */
    char stdbuf[BUFSIZ]; /* BUFSIZ is typically 512, according to man page. */

    /* Old style function declaration. Return type defaults to int. Param types
  5. @sinclairtarget sinclairtarget revised this gist Nov 11, 2018. 7 changed files with 1010 additions and 0 deletions.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    141 changes: 141 additions & 0 deletions 4-cat-bsd4.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,141 @@
    /*
    * Concatenate files.
    */
    static char *Sccsid = "@(#)cat.c 4.2 (Berkeley) 10/9/80";

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>

    char stdbuf[BUFSIZ];
    int bflg, eflg, nflg, sflg, tflg, vflg;
    int spaced, col, lno, inline;

    main(argc, argv)
    char **argv;
    {
    int fflg = 0;
    register FILE *fi;
    register c;
    int dev, ino = -1;
    struct stat statb;

    lno = 1;
    setbuf(stdout, stdbuf);
    for( ; argc>1 && argv[1][0]=='-'; argc--,argv++) {
    switch(argv[1][1]) {
    case 0:
    break;
    case 'u':
    setbuf(stdout, (char *)NULL);
    continue;
    case 'n':
    nflg++;
    continue;
    case 'b':
    bflg++;
    nflg++;
    continue;
    case 'v':
    vflg++;
    continue;
    case 's':
    sflg++;
    continue;
    case 'e':
    eflg++;
    vflg++;
    continue;
    case 't':
    tflg++;
    vflg++;
    continue;
    }
    break;
    }
    fstat(fileno(stdout), &statb);
    statb.st_mode &= S_IFMT;
    if (statb.st_mode!=S_IFCHR && statb.st_mode!=S_IFBLK) {
    dev = statb.st_dev;
    ino = statb.st_ino;
    }
    if (argc < 2) {
    argc = 2;
    fflg++;
    }
    while (--argc > 0) {
    if (fflg || (*++argv)[0]=='-' && (*argv)[1]=='\0')
    fi = stdin;
    else {
    if ((fi = fopen(*argv, "r")) == NULL) {
    fprintf(stderr, "cat: can't open %s\n", *argv);
    continue;
    }
    }
    fstat(fileno(fi), &statb);
    if (statb.st_dev==dev && statb.st_ino==ino) {
    fprintf(stderr, "cat: input %s is output\n",
    fflg?"-": *argv);
    fclose(fi);
    continue;
    }
    if (nflg||sflg||vflg)
    copyopt(fi);
    else {
    while ((c = getc(fi)) != EOF)
    putchar(c);
    }
    if (fi!=stdin)
    fclose(fi);
    }
    if (ferror(stdout))
    fprintf(stderr, "cat: output write error\n");
    return(0);
    }

    copyopt(f)
    register FILE *f;
    {
    register int c;

    top:
    c = getc(f);
    if (c == EOF)
    return;
    if (c == '\n') {
    if (inline == 0) {
    if (sflg && spaced)
    goto top;
    spaced = 1;
    }
    if (nflg && bflg==0 && inline == 0)
    printf("%6d\t", lno++);
    if (eflg)
    putchar('$');
    putchar('\n');
    inline = 0;
    goto top;
    }
    if (nflg && inline == 0)
    printf("%6d\t", lno++);
    inline = 1;
    if (vflg) {
    if (tflg==0 && c == '\t')
    putchar(c);
    else {
    if (c > 0177) {
    printf("M-");
    c &= 0177;
    }
    if (c < ' ')
    printf("^%c", c+'@');
    else if (c == 0177)
    printf("^?");
    else
    putchar(c);
    }
    } else
    putchar(c);
    spaced = 0;
    goto top;
    }
    277 changes: 277 additions & 0 deletions 5-cat-net2.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,277 @@
    /*
    * Copyright (c) 1989 The Regents of the University of California.
    * All rights reserved.
    *
    * This code is derived from software contributed to Berkeley by
    * Kevin Fall.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    * 3. All advertising materials mentioning features or use of this software
    * must display the following acknowledgement:
    * This product includes software developed by the University of
    * California, Berkeley and its contributors.
    * 4. Neither the name of the University nor the names of its contributors
    * may be used to endorse or promote products derived from this software
    * without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    * SUCH DAMAGE.
    */

    #ifndef lint
    char copyright[] =
    "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
    All rights reserved.\n";
    #endif /* not lint */

    #ifndef lint
    static char sccsid[] = "@(#)cat.c 5.15 (Berkeley) 5/23/91";
    #endif /* not lint */

    #include <sys/param.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>

    int bflag, eflag, nflag, sflag, tflag, vflag;
    int rval;
    char *filename;

    void cook_args(), cook_buf(), raw_args(), raw_cat();
    void err __P((int, const char *, ...));

    main(argc, argv)
    int argc;
    char **argv;
    {
    extern int optind;
    int ch;

    while ((ch = getopt(argc, argv, "benstuv")) != EOF)
    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, (char *)NULL);
    break;
    case 'v':
    vflag = 1;
    break;
    case '?':
    (void)fprintf(stderr,
    "usage: cat [-benstuv] [-] [file ...]\n");
    exit(1);
    }
    argv += optind;

    if (bflag || eflag || nflag || sflag || tflag || vflag)
    cook_args(argv);
    else
    raw_args(argv);
    if (fclose(stdout))
    err(1, "stdout: %s", strerror(errno));
    exit(rval);
    }

    void
    cook_args(argv)
    char **argv;
    {
    register FILE *fp;

    fp = stdin;
    filename = "stdin";
    do {
    if (*argv) {
    if (!strcmp(*argv, "-"))
    fp = stdin;
    else if (!(fp = fopen(*argv, "r"))) {
    err(0, "%s: %s", *argv, strerror(errno));
    ++argv;
    continue;
    }
    filename = *argv++;
    }
    cook_buf(fp);
    if (fp != stdin)
    (void)fclose(fp);
    } while (*argv);
    }

    void
    cook_buf(fp)
    register FILE *fp;
    {
    register int ch, gobble, line, prev;

    line = gobble = 0;
    for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
    if (prev == '\n') {
    if (ch == '\n') {
    if (sflag) {
    if (!gobble && putchar(ch) == EOF)
    break;
    gobble = 1;
    continue;
    }
    if (nflag && !bflag) {
    (void)fprintf(stdout, "%6d\t", ++line);
    if (ferror(stdout))
    break;
    }
    } else if (nflag) {
    (void)fprintf(stdout, "%6d\t", ++line);
    if (ferror(stdout))
    break;
    }
    }
    gobble = 0;
    if (ch == '\n') {
    if (eflag)
    if (putchar('$') == EOF)
    break;
    } else if (ch == '\t') {
    if (tflag) {
    if (putchar('^') == EOF || putchar('I') == EOF)
    break;
    continue;
    }
    } 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;
    }
    }
    if (putchar(ch) == EOF)
    break;
    }
    if (ferror(fp)) {
    err(0, "%s: %s", strerror(errno));
    clearerr(fp);
    }
    if (ferror(stdout))
    err(1, "stdout: %s", strerror(errno));
    }

    void
    raw_args(argv)
    char **argv;
    {
    register int fd;

    fd = fileno(stdin);
    filename = "stdin";
    do {
    if (*argv) {
    if (!strcmp(*argv, "-"))
    fd = fileno(stdin);
    else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
    err(0, "%s: %s", *argv, strerror(errno));
    ++argv;
    continue;
    }
    filename = *argv++;
    }
    raw_cat(fd);
    if (fd != fileno(stdin))
    (void)close(fd);
    } while (*argv);
    }

    void
    raw_cat(rfd)
    register int rfd;
    {
    register int nr, nw, off, wfd;
    static int bsize;
    static char *buf;
    struct stat sbuf;

    wfd = fileno(stdout);
    if (!buf) {
    if (fstat(wfd, &sbuf))
    err(1, "%s: %s", filename, strerror(errno));
    bsize = MAX(sbuf.st_blksize, 1024);
    if (!(buf = malloc((u_int)bsize)))
    err(1, "%s", strerror(errno));
    }
    while ((nr = read(rfd, buf, bsize)) > 0)
    for (off = 0; off < nr; nr -= nw, off += nw)
    if ((nw = write(wfd, buf + off, nr)) < 0)
    err(1, "stdout");
    if (nr < 0)
    err(0, "%s: %s", filename, strerror(errno));
    }

    #if __STDC__
    #include <stdarg.h>
    #else
    #include <varargs.h>
    #endif

    void
    #if __STDC__
    err(int ex, const char *fmt, ...)
    #else
    err(ex, fmt, va_alist)
    int ex;
    char *fmt;
    va_dcl
    #endif
    {
    va_list ap;
    #if __STDC__
    va_start(ap, fmt);
    #else
    va_start(ap);
    #endif
    (void)fprintf(stderr, "cat: ");
    (void)vfprintf(stderr, fmt, ap);
    va_end(ap);
    (void)fprintf(stderr, "\n");
    if (ex)
    exit(1);
    rval = 1;
    }
    278 changes: 278 additions & 0 deletions 6-cat-macosx.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,278 @@
    /* $NetBSD: cat.c,v 1.18 1998/07/28 05:31:22 mycroft Exp $ */

    /*
    * Copyright (c) 1989, 1993
    * The Regents of the University of California. All rights reserved.
    *
    * This code is derived from software contributed to Berkeley by
    * Kevin Fall.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    * 3. All advertising materials mentioning features or use of this software
    * must display the following acknowledgement:
    * This product includes software developed by the University of
    * California, Berkeley and its contributors.
    * 4. Neither the name of the University nor the names of its contributors
    * may be used to endorse or promote products derived from this software
    * without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    * SUCH DAMAGE.
    */

    #include <sys/cdefs.h>
    #ifndef lint
    __COPYRIGHT(
    "@(#) Copyright (c) 1989, 1993\n\
    The Regents of the University of California. All rights reserved.\n");
    #endif /* not lint */

    #ifndef lint
    #if 0
    static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95";
    #else
    __RCSID("$NetBSD: cat.c,v 1.18 1998/07/28 05:31:22 mycroft Exp $");
    #endif
    #endif /* not lint */

    #include <sys/param.h>
    #include <sys/stat.h>

    #include <locale.h>
    #include <ctype.h>
    #include <err.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>

    int bflag, eflag, nflag, sflag, tflag, vflag;
    int rval;
    char *filename;

    int main __P((int, char *[]));
    void cook_args __P((char *argv[]));
    void cook_buf __P((FILE *));
    void raw_args __P((char *argv[]));
    void raw_cat __P((int));

    int
    main(argc, argv)
    int argc;
    char *argv[];
    {
    extern int optind;
    int ch;

    (void)setlocale(LC_ALL, "");

    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, (char *)NULL);
    break;
    case 'v':
    vflag = 1;
    break;
    default:
    case '?':
    (void)fprintf(stderr,
    "usage: cat [-benstuv] [-] [file ...]\n");
    exit(1);
    /* NOTREACHED */
    }
    argv += optind;

    if (bflag || eflag || nflag || sflag || tflag || vflag)
    cook_args(argv);
    else
    raw_args(argv);
    if (fclose(stdout))
    err(1, "stdout");
    exit(rval);
    /* NOTREACHED */
    }

    void
    cook_args(argv)
    char **argv;
    {
    FILE *fp;

    fp = stdin;
    filename = "stdin";
    do {
    if (*argv) {
    if (!strcmp(*argv, "-"))
    fp = stdin;
    else if ((fp = fopen(*argv, "r")) == NULL) {
    warn("%s", *argv);
    rval = 1;
    ++argv;
    continue;
    }
    filename = *argv++;
    }
    cook_buf(fp);
    if (fp != stdin)
    (void)fclose(fp);
    } while (*argv);
    }

    void
    cook_buf(fp)
    FILE *fp;
    {
    int ch, gobble, line, prev;

    line = gobble = 0;
    for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
    if (prev == '\n') {
    if (ch == '\n') {
    if (sflag) {
    if (!gobble && putchar(ch) == EOF)
    break;
    gobble = 1;
    continue;
    }
    if (nflag) {
    if (!bflag) {
    (void)fprintf(stdout,
    "%6d\t", ++line);
    if (ferror(stdout))
    break;
    } else if (eflag) {
    (void)fprintf(stdout,
    "%6s\t", "");
    if (ferror(stdout))
    break;
    }
    }
    } else if (nflag) {
    (void)fprintf(stdout, "%6d\t", ++line);
    if (ferror(stdout))
    break;
    }
    }
    gobble = 0;
    if (ch == '\n') {
    if (eflag)
    if (putchar('$') == EOF)
    break;
    } else if (ch == '\t') {
    if (tflag) {
    if (putchar('^') == EOF || putchar('I') == EOF)
    break;
    continue;
    }
    } 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;
    }
    }
    if (putchar(ch) == EOF)
    break;
    }
    if (ferror(fp)) {
    warn("%s", filename);
    rval = 1;
    clearerr(fp);
    }
    if (ferror(stdout))
    err(1, "stdout");
    }

    void
    raw_args(argv)
    char **argv;
    {
    int fd;

    fd = fileno(stdin);
    filename = "stdin";
    do {
    if (*argv) {
    if (!strcmp(*argv, "-"))
    fd = fileno(stdin);
    else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
    warn("%s", *argv);
    rval = 1;
    ++argv;
    continue;
    }
    filename = *argv++;
    }
    raw_cat(fd);
    if (fd != fileno(stdin))
    (void)close(fd);
    } while (*argv);
    }

    void
    raw_cat(rfd)
    int rfd;
    {
    int nr, nw, off, wfd;
    static int bsize;
    static char *buf;
    struct stat sbuf;

    wfd = fileno(stdout);
    if (buf == NULL) {
    if (fstat(wfd, &sbuf))
    err(1, "%s", filename);
    bsize = MAX(sbuf.st_blksize, 1024);
    if ((buf = malloc((u_int)bsize)) == NULL)
    err(1, "cannot allocate buffer");
    }
    while ((nr = read(rfd, buf, (u_int)bsize)) > 0)
    for (off = 0; nr; nr -= nw, off += nw)
    if ((nw = write(wfd, buf + off, (u_int)nr)) < 0)
    err(1, "stdout");
    if (nr < 0) {
    warn("%s", filename);
    rval = 1;
    }
    }
    314 changes: 314 additions & 0 deletions 7-cat-macos-10-13.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,314 @@
    /*-
    * Copyright (c) 1989, 1993
    * The Regents of the University of California. All rights reserved.
    *
    * This code is derived from software contributed to Berkeley by
    * Kevin Fall.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    * 4. Neither the name of the University nor the names of its contributors
    * may be used to endorse or promote products derived from this software
    * without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    * SUCH DAMAGE.
    */

    #if 0
    #ifndef lint
    static char const copyright[] =
    "@(#) Copyright (c) 1989, 1993\n\
    The Regents of the University of California. All rights reserved.\n";
    #endif /* not lint */
    #endif

    #ifndef lint
    #if 0
    static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95";
    #endif
    #endif /* not lint */
    #include <sys/cdefs.h>
    __FBSDID("$FreeBSD: src/bin/cat/cat.c,v 1.32 2005/01/10 08:39:20 imp Exp $");

    #include <sys/param.h>
    #include <sys/stat.h>
    #ifndef NO_UDOM_SUPPORT
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <errno.h>
    #endif

    #include <ctype.h>
    #include <err.h>
    #include <fcntl.h>
    #include <locale.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <stddef.h>

    int bflag, eflag, nflag, sflag, tflag, vflag;
    int rval;
    const char *filename;

    static void usage(void);
    static void scanfiles(char *argv[], int cooked);
    static void cook_cat(FILE *);
    static void raw_cat(int);

    #ifndef NO_UDOM_SUPPORT
    static int udom_open(const char *path, int flags);
    #endif

    int
    main(int argc, char *argv[])
    {
    int ch;

    setlocale(LC_CTYPE, "");

    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:
    usage();
    }
    argv += optind;

    if (bflag || eflag || nflag || sflag || tflag || vflag)
    scanfiles(argv, 1);
    else
    scanfiles(argv, 0);
    if (fclose(stdout))
    err(1, "stdout");
    exit(rval);
    /* NOTREACHED */
    }

    static void
    usage(void)
    {
    fprintf(stderr, "usage: cat [-benstuv] [file ...]\n");
    exit(1);
    /* NOTREACHED */
    }

    static void
    scanfiles(char *argv[], int cooked)
    {
    int i = 0;
    char *path;
    FILE *fp;

    while ((path = argv[i]) != NULL || i == 0) {
    int fd;

    if (path == NULL || strcmp(path, "-") == 0) {
    filename = "stdin";
    fd = STDIN_FILENO;
    } else {
    filename = path;
    fd = open(path, O_RDONLY);
    #ifndef NO_UDOM_SUPPORT
    if (fd < 0 && errno == EOPNOTSUPP)
    fd = udom_open(path, O_RDONLY);
    #endif
    }
    if (fd < 0) {
    warn("%s", path);
    rval = 1;
    } else if (cooked) {
    if (fd == STDIN_FILENO)
    cook_cat(stdin);
    else {
    fp = fdopen(fd, "r");
    cook_cat(fp);
    fclose(fp);
    }
    } else {
    raw_cat(fd);
    if (fd != STDIN_FILENO)
    close(fd);
    }
    if (path == NULL)
    break;
    ++i;
    }
    }

    static void
    cook_cat(FILE *fp)
    {
    int ch, gobble, line, prev;

    /* Reset EOF condition on stdin. */
    if (fp == stdin && feof(stdin))
    clearerr(stdin);

    line = gobble = 0;
    for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
    if (prev == '\n') {
    if (sflag) {
    if (ch == '\n') {
    if (gobble)
    continue;
    gobble = 1;
    } else
    gobble = 0;
    }
    if (nflag && (!bflag || ch != '\n')) {
    (void)fprintf(stdout, "%6d\t", ++line);
    if (ferror(stdout))
    break;
    }
    }
    if (ch == '\n') {
    if (eflag && putchar('$') == EOF)
    break;
    } else if (ch == '\t') {
    if (tflag) {
    if (putchar('^') == EOF || putchar('I') == EOF)
    break;
    continue;
    }
    } else if (vflag) {
    if (!isascii(ch) && !isprint(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;
    }
    }
    if (putchar(ch) == EOF)
    break;
    }
    if (ferror(fp)) {
    warn("%s", filename);
    rval = 1;
    clearerr(fp);
    }
    if (ferror(stdout))
    err(1, "stdout");
    }

    static void
    raw_cat(int rfd)
    {
    int off, wfd;
    ssize_t nr, nw;
    static size_t bsize;
    static char *buf = NULL;
    struct stat sbuf;

    wfd = fileno(stdout);
    if (buf == NULL) {
    if (fstat(wfd, &sbuf))
    err(1, "%s", filename);
    bsize = MAX(sbuf.st_blksize, 1024);
    if ((buf = malloc(bsize)) == NULL)
    err(1, "buffer");
    }
    while ((nr = read(rfd, buf, bsize)) > 0)
    for (off = 0; nr; nr -= nw, off += nw)
    if ((nw = write(wfd, buf + off, (size_t)nr)) < 0)
    err(1, "stdout");
    if (nr < 0) {
    warn("%s", filename);
    rval = 1;
    }
    }

    #ifndef NO_UDOM_SUPPORT

    static int
    udom_open(const char *path, int flags)
    {
    struct sockaddr_un sou;
    int fd;
    unsigned int len;

    bzero(&sou, sizeof(sou));

    /*
    * Construct the unix domain socket address and attempt to connect
    */
    fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (fd >= 0) {
    sou.sun_family = AF_UNIX;
    if ((len = strlcpy(sou.sun_path, path,
    sizeof(sou.sun_path))) >= sizeof(sou.sun_path)) {
    errno = ENAMETOOLONG;
    return (-1);
    }
    len = offsetof(struct sockaddr_un, sun_path[len+1]);

    if (connect(fd, (void *)&sou, len) < 0) {
    close(fd);
    fd = -1;
    }
    }

    /*
    * handle the open flags by shutting down appropriate directions
    */
    if (fd >= 0) {
    switch(flags & O_ACCMODE) {
    case O_RDONLY:
    if (shutdown(fd, SHUT_WR) == -1)
    warn(NULL);
    break;
    case O_WRONLY:
    if (shutdown(fd, SHUT_RD) == -1)
    warn(NULL);
    break;
    default:
    break;
    }
    }
    return(fd);
    }

    #endif
  6. @sinclairtarget sinclairtarget revised this gist Nov 11, 2018. 3 changed files with 145 additions and 0 deletions.
    145 changes: 145 additions & 0 deletions 1_cat-pdp7.s
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,145 @@
    " cat

    lac 017777 i " Load accumulator (AC) with argument count
    sad d4 " Skip next if we have more than 4 words of args
    jmp nofiles " Otherwise, jump to nofiles
    lac 017777 " Load AC with address of args
    tad d1 " Increment AC by 1, past argument count
    tad d4 " Increment AC by 4, now AC points to first real arg
    dac name " Save arg pointer from AC into 'name'

    loop:
    sys open; name: 0; 0 " Open filename in 'name' in read mode
    spa " Skip next if AC is greater than 0
    jmp badfile " File descriptor is not positive, jump to badfile
    dac fi " Save AC, now the file descriptor, in 'fi'

    1:
    jms getc " Call subroutine getc
    sad o4 " Skip next if getc did not read EOF
    jmp 1f " Read EOF, jump forward to 1
    jms putc " Call subroutine putc
    jmp 1b " Jump back to 1

    1:
    lac fi " Load AC with file descriptor
    sys close " Close file

    loop1: " Below we basically subtract 4 from our arg count
    -4 " Maybe this should be 'lac -4'? Not sure
    tad 017777 i " Increment AC by count of args left
    dac 017777 i " Save AC to count of args left
    sad d4 " Skip next if AC is not 4
    jmp done " No args left, jump to done
    lac name " Load AC from name
    tad d4 " Increment by 4 words
    dac name " Save AC to name, name is now next arg
    jmp loop " Jump back to loop

    badfile:
    lac name " Load AC with bad filename
    dac 1f " Save filename to label 1 below
    lac d8 " Load 8 into AC (point write to stderr?)
    sys write; 1:0; 4 " Write four words of filename
    lac d8 " Load 8 into AC again
    sys write; 1f; 2 " Write ' ?\n'
    jmp loop1 " Jump back to loop1

    1: 040;077012 " String literal ' ?\n'
    nofiles:
    lac d8 " Load 8 into AC (point write to stderr?)
    sys write; 1f; 5 " Write 'no files\n'
    sys exit

    1: <no>; 040; <fi>;<le>;<s 012 " String literal 'no files\n'

    done: " Flush the output buffer if necessary before exit
    lac noc " Load AC with num chars left
    sns " Skip next if num chars left is not zero (sna?)
    sys exit " No chars left, exit
    and d1 " binary AND with 1, check num chars left is odd?
    sna cla " skip next if AC is not zero (num chars left is odd)
    jmp 1f " num chars left is even, jump forward to 1
    jms putc " call putc
    jmp done " go back up to 1
    1:
    lac noc " Load AC with num chars left
    rcr " Divide by two?
    dac 1f " Store AC in label 1 below
    lac fo " Load AC with file out descriptor
    sys write; iopt+1; 1:.. " Write remaining chars
    sys exit

    getc: 0
    lac ipt " Load pointer to next word in buffer
    sad eipt " Is pointer at end of input buffer?
    jmp 1f " Yes, jump forward to 1, we need to read more
    dac 2f "
    add o400000
    dac ipt
    ral
    lac 2f i
    szl
    lrss 9
    and o177
    sna
    jmp getc+1
    jmp getc i
    1:
    lac fi " Buffer empty, load file descriptor into AC
    sys read; iipt+1; 64 " Read into input buffer
    sna " Skip next if AC is not zero
    jmp 1f " We read zero characters, jump forward to 1
    tad iipt " Add chars read to input buffer base
    dac eipt " Save result in end buffer pointer
    lac iipt " Load base input buffer pointer
    dac ipt " Store in input pointer (so reset ipt to iipt)
    jmp getc+1 " Jump back to beginning of subroutine
    1:
    lac o4 " No chars left, return 4 (EOF?)
    jmp getc i " Return

    putc: 0
    and o177
    dac 2f+1
    lac opt
    dac 2f
    add o400000
    dac opt
    spa
    jmp 1f
    lac 2f i
    xor 2f+1
    jmp 3f
    1:
    lac 2f+1
    alss 9
    3:
    dac 2f i
    isz noc
    lac noc
    sad d128
    skp
    jmp putc i
    lac fo
    sys write; iopt+1; 64
    lac iopt
    dac opt
    dzm noc
    jmp putc i
    2: 0;0
    ipt: 0 " Input pointer (points to next word)
    eipt: 0 " Input buffer end pointer
    iipt: .+1; .=.+64 " Input buffer base pointer and input buffer
    fi: 0
    opt: .+2
    iopt: .+1; .=.+64
    noc: 0 " num chars queued to write
    fo: 1

    d1: 1
    o4:d4: 4
    d8: 8
    o400000: 0400000
    o177: 0177
    d128: 128
    File renamed without changes.
    File renamed without changes.
  7. @sinclairtarget sinclairtarget revised this gist Nov 11, 2018. No changes.
  8. @sinclairtarget sinclairtarget revised this gist Nov 11, 2018. 2 changed files with 79 additions and 0 deletions.
    File renamed without changes.
    79 changes: 79 additions & 0 deletions cat-v7.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,79 @@
    /*
    * Concatenate files.
    */

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>

    char stdbuf[BUFSIZ]; /* BUFSIZ is typically 512, according to man page. */

    /* Old style function declaration. Return type defaults to int. Param types
    * default to int. You can specify param types (when not int) after the
    * parentheses like below.
    */
    main(argc, argv)
    char **argv;
    {
    int fflg = 0; /* Flag set to 1 if reading from stdin */
    register FILE *fi; /* File handle */
    register c; /* Current char */
    int dev, ino = -1; /* Keep track of file inodes */
    struct stat statb; /* File status struct */

    /* Handle -u flag */
    setbuf(stdout, stdbuf);
    for( ; argc>1 && argv[1][0]=='-'; argc--,argv++) {
    switch(argv[1][1]) {
    case 0:
    break;
    case 'u': /* -u flag means don't buffer */
    setbuf(stdout, (char *)NULL);
    continue;
    }
    break;
    }

    fstat(fileno(stdout), &statb); /* Get file status. */
    statb.st_mode &= S_IFMT; /* Use mask to get file type. */

    /* If file is not "character special" or "block special"... */
    if (statb.st_mode!=S_IFCHR && statb.st_mode!=S_IFBLK) {
    /* Save file inode data in local vars */
    dev = statb.st_dev;
    ino = statb.st_ino;
    }

    if (argc < 2) {
    argc = 2;
    fflg++; /* We're reading from stdin */
    }

    while (--argc > 0) {
    if (fflg || (*++argv)[0]=='-' && (*argv)[1]=='\0')
    fi = stdin;
    else {
    if ((fi = fopen(*argv, "r")) == NULL) {
    fprintf(stderr, "cat: can't open %s\n", *argv);
    continue;
    }
    }

    fstat(fileno(fi), &statb);

    /* Check if we're reading from and writing to same file */
    if (statb.st_dev==dev && statb.st_ino==ino) {
    fprintf(stderr, "cat: input %s is output\n",
    fflg?"-": *argv);
    fclose(fi);
    continue;
    }

    while ((c = getc(fi)) != EOF)
    putchar(c);

    if (fi!=stdin)
    fclose(fi);
    }
    return(0);
    }
  9. @sinclairtarget sinclairtarget created this gist Nov 11, 2018.
    107 changes: 107 additions & 0 deletions cat.s
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,107 @@
    / cat -- concatinate files

    mov (sp)+,r5 / Pop argument count off stack and save in r5
    tst (sp)+ / Pop first argument and discard it
    mov $obuf,r2 / Store address of output buffer in r2
    cmp r5,$1 / Is argument count 1?
    beq 3f / If argument count was 1, jump to 3 below

    loop:
    dec r5 / Decrement argument count
    ble done / If argument count is <= 0, jump to done
    mov (sp)+,r0 / Pop next argument and save in r0
    cmpb (r0),$'- / Is next argument "-"?
    bne 2f / If next argument was not "-", jump down to 2
    clr fin / Clear file descriptor
    br 3f / Jump down to 3
    2:
    mov r0,0f / Store file name in r0 at label 0 right below
    sys open; 0:..; 0 / Open file in read mode (r0 now file descriptor)
    bes loop / If error opening file, jump to loop
    mov r0,fin / Save file descriptor to fin
    3:
    mov fin,r0 / Copy file descriptor to r0
    sys read; ibuf; 512. / Read from file descriptor in r0 into input buffer
    bes 3f / Jump forward to 3 on error
    mov r0,r4 / r0 now contains bytes read, save in r4
    beq 3f / If bytes read was zero, jump down to 3
    mov $ibuf,r3 / Copy address of input buffer to r3
    4:
    movb (r3)+,r0 / Copy byte from input buffer to r0, auto-increment
    jsr pc,putc / Call putc subroutine
    dec r4 / Decrement r4 (bytes read/left to write)
    bne 4b / If there are bytes left, jump back to 4
    br 3b / Otherwise, jump back to 3
    3:
    mov fin,r0 / Copy file descriptor to r0
    beq loop / If file descriptor was 0 (stdin), jump to loop
    sys close / Otherwise close file descriptor
    br loop / Jump to loop

    done:
    sub $obuf,r2 / Do we still have anything in the output buffer?
    beq 1f / If no, jump down to 1
    mov r2,0f / Copy bytes left to flush to label 0 below
    mov $1,r0 / Set up to write to stdout
    sys write; obuf; 0:.. / Write remaining bytes to stdout
    1:
    sys exit

    putc:
    movb r0,(r2)+ / Copy byte from input to output buffer
    cmp r2,$obuf+512. / Check output buffer size
    blo 1f / If output buffer is not full, jump down to 1
    mov $1,r0 / Set up to write to stdout
    sys write; obuf; 512. / Write output buffer
    mov $obuf,r2 / Reset output buffer index
    1:
    rts pc / Return from subroutine

    .bss
    ibuf: .=.+512. / Input buffer
    obuf: .=.+512. / Output buffer
    fin: .=.+2 / Input file descriptor
    .text

    / Not sure why this is here, seems to just repeat code from above?
    / Next line doesn't look like a complete statement
    ,$'-
    bne 2f
    clr fin
    br 3f
    2:
    mov r0,0f
    sys open; 0:..; 0
    bes loop
    mov r0,fin
    3:
    mov fin,r0
    sys read; ibuf; 512.
    bes 3f
    mov r0,r4
    beq 3f
    mov $ibuf,r3
    4:
    movb (r3)+,r0
    jsr pc,putc
    dec r4
    bne 4b
    br 3b
    3:
    mov fin,r0
    beq loop
    sys close
    br loop

    done:
    sub $obuf,r2
    beq 1f
    mov r2,0f
    mov $1,r0
    sys write; obuf; 0:..
    1:
    sys exit

    putc:
    movb r0,(r2)+
    cmp r2