From owner-svn-src-head@FreeBSD.ORG Wed Jun 10 01:27:40 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id A8C63F47; Wed, 10 Jun 2015 01:27:40 +0000 (UTC) (envelope-from marcel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9652E1227; Wed, 10 Jun 2015 01:27:40 +0000 (UTC) (envelope-from marcel@FreeBSD.org) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t5A1RehG051972; Wed, 10 Jun 2015 01:27:40 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t5A1RdX6051959; Wed, 10 Jun 2015 01:27:39 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201506100127.t5A1RdX6051959@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar Date: Wed, 10 Jun 2015 01:27:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r284198 - head/bin/ls X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 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: Wed, 10 Jun 2015 01:27:40 -0000 Author: marcel Date: Wed Jun 10 01:27:38 2015 New Revision: 284198 URL: https://svnweb.freebsd.org/changeset/base/284198 Log: Convert ls(1) to use libxo(3). Obtained from: Phil Shafer Sponsored by: Juniper Networks, Inc. Modified: head/bin/ls/Makefile head/bin/ls/extern.h head/bin/ls/ls.1 head/bin/ls/ls.c head/bin/ls/print.c head/bin/ls/util.c Modified: head/bin/ls/Makefile ============================================================================== --- head/bin/ls/Makefile Wed Jun 10 01:17:14 2015 (r284197) +++ head/bin/ls/Makefile Wed Jun 10 01:27:38 2015 (r284198) @@ -10,7 +10,7 @@ LIBADD= util .if !defined(RELEASE_CRUNCH) && \ ${MK_LS_COLORS} != no CFLAGS+= -DCOLORLS -LIBADD+= termcapw +LIBADD+= termcapw xo .endif .include Modified: head/bin/ls/extern.h ============================================================================== --- head/bin/ls/extern.h Wed Jun 10 01:17:14 2015 (r284197) +++ head/bin/ls/extern.h Wed Jun 10 01:27:38 2015 (r284198) @@ -45,14 +45,17 @@ int revsizecmp(const FTSENT *, const FT void printcol(const DISPLAY *); void printlong(const DISPLAY *); -int printname(const char *); +int printname(const char *, const char *); void printscol(const DISPLAY *); void printstream(const DISPLAY *); void usage(void); -int prn_normal(const char *); +int prn_normal(const char *, const char *); +char * getname(const char *); size_t len_octal(const char *, int); -int prn_octal(const char *); -int prn_printable(const char *); +int prn_octal(const char *, const char *); +char * get_octal(const char *); +int prn_printable(const char *, const char *); +char * get_printable(const char *); #ifdef COLORLS void parsecolors(const char *cs); void colorquit(int); Modified: head/bin/ls/ls.1 ============================================================================== --- head/bin/ls/ls.1 Wed Jun 10 01:17:14 2015 (r284197) +++ head/bin/ls/ls.1 Wed Jun 10 01:27:38 2015 (r284198) @@ -32,7 +32,7 @@ .\" @(#)ls.1 8.7 (Berkeley) 7/29/94 .\" $FreeBSD$ .\" -.Dd April 4, 2014 +.Dd June 8, 2015 .Dt LS 1 .Os .Sh NAME @@ -40,6 +40,7 @@ .Nd list directory contents .Sh SYNOPSIS .Nm +.Op Fl -libxo .Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1, .Op Fl D Ar format .Op Ar @@ -797,9 +798,11 @@ specification. .Xr getfacl 1 , .Xr sort 1 , .Xr xterm 1 , +.Xr libxo 3 , .Xr localeconv 3 , .Xr strftime 3 , .Xr strmode 3 , +.Xr xo_parse_args 3 , .Xr termcap 5 , .Xr maclabel 7 , .Xr sticky 7 , Modified: head/bin/ls/ls.c ============================================================================== --- head/bin/ls/ls.c Wed Jun 10 01:17:14 2015 (r284197) +++ head/bin/ls/ls.c Wed Jun 10 01:27:38 2015 (r284198) @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$"); #include #include #endif +#include #include "ls.h" #include "extern.h" @@ -185,6 +186,12 @@ main(int argc, char *argv[]) fts_options = FTS_PHYSICAL; if (getenv("LS_SAMESORT")) f_samesort = 1; + + argc = xo_parse_args(argc, argv); + if (argc < 0) + return (1); + xo_set_flags(NULL, XOF_COLUMNS); + while ((ch = getopt(argc, argv, "1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,")) != -1) { switch (ch) { @@ -381,7 +388,7 @@ main(int argc, char *argv[]) f_color = 1; } #else - warnx("color support not compiled in"); + xo_warnx("color support not compiled in"); #endif /*COLORLS*/ #ifdef COLORLS @@ -479,10 +486,13 @@ main(int argc, char *argv[]) else printfcn = printcol; + xo_open_container("file-information"); if (argc) traverse(argc, argv, fts_options); else traverse(1, dotav, fts_options); + xo_close_container("file-information"); + xo_finish(); exit(rval); } @@ -500,10 +510,11 @@ traverse(int argc, char *argv[], int opt FTS *ftsp; FTSENT *p, *chp; int ch_options; + int first = 1; if ((ftsp = fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL) - err(1, "fts_open"); + xo_err(1, "fts_open"); /* * We ignore errors from fts_children here since they will be @@ -525,11 +536,11 @@ traverse(int argc, char *argv[], int opt while ((p = fts_read(ftsp)) != NULL) switch (p->fts_info) { case FTS_DC: - warnx("%s: directory causes a cycle", p->fts_name); + xo_warnx("%s: directory causes a cycle", p->fts_name); break; case FTS_DNR: case FTS_ERR: - warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); + xo_warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; break; case FTS_D: @@ -537,31 +548,40 @@ traverse(int argc, char *argv[], int opt p->fts_name[0] == '.' && !f_listdot) break; + if (first) { + first = 0; + xo_open_list("directory"); + } + xo_open_instance("directory"); + /* * If already output something, put out a newline as * a separator. If multiple arguments, precede each * directory with its name. */ if (output) { - putchar('\n'); - (void)printname(p->fts_path); - puts(":"); + xo_emit("\n"); + (void)printname("path", p->fts_path); + xo_emit(":\n"); } else if (argc > 1) { - (void)printname(p->fts_path); - puts(":"); + (void)printname("path", p->fts_path); + xo_emit(":\n"); output = 1; } chp = fts_children(ftsp, ch_options); display(p, chp, options); + xo_close_instance("directory"); if (!f_recursive && chp != NULL) (void)fts_set(ftsp, p, FTS_SKIP); break; default: break; } + if (!first) + xo_close_list("directory"); if (errno) - err(1, "fts_read"); + xo_err(1, "fts_read"); } /* @@ -608,7 +628,7 @@ display(const FTSENT *p, FTSENT *list, i /* Fill-in "::" as "0:0:0" for the sake of scanf. */ jinitmax = malloc(strlen(initmax) * 2 + 2); if (jinitmax == NULL) - err(1, "malloc"); + xo_err(1, "malloc"); initmax2 = jinitmax; if (*initmax == ':') strcpy(initmax2, "0:"), initmax2 += 2; @@ -679,7 +699,7 @@ display(const FTSENT *p, FTSENT *list, i flags = NULL; for (cur = list, entries = 0; cur; cur = cur->fts_link) { if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) { - warnx("%s: %s", + xo_warnx("%s: %s", cur->fts_name, strerror(cur->fts_errno)); cur->fts_number = NO_PRINT; rval = 1; @@ -745,7 +765,7 @@ display(const FTSENT *p, FTSENT *list, i flags = strdup("-"); } if (flags == NULL) - err(1, "fflagstostr"); + xo_err(1, "fflagstostr"); flen = strlen(flags); if (flen > (size_t)maxflags) maxflags = flen; @@ -759,7 +779,7 @@ display(const FTSENT *p, FTSENT *list, i error = mac_prepare_file_label(&label); if (error == -1) { - warn("MAC label for %s/%s", + xo_warn("MAC label for %s/%s", cur->fts_parent->fts_path, cur->fts_name); goto label_out; @@ -780,7 +800,7 @@ display(const FTSENT *p, FTSENT *list, i error = mac_get_link(name, label); if (error == -1) { - warn("MAC label for %s/%s", + xo_warn("MAC label for %s/%s", cur->fts_parent->fts_path, cur->fts_name); mac_free(label); @@ -790,7 +810,7 @@ display(const FTSENT *p, FTSENT *list, i error = mac_to_text(label, &labelstr); if (error == -1) { - warn("MAC label for %s/%s", + xo_warn("MAC label for %s/%s", cur->fts_parent->fts_path, cur->fts_name); mac_free(label); @@ -808,7 +828,7 @@ label_out: if ((np = malloc(sizeof(NAMES) + labelstrlen + ulen + glen + flen + 4)) == NULL) - err(1, "malloc"); + xo_err(1, "malloc"); np->user = &np->data[0]; (void)strcpy(np->user, user); Modified: head/bin/ls/print.c ============================================================================== --- head/bin/ls/print.c Wed Jun 10 01:17:14 2015 (r284197) +++ head/bin/ls/print.c Wed Jun 10 01:27:38 2015 (r284198) @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); #include #include #endif +#include #include "ls.h" #include "extern.h" @@ -65,9 +66,9 @@ __FBSDID("$FreeBSD$"); static int printaname(const FTSENT *, u_long, u_long); static void printdev(size_t, dev_t); static void printlink(const FTSENT *); -static void printtime(time_t); +static void printtime(const char *, time_t); static int printtype(u_int); -static void printsize(size_t, off_t); +static void printsize(const char *, size_t, off_t); #ifdef COLORLS static void endcolor(int); static int colortype(mode_t); @@ -109,26 +110,46 @@ printscol(const DISPLAY *dp) { FTSENT *p; + xo_open_list("entry"); for (p = dp->list; p; p = p->fts_link) { if (IS_NOPRINT(p)) continue; + xo_open_instance("entry"); (void)printaname(p, dp->s_inode, dp->s_block); - (void)putchar('\n'); + xo_close_instance("entry"); + xo_emit("\n"); } + xo_close_list("entry"); } /* * print name in current style */ int -printname(const char *name) +printname(const char *field, const char *name) +{ + char fmt[BUFSIZ]; + char *s = getname(name); + int rc; + + snprintf(fmt, sizeof(fmt), "{:%s/%%hs}", field); + rc = xo_emit(fmt, s); + free(s); + return rc; +} + +/* + * print name in current style + */ +char * +getname(const char *name) { if (f_octal || f_octal_escape) - return prn_octal(name); + return get_octal(name); else if (f_nonprint) - return prn_printable(name); + return get_printable(name); else - return prn_normal(name); + return strdup(name); } void @@ -144,46 +165,59 @@ printlong(const DISPLAY *dp) if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && (f_longform || f_size)) { - (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); + xo_emit("{L:total} {:total-blocks/%lu}\n", + howmany(dp->btotal, blocksize)); } + xo_open_list("entry"); for (p = dp->list; p; p = p->fts_link) { + char *name; if (IS_NOPRINT(p)) continue; + xo_open_instance("entry"); sp = p->fts_statp; + name = getname(p->fts_name); + if (name) + xo_emit("{ke:name}", name); if (f_inode) - (void)printf("%*ju ", + xo_emit("{:inode/%*ju} ", dp->s_inode, (uintmax_t)sp->st_ino); if (f_size) - (void)printf("%*jd ", + xo_emit("{:blocks/%*jd} ", dp->s_block, howmany(sp->st_blocks, blocksize)); strmode(sp->st_mode, buf); aclmode(buf, p); np = p->fts_pointer; - (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, - sp->st_nlink, dp->s_user, np->user, dp->s_group, - np->group); + xo_attr("value", "%03o", (int) sp->st_mode & ALLPERMS); + xo_emit("{t:mode/%s} {:links/%*u} {:user/%-*s} {:group/%-*s} ", + buf, dp->s_nlink, sp->st_nlink, + dp->s_user, np->user, dp->s_group, np->group); if (f_flags) - (void)printf("%-*s ", dp->s_flags, np->flags); + xo_emit("{:flags/%-*s} ", dp->s_flags, np->flags); if (f_label) - (void)printf("%-*s ", dp->s_label, np->label); + xo_emit("{:label/%-*s} ", dp->s_label, np->label); if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) printdev(dp->s_size, sp->st_rdev); else - printsize(dp->s_size, sp->st_size); + printsize("size", dp->s_size, sp->st_size); if (f_accesstime) - printtime(sp->st_atime); + printtime("access-time", sp->st_atime); else if (f_birthtime) - printtime(sp->st_birthtime); + printtime("birth-time", sp->st_birthtime); else if (f_statustime) - printtime(sp->st_ctime); + printtime("change-time", sp->st_ctime); else - printtime(sp->st_mtime); + printtime("modify-time", sp->st_mtime); #ifdef COLORLS if (f_color) color_printed = colortype(sp->st_mode); #endif - (void)printname(p->fts_name); + + if (name) { + xo_emit("{dk:name}", name); + free(name); + } + #ifdef COLORLS if (f_color && color_printed) endcolor(0); @@ -192,8 +226,10 @@ printlong(const DISPLAY *dp) (void)printtype(sp->st_mode); if (S_ISLNK(sp->st_mode)) printlink(p); - (void)putchar('\n'); + xo_close_instance("entry"); + xo_emit("\n"); } + xo_close_list("entry"); } void @@ -208,17 +244,17 @@ printstream(const DISPLAY *dp) /* XXX strlen does not take octal escapes into account. */ if (strlen(p->fts_name) + chcnt + (p->fts_link ? 2 : 0) >= (unsigned)termwidth) { - putchar('\n'); + xo_emit("\n"); chcnt = 0; } chcnt += printaname(p, dp->s_inode, dp->s_block); if (p->fts_link) { - printf(", "); + xo_emit(", "); chcnt += 2; } } if (chcnt) - putchar('\n'); + xo_emit("\n"); } void @@ -252,7 +288,7 @@ printcol(const DISPLAY *dp) if (dp->entries > lastentries) { if ((narray = realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { - warn(NULL); + xo_warn(NULL); printscol(dp); return; } @@ -283,17 +319,21 @@ printcol(const DISPLAY *dp) if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && (f_longform || f_size)) { - (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); + xo_emit("{L:total} {:total-blocks/%lu}\n", + howmany(dp->btotal, blocksize)); } + xo_open_list("entry"); base = 0; for (row = 0; row < numrows; ++row) { endcol = colwidth; if (!f_sortacross) base = row; for (col = 0, chcnt = 0; col < numcols; ++col) { + xo_open_instance("entry"); chcnt += printaname(array[base], dp->s_inode, dp->s_block); + xo_close_instance("entry"); if (f_sortacross) base++; else @@ -304,13 +344,14 @@ printcol(const DISPLAY *dp) <= endcol) { if (f_sortacross && col + 1 >= numcols) break; - (void)putchar(f_notabs ? ' ' : '\t'); + xo_emit(f_notabs ? " " : "\t"); chcnt = cnt; } endcol += colwidth; } - (void)putchar('\n'); + xo_emit("\n"); } + xo_close_list("entry"); } /* @@ -329,16 +370,16 @@ printaname(const FTSENT *p, u_long inode sp = p->fts_statp; chcnt = 0; if (f_inode) - chcnt += printf("%*ju ", + chcnt += xo_emit("{:inode/%*ju} ", (int)inodefield, (uintmax_t)sp->st_ino); if (f_size) - chcnt += printf("%*jd ", + chcnt += xo_emit("{:size/%*jd} ", (int)sizefield, howmany(sp->st_blocks, blocksize)); #ifdef COLORLS if (f_color) color_printed = colortype(sp->st_mode); #endif - chcnt += printname(p->fts_name); + chcnt += printname("name", p->fts_name); #ifdef COLORLS if (f_color && color_printed) endcolor(0); @@ -354,14 +395,14 @@ printaname(const FTSENT *p, u_long inode static void printdev(size_t width, dev_t dev) { - - (void)printf("%#*jx ", (u_int)width, (uintmax_t)dev); + xo_emit("{:device/%#*jx} ", (u_int)width, (uintmax_t)dev); } static void -printtime(time_t ftime) +printtime(const char *field, time_t ftime) { char longstring[80]; + char fmt[BUFSIZ]; static time_t now = 0; const char *format; static int d_first = -1; @@ -384,8 +425,10 @@ printtime(time_t ftime) /* mmm dd yyyy || dd mmm yyyy */ format = d_first ? "%e %b %Y" : "%b %e %Y"; strftime(longstring, sizeof(longstring), format, localtime(&ftime)); - fputs(longstring, stdout); - fputc(' ', stdout); + + snprintf(fmt, sizeof(fmt), "{:%s/%%s} ", field); + xo_attr("value", "%ld", (long) ftime); + xo_emit(fmt, longstring); } static int @@ -394,7 +437,7 @@ printtype(u_int mode) if (f_slash) { if ((mode & S_IFMT) == S_IFDIR) { - (void)putchar('/'); + xo_emit("{D:\\/}{e:type/directory}"); return (1); } return (0); @@ -402,25 +445,25 @@ printtype(u_int mode) switch (mode & S_IFMT) { case S_IFDIR: - (void)putchar('/'); + xo_emit("{D:/\\/}{e:type/directory}"); return (1); case S_IFIFO: - (void)putchar('|'); + xo_emit("{D:|}{e:type/fifo}"); return (1); case S_IFLNK: - (void)putchar('@'); + xo_emit("{D:@}{e:type/link}"); return (1); case S_IFSOCK: - (void)putchar('='); + xo_emit("{D:=}{e:type/socket}"); return (1); case S_IFWHT: - (void)putchar('%'); + xo_emit("{D:%}{e:type/whiteout}"); return (1); default: break; } if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { - (void)putchar('*'); + xo_emit("{D:*}{e:executable/}"); return (1); } return (0); @@ -430,7 +473,7 @@ printtype(u_int mode) static int putch(int c) { - (void)putchar(c); + xo_emit("{D:/%c}", c); return 0; } @@ -539,7 +582,7 @@ parsecolors(const char *cs) if (c[j] >= '0' && c[j] <= '7') { colors[i].num[j] = c[j] - '0'; if (!legacy_warn) { - warnx("LSCOLORS should use " + xo_warnx("LSCOLORS should use " "characters a-h instead of 0-9 (" "see the manual page)"); } @@ -552,7 +595,7 @@ parsecolors(const char *cs) } else if (tolower((unsigned char)c[j]) == 'x') colors[i].num[j] = -1; else { - warnx("invalid character '%c' in LSCOLORS" + xo_warnx("invalid character '%c' in LSCOLORS" " env var", c[j]); colors[i].num[j] = -1; } @@ -584,18 +627,19 @@ printlink(const FTSENT *p) (void)snprintf(name, sizeof(name), "%s/%s", p->fts_parent->fts_accpath, p->fts_name); if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { - (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); + xo_error("\nls: %s: %s\n", name, strerror(errno)); return; } path[lnklen] = '\0'; - (void)printf(" -> "); - (void)printname(path); + xo_emit(" -> "); + (void)printname("target", path); } static void -printsize(size_t width, off_t bytes) +printsize(const char *field, size_t width, off_t bytes) { - + char fmt[BUFSIZ]; + if (f_humanval) { /* * Reserve one space before the size and allocate room for @@ -605,13 +649,15 @@ printsize(size_t width, off_t bytes) humanize_number(buf, sizeof(buf), (int64_t)bytes, "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); - (void)printf("%*s ", (u_int)width, buf); - } else if (f_thousands) { /* with commas */ + snprintf(fmt, sizeof(fmt), "{:%s/%%%ds} ", field, (int) width); + xo_attr("value", "%jd", (intmax_t) bytes); + xo_emit(fmt, buf); + } else { /* with commas */ /* This format assignment needed to work round gcc bug. */ - const char *format = "%*j'd "; - (void)printf(format, (u_int)width, bytes); - } else - (void)printf("%*jd ", (u_int)width, bytes); + snprintf(fmt, sizeof(fmt), "{:%s/%%%dj%sd} ", + field, (int) width, f_thousands ? "'" : ""); + xo_emit(fmt, (intmax_t) bytes); + } } /* @@ -654,7 +700,7 @@ aclmode(char *buf, const FTSENT *p) type = ACL_TYPE_NFS4; supports_acls = 1; } else if (ret < 0 && errno != EINVAL) { - warn("%s", name); + xo_warn("%s", name); return; } if (supports_acls == 0) { @@ -663,7 +709,7 @@ aclmode(char *buf, const FTSENT *p) type = ACL_TYPE_ACCESS; supports_acls = 1; } else if (ret < 0 && errno != EINVAL) { - warn("%s", name); + xo_warn("%s", name); return; } } @@ -672,12 +718,12 @@ aclmode(char *buf, const FTSENT *p) return; facl = acl_get_link_np(name, type); if (facl == NULL) { - warn("%s", name); + xo_warn("%s", name); return; } if (acl_is_trivial_np(facl, &trivial)) { acl_free(facl); - warn("%s", name); + xo_warn("%s", name); return; } if (!trivial) Modified: head/bin/ls/util.c ============================================================================== --- head/bin/ls/util.c Wed Jun 10 01:17:14 2015 (r284197) +++ head/bin/ls/util.c Wed Jun 10 01:27:38 2015 (r284198) @@ -50,13 +50,19 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include "ls.h" #include "extern.h" int -prn_normal(const char *s) +prn_normal(const char *field, const char *s) { + char fmt[_POSIX2_LINE_MAX]; + + snprintf(fmt, sizeof(fmt), "{:%s/%%hs}", field); + return xo_emit(fmt, s); +#if 0 mbstate_t mbs; wchar_t wc; int i, n; @@ -83,43 +89,47 @@ prn_normal(const char *s) n += wcwidth(wc); } return (n); +#endif } -int -prn_printable(const char *s) +char * +get_printable(const char *s) { mbstate_t mbs; wchar_t wc; int i, n; size_t clen; + int slen = strlen(s); + char *buf = alloca(slen + 1), *bp = buf; memset(&mbs, 0, sizeof(mbs)); n = 0; while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { if (clen == (size_t)-1) { - putchar('?'); + *bp++ = '?'; s++; n++; memset(&mbs, 0, sizeof(mbs)); continue; } if (clen == (size_t)-2) { - putchar('?'); + *bp++ = '?'; n++; break; } if (!iswprint(wc)) { - putchar('?'); + *bp++ = '?'; s += clen; n++; continue; } for (i = 0; i < (int)clen; i++) - putchar((unsigned char)s[i]); + *bp++ = (unsigned char)s[i]; s += clen; n += wcwidth(wc); } - return (n); + *bp = '\0'; + return strdup(buf); } /* @@ -165,8 +175,8 @@ len_octal(const char *s, int len) return (r); } -int -prn_octal(const char *s) +char * +get_octal(const char *s) { static const char esc[] = "\\\\\"\"\aa\bb\ff\nn\rr\tt\vv"; const char *p; @@ -175,6 +185,8 @@ prn_octal(const char *s) size_t clen; unsigned char ch; int goodchar, i, len, prtlen; + int slen = strlen(s); + char *buf = alloca(slen * 4 + 1), *bp = buf; memset(&mbs, 0, sizeof(mbs)); len = 0; @@ -182,7 +194,7 @@ prn_octal(const char *s) goodchar = clen != (size_t)-1 && clen != (size_t)-2; if (goodchar && iswprint(wc) && wc != L'\"' && wc != L'\\') { for (i = 0; i < (int)clen; i++) - putchar((unsigned char)s[i]); + *bp++ = (unsigned char)s[i]; len += wcwidth(wc); } else if (goodchar && f_octal_escape && #if WCHAR_MIN < 0 @@ -190,8 +202,8 @@ prn_octal(const char *s) #endif wc <= (wchar_t)UCHAR_MAX && (p = strchr(esc, (char)wc)) != NULL) { - putchar('\\'); - putchar(p[1]); + *bp ++ = '\\'; + *bp++ = p[1]; len += 2; } else { if (goodchar) @@ -202,10 +214,10 @@ prn_octal(const char *s) prtlen = strlen(s); for (i = 0; i < prtlen; i++) { ch = (unsigned char)s[i]; - putchar('\\'); - putchar('0' + (ch >> 6)); - putchar('0' + ((ch >> 3) & 7)); - putchar('0' + (ch & 7)); + *bp++ = '\\'; + *bp++ = '0' + (ch >> 6); + *bp++ = '0' + ((ch >> 3) & 7); + *bp++ = '0' + (ch & 7); len += 4; } } @@ -217,13 +229,15 @@ prn_octal(const char *s) } else s += clen; } - return (len); + + *bp = '\0'; + return strdup(buf); } void usage(void) { - (void)fprintf(stderr, + xo_error( #ifdef COLORLS "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]" #else