[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: library/2570: new libutil function: humanize_number(3)



On Thu, 25 Apr 2002 16:48:37 +0200 (CEST)
Tomas Svensson <tsn_(_at_)_gbdev_(_dot_)_net> wrote:

> >Number:         2570
> >Category:       library
> >Synopsis:       new libutil function: humanize_number(3)
> >Confidential:   no
> >Severity:       non-critical
> >Priority:       medium
> >Responsible:    bugs
> >State:          open
> >Class:          change-request
> >Submitter-Id:   net
> >Arrival-Date:   Thu Apr 25 06:50:01 MDT 2002
> >Last-Modified:
> >Originator:     Tomas Svensson
> >Organization:
> net
> >Release:        3.1-current
> >Environment:
> 	System      : OpenBSD 3.1
> 	Architecture: OpenBSD.i386
> 	Machine     : i386
> >Description:
> 	New humanize function for libutil to be used instead of
> 	prthuman() in df/du and can also be used for ls/pkg_add etc.
> 
> 	Direct improvement over prthuman would be that it it doesnt need
> 	libm        and it can guarantee that max 3 digits will be used
> 	(as prthuman() was originally intended to work:
> 	http://www.openbsd.org/cgi-bin/cvsweb/src/bin/df/df.1.diff?r1=1.8&r2=1.9&f=h
> 	since "1000K" should be replaced with "1M" even if its not
> 	"correct").
> 
> 	It can also be used to humanize numbers even more by using the
> 	same suffix for all numbers:


This seems very interesting. Me and a friend were working on a -h option
to ls as well. We coded up a semi working version. it's not yet
complete, current issues are that the total is incorrect when you
specify -h, and I suspect portability issues as well.

Here's the patch if you're interested in comparing (the patch isn't
really up to date, a new revision to ls has since been committed):


Index: cmp.c
===================================================================
RCS file: /cvs/src/bin/ls/cmp.c,v
retrieving revision 1.3
diff -u -r1.3 cmp.c
--- cmp.c	3 Jan 1997 22:36:07 -0000	1.3
+++ cmp.c	1 Mar 2002 09:46:56 -0000
@@ -54,23 +54,17 @@
 #include "ls.h"
 #include "extern.h"
 
-int
-namecmp(a, b)
-	const FTSENT *a, *b;
+int namecmp(const FTSENT *a, const FTSENT *b)
 {
 	return (strcmp(a->fts_name, b->fts_name));
 }
 
-int
-revnamecmp(a, b)
-	const FTSENT *a, *b;
+int revnamecmp(const FTSENT *a, const FTSENT *b)
 {
 	return (strcmp(b->fts_name, a->fts_name));
 }
 
-int
-modcmp(a, b)
-	const FTSENT *a, *b;
+int modcmp(const FTSENT *a, const FTSENT *b)
 {
 	if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
 		return (1);
@@ -84,9 +78,7 @@
 		return (namecmp(a, b));
 }
 
-int
-revmodcmp(a, b)
-	const FTSENT *a, *b;
+int revmodcmp(const FTSENT *a, const FTSENT *b)
 {
 	if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
 		return (-1);
@@ -100,9 +92,7 @@
 		return (revnamecmp(a, b));
 }
 
-int
-acccmp(a, b)
-	const FTSENT *a, *b;
+int acccmp(const FTSENT *a, const FTSENT *b)
 {
 	if (b->fts_statp->st_atime > a->fts_statp->st_atime)
 		return (1);
@@ -116,9 +106,7 @@
 		return (namecmp(a, b));
 }
 
-int
-revacccmp(a, b)
-	const FTSENT *a, *b;
+int revacccmp(const FTSENT *a, const FTSENT *b)
 {
 	if (b->fts_statp->st_atime > a->fts_statp->st_atime)
 		return (-1);
@@ -132,9 +120,7 @@
 		return (revnamecmp(a, b));
 }
 
-int
-statcmp(a, b)
-	const FTSENT *a, *b;
+int statcmp(const FTSENT *a, const FTSENT *b)
 {
 	if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
 		return (1);
@@ -148,9 +134,7 @@
 		return (namecmp(a, b));
 }
 
-int
-revstatcmp(a, b)
-	const FTSENT *a, *b;
+int revstatcmp(const FTSENT *a, const FTSENT *b)
 {
 	if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
 		return (-1);
@@ -164,9 +148,7 @@
 		return (revnamecmp(a, b));
 }
 
-int
-sizecmp(a, b)
-	const FTSENT *a, *b;
+int sizecmp(const FTSENT *a, const FTSENT *b)
 {
 	if (b->fts_statp->st_size > a->fts_statp->st_size)
 		return (1);
@@ -176,9 +158,7 @@
 		return (namecmp(a, b));
 }
 
-int
-revsizecmp(a, b)
-	const FTSENT *a, *b;
+int revsizecmp(const FTSENT *a, const FTSENT *b)
 {
 	if (b->fts_statp->st_size > a->fts_statp->st_size)
 		return (-1);
Index: ls.1
===================================================================
RCS file: /cvs/src/bin/ls/ls.1,v
retrieving revision 1.33
diff -u -r1.33 ls.1
--- ls.1	11 Feb 2002 18:43:51 -0000	1.33
+++ ls.1	1 Mar 2002 09:46:56 -0000
@@ -129,6 +129,8 @@
 .It Fl g
 Does nothing; kept for compatibility with older versions of
 .Xr ls 1 .
+.It Fl h
+Show filesize in human-readable format.
 .It Fl i
 For each file, print its inode number.
 .It Fl k
@@ -213,6 +215,13 @@
 The
 .Fl f
 option overrides any occurrence of either.
+.Pp
+The
+.Fl k
+and
+.Fl h
+options override each other; the last one specified determines
+the size option used.
 .Pp
 By default,
 .Nm
Index: ls.c
===================================================================
RCS file: /cvs/src/bin/ls/ls.c,v
retrieving revision 1.16
diff -u -r1.16 ls.c
--- ls.c	16 Feb 2002 21:27:07 -0000	1.16
+++ ls.c	1 Mar 2002 09:46:56 -0000
@@ -90,6 +90,7 @@
 int f_column;			/* columnated format */
 int f_columnacross;		/* columnated format, sorted across */
 int f_flags;			/* show flags associated with a file */
+int f_human;			/* list size in human readable form */
 int f_inode;			/* print inode */
 int f_listdir;			/* list actual directory, not contents */
 int f_listdot;			/* list files beginning with . */
@@ -112,15 +113,13 @@
 
 int rval;
 
-int
-ls_main(argc, argv)
-	int argc;
-	char *argv[];
+int ls_main(int argc, char *argv[])
 {
 	static char dot[] = ".", *dotav[] = { dot, NULL };
 	struct winsize win;
 	int ch, fts_options, notused;
 	int kflag = 0;
+	int hflag = 0;
 	char *p;
 
 	/* Terminal defaults to -Cq, non-terminal defaults to -1. */
@@ -139,7 +138,7 @@
 		f_listdot = 1;
 
 	fts_options = FTS_PHYSICAL;
-	while ((ch = getopt(argc, argv, "1ACFLRSTWacdfgiklmnopqrstux")) != -1)
{+	while ((ch = getopt(argc, argv, "1ACFLRSTWacdfghiklmnopqrstux")) !=
-1) { 		switch (ch) {
 		/*
 		 * The -1, -C and -l, -m and -x options all override each
@@ -207,12 +206,20 @@
 			break;
 		case 'g':		/* Compatibility with 4.3BSD. */
 			break;
+		case 'h':
+			blocksize = 512;
+			f_human = 1;
+			kflag = 0;
+			hflag = 1;
+			break;
 		case 'i':
 			f_inode = 1;
 			break;
 		case 'k':
 			blocksize = 1024;
+			f_human = 0;
 			kflag = 1;
+			hflag = 0;
 			break;
 		case 'o':
 			f_flags = 1;
@@ -273,7 +280,7 @@
 
 	/* If -l or -s, figure out block size. */
 	if (f_longform || f_size) {
-		if (!kflag)
+		if (!(kflag || hflag))
 			(void)getbsize(&notused, &blocksize);
 		blocksize /= 512;
 	}
@@ -342,10 +349,7 @@
  * traversal it passes linked lists of structures to display() which
represent  * a superset (may be exact set) of the files to be displayed.
  */
-static void
-traverse(argc, argv, options)
-	int argc, options;
-	char *argv[];
+static void traverse(int argc, char *argv[], int options)
 {
 	FTS *ftsp;
 	FTSENT *p, *chp;
@@ -408,9 +412,7 @@
  * along with any other necessary information to the print function.  P
  * points to the parent directory of the display list.
  */
-static void
-display(p, list)
-	FTSENT *p, *list;
+static void display(FTSENT *p, FTSENT *list)
 {
 	struct stat *sp;
 	DISPLAY d;
@@ -564,9 +566,7 @@
  * as larger than directories.  Within either group, use the sort
function.  * All other levels use the sort function.  Error entries
remain unsorted.  */
-static int
-mastercmp(a, b)
-	const FTSENT **a, **b;
+static int mastercmp(const FTSENT **a, const FTSENT **b)
 {
 	int a_info, b_info;
 
Index: ls.h
===================================================================
RCS file: /cvs/src/bin/ls/ls.h,v
retrieving revision 1.4
diff -u -r1.4 ls.h
--- ls.h	1 May 1999 23:54:47 -0000	1.4
+++ ls.h	1 Mar 2002 09:46:56 -0000
@@ -50,6 +50,7 @@
 extern int f_nonprint;		/* show unprintables as ? */
 extern int f_sectime;		/* print the real time for all files */
 extern int f_size;		/* list size in short listing */
+extern int f_human;		/* list size in human readable form */
 extern int f_statustime;	/* use time of last mode change */
 extern int f_type;		/* add type character for non-regular files */
 extern int f_typedir;		/* add type character for directories */
Index: main.c
===================================================================
RCS file: /cvs/src/bin/ls/main.c,v
retrieving revision 1.2
diff -u -r1.2 main.c
--- main.c	16 Feb 2002 21:27:07 -0000	1.2
+++ main.c	1 Mar 2002 09:46:56 -0000
@@ -8,10 +8,7 @@
 
 int ls_main(int argc, char **argv);
 
-int
-main(argc, argv)
-	int argc;
-	char **argv;
+int main(int argc, char **argv)
 {
 	return ls_main(argc, argv);
 }
Index: print.c
===================================================================
RCS file: /cvs/src/bin/ls/print.c,v
retrieving revision 1.16
diff -u -r1.16 print.c
--- print.c	16 Feb 2002 21:27:07 -0000	1.16
+++ print.c	1 Mar 2002 09:46:56 -0000
@@ -69,12 +69,11 @@
 static void	printtime(time_t);
 static int	printtype(u_int);
 static int	compute_columns(DISPLAY *, int *);
+static void	humanize (int, char*);
 
 #define	IS_NOPRINT(p)	((p)->fts_number == NO_PRINT)
 
-void
-printscol(dp)
-	DISPLAY *dp;
+void printscol(DISPLAY *dp)
 {
 	FTSENT *p;
 
@@ -86,14 +85,13 @@
 	}
 }
 
-void
-printlong(dp)
-	DISPLAY *dp;
+void printlong(DISPLAY *dp)
 {
 	struct stat *sp;
 	FTSENT *p;
 	NAMES *np;
 	char buf[20];
+	char *human;
 
 	if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform ||
f_size)) 		(void)printf("total %lu\n", howmany(dp->btotal,
blocksize));@@ -120,7 +118,10 @@
 		else if (dp->bcfile)
 			(void)printf("%*s%*qd ",
 			    8 - dp->s_size, "", dp->s_size, sp->st_size);
-		else
+		else if (f_human) {
+			(void)humanize(sp->st_size, human);
+			(void)printf("%*qs ", dp->s_size, human);
+		} else
 			(void)printf("%*qd ", dp->s_size, sp->st_size);
 		if (f_accesstime)
 			printtime(sp->st_atime);
@@ -137,10 +138,7 @@
 	}
 }
 
-static int
-compute_columns(dp, pnum)
-	DISPLAY *dp;
-	int	*pnum;
+static int compute_columns (DISPLAY *dp, int *pnum)
 {
 	int colwidth;
 	extern int termwidth;
@@ -166,9 +164,7 @@
 	return (mywidth / *pnum);		/* spread out if possible */
 }
 
-void
-printcol(dp)
-	DISPLAY *dp;
+void printcol(DISPLAY *dp)
 {
 	static FTSENT **array;
 	static int lastentries = -1;
@@ -222,10 +218,7 @@
  * print [inode] [size] name
  * return # of characters printed, no trailing characters.
  */
-static int
-printaname(p, inodefield, sizefield)
-	FTSENT *p;
-	u_long sizefield, inodefield;
+static int printaname(FTSENT *p, u_long sizefield, u_long inodefield)
 {
 	struct stat *sp;
 	int chcnt;
@@ -243,9 +236,7 @@
 	return (chcnt);
 }
 
-static void
-printtime(ftime)
-	time_t ftime;
+static void printtime(time_t ftime)
 {
 	int i;
 	char *longstring;
@@ -269,9 +260,7 @@
 	(void)putchar(' ');
 }
 
-void
-printacol(dp)
-	DISPLAY *dp;
+void printacol(DISPLAY *dp)
 {
 	FTSENT *p;
 	int chcnt, col, colwidth;
@@ -300,9 +289,7 @@
 	(void)putchar('\n');
 }
 
-void
-printstream(dp)
-	DISPLAY *dp;
+void printstream(DISPLAY *dp)
 {
 	extern int termwidth;
 	FTSENT *p;
@@ -332,9 +319,7 @@
 	(void)putchar('\n');
 }
 
-static int
-printtype(mode)
-	u_int mode;
+static int printtype(u_int mode)
 {
 	switch (mode & S_IFMT) {
 	case S_IFDIR:
@@ -360,9 +345,7 @@
 	return (0);
 }
 
-static void
-printlink(p)
-	FTSENT *p;
+static void printlink(FTSENT *p)
 {
 	int lnklen;
 	char name[MAXPATHLEN], path[MAXPATHLEN];
@@ -379,4 +362,49 @@
 	path[lnklen] = '\0';
 	(void)printf(" -> ");
 	(void)putname(path);
+}
+
+/*
+ * "human-readable" output: use 3 digits max.--put unit suffixes at
+ * the end.  Makes output compact and easy-to-read.
+ * copied from du(1) source
+ */
+
+typedef enum { NONE = 0, KILO, MEGA, GIGA, TERA, PETA /* , EXA */ }
unit_t;+
+unit_t unit_adjust(int *val)
+{
+	int abval = (int)*val;
+        unit_t unit;
+
+        if (abval < 1024)
+                unit = NONE;
+        else if (abval < 1048576ULL) {
+                unit = KILO;
+                *val /= 1024;
+        } else if (abval < 1073741824ULL) {
+                unit = MEGA;
+                *val /= 1048576;
+        } else if (abval < 1099511627776ULL) {
+                unit = GIGA;
+                *val /= 1073741824ULL;
+        } else if (abval < 1125899906842624ULL) {
+                unit = TERA;
+                *val /= 1099511627776ULL;
+        } else /* if (abval < 1152921504606846976ULL) */ {
+                unit = PETA;
+                *val /= 1125899906842624ULL;
+        }
+        return (unit);
+}
+
+static void humanize(int size, char *result)
+{
+	int bytes;
+	unit_t unit;
+
+	bytes = size;
+	unit = unit_adjust(&bytes);
+
+	(void)sprintf(result, "%d%c", bytes, "BKMGTPE"[unit]);
 }
Index: util.c
===================================================================
RCS file: /cvs/src/bin/ls/util.c,v
retrieving revision 1.7
diff -u -r1.7 util.c
--- util.c	6 Sep 2001 13:29:08 -0000	1.7
+++ util.c	1 Mar 2002 09:46:56 -0000
@@ -57,9 +57,7 @@
 #include "ls.h"
 #include "extern.h"
 
-int
-putname(name)
-	char *name;
+int putname(char *name)
 {
 	int len;
 
@@ -68,8 +66,7 @@
 	return len;
 }
 
-void
-usage()
+void usage()
 {
 	(void)fprintf(stderr,
 	    "usage: %s [-1ACFLRSTWacdfiklmnopqrstux] [file ...]\n",


// nick


Visit your host, monkey.org