Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Jun 2015 01:27:39 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r284198 - head/bin/ls
Message-ID:  <201506100127.t5A1RdX6051959@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <phil@juniper.net>
  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 <bsd.prog.mk>

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 <termcap.h>
 #include <signal.h>
 #endif
+#include <libxo/xo.h>
 
 #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 <termcap.h>
 #include <signal.h>
 #endif
+#include <libxo/xo.h>
 
 #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 <string.h>
 #include <wchar.h>
 #include <wctype.h>
+#include <libxo/xo.h>
 
 #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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506100127.t5A1RdX6051959>