From owner-svn-src-head@FreeBSD.ORG Mon Mar 8 19:40:23 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3D76A106566C; Mon, 8 Mar 2010 19:40:23 +0000 (UTC) (envelope-from ache@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2BADF8FC18; Mon, 8 Mar 2010 19:40:23 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o28JeNqe088003; Mon, 8 Mar 2010 19:40:23 GMT (envelope-from ache@svn.freebsd.org) Received: (from ache@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o28JeNka088001; Mon, 8 Mar 2010 19:40:23 GMT (envelope-from ache@svn.freebsd.org) Message-Id: <201003081940.o28JeNka088001@svn.freebsd.org> From: "Andrey A. Chernov" Date: Mon, 8 Mar 2010 19:40:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r204876 - head/usr.bin/uniq X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 Mar 2010 19:40:23 -0000 Author: ache Date: Mon Mar 8 19:40:22 2010 New Revision: 204876 URL: http://svn.freebsd.org/changeset/base/204876 Log: 1) Reimplement (differently) unlimited line length restricted in prev. commit. 2) Honor missing the very last \n (if absent) on output. Modified: head/usr.bin/uniq/uniq.c Modified: head/usr.bin/uniq/uniq.c ============================================================================== --- head/usr.bin/uniq/uniq.c Mon Mar 8 18:51:28 2010 (r204875) +++ head/usr.bin/uniq/uniq.c Mon Mar 8 19:40:22 2010 (r204876) @@ -53,6 +53,7 @@ static const char rcsid[] = #include #include #include +#define _WITH_GETLINE #include #include #include @@ -64,8 +65,8 @@ int cflag, dflag, uflag, iflag; int numchars, numfields, repeats; FILE *file(const char *, const char *); -wchar_t *convert(wchar_t *, const char *); -char *getlinemax(char *, FILE *); +wchar_t *convert(const char *); +int inlcmp(const char *, const char *); void show(FILE *, const char *); wchar_t *skip(wchar_t *); void obsolete(char *[]); @@ -74,9 +75,10 @@ static void usage(void); int main (int argc, char *argv[]) { - wchar_t *tprev, *tthis, *wprev, *wthis, *wp; + wchar_t *tprev, *tthis; FILE *ifp, *ofp; int ch, comp; + size_t prevbuflen, thisbuflen, b1; char *prevline, *thisline, *p; const char *ifn; @@ -133,29 +135,27 @@ main (int argc, char *argv[]) if (argc > 1) ofp = file(argv[1], "w"); - prevline = malloc(LINE_MAX); - thisline = malloc(LINE_MAX); - wprev = malloc(LINE_MAX * sizeof(*wprev)); - wthis = malloc(LINE_MAX * sizeof(*wthis)); - if (prevline == NULL || thisline == NULL || - wprev == NULL || wthis == NULL) - err(1, "malloc"); + prevbuflen = thisbuflen = 0; + prevline = thisline = NULL; - if ((prevline = getlinemax(prevline, ifp)) == NULL) { + if (getline(&prevline, &prevbuflen, ifp) < 0) { if (ferror(ifp)) err(1, "%s", ifn); exit(0); } - tprev = convert(wprev, prevline); + tprev = convert(prevline); if (!cflag && uflag && dflag) show(ofp, prevline); - while ((thisline = getlinemax(thisline, ifp)) != NULL) { - tthis = convert(wthis, thisline); + tthis = NULL; + while (getline(&thisline, &thisbuflen, ifp) >= 0) { + if (tthis != NULL) + free(tthis); + tthis = convert(thisline); if (tthis == NULL && tprev == NULL) - comp = strcmp(thisline, prevline); + comp = inlcmp(thisline, prevline); else if (tthis == NULL || tprev == NULL) comp = 1; else @@ -166,14 +166,17 @@ main (int argc, char *argv[]) if (cflag || !dflag || !uflag) show(ofp, prevline); p = prevline; - wp = wprev; + b1 = prevbuflen; prevline = thisline; - wprev = wthis; + prevbuflen = thisbuflen; + if (tprev != NULL) + free(tprev); tprev = tthis; if (!cflag && uflag && dflag) show(ofp, prevline); thisline = p; - wthis = wp; + thisbuflen = b1; + tthis = NULL; repeats = 0; } else ++repeats; @@ -185,46 +188,54 @@ main (int argc, char *argv[]) exit(0); } -char * -getlinemax(char *buf, FILE *fp) +wchar_t * +convert(const char *str) { - size_t bufpos; - int ch; + size_t n; + wchar_t *buf, *ret, *p; + + if ((n = mbstowcs(NULL, str, 0)) == (size_t)-1) + return (NULL); + if ((buf = malloc((n + 1) * sizeof(*buf))) == NULL) + err(1, "malloc"); + if (mbstowcs(buf, str, n + 1) != n) + errx(1, "internal mbstowcs() error"); + /* The last line may not end with \n. */ + if (n > 0 && buf[n - 1] == L'\n') + buf[n - 1] = L'\0'; + + /* If requested get the chosen fields + character offsets. */ + if (numfields || numchars) { + if ((ret = wcsdup(skip(buf))) == NULL) + err(1, "wcsdup"); + free(buf); + } else + ret = buf; - bufpos = 0; - while ((ch = getc(fp)) != EOF && ch != '\n') { - buf[bufpos++] = ch; - if (bufpos >= LINE_MAX) - errx(1, "Maximum line length (%d) exceeded", - LINE_MAX); + if (iflag) { + for (p = ret; *p != L'\0'; p++) + *p = towlower(*p); } - buf[bufpos] = '\0'; - return (bufpos != 0 || ch == '\n' ? buf : NULL); + return (ret); } -wchar_t * -convert(wchar_t *buf, const char *str) +int +inlcmp(const char *s1, const char *s2) { - size_t n; - wchar_t *p, *ret; + int c1, c2; - if ((n = mbstowcs(buf, str, LINE_MAX)) == LINE_MAX) - errx(1, "Maximum line length (%d) exceeded", LINE_MAX); - else if (n != (size_t)-1) { - /* If requested get the chosen fields + character offsets. */ - if (numfields || numchars) - ret = skip(buf); - else - ret = buf; - if (iflag) { - for (p = ret; *p != L'\0'; p++) - *p = towlower(*p); - } - } else - ret = NULL; - - return (ret); + while (*s1 == *s2++) + if (*s1++ == '\0') + return (0); + c1 = (unsigned char)*s1; + c2 = (unsigned char)*(s2 - 1); + /* The last line may not end with \n. */ + if (c1 == '\n') + c1 = '\0'; + if (c2 == '\n') + c2 = '\0'; + return (c1 - c2); } /* @@ -237,9 +248,9 @@ show(FILE *ofp, const char *str) { if (cflag) - (void)fprintf(ofp, "%4d %s\n", repeats + 1, str); + (void)fprintf(ofp, "%4d %s", repeats + 1, str); if ((dflag && repeats) || (uflag && !repeats)) - (void)fprintf(ofp, "%s\n", str); + (void)fprintf(ofp, "%s", str); } wchar_t *