Source-Changes-HG archive

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

[src/trunk]: src/usr.bin/units Add -l and -L options to units(1). "-l" simpl...



details:   https://anonhg.NetBSD.org/src/rev/15fa2037a2d0
branches:  trunk
changeset: 783616:15fa2037a2d0
user:      apb <apb%NetBSD.org@localhost>
date:      Tue Jan 01 11:51:55 2013 +0000

description:
Add -l and -L options to units(1).  "-l" simply lists all unit
definitions, while "-L" alsoreduces them to depend only on a few
primitive units (such as m, kg, sec).

diffstat:

 usr.bin/units/units.1 |   22 +++++-
 usr.bin/units/units.c |  174 ++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 175 insertions(+), 21 deletions(-)

diffs (truncated from 343 to 300 lines):

diff -r b48ee207f549 -r 15fa2037a2d0 usr.bin/units/units.1
--- a/usr.bin/units/units.1     Tue Jan 01 11:44:00 2013 +0000
+++ b/usr.bin/units/units.1     Tue Jan 01 11:51:55 2013 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: units.1,v 1.18 2012/12/28 13:25:25 apb Exp $
+.\"    $NetBSD: units.1,v 1.19 2013/01/01 11:51:55 apb Exp $
 .Dd December 28, 2012
 .Dt UNITS 1
 .Os
@@ -8,7 +8,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl f Ar filename
-.Op Fl qv
+.Op Fl lLqv
 .Oo
 .Op Ar count
 .Ar from-unit to-unit
@@ -25,6 +25,24 @@
 .Bl -tag -width "-fXfilenameX" -offset indent
 .It Fl f Ar filename
 Specifies the name of the units data file to load.
+.It Fl l No or Fl L
+List all unit definitions to the standard output,
+instead of performing any conversions.
+The result may include error messages and comments, beginning with
+.Ql \&/ .
+.Pp
+With the
+.Fl l
+option, unit definitions will be listed in a format
+almost identical to the the units data file that was loaded,
+except that comments will be removed, spacing may be changed,
+and lines may be re-ordered.
+.Pp
+With the
+.Fl L
+option, all unit definitions will be reduced to a form that
+depends on only a few primitive units (such as
+.Sy m , kg , sec ) .
 .It Fl q
 Suppresses prompting of the user for units and the display of statistics
 about the number of units loaded.
diff -r b48ee207f549 -r 15fa2037a2d0 usr.bin/units/units.c
--- a/usr.bin/units/units.c     Tue Jan 01 11:44:00 2013 +0000
+++ b/usr.bin/units/units.c     Tue Jan 01 11:51:55 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: units.c,v 1.20 2013/01/01 11:44:00 apb Exp $   */
+/*     $NetBSD: units.c,v 1.21 2013/01/01 11:51:55 apb Exp $   */
 
 /*
  * units.c   Copyright (c) 1993 by Adrian Mariano (adrian%cam.cornell.edu@localhost)
@@ -19,6 +19,7 @@
 
 #include <ctype.h>
 #include <err.h>
+#include <float.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -39,6 +40,13 @@
 
 #define PRIMITIVECHAR '!'
 
+static int precision = 8;              /* for printf with "%.*g" format */
+
+static const char *errprefix = NULL;   /* if not NULL, then prepend this
+                                        * to error messages and send them to
+                                        * stdout instead of stderr.
+                                        */
+
 static const char *powerstring = "^";
 
 static struct {
@@ -98,9 +106,27 @@
 
 
 static void
+mywarnx(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       if (errprefix) {
+               /* warn to stdout, with errprefix prepended */
+               printf("%s", errprefix);
+               vprintf(fmt, args);
+               printf("%s", "\n");
+       } else {
+               /* warn to stderr */
+               vwarnx(fmt, args);
+       }
+       va_end(args);
+}
+
+static void
 readerror(int linenum)
 {
-       warnx("Error in units file '%s' line %d", UNITSFILE, linenum);
+       mywarnx("Error in units file '%s' line %d", UNITSFILE, linenum);
 }
 
 
@@ -168,8 +194,9 @@
                        continue;
                if (lineptr[strlen(lineptr) - 1] == '-') { /* it's a prefix */
                        if (prefixcount == MAXPREFIXES) {
-                               warnx("Memory for prefixes exceeded in line %d",
-                                   linenum);
+                               mywarnx(
+                       "Memory for prefixes exceeded in line %d",
+                                       linenum);
                                continue;
                        }
                        lineptr[strlen(lineptr) - 1] = 0;
@@ -181,7 +208,7 @@
                                }
                        }
                        if (isdup) {
-                               warnx(
+                               mywarnx(
                        "Redefinition of prefix '%s' on line %d ignored",
                                    lineptr, linenum);
                                continue;
@@ -199,7 +226,7 @@
                }
                else {          /* it's not a prefix */
                        if (unitcount == MAXUNITS) {
-                               warnx("Memory for units exceeded in line %d",
+                               mywarnx("Memory for units exceeded in line %d",
                                    linenum);
                                continue;
                        }
@@ -210,7 +237,7 @@
                                }
                        }
                        if (isdup) {
-                               warnx(
+                               mywarnx(
                                "Redefinition of unit '%s' on line %d ignored",
                                    lineptr, linenum);
                                continue;
@@ -244,7 +271,7 @@
 
        for (ptr = product; *ptr && *ptr != NULLUNIT; ptr++);
        if (ptr >= product + MAXSUBUNITS) {
-               warnx("Memory overflow in unit reduction");
+               mywarnx("Memory overflow in unit reduction");
                return 1;
        }
        if (!*ptr)
@@ -260,7 +287,7 @@
        int printedslash;
        int counter = 1;
 
-       printf("\t%.8g", theunit->factor);
+       printf("\t%.*g", precision, theunit->factor);
        for (ptr = theunit->numerator; *ptr; ptr++) {
                if (ptr > theunit->numerator && **ptr &&
                    !strcmp(*ptr, *(ptr - 1)))
@@ -301,7 +328,7 @@
 static void
 zeroerror(void)
 {
-       warnx("Unit reduces to zero");
+       mywarnx("Unit reduces to zero");
 }
 
 /*
@@ -347,8 +374,7 @@
                                        }
                                        if (endptr != divider) {
                                                /* "6foo|2" is an error */
-                                               warnx("Junk between number "
-                                                     "and '|'");
+                                               mywarnx("Junk before '|'");
                                                return 1;
                                        }
                                        if (doingtop ^ flip)
@@ -562,7 +588,7 @@
                                break;
                        toadd = lookupunit(*product);
                        if (!toadd) {
-                               printf("unknown unit '%s'\n", *product);
+                               mywarnx("Unknown unit '%s'", *product);
                                return ERROR;
                        }
                        if (strchr(toadd, PRIMITIVECHAR))
@@ -660,15 +686,109 @@
                        showunit(want);
                } else {
                        printf("\treciprocal conversion\n");
-                       printf("\t* %.8g\n\t/ %.8g\n", 1 / (have->factor * want->factor),
-                           want->factor * have->factor);
+                       printf("\t* %.*g\n\t/ %.*g\n",
+                           precision, 1 / (have->factor * want->factor),
+                           precision, want->factor * have->factor);
                }
        }
        else
-               printf("\t* %.8g\n\t/ %.8g\n", have->factor / want->factor,
-                   want->factor / have->factor);
+               printf("\t* %.*g\n\t/ %.*g\n",
+                   precision, have->factor / want->factor,
+                   precision, want->factor / have->factor);
 }
 
+static int
+listunits(int expand)
+{
+       struct unittype theunit;
+       const char *thename;
+       const char *thedefn;
+       int errors = 0;
+       int i;
+       int printexpansion;
+
+       /*
+        * send error and warning messages to stdout,
+        * and make them look like comments.
+        */
+       errprefix = "/ ";
+
+#if 0 /* debug */
+       printf("/ expand=%d precision=%d unitcount=%d prefixcount=%d\n",
+           expand, precision, unitcount, prefixcount);
+#endif
+
+       /* 1. Dump all primitive units, e.g. "m !a!", "kg !b!", ... */
+       printf("/ Primitive units\n");
+       for (i = 0; i < unitcount; i++) {
+               thename = unittable[i].uname;
+               thedefn = unittable[i].uval;
+               if (thedefn[0] == PRIMITIVECHAR) {
+                       printf("%s\t%s\n", thename, thedefn);
+               }
+       }
+
+       /* 2. Dump all prefixes, e.g. "yotta- 1e24", "zetta- 1e21", ... */
+       printf("/ Prefixes\n");
+       for (i = 0; i < prefixcount; i++) {
+               printexpansion = expand;
+               thename = prefixtable[i].prefixname;
+               thedefn = prefixtable[i].prefixval;
+               if (expand) {
+                       /*
+                        * prefix names are sometimes identical to unit
+                        * names, so we have to expand thedefn instead of
+                        * expanding thename.
+                        */
+                       initializeunit(&theunit);
+                       if (addunit(&theunit, thedefn, 0) != 0
+                           || completereduce(&theunit) != 0) {
+                               errors++;
+                               printexpansion = 0;
+                               mywarnx("Error in prefix '%s-'", thename);
+                       }
+               }
+               if (printexpansion) {
+                       printf("%s-", thename);
+                       showunit(&theunit);
+               } else
+                       printf("%s-\t%s\n", thename, thedefn);
+       }
+
+       /* 3. Dump all other units. */
+       printf("/ Other units\n");
+       for (i = 0; i < unitcount; i++) {
+               printexpansion = expand;
+               thename = unittable[i].uname;
+               thedefn = unittable[i].uval;
+               if (thedefn[0] == PRIMITIVECHAR)
+                       continue;
+               if (expand) {
+                       /*
+                        * expand thename, not thedefn, so that
+                        * we can catch errors in the name itself.
+                        * e.g. a name that contains a hyphen
+                        * will be interpreted
+                        */
+                       initializeunit(&theunit);
+                       if (addunit(&theunit, thedefn/*XXX*/, 0) != 0
+                           || completereduce(&theunit) != 0) {
+                               errors++;
+                               printexpansion = 0;
+                               mywarnx("Error in unit '%s'", thename);
+                       }
+               }
+               if (printexpansion) {
+                       printf("%s", thename);
+                       showunit(&theunit);
+               } else
+                       printf("%s\t%s\n", thename, thedefn);
+       }
+
+       if (errors)
+               mywarnx("Definitions with errors: %d", errors);
+       return (errors ? 1 : 0);
+}
 



Home | Main Index | Thread Index | Old Index