BSD 4_4_Lite1 release
[unix-history] / usr / src / usr.bin / join / join.c
index 51c7090..587fa84 100644 (file)
@@ -1,5 +1,5 @@
 /*-
 /*-
- * Copyright (c) 1991, 1993
+ * Copyright (c) 1991, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  *     The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
 
 #ifndef lint
 static char copyright[] =
 
 #ifndef lint
 static char copyright[] =
-"@(#) Copyright (c) 1991, 1993\n\
+"@(#) Copyright (c) 1991, 1993, 1994\n\
        The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
        The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)join.c     8.1 (Berkeley) 6/6/93";
+static char sccsid[] = "@(#)join.c     8.3 (Berkeley) 4/16/94";
 #endif /* not lint */
 
 #include <sys/param.h>
 
 #include <ctype.h>
 #endif /* not lint */
 
 #include <sys/param.h>
 
 #include <ctype.h>
+#include <err.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -92,18 +93,15 @@ u_long olistalloc;          /* output field allocated count */
 
 int joinout = 1;               /* show lines with matched join fields (-v) */
 int needsep;                   /* need separator character */
 
 int joinout = 1;               /* show lines with matched join fields (-v) */
 int needsep;                   /* need separator character */
-int showusage = 1;             /* show usage for usage err() calls */
 int spans = 1;                 /* span multiple delimiters (-t) */
 char *empty;                   /* empty field replacement string (-e) */
 char *tabchar = " \t";         /* delimiter characters (-t) */
 
 int  cmp __P((LINE *, u_long, LINE *, u_long));
 int spans = 1;                 /* span multiple delimiters (-t) */
 char *empty;                   /* empty field replacement string (-e) */
 char *tabchar = " \t";         /* delimiter characters (-t) */
 
 int  cmp __P((LINE *, u_long, LINE *, u_long));
-void enomem __P((void));
-void err __P((const char *, ...));
 void fieldarg __P((char *));
 void joinlines __P((INPUT *, INPUT *));
 void obsolete __P((char **));
 void fieldarg __P((char *));
 void joinlines __P((INPUT *, INPUT *));
 void obsolete __P((char **));
-void outfield __P((LINE *, u_long));
+void outfield __P((LINE *, u_long, int));
 void outoneline __P((INPUT *, LINE *));
 void outtwoline __P((INPUT *, LINE *, INPUT *, LINE *));
 void slurp __P((INPUT *));
 void outoneline __P((INPUT *, LINE *));
 void outtwoline __P((INPUT *, LINE *, INPUT *, LINE *));
 void slurp __P((INPUT *));
@@ -114,7 +112,7 @@ main(argc, argv)
        int argc;
        char *argv[];
 {
        int argc;
        char *argv[];
 {
-       register INPUT *F1, *F2;
+       INPUT *F1, *F2;
        int aflag, ch, cval, vflag;
        char *end;
 
        int aflag, ch, cval, vflag;
        char *end;
 
@@ -125,22 +123,22 @@ main(argc, argv)
        obsolete(argv);
        while ((ch = getopt(argc, argv, "\01a:e:j:1:2:o:t:v:")) != EOF) {
                switch (ch) {
        obsolete(argv);
        while ((ch = getopt(argc, argv, "\01a:e:j:1:2:o:t:v:")) != EOF) {
                switch (ch) {
-               case '\01':
+               case '\01':             /* See comment in obsolete(). */
                        aflag = 1;
                        F1->unpair = F2->unpair = 1;
                        break;
                case '1':
                        if ((F1->joinf = strtol(optarg, &end, 10)) < 1)
                        aflag = 1;
                        F1->unpair = F2->unpair = 1;
                        break;
                case '1':
                        if ((F1->joinf = strtol(optarg, &end, 10)) < 1)
-                               err("-1 option field number less than 1");
+                               errx(1, "-1 option field number less than 1");
                        if (*end)
                        if (*end)
-                               err("illegal field number -- %s", optarg);
+                               errx(1, "illegal field number -- %s", optarg);
                        --F1->joinf;
                        break;
                case '2':
                        if ((F2->joinf = strtol(optarg, &end, 10)) < 1)
                        --F1->joinf;
                        break;
                case '2':
                        if ((F2->joinf = strtol(optarg, &end, 10)) < 1)
-                               err("-2 option field number less than 1");
+                               errx(1, "-2 option field number less than 1");
                        if (*end)
                        if (*end)
-                               err("illegal field number -- %s", optarg);
+                               errx(1, "illegal field number -- %s", optarg);
                        --F2->joinf;
                        break;
                case 'a':
                        --F2->joinf;
                        break;
                case 'a':
@@ -153,11 +151,11 @@ main(argc, argv)
                                F2->unpair = 1;
                                break;
                        default:
                                F2->unpair = 1;
                                break;
                        default:
-                               err("-a option file number not 1 or 2");
+                               errx(1, "-a option file number not 1 or 2");
                                break;
                        }
                        if (*end)
                                break;
                        }
                        if (*end)
-                               err("illegal file number -- %s", optarg);
+                               errx(1, "illegal file number -- %s", optarg);
                        break;
                case 'e':
                        empty = optarg;
                        break;
                case 'e':
                        empty = optarg;
@@ -165,9 +163,9 @@ main(argc, argv)
                case 'j':
                        if ((F1->joinf = F2->joinf =
                            strtol(optarg, &end, 10)) < 1)
                case 'j':
                        if ((F1->joinf = F2->joinf =
                            strtol(optarg, &end, 10)) < 1)
-                               err("-j option field number less than 1");
+                               errx(1, "-j option field number less than 1");
                        if (*end)
                        if (*end)
-                               err("illegal field number -- %s", optarg);
+                               errx(1, "illegal field number -- %s", optarg);
                        --F1->joinf;
                        --F2->joinf;
                        break;
                        --F1->joinf;
                        --F2->joinf;
                        break;
@@ -177,12 +175,12 @@ main(argc, argv)
                case 't':
                        spans = 0;
                        if (strlen(tabchar = optarg) != 1)
                case 't':
                        spans = 0;
                        if (strlen(tabchar = optarg) != 1)
-                               err("illegal tab character specification");
+                               errx(1, "illegal tab character specification");
                        break;
                case 'v':
                        vflag = 1;
                        joinout = 0;
                        break;
                case 'v':
                        vflag = 1;
                        joinout = 0;
-                       switch(strtol(optarg, &end, 10)) {
+                       switch (strtol(optarg, &end, 10)) {
                        case 1:
                                F1->unpair = 1;
                                break;
                        case 1:
                                F1->unpair = 1;
                                break;
@@ -190,11 +188,11 @@ main(argc, argv)
                                F2->unpair = 1;
                                break;
                        default:
                                F2->unpair = 1;
                                break;
                        default:
-                               err("-v option file number not 1 or 2");
+                               errx(1, "-v option file number not 1 or 2");
                                break;
                        }
                        if (*end)
                                break;
                        }
                        if (*end)
-                               err("illegal file number -- %s", optarg);
+                               errx(1, "illegal file number -- %s", optarg);
                        break;
                case '?':
                default:
                        break;
                case '?':
                default:
@@ -205,24 +203,23 @@ main(argc, argv)
        argv += optind;
 
        if (aflag && vflag)
        argv += optind;
 
        if (aflag && vflag)
-               err("-a and -v options mutually exclusive");
+               errx(1, "the -a and -v options are mutually exclusive");
 
        if (argc != 2)
                usage();
 
        if (argc != 2)
                usage();
-       showusage = 0;
 
        /* Open the files; "-" means stdin. */
        if (!strcmp(*argv, "-"))
                F1->fp = stdin;
        else if ((F1->fp = fopen(*argv, "r")) == NULL)
 
        /* Open the files; "-" means stdin. */
        if (!strcmp(*argv, "-"))
                F1->fp = stdin;
        else if ((F1->fp = fopen(*argv, "r")) == NULL)
-               err("%s: %s", *argv, strerror(errno));
+               err(1, "%s", *argv);
        ++argv;
        if (!strcmp(*argv, "-"))
                F2->fp = stdin;
        else if ((F2->fp = fopen(*argv, "r")) == NULL)
        ++argv;
        if (!strcmp(*argv, "-"))
                F2->fp = stdin;
        else if ((F2->fp = fopen(*argv, "r")) == NULL)
-               err("%s: %s", *argv, strerror(errno));
+               err(1, "%s", *argv);
        if (F1->fp == stdin && F2->fp == stdin)
        if (F1->fp == stdin && F2->fp == stdin)
-               err("only one input file may be stdin");
+               errx(1, "only one input file may be stdin");
 
        slurp(F1);
        slurp(F2);
 
        slurp(F1);
        slurp(F2);
@@ -268,8 +265,7 @@ void
 slurp(F)
        INPUT *F;
 {
 slurp(F)
        INPUT *F;
 {
-       register LINE *lp, *lastlp;
-       LINE tmp;
+       LINE *lp, *lastlp, tmp;
        size_t len;
        int cnt;
        char *bp, *fieldp;
        size_t len;
        int cnt;
        char *bp, *fieldp;
@@ -290,8 +286,8 @@ slurp(F)
                        F->setalloc += 50;
                        if ((F->set = realloc(F->set,
                            F->setalloc * sizeof(LINE))) == NULL)
                        F->setalloc += 50;
                        if ((F->set = realloc(F->set,
                            F->setalloc * sizeof(LINE))) == NULL)
-                               enomem();
-                       bzero(F->set + cnt, 50 * sizeof(LINE));
+                               err(1, NULL);
+                       memset(F->set + cnt, 0, 50 * sizeof(LINE));
                }
                        
                /*
                }
                        
                /*
@@ -310,15 +306,15 @@ slurp(F)
                        F->pushbool = 0;
                        continue;
                }
                        F->pushbool = 0;
                        continue;
                }
-               if ((bp = fgetline(F->fp, &len)) == NULL)
+               if ((bp = fgetln(F->fp, &len)) == NULL)
                        return;
                if (lp->linealloc <= len + 1) {
                        lp->linealloc += MAX(100, len + 1);
                        if ((lp->line =
                            realloc(lp->line, lp->linealloc)) == NULL)
                        return;
                if (lp->linealloc <= len + 1) {
                        lp->linealloc += MAX(100, len + 1);
                        if ((lp->line =
                            realloc(lp->line, lp->linealloc)) == NULL)
-                               enomem();
+                               err(1, NULL);
                }
                }
-               bcopy(bp, lp->line, len);
+               memmove(lp->line, bp, len);
 
                /* Replace trailing newline, if it exists. */
                if (bp[len - 1] == '\n')
 
                /* Replace trailing newline, if it exists. */
                if (bp[len - 1] == '\n')
@@ -336,7 +332,7 @@ slurp(F)
                                lp->fieldalloc += 50;
                                if ((lp->fields = realloc(lp->fields,
                                    lp->fieldalloc * sizeof(char *))) == NULL)
                                lp->fieldalloc += 50;
                                if ((lp->fields = realloc(lp->fields,
                                    lp->fieldalloc * sizeof(char *))) == NULL)
-                                       enomem();
+                                       err(1, NULL);
                        }
                        lp->fields[lp->fieldcnt++] = fieldp;
                }
                        }
                        lp->fields[lp->fieldcnt++] = fieldp;
                }
@@ -364,9 +360,9 @@ cmp(lp1, fieldno1, lp2, fieldno2)
 
 void
 joinlines(F1, F2)
 
 void
 joinlines(F1, F2)
-       register INPUT *F1, *F2;
+       INPUT *F1, *F2;
 {
 {
-       register int cnt1, cnt2;
+       int cnt1, cnt2;
 
        /*
         * Output the results of a join comparison.  The output may be from
 
        /*
         * Output the results of a join comparison.  The output may be from
@@ -386,9 +382,9 @@ joinlines(F1, F2)
 void
 outoneline(F, lp)
        INPUT *F;
 void
 outoneline(F, lp)
        INPUT *F;
-       register LINE *lp;
+       LINE *lp;
 {
 {
-       register int cnt;
+       int cnt;
 
        /*
         * Output a single line from one of the files, according to the
 
        /*
         * Output a single line from one of the files, according to the
@@ -398,59 +394,62 @@ outoneline(F, lp)
        if (olist)
                for (cnt = 0; cnt < olistcnt; ++cnt) {
                        if (olist[cnt].filenum == F->number)
        if (olist)
                for (cnt = 0; cnt < olistcnt; ++cnt) {
                        if (olist[cnt].filenum == F->number)
-                               outfield(lp, olist[cnt].fieldno);
+                               outfield(lp, olist[cnt].fieldno, 0);
+                       else
+                               outfield(lp, 0, 1);
                }
        else
                for (cnt = 0; cnt < lp->fieldcnt; ++cnt)
                }
        else
                for (cnt = 0; cnt < lp->fieldcnt; ++cnt)
-                       outfield(lp, cnt);
+                       outfield(lp, cnt, 0);
        (void)printf("\n");
        if (ferror(stdout))
        (void)printf("\n");
        if (ferror(stdout))
-               err("stdout: %s", strerror(errno));
+               err(1, "stdout");
        needsep = 0;
 }
 
 void
 outtwoline(F1, lp1, F2, lp2)
        needsep = 0;
 }
 
 void
 outtwoline(F1, lp1, F2, lp2)
-       register INPUT *F1, *F2;
-       register LINE *lp1, *lp2;
+       INPUT *F1, *F2;
+       LINE *lp1, *lp2;
 {
 {
-       register int cnt;
+       int cnt;
 
        /* Output a pair of lines according to the join list (if any). */
        if (olist)
                for (cnt = 0; cnt < olistcnt; ++cnt)
                        if (olist[cnt].filenum == 1)
 
        /* Output a pair of lines according to the join list (if any). */
        if (olist)
                for (cnt = 0; cnt < olistcnt; ++cnt)
                        if (olist[cnt].filenum == 1)
-                               outfield(lp1, olist[cnt].fieldno);
+                               outfield(lp1, olist[cnt].fieldno, 0);
                        else /* if (olist[cnt].filenum == 2) */
                        else /* if (olist[cnt].filenum == 2) */
-                               outfield(lp2, olist[cnt].fieldno);
+                               outfield(lp2, olist[cnt].fieldno, 0);
        else {
                /*
                 * Output the join field, then the remaining fields from F1
                 * and F2.
                 */
        else {
                /*
                 * Output the join field, then the remaining fields from F1
                 * and F2.
                 */
-               outfield(lp1, F1->joinf);
+               outfield(lp1, F1->joinf, 0);
                for (cnt = 0; cnt < lp1->fieldcnt; ++cnt)
                        if (F1->joinf != cnt)
                for (cnt = 0; cnt < lp1->fieldcnt; ++cnt)
                        if (F1->joinf != cnt)
-                               outfield(lp1, cnt);
+                               outfield(lp1, cnt, 0);
                for (cnt = 0; cnt < lp2->fieldcnt; ++cnt)
                        if (F2->joinf != cnt)
                for (cnt = 0; cnt < lp2->fieldcnt; ++cnt)
                        if (F2->joinf != cnt)
-                               outfield(lp2, cnt);
+                               outfield(lp2, cnt, 0);
        }
        (void)printf("\n");
        if (ferror(stdout))
        }
        (void)printf("\n");
        if (ferror(stdout))
-               err("stdout: %s", strerror(errno));
+               err(1, "stdout");
        needsep = 0;
 }
 
 void
        needsep = 0;
 }
 
 void
-outfield(lp, fieldno)
+outfield(lp, fieldno, out_empty)
        LINE *lp;
        u_long fieldno;
        LINE *lp;
        u_long fieldno;
+       int out_empty;
 {
        if (needsep++)
                (void)printf("%c", *tabchar);
        if (!ferror(stdout))
 {
        if (needsep++)
                (void)printf("%c", *tabchar);
        if (!ferror(stdout))
-               if (lp->fieldcnt < fieldno) {
+               if (lp->fieldcnt < fieldno || out_empty) {
                        if (empty != NULL)
                                (void)printf("%s", empty);
                } else {
                        if (empty != NULL)
                                (void)printf("%s", empty);
                } else {
@@ -459,7 +458,7 @@ outfield(lp, fieldno)
                        (void)printf("%s", lp->fields[fieldno]);
                }
        if (ferror(stdout))
                        (void)printf("%s", lp->fields[fieldno]);
                }
        if (ferror(stdout))
-               err("stdout: %s", strerror(errno));
+               err(1, "stdout");
 }
 
 /*
 }
 
 /*
@@ -477,17 +476,17 @@ fieldarg(option)
                if (*token == '\0')
                        continue;
                if (token[0] != '1' && token[0] != '2' || token[1] != '.')
                if (*token == '\0')
                        continue;
                if (token[0] != '1' && token[0] != '2' || token[1] != '.')
-                       err("malformed -o option field");
+                       errx(1, "malformed -o option field");
                fieldno = strtol(token + 2, &end, 10);
                if (*end)
                fieldno = strtol(token + 2, &end, 10);
                if (*end)
-                       err("malformed -o option field");
+                       errx(1, "malformed -o option field");
                if (fieldno == 0)
                if (fieldno == 0)
-                       err("field numbers are 1 based");
+                       errx(1, "field numbers are 1 based");
                if (olistcnt == olistalloc) {
                        olistalloc += 50;
                        if ((olist = realloc(olist,
                            olistalloc * sizeof(OLIST))) == NULL)
                if (olistcnt == olistalloc) {
                        olistalloc += 50;
                        if ((olist = realloc(olist,
                            olistalloc * sizeof(OLIST))) == NULL)
-                               enomem();
+                               err(1, NULL);
                }
                olist[olistcnt].filenum = token[0] - '0';
                olist[olistcnt].fieldno = fieldno - 1;
                }
                olist[olistcnt].filenum = token[0] - '0';
                olist[olistcnt].fieldno = fieldno - 1;
@@ -502,7 +501,7 @@ obsolete(argv)
        int len;
        char **p, *ap, *t;
 
        int len;
        char **p, *ap, *t;
 
-       while (ap = *++argv) {
+       while ((ap = *++argv) != NULL) {
                /* Return if "--". */
                if (ap[0] == '-' && ap[1] == '-')
                        return;
                /* Return if "--". */
                if (ap[0] == '-' && ap[1] == '-')
                        return;
@@ -542,29 +541,29 @@ obsolete(argv)
                        case '\0':
                                break;
                        default:
                        case '\0':
                                break;
                        default:
-jbad:                          err("illegal option -- %s", ap);
+jbad:                          errx(1, "illegal option -- %s", ap);
                                usage();
                        }
                        break;
                case 'o':
                        /*
                                usage();
                        }
                        break;
                case 'o':
                        /*
-                        * The original join allowed "-o arg arg".  Convert to
-                        * "-o arg -o arg".
+                        * The original join allowed "-o arg arg".
+                        * Convert to "-o arg -o arg".
                         */
                        if (ap[2] != '\0')
                                break;
                        for (p = argv + 2; *p; ++p) {
                         */
                        if (ap[2] != '\0')
                                break;
                        for (p = argv + 2; *p; ++p) {
-                               if (p[0][0] != '1' && p[0][0] != '2' ||
-                                   p[0][1] != '.')
+                               if (p[0][0] != '1' &&
+                                   p[0][0] != '2' || p[0][1] != '.')
                                        break;
                                len = strlen(*p);
                                if (len - 2 != strspn(*p + 2, "0123456789"))
                                        break;
                                if ((t = malloc(len + 3)) == NULL)
                                        break;
                                len = strlen(*p);
                                if (len - 2 != strspn(*p + 2, "0123456789"))
                                        break;
                                if ((t = malloc(len + 3)) == NULL)
-                                       enomem();
+                                       err(1, NULL);
                                t[0] = '-';
                                t[1] = 'o';
                                t[0] = '-';
                                t[1] = 'o';
-                               bcopy(*p, t + 2, len + 1);
+                               memmove(t + 2, *p, len + 1);
                                *p = t;
                        }
                        argv = p - 1;
                                *p = t;
                        }
                        argv = p - 1;
@@ -573,13 +572,6 @@ jbad:                              err("illegal option -- %s", ap);
        }
 }
 
        }
 }
 
-void
-enomem()
-{
-       showusage = 0;
-       err("%s", strerror(errno));
-}
-
 void
 usage()
 {
 void
 usage()
 {
@@ -588,34 +580,3 @@ usage()
            "[-2 field]\n            [-o list] [-t char] file1 file2");
        exit(1);
 }
            "[-2 field]\n            [-o list] [-t char] file1 file2");
        exit(1);
 }
-
-#if __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-void
-#if __STDC__
-err(const char *fmt, ...)
-#else
-err(fmt, va_alist)
-       char *fmt;
-        va_dcl
-#endif
-{
-       va_list ap;
-#if __STDC__
-       va_start(ap, fmt);
-#else
-       va_start(ap);
-#endif
-       (void)fprintf(stderr, "join: ");
-       (void)vfprintf(stderr, fmt, ap);
-       va_end(ap);
-       (void)fprintf(stderr, "\n");
-       if (showusage)
-               usage();
-       exit(1);
-       /* NOTREACHED */
-}