summaryrefslogtreecommitdiffstats
path: root/usr.bin/units
diff options
context:
space:
mode:
authorsjg <sjg@FreeBSD.org>2014-08-19 06:50:54 +0000
committersjg <sjg@FreeBSD.org>2014-08-19 06:50:54 +0000
commitd7cd1d425cc1ea9451fa235e3af9b6625c3e0de2 (patch)
treeb04f4bd7cd887f50e7d98af35f46b9834ff86c80 /usr.bin/units
parent3c8e37b1d04827f33c0c9a7594bd1b1ef7cdb3d3 (diff)
parent4fbde208c6460d576f64d6dc3cdc6cab085a4283 (diff)
downloadFreeBSD-src-d7cd1d425cc1ea9451fa235e3af9b6625c3e0de2.zip
FreeBSD-src-d7cd1d425cc1ea9451fa235e3af9b6625c3e0de2.tar.gz
Merge head from 7/28
Diffstat (limited to 'usr.bin/units')
-rw-r--r--usr.bin/units/Makefile10
-rw-r--r--usr.bin/units/Makefile.depend2
-rw-r--r--usr.bin/units/tests/Makefile9
-rw-r--r--usr.bin/units/tests/basics_test.sh22
-rw-r--r--usr.bin/units/units.132
-rw-r--r--usr.bin/units/units.c147
-rw-r--r--usr.bin/units/units.lib62
7 files changed, 191 insertions, 93 deletions
diff --git a/usr.bin/units/Makefile b/usr.bin/units/Makefile
index ebd1e07..3757c85 100644
--- a/usr.bin/units/Makefile
+++ b/usr.bin/units/Makefile
@@ -1,10 +1,16 @@
# $FreeBSD$
+.include <src.opts.mk>
+
PROG= units
FILES= units.lib
FILESDIR= ${SHAREDIR}/misc
-LDADD+=-ledit -ltermcap
-DPADD+=${LIBEDIT} ${LIBTERMCAP}
+LDADD+=-ledit -ltermcapw
+DPADD+=${LIBEDIT} ${LIBTERMCAPW}
+
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
.include <bsd.prog.mk>
diff --git a/usr.bin/units/Makefile.depend b/usr.bin/units/Makefile.depend
index 6fc94a4..1ba7586 100644
--- a/usr.bin/units/Makefile.depend
+++ b/usr.bin/units/Makefile.depend
@@ -11,7 +11,7 @@ DIRDEPS = \
lib/libc \
lib/libcompiler_rt \
lib/libedit \
- lib/ncurses/ncurses \
+ lib/ncurses/ncursesw \
.include <dirdeps.mk>
diff --git a/usr.bin/units/tests/Makefile b/usr.bin/units/tests/Makefile
new file mode 100644
index 0000000..0694eff
--- /dev/null
+++ b/usr.bin/units/tests/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/usr.bin/units
+
+TAP_TESTS_SH= basics_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/units/tests/basics_test.sh b/usr.bin/units/tests/basics_test.sh
new file mode 100644
index 0000000..adc28e0
--- /dev/null
+++ b/usr.bin/units/tests/basics_test.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+# $FreeBSD$
+
+base=`basename $0`
+
+echo "1..3"
+
+assert_equals() {
+ testnum="$1"
+ expected="$2"
+ fn="$3"
+ if [ "$expected" = "$($fn)" ]
+ then
+ echo "ok $testnum - $fn"
+ else
+ echo "not ok $testnum - $fn"
+ fi
+}
+
+assert_equals 1 1 "units -t ft ft"
+assert_equals 2 12 "units -t ft in"
+assert_equals 3 0.083333333 "units -t in ft"
diff --git a/usr.bin/units/units.1 b/usr.bin/units/units.1
index 83f2d9e..751d9ce 100644
--- a/usr.bin/units/units.1
+++ b/usr.bin/units/units.1
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.Dd April 14, 2014
+.Dd July 4, 2014
.Dt UNITS 1
.Os
.Sh NAME
@@ -13,17 +13,31 @@
.Sh OPTIONS
The following options are available:
.Bl -tag -width indent
-.It Fl f Ar filename
+.It Fl h No , Fl -help
+Show an overview of options
+.It Fl f Ar filename No , Fl -file Ar filename
Specify the name of the units data file to load.
-.It Fl q
+.It Fl e , Fl -exponential
+Behave as if -o '%6e' was typed.
+.It Fl q No , Fl -quiet
Suppress prompting of the user for units and the display of statistics
about the number of units loaded.
-.It Fl U
-If the default unit file exists prints its location. If not, print
+.It Fl U No , Fl -unitsfile
+If the default unit file exists prints its location.
+If not, print
.Qo
Units data file not found
.Qc
-.It Fl V
+.It Fl t No , Fl -terse
+Only print the result. This is used when calling
+.Nm
+from other programs for easy to parse results.
+.It Fl v No , Fl -verbose
+Print the units in the conversion output.
+Be more verbose in general.
+.It Fl o Ar format No , Fl -output-format Ar format
+Select the output format string by which numbers are printed.
+.It Fl V No , Fl -version
Print the version number, usage, and then exit.
.It Ar from-unit to-unit
Allow a single unit conversion to be done directly from the command
@@ -31,8 +45,6 @@ line.
The program will not print prompts.
It will print out the
result of the single specified conversion.
-.It Fl v
-Print the units in the conversion output. Be more verbose in general.
.El
.Sh DESCRIPTION
The
@@ -141,7 +153,7 @@ The
program will not detect infinite loops that could be caused
by careless unit definitions.
Comments in the unit definition file
-begin with a '/' character at the beginning of a line.
+begin with a '#' or '/' character at the beginning of a line.
.Pp
Prefixes are defined in the same was as standard units, but with
a trailing dash at the end of the prefix name.
@@ -170,7 +182,7 @@ units.
the standard units library
.El
.Sh AUTHORS
-.An Adrian Mariano Aq adrian@cam.cornell.edu
+.An Adrian Mariano Aq Mt adrian@cam.cornell.edu
.Sh BUGS
The effect of including a '/' in a prefix is surprising.
.Pp
diff --git a/usr.bin/units/units.c b/usr.bin/units/units.c
index 70bd9ec..3d39d0e 100644
--- a/usr.bin/units/units.c
+++ b/usr.bin/units/units.c
@@ -24,6 +24,7 @@ static const char rcsid[] =
#include <err.h>
#include <errno.h>
#include <histedit.h>
+#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -68,19 +69,16 @@ static struct {
static char NULLUNIT[] = "";
-#ifdef MSDOS
-#define SEPARATOR ";"
-#else
#define SEPARATOR ":"
-#endif
static int unitcount;
static int prefixcount;
static bool verbose = false;
+static bool terse = false;
+static const char * outputformat;
static const char * havestr;
static const char * wantstr;
-
static int addsubunit(char *product[], char *toadd);
static int addunit(struct unittype *theunit, const char *toadd, int flip, int quantity);
static void cancelunit(struct unittype * theunit);
@@ -106,20 +104,19 @@ static const char * prompt(EditLine *e __unused) {
return promptstr;
}
-char *
+static char *
dupstr(const char *str)
{
char *ret;
- ret = malloc(strlen(str) + 1);
+ ret = strdup(str);
if (!ret)
- errx(3, "memory allocation error");
- strcpy(ret, str);
+ err(3, "dupstr");
return (ret);
}
-void
+static void
readunits(const char *userfile)
{
FILE *unitfile;
@@ -166,7 +163,7 @@ readunits(const char *userfile)
break;
linenum++;
lineptr = line;
- if (*lineptr == '/')
+ if (*lineptr == '/' || *lineptr == '#')
continue;
lineptr += strspn(lineptr, " \n\t");
len = strcspn(lineptr, " \n\t");
@@ -224,7 +221,7 @@ readunits(const char *userfile)
fclose(unitfile);
}
-void
+static void
initializeunit(struct unittype * theunit)
{
theunit->numerator[0] = theunit->denominator[0] = NULL;
@@ -234,7 +231,7 @@ initializeunit(struct unittype * theunit)
}
-int
+static int
addsubunit(char *product[], char *toadd)
{
char **ptr;
@@ -251,7 +248,7 @@ addsubunit(char *product[], char *toadd)
}
-void
+static void
showunit(struct unittype * theunit)
{
char **ptr;
@@ -293,7 +290,7 @@ showunit(struct unittype * theunit)
counter = 1;
}
}
- if ( counter > 1)
+ if (counter > 1)
printf("%s%d", powerstring, counter);
printf("\n");
}
@@ -313,7 +310,7 @@ zeroerror(void)
Returns 0 for successful addition, nonzero on error.
*/
-int
+static int
addunit(struct unittype * theunit, const char *toadd, int flip, int quantity)
{
char *scratch, *savescr;
@@ -421,14 +418,14 @@ addunit(struct unittype * theunit, const char *toadd, int flip, int quantity)
}
-int
+static int
compare(const void *item1, const void *item2)
{
return strcmp(*(const char * const *)item1, *(const char * const *)item2);
}
-void
+static void
sortunit(struct unittype * theunit)
{
char **ptr;
@@ -549,7 +546,7 @@ lookupunit(const char *unit)
#define ERROR 4
-int
+static int
reduceproduct(struct unittype * theunit, int flip)
{
@@ -592,7 +589,7 @@ reduceproduct(struct unittype * theunit, int flip)
Returns 0 on success, or 1 on unknown unit error.
*/
-int
+static int
reduceunit(struct unittype * theunit)
{
int ret;
@@ -607,7 +604,7 @@ reduceunit(struct unittype * theunit)
}
-int
+static int
compareproducts(char **one, char **two)
{
while (*one || *two) {
@@ -630,7 +627,7 @@ compareproducts(char **one, char **two)
/* Return zero if units are compatible, nonzero otherwise */
-int
+static int
compareunits(struct unittype * first, struct unittype * second)
{
return
@@ -639,7 +636,7 @@ compareunits(struct unittype * first, struct unittype * second)
}
-int
+static int
completereduce(struct unittype * unit)
{
if (reduceunit(unit))
@@ -649,32 +646,40 @@ completereduce(struct unittype * unit)
return 0;
}
-void
+static void
showanswer(struct unittype * have, struct unittype * want)
{
double ans;
+ char* oformat;
if (compareunits(have, want)) {
printf("conformability error\n");
if (verbose)
printf("\t%s = ", havestr);
- else
+ else if (!terse)
printf("\t");
showunit(have);
- if (verbose)
- printf("\t%s = ", wantstr);
- else
- printf("\t");
- showunit(want);
+ if (!terse) {
+ if (verbose)
+ printf("\t%s = ", wantstr);
+ else
+ printf("\t");
+ showunit(want);
+ }
}
else if (have->offset != want->offset) {
if (want->quantity)
printf("WARNING: conversion of non-proportional quantities.\n");
- if (have->quantity)
- printf("\t%.8g\n",
+ if (have->quantity) {
+ asprintf(&oformat, "\t%s\n", outputformat);
+ printf(oformat,
(have->factor + have->offset-want->offset)/want->factor);
+ free(oformat);
+ }
else {
- printf("\t (-> x*%.8g %+.8g)\n\t (<- y*%.8g %+.8g)\n",
+ asprintf(&oformat, "\t (-> x*%sg %sg)\n\t (<- y*%sg %sg)\n",
+ outputformat, outputformat, outputformat, outputformat);
+ printf(oformat,
have->factor / want->factor,
(have->offset-want->offset)/want->factor,
want->factor / have->factor,
@@ -683,20 +688,38 @@ showanswer(struct unittype * have, struct unittype * want)
}
else {
ans = have->factor / want->factor;
- if (verbose)
- printf("\t%s = %.8g * %s\n", havestr, ans, wantstr);
- else
- printf("\t* %.8g\n", ans);
- if (verbose)
- printf("\t%s = (1 / %.8g) * %s\n", havestr, 1/ans, wantstr);
- else
- printf("\t/ %.8g\n", 1/ans);
+ if (verbose) {
+ printf("\t%s = ", havestr);
+ printf(outputformat, ans);
+ printf(" * %s", wantstr);
+ printf("\n");
+ }
+ else if (terse) {
+ printf(outputformat, ans);
+ printf("\n");
+ }
+ else {
+ printf("\t* ");
+ printf(outputformat, ans);
+ printf("\n");
+ }
+
+ if (verbose) {
+ printf("\t%s = (1 / ", havestr);
+ printf(outputformat, 1/ans);
+ printf(") * %s\n", wantstr);
+ }
+ else if (!terse) {
+ printf("\t/ ");
+ printf(outputformat, 1/ans);
+ printf("\n");
+ }
}
}
-void
+static void
usage(void)
{
fprintf(stderr,
@@ -704,6 +727,19 @@ usage(void)
exit(3);
}
+static struct option longopts[] = {
+ {"help", no_argument, NULL, 'h'},
+ {"exponential", no_argument, NULL, 'e'},
+ {"file", required_argument, NULL, 'f'},
+ {"output-format", required_argument, NULL, 'o'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"terse", no_argument, NULL, 't'},
+ {"unitsfile", no_argument, NULL, 'U'},
+ {"verbose", no_argument, NULL, 'v'},
+ {"version", no_argument, NULL, 'V'},
+ { 0, 0, 0, 0 }
+};
+
int
main(int argc, char **argv)
@@ -720,8 +756,12 @@ main(int argc, char **argv)
quiet = false;
readfile = false;
- while ((optchar = getopt(argc, argv, "fqvUV:")) != -1) {
+ outputformat = "%.8g";
+ while ((optchar = getopt_long(argc, argv, "+ehf:oqtvUV", longopts, NULL)) != -1) {
switch (optchar) {
+ case 'e':
+ outputformat = "%6e";
+ break;
case 'f':
readfile = true;
if (strlen(optarg) == 0)
@@ -732,9 +772,18 @@ main(int argc, char **argv)
case 'q':
quiet = true;
break;
+ case 't':
+ terse = true;
+ break;
+ case 'o':
+ outputformat = optarg;
+ break;
case 'v':
verbose = true;
break;
+ case 'V':
+ fprintf(stderr, "FreeBSD units\n");
+ /* FALLTHROUGH */
case 'U':
if (access(UNITSFILE, F_OK) == 0)
printf("%s\n", UNITSFILE);
@@ -742,10 +791,9 @@ main(int argc, char **argv)
printf("Units data file not found");
exit(0);
break;
- case 'V':
- fprintf(stderr, "FreeBSD units\n");
- usage();
- break;
+ case 'h':
+ /* FALLTHROUGH */
+
default:
usage();
}
@@ -763,7 +811,7 @@ main(int argc, char **argv)
el_source(el, NULL);
history(inhistory, &ev, H_SETSIZE, 800);
if (inhistory == 0)
- err(1, "Could not initalize history");
+ err(1, "Could not initialize history");
if (cap_enter() < 0 && errno != ENOSYS)
err(1, "unable to enter capability mode");
@@ -813,5 +861,6 @@ main(int argc, char **argv)
}
history_end(inhistory);
- return(0);
+ el_end(el);
+ return (0);
}
diff --git a/usr.bin/units/units.lib b/usr.bin/units/units.lib
index 4c48322..3efafd8 100644
--- a/usr.bin/units/units.lib
+++ b/usr.bin/units/units.lib
@@ -1,6 +1,6 @@
-/ $FreeBSD$
+# $FreeBSD$
-/ primitive units
+# primitive units
m !a!
kg !b!
@@ -13,7 +13,7 @@ bit !h!
erlang !i!
K !j!
-/ prefixes
+# prefixes
yotta- 1e24
zetta- 1e21
@@ -68,7 +68,7 @@ a- atto
z- zopto
y- yocto
-/ binary prefixes introduced in 1999
+# binary prefixes introduced in 1999
exbi- 1152921504606846976
pebi- 1125899906842624
tebi- 1099511627776
@@ -83,7 +83,7 @@ Gi- gibi
Mi- mebi
Ki- kibi
-/ constants
+# constants
fuzz 1
pi 3.14159265358979323846
@@ -109,7 +109,7 @@ electronmass 9.1093821545-31 kg
protonmass 1.6726217129-27 kg
neutronmass 1.6749272928-27 kg
-/ dimensionless
+# dimensionless
radian .5 / pi
degree 1|180 pi-radian
@@ -127,7 +127,7 @@ steradian radian2
sphere 4 pi-steradian
sr steradian
-/ Time
+# Time
second sec
s sec
@@ -143,13 +143,13 @@ yr year
month 1|12 year
us microsec
-/ Mass
+# Mass
gram millikg
gm gram
metricton kilokg
-/ Avoirdupois
+# Avoirdupois
lb .45359237 kg
pound lb
@@ -164,7 +164,7 @@ shortton 2000 lb
ton shortton
longton 2240 lb
-/ Apothecary
+# Apothecary
scruple 20 grain
apdram 60 grain
@@ -172,7 +172,7 @@ apounce 480 grain
appound 5760 grain
troypound appound
-/ Mining
+# Mining
troyounce apounce
troz apounce
@@ -180,7 +180,7 @@ pennyweight 1|20 troz
pwt pennyweight
dwt pennyweight
-/ Length
+# Length
meter m
micron micrometer
@@ -208,7 +208,7 @@ cc cm3
liter kilocc
ml milliliter
-/ US Liquid
+# US Liquid
gallon 231 in3
imperial 1.20095
@@ -222,7 +222,7 @@ floz 1|16 pt
fldr 1|8 floz
shot 3|2 floz
-/ US Dry
+# US Dry
dry 268.8025 in3/gallon fuzz
peck 8 dry-quart
@@ -231,7 +231,7 @@ bushel 4 peck
bu bushel
chaldron 36 bushel
-/ British
+# British
brgallon 277.420 in3 fuzz
brquart 1|4 brgallon
@@ -241,10 +241,10 @@ brpeck 554.84 in3 fuzz
brbushel 4 brpeck
brhundredweight 112 lb
-/ Bottles
+# Bottles
bottle 750 milliliter
-/bottle fifth
+#bottle fifth
miniature 100 milliliter
split 1|4 bottle
@@ -258,7 +258,7 @@ balthazar 16 bottle
nebuchadnezzar 20 bottle
sovereign 34 bottle
-/ Bottles - alternate names and spellings
+# Bottles - alternate names and spellings
pony split
fillette half
@@ -266,7 +266,7 @@ tappit-hen 3 imperial
rheoboam rehoboam
shalmaneser salmanazar
-/ Russian
+# Russian
berkovets 10 pood
pood 40 funt
funt 0.40951 kg
@@ -279,7 +279,7 @@ verst 1066.8 m
sazhen 1|500 verst
kosayasazhen 1|430.2 verst
arshin 1|1500 verst
-/ is not exactly defined
+# is not exactly defined
ruell 16.54 in
liniya 1|10 in
vershok 1.75 in
@@ -296,7 +296,7 @@ sqverst 104.2 desyatina_state
sqarshin 1|21600 desyatina_state
sqfoot 1|117600 desyatina_state
-/ Energy Work
+# Energy Work
newton kg-m/sec2
nt newton
@@ -306,7 +306,7 @@ J joule
cal 4.1868 joule
ergon erg
-/ Electrical
+# Electrical
coulomb coul
C coul
@@ -325,14 +325,14 @@ H henry
weber volt-sec
Wb weber
-/ Light
+# Light
cd candela
lumen cd sr
lux cd sr/m2
-/ EMU currencies have constant exchange rate against Euro since 1.1.1999.
-/ See http://en.wikipedia.org/wiki/Euro for details.
+# EMU currencies have constant exchange rate against Euro since 1.1.1999.
+# See http://en.wikipedia.org/wiki/Euro for details.
austriaschilling 1|13.7603 euro
belgiumfranc 1|40.3399 euro
finlandmarkka 1|5.94573 euro
@@ -350,8 +350,8 @@ cypriotpound 1|0.585274 euro
malteselira 1|0.429300 euro
slovakkoruna 1|30.1260 euro
-/ These ones are pegged to the Euro
-/ See http://en.wikipedia.org/wiki/Euro for details.
+# These ones are pegged to the Euro
+# See http://en.wikipedia.org/wiki/Euro for details.
bosniaherzegovinamark 1|1.95583 euro
bulgarianlev 1|1.95583 euro
capeverdeanescudo 1|110.265 euro
@@ -363,8 +363,8 @@ lithuanianlitas 1|3.45280 euro
pacificfrancexchange 1|0.00838 euro
westafricancfafranc 1|655.957 euro
-/ These ones are pegged on the US Dollar
-/ See http://en.wikipedia.org/wiki/USD for details.
+# These ones are pegged on the US Dollar
+# See http://en.wikipedia.org/wiki/USD for details.
dollar usdollar
arubanflorin 1|1.75 usdollar
bahamiandollar 1|1 usdollar
@@ -404,7 +404,7 @@ markka finlandmarkka
peseta spainpeseta
rand southafricarand
-/ computer
+# computer
baud bit/sec
nibble 4 bit
@@ -424,7 +424,7 @@ kilobyte kbyte
meg megabyte
-/ Trivia
+# Trivia
% 1|100
abampere 10 ampere
OpenPOWER on IntegriCloud