1256130Sjmg/*- 2256130Sjmg * Copyright 2012 Clifton Royston 3256130Sjmg * Copyright 2013 John-Mark Gurney 4256130Sjmg * All rights reserved. 5256130Sjmg * 6256130Sjmg * Redistribution and use in source and binary forms, with or without 7256130Sjmg * modification, are permitted provided that the following conditions 8256130Sjmg * are met: 9256130Sjmg * 1. Redistributions of source code must retain the above copyright 10256130Sjmg * notice, this list of conditions and the following disclaimer. 11256130Sjmg * 2. Redistributions in binary form must reproduce the above copyright 12256130Sjmg * notice, this list of conditions and the following disclaimer in the 13256130Sjmg * documentation and/or other materials provided with the distribution. 14256130Sjmg * 15256130Sjmg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16256130Sjmg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17256130Sjmg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18256130Sjmg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19256130Sjmg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20256130Sjmg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21256130Sjmg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22256130Sjmg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23256130Sjmg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24256130Sjmg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25256130Sjmg * SUCH DAMAGE. 26256130Sjmg * 27256130Sjmg * $FreeBSD$ 28256130Sjmg * 29256130Sjmg */ 30256130Sjmg 31256130Sjmg#include <sys/types.h> 32256130Sjmg#include <stdlib.h> 33256130Sjmg#include <libutil.h> 34256130Sjmg#include <stdio.h> 35256130Sjmg#include <string.h> 36256130Sjmg#include <inttypes.h> 37256130Sjmg#include <math.h> 38256130Sjmg#include <unistd.h> 39256130Sjmg#include <limits.h> 40256130Sjmg 41256130Sjmgextern char * optarg; 42256130Sjmg 43256130Sjmg#define MAX_STR_FLAGS_RESULT 80 44256130Sjmg#define MAX_INT_STR_DIGITS 12 45256130Sjmg 46256130Sjmgstatic const int64_t halfExabyte = (int64_t)500*1000*1000*1000*1000*1000L; 47256130Sjmg 48256130Sjmgstatic struct { 49256130Sjmg int retval; 50256130Sjmg const char *res; 51256130Sjmg int64_t num; 52256130Sjmg int flags; 53256130Sjmg int scale; 54256130Sjmg} test_args[] = { 55256130Sjmg /* tests 0-13 test 1000 suffixes */ 56256130Sjmg { 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, HN_AUTOSCALE }, 57256130Sjmg { 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, HN_AUTOSCALE }, 58256130Sjmg { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 59256130Sjmg { 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 60256130Sjmg { 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 61256130Sjmg { 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 62256130Sjmg { 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 63256130Sjmg { 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, HN_AUTOSCALE }, 64256130Sjmg { 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, HN_AUTOSCALE }, 65256130Sjmg { 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 66256130Sjmg { 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 67256130Sjmg { 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 68256130Sjmg { 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 69256130Sjmg { 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 70256130Sjmg 71256130Sjmg /* tests 14-27 test 1024 suffixes */ 72256130Sjmg { 2, "0 ", (int64_t)0L, 0, HN_AUTOSCALE }, 73256130Sjmg { 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE }, 74256130Sjmg { 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE }, 75256130Sjmg { 3, "1 G", (int64_t)512*1024*1024L, 0, HN_AUTOSCALE }, 76256130Sjmg { 3, "1 T", (int64_t)512*1024*1024*1024L, 0, HN_AUTOSCALE }, 77256130Sjmg { 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, HN_AUTOSCALE }, 78256130Sjmg { 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE }, 79256130Sjmg { 2, "1 ", (int64_t)1L, 0, HN_AUTOSCALE }, 80256130Sjmg { 3, "2 K", (int64_t)1536L, 0, HN_AUTOSCALE }, 81256130Sjmg { 3, "2 M", (int64_t)1536*1024L, 0, HN_AUTOSCALE }, 82256130Sjmg { 3, "2 G", (int64_t)1536*1024*1024L, 0, HN_AUTOSCALE }, 83256130Sjmg { 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, HN_AUTOSCALE }, 84256130Sjmg { 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, HN_AUTOSCALE }, 85256130Sjmg { 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE }, 86256130Sjmg 87256130Sjmg /* tests 28-37 test rounding */ 88256130Sjmg { 3, "0 M", (int64_t)500*1000L-1, HN_DIVISOR_1000, HN_AUTOSCALE }, 89256130Sjmg { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 90256130Sjmg { 3, "1 M", (int64_t)1000*1000L + 500*1000L-1, HN_DIVISOR_1000, HN_AUTOSCALE }, 91256130Sjmg { 3, "2 M", (int64_t)1000*1000L + 500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 92256130Sjmg { 3, "0 K", (int64_t)512L-1, 0, HN_AUTOSCALE }, 93256130Sjmg { 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE }, 94256130Sjmg { 3, "0 M", (int64_t)512*1024L-1, 0, HN_AUTOSCALE }, 95256130Sjmg { 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE }, 96256130Sjmg { 3, "1 M", (int64_t)1024*1024L + 512*1024L-1, 0, HN_AUTOSCALE }, 97256130Sjmg { 3, "2 M", (int64_t)1024*1024L + 512*1024L, 0, HN_AUTOSCALE }, 98256130Sjmg 99256130Sjmg /* tests 38-61 test specific scale factors with 1000 divisor */ 100256130Sjmg { 3, "0 k", (int64_t)0L, HN_DIVISOR_1000, 1 }, 101256130Sjmg { 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, 1 }, 102256130Sjmg { 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, 2 }, 103256130Sjmg { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, 2 }, 104256130Sjmg { 3, "0 G", (int64_t)500*1000L, HN_DIVISOR_1000, 3 }, 105256130Sjmg { 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 3 }, 106256130Sjmg { 3, "0 T", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 4 }, 107256130Sjmg { 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 4 }, 108256130Sjmg { 3, "0 P", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 5 }, 109256130Sjmg { 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 }, 110256130Sjmg { 3, "0 E", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 }, 111256130Sjmg { 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 }, 112256130Sjmg { 3, "0 k", (int64_t)1L, HN_DIVISOR_1000, 1 }, 113256130Sjmg { 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, 1 }, 114256130Sjmg { 3, "0 M", (int64_t)1500L, HN_DIVISOR_1000, 2 }, 115256130Sjmg { 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, 2 }, 116256130Sjmg { 3, "0 G", (int64_t)1500*1000L, HN_DIVISOR_1000, 3 }, 117256130Sjmg { 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 3 }, 118256130Sjmg { 3, "0 T", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 4 }, 119256130Sjmg { 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 4 }, 120256130Sjmg { 3, "0 P", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 5 }, 121256130Sjmg { 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 }, 122256130Sjmg { 3, "0 E", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 }, 123256130Sjmg { 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 }, 124256130Sjmg 125256130Sjmg /* tests 62-85 test specific scale factors with 1024 divisor */ 126256130Sjmg { 3, "0 K", (int64_t)0L, 0, 1 }, 127256130Sjmg { 3, "1 K", (int64_t)512L, 0, 1 }, 128256130Sjmg { 3, "0 M", (int64_t)512L, 0, 2 }, 129256130Sjmg { 3, "1 M", (int64_t)512*1024L, 0, 2 }, 130256130Sjmg { 3, "0 G", (int64_t)512*1024L, 0, 3 }, 131256130Sjmg { 3, "1 G", (int64_t)512*1024*1024L, 0, 3 }, 132256130Sjmg { 3, "0 T", (int64_t)512*1024*1024L, 0, 4 }, 133256130Sjmg { 3, "1 T", (int64_t)512*1024*1024*1024L, 0, 4 }, 134256130Sjmg { 3, "0 P", (int64_t)512*1024*1024*1024L, 0, 5 }, 135256130Sjmg { 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, 5 }, 136256130Sjmg { 3, "0 E", (int64_t)512*1024*1024*1024*1024L, 0, 6 }, 137256130Sjmg { 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, 6 }, 138256130Sjmg { 3, "0 K", (int64_t)1L, 0, 1 }, 139256130Sjmg { 3, "2 K", (int64_t)1536L, 0, 1 }, 140256130Sjmg { 3, "0 M", (int64_t)1536L, 0, 2 }, 141256130Sjmg { 3, "2 M", (int64_t)1536*1024L, 0, 2 }, 142256130Sjmg { 3, "0 G", (int64_t)1536*1024L, 0, 3 }, 143256130Sjmg { 3, "2 G", (int64_t)1536*1024*1024L, 0, 3 }, 144256130Sjmg { 3, "0 T", (int64_t)1536*1024*1024L, 0, 4 }, 145256130Sjmg { 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, 4 }, 146256130Sjmg { 3, "0 P", (int64_t)1536*1024*1024*1024L, 0, 5 }, 147256130Sjmg { 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, 5 }, 148256130Sjmg { 3, "0 E", (int64_t)1536*1024*1024*1024*1024L, 0, 6 }, 149256130Sjmg { 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, 6 }, 150256130Sjmg 151256130Sjmg /* tests 86-99 test invalid specific scale values of < 0 or >= 7 with 152256130Sjmg and without HN_DIVISOR_1000 set */ 153256130Sjmg /* all should return errors with new code; with old, the latter 3 154256130Sjmg are instead processed as if having AUTOSCALE and/or GETSCALE set */ 155256130Sjmg { -1, "", (int64_t)1L, 0, 7 }, 156256130Sjmg { -1, "", (int64_t)1L, HN_DIVISOR_1000, 7 }, 157256130Sjmg { -1, "", (int64_t)1L, 0, 1000 }, 158256130Sjmg { -1, "", (int64_t)1L, HN_DIVISOR_1000, 1000 }, 159256130Sjmg { -1, "", (int64_t)0L, 0, 1000*1000 }, 160256130Sjmg { -1, "", (int64_t)0L, HN_DIVISOR_1000, 1000*1000 }, 161256130Sjmg { -1, "", (int64_t)0L, 0, INT_MAX }, 162256130Sjmg { -1, "", (int64_t)0L, HN_DIVISOR_1000, INT_MAX }, 163256130Sjmg 164256130Sjmg /* Negative scale values are not handled well 165256130Sjmg by the existing library routine - should report as error */ 166256130Sjmg /* all should return errors with new code, fail assertion with old */ 167256130Sjmg 168256130Sjmg { -1, "", (int64_t)1L, 0, -1 }, 169256130Sjmg { -1, "", (int64_t)1L, HN_DIVISOR_1000, -1 }, 170256130Sjmg { -1, "", (int64_t)1L, 0, -1000 }, 171256130Sjmg { -1, "", (int64_t)1L, HN_DIVISOR_1000, -1000 }, 172256130Sjmg 173256130Sjmg /* __INT_MIN doesn't print properly, skipped. */ 174256130Sjmg 175256130Sjmg { -1, "", (int64_t)1L, 0, -__INT_MAX }, 176256130Sjmg { -1, "", (int64_t)1L, HN_DIVISOR_1000, -__INT_MAX }, 177256130Sjmg 178256130Sjmg 179256130Sjmg /* tests for scale == 0, without autoscale */ 180256130Sjmg /* tests 100-114 test scale 0 with 1000 divisor - print first N digits */ 181256130Sjmg { 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, 0 }, 182256130Sjmg { 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, 0 }, 183256130Sjmg { 3, "10 ", (int64_t)10L, HN_DIVISOR_1000, 0 }, 184256130Sjmg { 3, "0 M", (int64_t)150L, HN_DIVISOR_1000, HN_NOSPACE }, 185256130Sjmg { 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, HN_NOSPACE }, 186256130Sjmg { 3, "0 M", (int64_t)999L, HN_DIVISOR_1000, HN_NOSPACE }, 187256130Sjmg { 4, "150", (int64_t)150L, HN_DIVISOR_1000, 0 }, 188256130Sjmg { 4, "500", (int64_t)500L, HN_DIVISOR_1000, 0 }, 189256130Sjmg { 4, "999", (int64_t)999L, HN_DIVISOR_1000, 0 }, 190256130Sjmg { 5, "100", (int64_t)1000L, HN_DIVISOR_1000, 0 }, 191256130Sjmg { 5, "150", (int64_t)1500L, HN_DIVISOR_1000, 0 }, 192256130Sjmg { 7, "500", (int64_t)500*1000L, HN_DIVISOR_1000, 0 }, 193256130Sjmg { 8, "150", (int64_t)1500*1000L, HN_DIVISOR_1000, 0 }, 194256130Sjmg { 10, "500", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 0 }, 195256130Sjmg { 11, "150", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 0 }, 196256130Sjmg 197256130Sjmg /* tests 115-126 test scale 0 with 1024 divisor - print first N digits */ 198256130Sjmg { 2, "0 ", (int64_t)0L, 0, 0 }, 199256130Sjmg { 2, "1 ", (int64_t)1L, 0, 0 }, 200256130Sjmg { 3, "10 ", (int64_t)10L, 0, 0 }, 201256130Sjmg { 4, "150", (int64_t)150L, 0, 0 }, 202256130Sjmg { 4, "500", (int64_t)500L, 0, 0 }, 203256130Sjmg { 4, "999", (int64_t)999L, 0, 0 }, 204256130Sjmg { 5, "100", (int64_t)1000L, 0, 0 }, 205256130Sjmg { 5, "150", (int64_t)1500L, 0, 0 }, 206256130Sjmg { 7, "500", (int64_t)500*1000L, 0, 0 }, 207256130Sjmg { 8, "150", (int64_t)1500*1000L, 0, 0 }, 208256130Sjmg { 10, "500", (int64_t)500*1000*1000L, 0, 0 }, 209256130Sjmg { 11, "150", (int64_t)1500*1000*1000L, 0, 0 }, 210256130Sjmg 211256130Sjmg /* Test boundary cases for very large positive/negative number formatting */ 212256130Sjmg /* Explicit scale, divisor 1024 */ 213256130Sjmg 214256130Sjmg /* XXX = requires length 5 (buflen 6) for some cases*/ 215256130Sjmg /* KLUDGE - test loop below will bump length 5 up to 5 */ 216256130Sjmg { 3, "8 E", INT64_MAX, 0, 6 }, 217256130Sjmg { 4, "-8 E", -INT64_MAX, 0, 6 }, 218256130Sjmg { 3, "0 E", (int64_t)92*1024*1024*1024*1024*1024L, 0, 6 }, 219256130Sjmg { 3, "0 E", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 6 }, 220256130Sjmg { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, 0, 6 }, 221256130Sjmg { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 6 }, 222256130Sjmg { 3, "0 E", (int64_t)81*1024*1024*1024*1024*1024L, 0, 6 }, 223256130Sjmg { 3, "0 E", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 6 }, 224256130Sjmg { 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, 5 }, 225256130Sjmg { 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 5 }, 226256130Sjmg { 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, 5 }, 227256130Sjmg { 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 5 }, 228256130Sjmg { 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, 5 }, 229256130Sjmg { 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 5 }, 230256130Sjmg 231256130Sjmg /* Explicit scale, divisor 1000 */ 232256130Sjmg { 3, "9 E", INT64_MAX, HN_DIVISOR_1000, 6 }, 233256130Sjmg { 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000, 6 }, 234256130Sjmg { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 6 }, 235256130Sjmg { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 6 }, 236256130Sjmg { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 6 }, 237256130Sjmg { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 6 }, 238256130Sjmg { 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 5 }, 239256130Sjmg { 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 5 }, 240256130Sjmg { 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 5 }, 241256130Sjmg { 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 5 }, 242256130Sjmg 243256130Sjmg /* Autoscale, divisor 1024 */ 244256130Sjmg { 3, "8 E", INT64_MAX, 0, HN_AUTOSCALE }, 245256130Sjmg { 4, "-8 E", -INT64_MAX, 0, HN_AUTOSCALE }, 246256130Sjmg { 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE }, 247256130Sjmg { 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE }, 248256130Sjmg { 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE }, 249256130Sjmg { 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE }, 250256130Sjmg { 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE }, 251256130Sjmg { 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE }, 252256130Sjmg /* Autoscale, divisor 1000 */ 253256130Sjmg { 3, "9 E", INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE }, 254256130Sjmg { 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE }, 255256130Sjmg { 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE }, 256256130Sjmg { 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE }, 257256130Sjmg { 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE }, 258256130Sjmg { 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE }, 259256130Sjmg 260256130Sjmg /* 0 scale, divisor 1024 */ 261256130Sjmg { 12, "skdj", INT64_MAX, 0, 0 }, 262256130Sjmg { 21, "-9223", -INT64_MAX, 0, 0 }, 263256130Sjmg { 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, 0, 0 }, 264256130Sjmg { 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 0 }, 265256130Sjmg { 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, 0, 0 }, 266256130Sjmg { 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 0 }, 267256130Sjmg { 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, 0, 0 }, 268256130Sjmg { 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 0 }, 269256130Sjmg 270256130Sjmg /* 0 scale, divisor 1000 */ 271256130Sjmg /* XXX - why does this fail? */ 272256130Sjmg { -1, "", INT64_MAX, HN_DIVISOR_1000, 0 }, 273256130Sjmg { 21, "-9223", -INT64_MAX, HN_DIVISOR_1000, 0 }, 274256130Sjmg { 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 0 }, 275256130Sjmg { 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 0 }, 276256130Sjmg { 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 0 }, 277256130Sjmg { 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 0 }, 278256130Sjmg /* Expected to pass */ 279256130Sjmg { 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 0 }, 280256130Sjmg { 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 0 }, 281256130Sjmg 282256130Sjmg 283256130Sjmg 284256130Sjmg /* Need to implement tests for GETSCALE */ 285256130Sjmg/* { ?, "", (int64_t)0L, HN_DIVISOR_1000, HN_GETSCALE }, 286256130Sjmg ... 287256130Sjmg*/ 288256130Sjmg /* Tests for HN_DECIMAL */ 289256130Sjmg /* Positive, Autoscale */ 290256130Sjmg { 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 291256130Sjmg { 5, "994 k", (int64_t)994*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 292256130Sjmg { 5, "995 k", (int64_t)995*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 293256130Sjmg { 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 294256130Sjmg { 5, "1.0 M", (int64_t)1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 295256130Sjmg { 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 296256130Sjmg { 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 297256130Sjmg { 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 298256130Sjmg { 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 299256130Sjmg { 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 300256130Sjmg { 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 301256130Sjmg { 5, "994 M", (int64_t)994*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 302256130Sjmg { 5, "995 M", (int64_t)995*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 303256130Sjmg { 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 304256130Sjmg 305256130Sjmg { 5, "500 K", (int64_t)500*1024L, HN_DECIMAL, HN_AUTOSCALE }, 306256130Sjmg { 5, "994 K", (int64_t)994*1024L, HN_DECIMAL, HN_AUTOSCALE }, 307256130Sjmg { 5, "995 K", (int64_t)995*1024L, HN_DECIMAL, HN_AUTOSCALE }, 308256130Sjmg { 5, "999 K", (int64_t)999*1024L, HN_DECIMAL, HN_AUTOSCALE }, 309256130Sjmg { 5, "1.0 M", (int64_t)1000*1024L, HN_DECIMAL, HN_AUTOSCALE }, 310256130Sjmg { 5, "1.0 M", (int64_t)1018*1024L, HN_DECIMAL, HN_AUTOSCALE }, 311256130Sjmg { 5, "1.0 M", (int64_t)1019*1024L, HN_DECIMAL, HN_AUTOSCALE }, 312256130Sjmg { 5, "1.5 M", (int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE }, 313256130Sjmg { 5, "1.9 M", (int64_t)1996*1024L, HN_DECIMAL, HN_AUTOSCALE }, 314256130Sjmg { 5, "2.0 M", (int64_t)1997*1024L, HN_DECIMAL, HN_AUTOSCALE }, 315256130Sjmg { 5, "2.0 M", (int64_t)2047*1024L, HN_DECIMAL, HN_AUTOSCALE }, 316256130Sjmg { 5, "2.0 M", (int64_t)2048*1024L, HN_DECIMAL, HN_AUTOSCALE }, 317256130Sjmg { 5, "2.0 M", (int64_t)2099*1024L, HN_DECIMAL, HN_AUTOSCALE }, 318256130Sjmg { 5, "2.1 M", (int64_t)2100*1024L, HN_DECIMAL, HN_AUTOSCALE }, 319256130Sjmg { 5, "9.9 M", (int64_t)10188*1024L, HN_DECIMAL, HN_AUTOSCALE }, 320256130Sjmg /* XXX - shouldn't the following two be "10. M"? */ 321256130Sjmg { 4, "10 M", (int64_t)10189*1024L, HN_DECIMAL, HN_AUTOSCALE }, 322256130Sjmg { 4, "10 M", (int64_t)10240*1024L, HN_DECIMAL, HN_AUTOSCALE }, 323256130Sjmg { 5, "500 M", (int64_t)500*1024*1024L, HN_DECIMAL, HN_AUTOSCALE }, 324256130Sjmg { 5, "994 M", (int64_t)994*1024*1024L, HN_DECIMAL, HN_AUTOSCALE }, 325256130Sjmg { 5, "995 M", (int64_t)995*1024*1024L, HN_DECIMAL, HN_AUTOSCALE }, 326256130Sjmg { 5, "999 M", (int64_t)999*1024*1024L, HN_DECIMAL, HN_AUTOSCALE }, 327256130Sjmg { 5, "1.0 G", (int64_t)1000*1024*1024L, HN_DECIMAL, HN_AUTOSCALE }, 328256130Sjmg { 5, "1.0 G", (int64_t)1023*1024*1024L, HN_DECIMAL, HN_AUTOSCALE }, 329256130Sjmg 330256130Sjmg /* Negative, Autoscale - should pass */ 331256130Sjmg { 6, "-1.5 ", -(int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 332256130Sjmg { 6, "-1.9 ", -(int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 333256130Sjmg { 6, "-9.9 ", -(int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 334256130Sjmg 335256130Sjmg { 6, "-1.5 ", -(int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE }, 336256130Sjmg { 6, "-1.9 ", -(int64_t)1949*1024L, HN_DECIMAL, HN_AUTOSCALE }, 337256130Sjmg { 6, "-9.7 ", -(int64_t)9949*1024L, HN_DECIMAL, HN_AUTOSCALE }, 338256130Sjmg 339256130Sjmg /* Positive/negative, at maximum scale */ 340256130Sjmg { 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 341256130Sjmg { 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 342256130Sjmg { 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE }, 343256130Sjmg { 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 344256130Sjmg /* Negatives work with latest rev only: */ 345256130Sjmg { 6, "-9.2 ", -INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 346256130Sjmg { 6, "-8.9 ", -(int64_t)8949*1000*1000*1000*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE }, 347256130Sjmg 348256130Sjmg { 5, "8.0 E", INT64_MAX, HN_DECIMAL, HN_AUTOSCALE }, 349256130Sjmg { 5, "7.9 E", INT64_MAX-(int64_t)100*1024*1024*1024*1024*1024LL, HN_DECIMAL, HN_AUTOSCALE }, 350256130Sjmg { 6, "-8.0 ", -INT64_MAX, HN_DECIMAL, HN_AUTOSCALE }, 351256130Sjmg { 6, "-7.9 ", -INT64_MAX+(int64_t)100*1024*1024*1024*1024*1024LL, HN_DECIMAL, HN_AUTOSCALE }, 352256130Sjmg 353256130Sjmg /* Positive, Fixed scales */ 354256130Sjmg { 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 }, 355256130Sjmg { 5, "0.5 M", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 356256130Sjmg { 5, "949 k", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 }, 357256130Sjmg { 5, "0.9 M", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 358256130Sjmg { 5, "950 k", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 }, 359256130Sjmg { 5, "1.0 M", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 360256130Sjmg { 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 }, 361256130Sjmg { 5, "1.0 M", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 362256130Sjmg { 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 363256130Sjmg { 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 364256130Sjmg { 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 365256130Sjmg { 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 366256130Sjmg { 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 367256130Sjmg { 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 368256130Sjmg { 5, "0.5 G", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3 }, 369256130Sjmg { 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 }, 370256130Sjmg { 5, "1.0 G", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3 }, 371256130Sjmg /* Positive/negative, at maximum scale */ 372256130Sjmg { 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 }, 373256130Sjmg { 5, "1.0 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 }, 374256130Sjmg { 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 }, 375256130Sjmg { 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 }, 376256130Sjmg { 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, 6 }, 377256130Sjmg 378256130Sjmg /* HN_DECIMAL + binary + fixed scale cases not completed */ 379256130Sjmg { 5, "512 K", (int64_t)512*1024L, HN_DECIMAL, 1 }, 380256130Sjmg { 5, "0.5 M", (int64_t)512*1024L, HN_DECIMAL, 2 }, 381256130Sjmg 382256130Sjmg /* Negative, Fixed scales */ 383256130Sjmg /* Not yet added, but should work with latest rev */ 384256130Sjmg 385256130Sjmg}; 386256130Sjmg 387256130Sjmg 388256130Sjmg/* Command line options usage */ 389256130Sjmgstatic void 390256130Sjmgusage(char * progname) { 391256130Sjmg printf("%s: tests libutil humanize_number function\n", progname); 392256130Sjmg printf("Usage: %s [-nE] [-l num] [-v]\n\n", progname); 393256130Sjmg printf("Options:\n"); 394256130Sjmg printf("\t-l num\tSet max length for result; buflen = num + 1\n"); 395256130Sjmg printf("\t\t (NOTE: does not change expected result strings.)\n"); 396256130Sjmg printf("\t-n\tInclude negative scale tests, which cause older libutil\n"); 397256130Sjmg printf("\t\t version of function to coredump with assertion failure\n"); 398256130Sjmg printf("\t-E\tInclude numbers > 1/2 Exa[byte] which currently fail\n"); 399256130Sjmg printf("\t-v\tVerbose - always print summary results\n"); 400256130Sjmg printf("\t-h, -?\tShow options\n"); 401256130Sjmg} 402256130Sjmg 403256130Sjmg/* Parse command line options */ 404256130Sjmgstatic void 405256130Sjmgread_options(int argc, char * const argv[], size_t *bufLength, 406256130Sjmg int *includeNegativeScale, int *includeExabytes, int *verbose) { 407256130Sjmg int ch; 408256130Sjmg size_t temp; 409256130Sjmg 410256130Sjmg while ((ch = getopt(argc, argv, "nEh?vl:")) != -1) { 411256130Sjmg switch (ch) { 412256130Sjmg default: 413256130Sjmg usage(argv[0]); 414256130Sjmg exit(1); 415256130Sjmg break; /* UNREACHABLE */ 416256130Sjmg case 'h' : 417256130Sjmg case '?' : 418256130Sjmg usage(argv[0]); 419256130Sjmg exit(0); 420256130Sjmg break; /* UNREACHABLE */ 421256130Sjmg case 'l' : 422256130Sjmg sscanf(optarg, "%zu", &temp); 423256130Sjmg *bufLength = temp + 1; 424256130Sjmg break; 425256130Sjmg case 'n' : 426256130Sjmg *includeNegativeScale = 1; 427256130Sjmg break; 428256130Sjmg case 'E' : 429256130Sjmg *includeExabytes = 1; 430256130Sjmg break; 431256130Sjmg case 'v' : 432256130Sjmg *verbose = 1; 433256130Sjmg break; 434256130Sjmg } 435256130Sjmg } 436256130Sjmg} 437256130Sjmg 438256130Sjmgstatic struct { 439256130Sjmg int value; 440256130Sjmg const char *name; 441256130Sjmg } flags[] = { 442256130Sjmg { HN_AUTOSCALE, "HN_AUTOSCALE" }, 443256130Sjmg { HN_GETSCALE, "HN_GETSCALE" }, 444256130Sjmg { HN_DIVISOR_1000, "HN_DIVISOR_1000"}, 445256130Sjmg { HN_B, "HN_B"}, 446256130Sjmg { HN_DECIMAL, "HN_DECIMAL"}, 447256130Sjmg}; 448256130Sjmg 449256130Sjmgstatic const char *separator = "|"; 450256130Sjmg 451256130Sjmg/* Format flags parameter for meaningful display */ 452256130Sjmgstatic char * 453256130Sjmgstr_flags(int hn_flags, char *noFlags) { 454256130Sjmg size_t i; 455256130Sjmg char * result; 456256130Sjmg 457256130Sjmg result = malloc(MAX_STR_FLAGS_RESULT); 458256130Sjmg result[0] = '\0'; 459256130Sjmg 460256130Sjmg for (i = 0; i < sizeof flags / sizeof *flags; i++) { 461256130Sjmg if (hn_flags & flags[i].value) { 462256130Sjmg if (*result != 0) 463256130Sjmg strlcat(result, separator, 464256130Sjmg MAX_STR_FLAGS_RESULT); 465256130Sjmg strlcat(result, flags[i].name, MAX_STR_FLAGS_RESULT); 466256130Sjmg } 467256130Sjmg } 468256130Sjmg 469256130Sjmg if (strlen(result) == 0) 470256130Sjmg strlcat(result, noFlags, MAX_STR_FLAGS_RESULT); 471256130Sjmg return result; 472256130Sjmg} 473256130Sjmg 474256130Sjmg 475256130Sjmg/* Format scale parameter for meaningful display */ 476256130Sjmgstatic char * 477256130Sjmgstr_scale(int scale) { 478256130Sjmg char *result; 479256130Sjmg 480256130Sjmg if (scale == HN_AUTOSCALE || scale == HN_GETSCALE) 481256130Sjmg return str_flags(scale, ""); 482256130Sjmg 483256130Sjmg result = malloc(MAX_INT_STR_DIGITS); 484256130Sjmg result[0] = '\0'; 485256130Sjmg snprintf(result, MAX_INT_STR_DIGITS, "%d", scale); 486256130Sjmg return result; 487256130Sjmg} 488256130Sjmg 489256130Sjmgstatic void 490256130Sjmgtestskipped(size_t i) 491256130Sjmg{ 492256130Sjmg 493256130Sjmg printf("ok %lu # skip - not turned on\n", i); 494256130Sjmg} 495256130Sjmg 496256130Sjmgint 497256130Sjmgmain(int argc, char * const argv[]) 498256130Sjmg{ 499256130Sjmg char *buf; 500256130Sjmg char *flag_str, *scale_str; 501256130Sjmg size_t i; 502256130Sjmg size_t errcnt, tested, skipped; 503256130Sjmg int r; 504256130Sjmg size_t buflen; 505256130Sjmg int includeNegScale; 506256130Sjmg int includeExabyteTests; 507256130Sjmg int verbose; 508256130Sjmg 509256130Sjmg buflen = 4; 510256130Sjmg includeNegScale = 0; 511256130Sjmg includeExabyteTests = 0; 512256130Sjmg verbose = 0; 513256130Sjmg 514256130Sjmg read_options(argc, argv, &buflen, &includeNegScale, 515256130Sjmg &includeExabyteTests, &verbose); 516256130Sjmg 517256130Sjmg buf = malloc(buflen); 518256130Sjmg errcnt = 0; 519256130Sjmg tested = 0; 520256130Sjmg skipped = 0; 521256130Sjmg 522256130Sjmg if (buflen != 4) 523256130Sjmg printf("Warning: buffer size %zu != 4, expect some results to differ.\n", buflen); 524256130Sjmg 525256130Sjmg printf("1..%lu\n", sizeof test_args / sizeof *test_args); 526256130Sjmg for (i = 0; i < sizeof test_args / sizeof *test_args; i++) { 527256130Sjmg /* KLUDGE */ 528256130Sjmg if (test_args[i].num == INT64_MAX && buflen == 4) { 529256130Sjmg /* Start final tests which require buffer of 6 */ 530256130Sjmg free(buf); 531256130Sjmg buflen = 6; 532256130Sjmg buf = malloc(buflen); 533256130Sjmg if (verbose) 534256130Sjmg printf("Buffer length increased to %zu\n", 535256130Sjmg buflen); 536256130Sjmg } 537256130Sjmg 538256130Sjmg if (test_args[i].scale < 0 && ! includeNegScale) { 539256130Sjmg skipped++; 540256130Sjmg testskipped(i); 541256130Sjmg continue; 542256130Sjmg } 543256130Sjmg if (test_args[i].num >= halfExabyte && ! includeExabyteTests) { 544256130Sjmg skipped++; 545256130Sjmg testskipped(i); 546256130Sjmg continue; 547256130Sjmg } 548256130Sjmg 549256130Sjmg r = humanize_number(buf, buflen, test_args[i].num, "", 550256130Sjmg test_args[i].scale, test_args[i].flags); 551256130Sjmg flag_str = str_flags(test_args[i].flags, "[no flags]"); 552256130Sjmg scale_str = str_scale(test_args[i].scale); 553256130Sjmg 554256130Sjmg if (r != test_args[i].retval) { 555256130Sjmg if (verbose) 556256130Sjmg printf("wrong return value on index %lu, buflen: %zu, got: %d + \"%s\", expected %d + \"%s\"; num = %" PRId64 ", scale = %s, flags= %s.\n", 557256130Sjmg i, buflen, r, buf, test_args[i].retval, 558256130Sjmg test_args[i].res, test_args[i].num, 559256130Sjmg scale_str, flag_str); 560256130Sjmg else 561256130Sjmg printf("not ok %lu # return %d != %d\n", i, r, 562256130Sjmg test_args[i].retval); 563256130Sjmg errcnt++; 564256130Sjmg } else if (strcmp(buf, test_args[i].res) != 0) { 565256130Sjmg if (verbose) 566256130Sjmg printf("result mismatch on index %lu, got: \"%s\", expected \"%s\"; num = %" PRId64 ", scale = %s, flags= %s.\n", 567256130Sjmg i, buf, test_args[i].res, test_args[i].num, 568256130Sjmg scale_str, flag_str); 569256130Sjmg else 570256130Sjmg printf("not ok %lu # buf \"%s\" != \"%s\"\n", i, 571256130Sjmg buf, test_args[i].res); 572256130Sjmg errcnt++; 573256130Sjmg } else { 574256130Sjmg if (verbose) 575256130Sjmg printf("successful result on index %lu, returned %d, got: \"%s\"; num = %" PRId64 ", scale = %s, flags= %s.\n", 576256130Sjmg i, r, buf, test_args[i].num, scale_str, 577256130Sjmg flag_str); 578256130Sjmg else 579256130Sjmg printf("ok %lu\n", i); 580256130Sjmg } 581256130Sjmg tested++; 582256130Sjmg } 583256130Sjmg 584256130Sjmg if (verbose) 585256130Sjmg printf("total errors: %lu/%lu tests, %lu skipped\n", errcnt, 586256130Sjmg tested, skipped); 587256130Sjmg 588256130Sjmg if (errcnt) 589256130Sjmg return 1; 590256130Sjmg 591256130Sjmg return 0; 592256130Sjmg} 593