]> diplodocus.org Git - nmh/commitdiff
add $(kibi) function, as complement to %(kilo)
authorPaul Fox <pgf@foxharp.boston.ma.us>
Tue, 13 May 2014 14:10:09 +0000 (10:10 -0400)
committerPaul Fox <pgf@foxharp.boston.ma.us>
Wed, 14 May 2014 13:26:59 +0000 (09:26 -0400)
%(kibi) will convert a number to IEC prefix units, i.e. Ki, Mi, Gi,
Ti, representing factors of 1024.  (by comparison, %(kilo) represents
factors of 1000.)

h/fmt_compile.h
man/mh-format.man
sbr/fmt_compile.c
sbr/fmt_scan.c
uip/fmtdump.c

index bfe47204aa0267a72dc6c81a4e1aad4689e4584f..b0c12c0845c794029c54b710f32c1d3dec269d2e 100644 (file)
  */
 
 /* types that output text */
-#define FT_COMP                1       /* the text of a component                 */
-#define FT_COMPF       2       /* comp text, filled                       */
-#define FT_LIT         3       /* literal text                            */
-#define FT_LITF                4       /* literal text, filled                    */
-#define FT_CHAR                5       /* a single ascii character                */
-#define FT_NUM         6       /* "value" as decimal number               */
-#define FT_NUMF                7       /* "value" as filled dec number            */
-#define FT_STR         8       /* "str" as text                           */
-#define FT_STRF                9       /* "str" as text, filled                   */
-#define FT_STRFW       10      /* "str" as text, filled, width in "value" */
-#define FT_STRLIT      11      /* "str" as text, no space compression     */
-#define FT_STRLITZ     12      /* literal text with zero display width    */
-#define FT_PUTADDR     13      /* split and print address line            */
+#define FT_COMP         1       /* the text of a component                 */
+#define FT_COMPF        2       /* comp text, filled                       */
+#define FT_LIT          3       /* literal text                            */
+#define FT_LITF         4       /* literal text, filled                    */
+#define FT_CHAR         5       /* a single ascii character                */
+#define FT_NUM          6       /* "value" as decimal number               */
+#define FT_NUMF         7       /* "value" as filled dec number            */
+#define FT_STR          8       /* "str" as text                           */
+#define FT_STRF         9       /* "str" as text, filled                   */
+#define FT_STRFW        10      /* "str" as text, filled, width in "value" */
+#define FT_STRLIT       11      /* "str" as text, no space compression     */
+#define FT_STRLITZ      12      /* literal text with zero display width    */
+#define FT_PUTADDR      13      /* split and print address line            */
 
 /* types that modify the "str" or "value" registers                     */
-#define FT_LS_COMP     14      /* set "str" to component text          */
-#define FT_LS_LIT      15      /* set "str" to literal text            */
-#define FT_LS_GETENV   16      /* set "str" to getenv(text)            */
-#define FT_LS_CFIND    17      /* set "str" to context_find(text)      */
-#define FT_LS_DECODECOMP 18    /* set "str" to decoded component text  */
-#define FT_LS_DECODE   19      /* decode "str" as RFC-2047 header      */
-#define FT_LS_TRIM     20      /* trim trailing white space from "str" */
-#define FT_LV_COMP     21      /* set "value" to comp (as dec. num)    */
-#define FT_LV_COMPFLAG 22      /* set "value" to comp flag word        */
-#define FT_LV_LIT      23      /* set "value" to literal num           */
-#define FT_LV_DAT      24      /* set "value" to dat[n]                */
-#define FT_LV_STRLEN   25      /* set "value" to length of "str"       */
-#define FT_LV_PLUS_L   26      /* set "value" += literal               */
-#define FT_LV_MINUS_L  27      /* set "value" -= literal               */
-#define FT_LV_DIVIDE_L 28      /* set "value" to value / literal       */
-#define FT_LV_MODULO_L 29      /* set "value" to value % literal       */
-#define FT_LV_CHAR_LEFT 30     /* set "value" to char left in output   */
+#define FT_LS_COMP      14      /* set "str" to component text          */
+#define FT_LS_LIT       15      /* set "str" to literal text            */
+#define FT_LS_GETENV    16      /* set "str" to getenv(text)            */
+#define FT_LS_CFIND     17      /* set "str" to context_find(text)      */
+#define FT_LS_DECODECOMP 18     /* set "str" to decoded component text  */
+#define FT_LS_DECODE    19      /* decode "str" as RFC-2047 header      */
+#define FT_LS_TRIM      20      /* trim trailing white space from "str" */
+#define FT_LV_COMP      21      /* set "value" to comp (as dec. num)    */
+#define FT_LV_COMPFLAG  22      /* set "value" to comp flag word        */
+#define FT_LV_LIT       23      /* set "value" to literal num           */
+#define FT_LV_DAT       24      /* set "value" to dat[n]                */
+#define FT_LV_STRLEN    25      /* set "value" to length of "str"       */
+#define FT_LV_PLUS_L    26      /* set "value" += literal               */
+#define FT_LV_MINUS_L   27      /* set "value" -= literal               */
+#define FT_LV_DIVIDE_L  28      /* set "value" to value / literal       */
+#define FT_LV_MODULO_L  29      /* set "value" to value % literal       */
+#define FT_LV_CHAR_LEFT 30      /* set "value" to char left in output   */
 
-#define FT_LS_MONTH    31      /* set "str" to tws month                   */
-#define FT_LS_LMONTH   32      /* set "str" to long tws month              */
-#define FT_LS_ZONE     33      /* set "str" to tws timezone                */
-#define FT_LS_DAY      34      /* set "str" to tws weekday                 */
-#define FT_LS_WEEKDAY  35      /* set "str" to long tws weekday            */
-#define FT_LS_822DATE  36      /* set "str" to 822 date str                */
-#define FT_LS_PRETTY   37      /* set "str" to pretty (?) date str         */
-#define FT_LS_KILO     38      /* set "str" to "<value>[KMGT]"             */
-#define FT_LV_SEC      39      /* set "value" to tws second                */
-#define FT_LV_MIN      40      /* set "value" to tws minute                */
-#define FT_LV_HOUR     41      /* set "value" to tws hour                  */
-#define FT_LV_MDAY     42      /* set "value" to tws day of month          */
-#define FT_LV_MON      43      /* set "value" to tws month                 */
-#define FT_LV_YEAR     44      /* set "value" to tws year                  */
-#define FT_LV_YDAY     45      /* set "value" to tws day of year           */
-#define FT_LV_WDAY     46      /* set "value" to tws weekday               */
-#define FT_LV_ZONE     47      /* set "value" to tws timezone              */
-#define FT_LV_CLOCK    48      /* set "value" to tws clock                 */
-#define FT_LV_RCLOCK   49      /* set "value" to now - tws clock           */
-#define FT_LV_DAYF     50      /* set "value" to tws day flag              */
-#define FT_LV_DST      51      /* set "value" to tws daylight savings flag */
-#define FT_LV_ZONEF    52      /* set "value" to tws timezone flag         */
+#define FT_LS_MONTH     31      /* set "str" to tws month                   */
+#define FT_LS_LMONTH    32      /* set "str" to long tws month              */
+#define FT_LS_ZONE      33      /* set "str" to tws timezone                */
+#define FT_LS_DAY       34      /* set "str" to tws weekday                 */
+#define FT_LS_WEEKDAY   35      /* set "str" to long tws weekday            */
+#define FT_LS_822DATE   36      /* set "str" to 822 date str                */
+#define FT_LS_PRETTY    37      /* set "str" to pretty (?) date str         */
+#define FT_LS_KILO      38      /* set "str" to "<value>[KMGT]"             */
+#define FT_LS_KIBI      39      /* set "str" to "<value>[KMGT]"             */
+#define FT_LV_SEC       40      /* set "value" to tws second                */
+#define FT_LV_MIN       41      /* set "value" to tws minute                */
+#define FT_LV_HOUR      42      /* set "value" to tws hour                  */
+#define FT_LV_MDAY      43      /* set "value" to tws day of month          */
+#define FT_LV_MON       44      /* set "value" to tws month                 */
+#define FT_LV_YEAR      45      /* set "value" to tws year                  */
+#define FT_LV_YDAY      46      /* set "value" to tws day of year           */
+#define FT_LV_WDAY      47      /* set "value" to tws weekday               */
+#define FT_LV_ZONE      48      /* set "value" to tws timezone              */
+#define FT_LV_CLOCK     49      /* set "value" to tws clock                 */
+#define FT_LV_RCLOCK    50      /* set "value" to now - tws clock           */
+#define FT_LV_DAYF      51      /* set "value" to tws day flag              */
+#define FT_LV_DST       52      /* set "value" to tws daylight savings flag */
+#define FT_LV_ZONEF     53      /* set "value" to tws timezone flag         */
 
-#define FT_LS_PERS     53      /* set "str" to person part of addr    */
-#define FT_LS_MBOX     54      /* set "str" to mbox part of addr      */
-#define FT_LS_HOST     55      /* set "str" to host part of addr      */
-#define FT_LS_PATH     56      /* set "str" to route part of addr     */
-#define FT_LS_GNAME    57      /* set "str" to group part of addr     */
-#define FT_LS_NOTE     58      /* set "str" to comment part of addr   */
-#define FT_LS_ADDR     59      /* set "str" to mbox@host              */
-#define FT_LS_822ADDR  60      /* set "str" to 822 format addr        */
-#define FT_LS_FRIENDLY 61      /* set "str" to "friendly" format addr */
-#define FT_LV_HOSTTYPE 62      /* set "value" to addr host type       */
-#define FT_LV_INGRPF   63      /* set "value" to addr in-group flag   */
-#define FT_LS_UNQUOTE  64      /* remove RFC 2822 quotes from "str"   */
-#define FT_LV_NOHOSTF  65      /* set "value" to addr no-host flag */
+#define FT_LS_PERS      54      /* set "str" to person part of addr    */
+#define FT_LS_MBOX      55      /* set "str" to mbox part of addr      */
+#define FT_LS_HOST      56      /* set "str" to host part of addr      */
+#define FT_LS_PATH      57      /* set "str" to route part of addr     */
+#define FT_LS_GNAME     58      /* set "str" to group part of addr     */
+#define FT_LS_NOTE      59      /* set "str" to comment part of addr   */
+#define FT_LS_ADDR      60      /* set "str" to mbox@host              */
+#define FT_LS_822ADDR   61      /* set "str" to 822 format addr        */
+#define FT_LS_FRIENDLY  62      /* set "str" to "friendly" format addr */
+#define FT_LV_HOSTTYPE  63      /* set "value" to addr host type       */
+#define FT_LV_INGRPF    64      /* set "value" to addr in-group flag   */
+#define FT_LS_UNQUOTE   65      /* remove RFC 2822 quotes from "str"   */
+#define FT_LV_NOHOSTF   66     /* set "value" to addr no-host flag */
 
 /* Date Coercion */
-#define FT_LOCALDATE   66      /* Coerce date to local timezone */
-#define FT_GMTDATE     67      /* Coerce date to gmt            */
+#define FT_LOCALDATE    67      /* Coerce date to local timezone */
+#define FT_GMTDATE      68      /* Coerce date to gmt            */
 
 /* pre-format processing */
-#define FT_PARSEDATE   68      /* parse comp into a date (tws) struct */
-#define FT_PARSEADDR   69      /* parse comp into a mailaddr struct   */
-#define FT_FORMATADDR  70      /* let external routine format addr    */
-#define FT_CONCATADDR  71      /* formataddr w/out duplicate removal  */
-#define FT_MYMBOX      72      /* do "mymbox" test on comp            */
+#define FT_PARSEDATE    69      /* parse comp into a date (tws) struct */
+#define FT_PARSEADDR    70      /* parse comp into a mailaddr struct   */
+#define FT_FORMATADDR   71      /* let external routine format addr    */
+#define FT_CONCATADDR   72      /* formataddr w/out duplicate removal  */
+#define FT_MYMBOX       73      /* do "mymbox" test on comp            */
 
 /* conditionals & control flow (must be last) */
-#define FT_SAVESTR     73      /* save current str reg               */
-#define FT_DONE                74      /* stop formatting                    */
-#define FT_PAUSE       75      /* pause                              */
-#define FT_NOP         76      /* nop                                */
-#define FT_GOTO                77      /* (relative) goto                    */
-#define FT_IF_S_NULL   78      /* test if "str" null                 */
-#define FT_IF_S                79      /* test if "str" non-null             */
-#define FT_IF_V_EQ     80      /* test if "value" = literal          */
-#define FT_IF_V_NE     81      /* test if "value" != literal         */
-#define FT_IF_V_GT     82      /* test if "value" > literal          */
-#define FT_IF_MATCH    83      /* test if "str" contains literal     */
-#define FT_IF_AMATCH   84      /* test if "str" starts with literal  */
-#define FT_S_NULL      85      /* V = 1 if "str" null                */
-#define FT_S_NONNULL   86      /* V = 1 if "str" non-null            */
-#define FT_V_EQ                87      /* V = 1 if "value" = literal         */
-#define FT_V_NE                88      /* V = 1 if "value" != literal        */
-#define FT_V_GT                89      /* V = 1 if "value" > literal         */
-#define FT_V_MATCH     90      /* V = 1 if "str" contains literal    */
-#define FT_V_AMATCH    91      /* V = 1 if "str" starts with literal */
+#define FT_SAVESTR      74      /* save current str reg               */
+#define FT_DONE         75      /* stop formatting                    */
+#define FT_PAUSE        76      /* pause                              */
+#define FT_NOP          77      /* nop                                */
+#define FT_GOTO         78      /* (relative) goto                    */
+#define FT_IF_S_NULL    79      /* test if "str" null                 */
+#define FT_IF_S         80      /* test if "str" non-null             */
+#define FT_IF_V_EQ      81      /* test if "value" = literal          */
+#define FT_IF_V_NE      82      /* test if "value" != literal         */
+#define FT_IF_V_GT      83      /* test if "value" > literal          */
+#define FT_IF_MATCH     84      /* test if "str" contains literal     */
+#define FT_IF_AMATCH    85      /* test if "str" starts with literal  */
+#define FT_S_NULL       86      /* V = 1 if "str" null                */
+#define FT_S_NONNULL    87      /* V = 1 if "str" non-null            */
+#define FT_V_EQ         88      /* V = 1 if "value" = literal         */
+#define FT_V_NE         89      /* V = 1 if "value" != literal        */
+#define FT_V_GT         90      /* V = 1 if "value" > literal         */
+#define FT_V_MATCH      91      /* V = 1 if "str" contains literal    */
+#define FT_V_AMATCH     92      /* V = 1 if "str" starts with literal */
 
-#define IF_FUNCS FT_S_NULL     /* start of "if" functions */
+#define IF_FUNCS FT_S_NULL      /* start of "if" functions */
index 82128e807c717b58a1ffa8f8f72275829a8481d4..dc2d9b0cb598e65710399ce55ba4714f85b2c5c9 100644 (file)
@@ -291,6 +291,9 @@ decode      expr    string  decode \fIstr\fR as RFC 2047 (MIME-encoded)
 unquote        expr    string  remove RFC 2822 quotes from \fIstr\fR
 trim   expr            trim trailing whitespace from \fIstr\fR
 kilo   expr    string  express in SI units: 15.9K, 2.3M, etc.
+                       %(kilo) scales by factors of 1000,
+kibi   expr    string  express in IEC units: 15.5Ki, 2.2Mi.
+                       %(kibi) scales by factors of 1024.
 putstr expr            print \fIstr\fR
 putstrf        expr            print \fIstr\fR in a fixed width
 putnum expr            print \fInum\fR
index dbd86631fd0b0b11aca0a47af91f5064e3e28946..62b27eacc512cc2539f2f82f97b2b10bff2f7d4a 100644 (file)
@@ -160,6 +160,7 @@ static struct ftable functable[] = {
      { "decode",     TF_EXPR,  FT_LS_DECODE,   0,              TFL_PUTS },
      { "trim",       TF_EXPR,  FT_LS_TRIM,     0,              0 },
      { "kilo",       TF_EXPR,  FT_LS_KILO,     0,              TFL_PUTS },
+     { "kibi",       TF_EXPR,  FT_LS_KIBI,     0,              TFL_PUTS },
      { "compval",    TF_COMP,  FT_LV_COMP,     0,              TFL_PUTN },
      { "compflag",   TF_COMP,  FT_LV_COMPFLAG, 0,              TFL_PUTN },
      { "num",        TF_NUM,   FT_LV_LIT,      0,              TFL_PUTN },
index 20420516fefee8fc92972694a210697357e5621e..ec94897eccfa566009ff707a659dc77e94ee7500 100644 (file)
@@ -491,16 +491,25 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat,
            }
            break;
        case FT_LS_KILO:
+       case FT_LS_KIBI:
            {
                char *unitcp;
                unsigned int whole, tenths;
+               unsigned int scale;
+               unsigned int val = (unsigned int)value;
+               char *kibisuff;
 
-               if (value < 1000) {
-                   snprintf(buffer, sizeof(buffer), "%u", value);
+               switch (fmt->f_type) {
+               case FT_LS_KILO: scale = 1000; kibisuff = ""; break;
+               case FT_LS_KIBI: scale = 1024; kibisuff = "i"; break;
+               }
+
+               if (val < scale) {
+                   snprintf(buffer, sizeof(buffer), "%u", val);
                } else {
 
                    /* find correct scale for size (Kilo/Mega/Giga/Tera) */
-                   for (unitcp = "KMGT"; value > 999999; value /= 1000) {
+                   for (unitcp = "KMGT"; val > (scale * scale); val /= scale) {
                        if (!*++unitcp)
                            break;
                    }
@@ -508,17 +517,22 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat,
                    if (!*unitcp) {
                        strcpy(buffer, "huge");
                    } else {
-                       /* round up to next higer tenth of kilo-/mega-/giga- */
-                       value += 99; value /= 100;
+                       /* val is scale times too big.  we want tenths */
+                       val *= 10;
+
+                       /* round up */
+                       val += (scale - 1);
+                       val /= scale;
 
-                       /* want one digit after decimal, avoid float */
-                       whole = value / 10;
-                       tenths = value - (whole * 10);
+                       whole = val / 10;
+                       tenths = val - (whole * 10);
 
                        if (tenths) {
-                           snprintf(buffer, sizeof(buffer), "%u.%u%c", whole, tenths, *unitcp);
+                           snprintf(buffer, sizeof(buffer), "%u.%u%c%s",
+                                   whole, tenths, *unitcp, kibisuff);
                        } else {
-                           snprintf(buffer, sizeof(buffer), "%u%c", whole, *unitcp);
+                           snprintf(buffer, sizeof(buffer), "%u%c%s",
+                                   whole, *unitcp, kibisuff);
                        }
                    }
                }
index c8204f6b33c673fb0721f3c0e35c993977b290d5..86dbfefc69b80ddf060b80e91b352c5e7d804bcb 100644 (file)
@@ -372,6 +372,7 @@ f_typestr(int t)
        case FT_LV_MODULO_L: return("LV_MODULO_L");
        case FT_LV_CHAR_LEFT: return("LV_CHAR_LEFT");
        case FT_LS_KILO: return("LS_KILO");
+       case FT_LS_KIBI: return("LS_KIBI");
        case FT_LS_MONTH: return("LS_MONTH");
        case FT_LS_LMONTH: return("LS_LMONTH");
        case FT_LS_ZONE: return("LS_ZONE");