10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
54891Svk199839 * Common Development and Distribution License (the "License").
64891Svk199839 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*13093SRoger.Faulkner@Oracle.COM
220Sstevel@tonic-gate /*
23*13093SRoger.Faulkner@Oracle.COM * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <sys/param.h>
270Sstevel@tonic-gate #include <libintl.h>
280Sstevel@tonic-gate #include <string.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <stdarg.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <errno.h>
330Sstevel@tonic-gate #include <strings.h>
340Sstevel@tonic-gate #include <sys/types.h>
350Sstevel@tonic-gate #include <limits.h>
360Sstevel@tonic-gate #include "utils.h"
370Sstevel@tonic-gate
380Sstevel@tonic-gate static char PNAME_FMT[] = "%s: ";
390Sstevel@tonic-gate static char ERRNO_FMT[] = ": %s\n";
400Sstevel@tonic-gate static char EOL_FMT[] = "\n";
410Sstevel@tonic-gate
420Sstevel@tonic-gate static char *pname;
430Sstevel@tonic-gate
440Sstevel@tonic-gate char *
setpname(char * arg0)45*13093SRoger.Faulkner@Oracle.COM setpname(char *arg0)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate char *p = strrchr(arg0, '/');
480Sstevel@tonic-gate
490Sstevel@tonic-gate if (p == NULL)
500Sstevel@tonic-gate p = arg0;
510Sstevel@tonic-gate else
520Sstevel@tonic-gate p++;
530Sstevel@tonic-gate pname = p;
540Sstevel@tonic-gate return (pname);
550Sstevel@tonic-gate }
560Sstevel@tonic-gate
570Sstevel@tonic-gate /*PRINTFLIKE1*/
580Sstevel@tonic-gate void
warn(const char * format,...)594891Svk199839 warn(const char *format, ...)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate int err = errno;
620Sstevel@tonic-gate va_list alist;
630Sstevel@tonic-gate if (pname != NULL)
640Sstevel@tonic-gate (void) fprintf(stderr, gettext(PNAME_FMT), pname);
650Sstevel@tonic-gate va_start(alist, format);
660Sstevel@tonic-gate (void) vfprintf(stderr, format, alist);
670Sstevel@tonic-gate va_end(alist);
680Sstevel@tonic-gate if (strchr(format, '\n') == NULL)
690Sstevel@tonic-gate if (err)
700Sstevel@tonic-gate (void) fprintf(stderr,
710Sstevel@tonic-gate gettext(ERRNO_FMT), strerror(err));
720Sstevel@tonic-gate else
730Sstevel@tonic-gate (void) fprintf(stderr, gettext(EOL_FMT));
740Sstevel@tonic-gate
750Sstevel@tonic-gate
760Sstevel@tonic-gate }
770Sstevel@tonic-gate
780Sstevel@tonic-gate static char *__metric_modifiers[] = { "K", "M", "G", "T", "P", "E", NULL };
790Sstevel@tonic-gate static uint64_t __metric_scales[] = {
800Sstevel@tonic-gate 1000LLU,
810Sstevel@tonic-gate 1000LLU * 1000,
820Sstevel@tonic-gate 1000LLU * 1000 * 1000,
830Sstevel@tonic-gate 1000LLU * 1000 * 1000 * 1000,
840Sstevel@tonic-gate 1000LLU * 1000 * 1000 * 1000 * 1000,
850Sstevel@tonic-gate 1000LLU * 1000 * 1000 * 1000 * 1000 * 1000
860Sstevel@tonic-gate };
870Sstevel@tonic-gate static scale_t __metric_scale = { __metric_modifiers, __metric_scales };
880Sstevel@tonic-gate
890Sstevel@tonic-gate static char *__binary_modifiers[] = {"K", "M", "G", "T", "P", "E", NULL};
900Sstevel@tonic-gate static uint64_t __binary_scales[] = {
910Sstevel@tonic-gate 1024LLU,
920Sstevel@tonic-gate 1024LLU * 1024,
930Sstevel@tonic-gate 1024LLU * 1024 * 1024,
940Sstevel@tonic-gate 1024LLU * 1024 * 1024 * 1024,
950Sstevel@tonic-gate 1024LLU * 1024 * 1024 * 1024 * 1024,
960Sstevel@tonic-gate 1024LLU * 1024 * 1024 * 1024 * 1024 * 1024
970Sstevel@tonic-gate };
980Sstevel@tonic-gate static scale_t __binary_scale = { __binary_modifiers, __binary_scales };
990Sstevel@tonic-gate
1000Sstevel@tonic-gate scale_t *scale_metric = &__metric_scale;
1010Sstevel@tonic-gate scale_t *scale_binary = &__binary_scale;
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate int
scaledtouint64(char * scaledin,uint64_t * uint64out,int * widthout,char ** modifierout,char ** unitout,scale_t * scale,char * unit,int flags)1040Sstevel@tonic-gate scaledtouint64(char *scaledin,
1050Sstevel@tonic-gate uint64_t *uint64out,
1060Sstevel@tonic-gate int *widthout, char **modifierout, char **unitout,
1070Sstevel@tonic-gate scale_t *scale, char *unit, int flags) {
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate double result;
1100Sstevel@tonic-gate double value;
1110Sstevel@tonic-gate int index = 0;
1120Sstevel@tonic-gate uint64_t multiplier = 1;
1130Sstevel@tonic-gate char string[SCALED_STRLEN];
1140Sstevel@tonic-gate char *endptr;
1150Sstevel@tonic-gate int cmp;
1160Sstevel@tonic-gate int hasmodifier = 0;
1170Sstevel@tonic-gate char **modifiers = scale->modifers;
1180Sstevel@tonic-gate uint64_t *scales = scale->scales;
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate if (modifierout)
1210Sstevel@tonic-gate *modifierout = NULL;
1220Sstevel@tonic-gate if (unitout)
1230Sstevel@tonic-gate *unitout = NULL;
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate * first check for hex value, which cannot be scaled, as
1270Sstevel@tonic-gate * hex letters cannot be disserned from modifier or unit letters
1280Sstevel@tonic-gate */
1290Sstevel@tonic-gate if ((strncmp("0x", scaledin, 2) == 0) ||
1300Sstevel@tonic-gate (strncmp("0X", scaledin, 2) == 0)) {
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate /* unit cannot be required on hex values */
1330Sstevel@tonic-gate if ((unit && *unit != '\0') &&
1340Sstevel@tonic-gate !(flags & SCALED_UNIT_OPTIONAL_FLAG))
1350Sstevel@tonic-gate return (SCALED_INVALID_UNIT);
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate errno = 0;
1380Sstevel@tonic-gate *uint64out = strtoull(scaledin, &endptr, 16);
1390Sstevel@tonic-gate if (errno) {
1400Sstevel@tonic-gate if (errno == ERANGE)
1410Sstevel@tonic-gate return (SCALED_OVERFLOW);
1420Sstevel@tonic-gate else
1430Sstevel@tonic-gate return (SCALED_INVALID_NUMBER);
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate if (*endptr != '\0')
1460Sstevel@tonic-gate return (SCALED_INVALID_NUMBER);
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate /* compute width of decimal equivalent */
1490Sstevel@tonic-gate if (widthout) {
1500Sstevel@tonic-gate (void) snprintf(
1510Sstevel@tonic-gate string, SCALED_STRLEN, "%llu", *uint64out);
1520Sstevel@tonic-gate *widthout = strlen(string);
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate return (0);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate /* scan out numeric value */
1580Sstevel@tonic-gate errno = 0;
1590Sstevel@tonic-gate value = strtod(scaledin, &endptr);
1600Sstevel@tonic-gate if (errno) {
1610Sstevel@tonic-gate if (errno == ERANGE)
1620Sstevel@tonic-gate return (SCALED_OVERFLOW);
1630Sstevel@tonic-gate else
1640Sstevel@tonic-gate return (SCALED_INVALID_NUMBER);
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate if (endptr == scaledin)
1680Sstevel@tonic-gate return (SCALED_INVALID_NUMBER);
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate /* no negative values */
1710Sstevel@tonic-gate if (strchr(scaledin, '-'))
1720Sstevel@tonic-gate return (SCALED_INVALID_NUMBER);
1730Sstevel@tonic-gate if (value < 0.0)
1740Sstevel@tonic-gate return (SCALED_INVALID_NUMBER);
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate /* compute width of number string */
1780Sstevel@tonic-gate if (widthout)
1790Sstevel@tonic-gate *widthout = (int)(endptr - scaledin);
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate /* check possible modifier */
1820Sstevel@tonic-gate if (*endptr != '\0') {
1830Sstevel@tonic-gate index = 0;
1840Sstevel@tonic-gate while (modifiers[index] != NULL) {
1850Sstevel@tonic-gate if (flags & SCALED_MODIFIER_CASE_INSENSITIVE_FLAG)
1860Sstevel@tonic-gate cmp = strncasecmp(modifiers[index], endptr,
1870Sstevel@tonic-gate strlen(modifiers[index]));
1880Sstevel@tonic-gate else
1890Sstevel@tonic-gate cmp = strncmp(modifiers[index], endptr,
1900Sstevel@tonic-gate strlen(modifiers[index]));
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate if (cmp == 0) {
1930Sstevel@tonic-gate if (modifierout)
1940Sstevel@tonic-gate *modifierout = modifiers[index];
1950Sstevel@tonic-gate endptr += strlen(modifiers[index]);
1960Sstevel@tonic-gate multiplier = scales[index];
1970Sstevel@tonic-gate result = value * multiplier;
1980Sstevel@tonic-gate if (result > UINT64_MAX)
1990Sstevel@tonic-gate return (SCALED_OVERFLOW);
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate *uint64out = (uint64_t)result;
2020Sstevel@tonic-gate hasmodifier = 1;
2030Sstevel@tonic-gate break;
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate index++;
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate /* if there is no modifier, value must be an integer */
2090Sstevel@tonic-gate if (!hasmodifier) {
2100Sstevel@tonic-gate errno = 0;
2110Sstevel@tonic-gate *uint64out = strtoull(scaledin, &endptr, 0);
2120Sstevel@tonic-gate if (errno) {
2130Sstevel@tonic-gate if (errno == ERANGE)
2140Sstevel@tonic-gate return (SCALED_OVERFLOW);
2150Sstevel@tonic-gate else
2160Sstevel@tonic-gate return (SCALED_INVALID_NUMBER);
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate if (endptr == scaledin)
2190Sstevel@tonic-gate return (SCALED_INVALID_NUMBER);
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate /* if unit is present when no unit is allowed, fail */
2230Sstevel@tonic-gate if ((unit == NULL || *unit == '\0') && (*endptr != '\0'))
2240Sstevel@tonic-gate return (SCALED_INVALID_UNIT);
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate /* check for missing unit when unit is required */
2270Sstevel@tonic-gate if ((unit && *unit != '\0') &&
2280Sstevel@tonic-gate !(flags & SCALED_UNIT_OPTIONAL_FLAG) &&
2290Sstevel@tonic-gate (*endptr == '\0'))
2300Sstevel@tonic-gate return (SCALED_INVALID_UNIT);
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate /* validate unit */
2330Sstevel@tonic-gate if (unit && *unit != '\0') {
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate /* allow for missing unit if it is optional */
2360Sstevel@tonic-gate if ((flags & SCALED_UNIT_OPTIONAL_FLAG) &&
2370Sstevel@tonic-gate (*endptr == '\0'))
2380Sstevel@tonic-gate return (0);
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate if (flags & SCALED_UNIT_CASE_INSENSITIVE_FLAG)
2410Sstevel@tonic-gate cmp = strncasecmp(unit, endptr, strlen(unit));
2420Sstevel@tonic-gate else
2430Sstevel@tonic-gate cmp = strncmp(unit, endptr, strlen(unit));
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate if (cmp != 0)
2460Sstevel@tonic-gate return (SCALED_INVALID_UNIT);
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate if (*(endptr + strlen(unit)) != '\0')
2490Sstevel@tonic-gate return (SCALED_INVALID_UNIT);
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate if (unitout)
2520Sstevel@tonic-gate *unitout = unit;
2530Sstevel@tonic-gate }
2540Sstevel@tonic-gate return (0);
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate int
uint64toscaled(uint64_t uint64in,int widthin,char * maxmodifierin,char * scaledout,int * widthout,char ** modifierout,scale_t * scale,char * unit,int flags)2590Sstevel@tonic-gate uint64toscaled(uint64_t uint64in, int widthin, char *maxmodifierin,
2600Sstevel@tonic-gate char *scaledout, int *widthout, char **modifierout,
2610Sstevel@tonic-gate scale_t *scale, char *unit, int flags) {
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate int index = 0;
2640Sstevel@tonic-gate int count;
2650Sstevel@tonic-gate int width;
2660Sstevel@tonic-gate int decimals = 0;
2670Sstevel@tonic-gate char string[SCALED_STRLEN];
2680Sstevel@tonic-gate double value;
2690Sstevel@tonic-gate char **modifiers = scale->modifers;
2700Sstevel@tonic-gate uint64_t *scales = scale->scales;
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate /* don't scale if there is no reason to */
2730Sstevel@tonic-gate if (uint64in < scales[0] || maxmodifierin == NULL) {
2740Sstevel@tonic-gate if (flags & SCALED_PAD_WIDTH_FLAG)
2750Sstevel@tonic-gate width = widthin;
2760Sstevel@tonic-gate else
2770Sstevel@tonic-gate width = 0;
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate (void) snprintf(string, SCALED_STRLEN, "%%%dllu", width);
2800Sstevel@tonic-gate /* LINTED */
2810Sstevel@tonic-gate count = snprintf(scaledout, SCALED_STRLEN, string, uint64in);
2820Sstevel@tonic-gate if (unit && *unit != '\0')
2830Sstevel@tonic-gate (void) strcat(scaledout, unit);
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate if (widthout)
2860Sstevel@tonic-gate *widthout = count;
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate if (modifierout)
2890Sstevel@tonic-gate *modifierout = NULL;
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate return (0);
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate for (index = 0; modifiers[index + 1] != NULL; index++) {
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate if (uint64in >= scales[index] &&
2970Sstevel@tonic-gate uint64in < scales[index + 1])
2980Sstevel@tonic-gate break;
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate if ((strncmp(modifiers[index], maxmodifierin,
3010Sstevel@tonic-gate strlen(modifiers[index])) == 0) &&
3020Sstevel@tonic-gate (strlen(modifiers[index]) == strlen(maxmodifierin)))
3030Sstevel@tonic-gate break;
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate value = ((double)(uint64in)) / scales[index];
3080Sstevel@tonic-gate if (modifierout)
3090Sstevel@tonic-gate *modifierout = modifiers[index];
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate count = snprintf(string, SCALED_STRLEN, "%0.0lf", value);
3120Sstevel@tonic-gate while (count < widthin) {
3130Sstevel@tonic-gate decimals++;
3140Sstevel@tonic-gate (void) snprintf(string, SCALED_STRLEN, "%%0.%dlf", decimals);
3150Sstevel@tonic-gate /* LINTED */
3160Sstevel@tonic-gate count = snprintf(scaledout, SCALED_STRLEN, string, value);
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate /* reduce decimal places if we've overshot the desired width */
3190Sstevel@tonic-gate if (count > widthin) {
3200Sstevel@tonic-gate decimals--;
3210Sstevel@tonic-gate break;
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate if (flags & SCALED_PAD_WIDTH_FLAG)
3260Sstevel@tonic-gate width = widthin;
3270Sstevel@tonic-gate else
3280Sstevel@tonic-gate width = 0;
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate (void) snprintf(string, SCALED_STRLEN, "%%%d.%dlf", width, decimals);
3310Sstevel@tonic-gate /* LINTED */
3320Sstevel@tonic-gate count = snprintf(scaledout, SCALED_STRLEN, string, value);
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate (void) strcat(scaledout, modifiers[index]);
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate if (unit && *unit != '\0')
3370Sstevel@tonic-gate (void) strcat(scaledout, unit);
3380Sstevel@tonic-gate
3390Sstevel@tonic-gate if (widthout)
3400Sstevel@tonic-gate *widthout = count;
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate return (0);
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate int
scaledtoscaled(char * scaledin,int widthin,char * maxmodifierin,char * scaledout,int * widthout,char ** modifierout,scale_t * scale,char * unit,int flags)3460Sstevel@tonic-gate scaledtoscaled(char *scaledin, int widthin, char *maxmodifierin,
3470Sstevel@tonic-gate char *scaledout, int *widthout, char **modifierout,
3480Sstevel@tonic-gate scale_t *scale, char *unit, int flags) {
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate int ret;
3510Sstevel@tonic-gate uint64_t val;
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate ret = scaledtouint64(scaledin, &val, NULL, NULL, NULL,
3540Sstevel@tonic-gate scale, unit, flags);
3550Sstevel@tonic-gate if (ret)
3560Sstevel@tonic-gate return (ret);
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate ret = uint64toscaled(val, widthin, maxmodifierin,
3590Sstevel@tonic-gate scaledout, widthout, modifierout,
3600Sstevel@tonic-gate scale, unit, flags);
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate return (ret);
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate int
scaledeqscaled(char * scaled1,char * scaled2,scale_t * scale,char * unit,int flags)3660Sstevel@tonic-gate scaledeqscaled(char *scaled1, char *scaled2,
3670Sstevel@tonic-gate scale_t *scale, char *unit, int flags) {
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate int ret;
3700Sstevel@tonic-gate uint64_t uint64;
3710Sstevel@tonic-gate char *modifier1;
3720Sstevel@tonic-gate char *modifier2;
3730Sstevel@tonic-gate char *modifier = NULL;
3740Sstevel@tonic-gate int i;
3750Sstevel@tonic-gate int width;
3760Sstevel@tonic-gate int width1;
3770Sstevel@tonic-gate int width2;
3780Sstevel@tonic-gate char scaledA[SCALED_STRLEN];
3790Sstevel@tonic-gate char scaledB[SCALED_STRLEN];
3800Sstevel@tonic-gate char **modifiers = scale->modifers;
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate /*
3830Sstevel@tonic-gate * remove padding flag, so strings to compare will not have
3840Sstevel@tonic-gate * whitespace
3850Sstevel@tonic-gate */
3860Sstevel@tonic-gate flags = flags & (~SCALED_PAD_WIDTH_FLAG);
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate /* determine each number's width and modifier */
3890Sstevel@tonic-gate ret = scaledtouint64(scaled1, &uint64, &width1, &modifier1, NULL,
3900Sstevel@tonic-gate scale, unit, flags);
3910Sstevel@tonic-gate if (ret)
3920Sstevel@tonic-gate return (0);
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate ret = scaledtouint64(scaled2, &uint64, &width2, &modifier2, NULL,
3950Sstevel@tonic-gate scale, unit, flags);
3960Sstevel@tonic-gate if (ret)
3970Sstevel@tonic-gate return (0);
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /*
4000Sstevel@tonic-gate * determine the width and modifier to use for comparison.
4010Sstevel@tonic-gate * Use widest width and smallest modifier.
4020Sstevel@tonic-gate * Rescale to new width and modifier
4030Sstevel@tonic-gate */
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate if (modifier1 == NULL || modifier2 == NULL)
4060Sstevel@tonic-gate modifier = NULL;
4070Sstevel@tonic-gate else {
4080Sstevel@tonic-gate for (i = 0; modifiers[i] != NULL; i++) {
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate if (strcmp(modifier1, modifiers[i]) == 0) {
4110Sstevel@tonic-gate modifier = modifiers[i];
4120Sstevel@tonic-gate break;
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate if (strcmp(modifier2, modifiers[i]) == 0) {
4150Sstevel@tonic-gate modifier = modifiers[i];
4160Sstevel@tonic-gate break;
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate width = 0;
4210Sstevel@tonic-gate if (width1 > width)
4220Sstevel@tonic-gate width = width1;
4230Sstevel@tonic-gate if (width2 > width)
4240Sstevel@tonic-gate width = width2;
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate /*
4270Sstevel@tonic-gate * Convert first number to width and modifier.
4280Sstevel@tonic-gate * This is done for the following reasons:
4290Sstevel@tonic-gate * 1. In case first number is hecadecimal. This will convert
4300Sstevel@tonic-gate * it to decimal
4310Sstevel@tonic-gate * 2. In case the first number has < the minimum number of
4320Sstevel@tonic-gate * columns.
4330Sstevel@tonic-gate * 3. The first number is missing an optional unit string.
4340Sstevel@tonic-gate * 4. Fix casing of modifier and unit.
4350Sstevel@tonic-gate */
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate ret = scaledtoscaled(scaled1, width, modifier,
4380Sstevel@tonic-gate scaledA, NULL, NULL, scale, unit, flags);
4390Sstevel@tonic-gate if (ret)
4400Sstevel@tonic-gate return (0);
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate /* convert second number to width and modifier matching first number */
4430Sstevel@tonic-gate ret = scaledtoscaled(scaled2, width, modifier,
4440Sstevel@tonic-gate scaledB, NULL, NULL, scale, unit, flags);
4450Sstevel@tonic-gate if (ret)
4460Sstevel@tonic-gate return (0);
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate /* numbers are equal if strings match */
4490Sstevel@tonic-gate return ((strncmp(scaledA, scaledB, strlen(scaledA)) == 0) &&
4500Sstevel@tonic-gate (strlen(scaledA) == strlen(scaledB)));
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate int
scaledequint64(char * scaled,uint64_t uint64,int minwidth,scale_t * scale,char * unit,int flags)4550Sstevel@tonic-gate scaledequint64(char *scaled, uint64_t uint64, int minwidth,
4560Sstevel@tonic-gate scale_t *scale, char *unit, int flags) {
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate int ret;
4590Sstevel@tonic-gate uint64_t tmpuint64;
4600Sstevel@tonic-gate char *modifier;
4610Sstevel@tonic-gate int width;
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate char scaledA[SCALED_STRLEN];
4640Sstevel@tonic-gate char scaledB[SCALED_STRLEN];
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate /* determine for number's width and modifier */
4670Sstevel@tonic-gate ret = scaledtouint64(scaled, &tmpuint64, &width, &modifier, NULL,
4680Sstevel@tonic-gate scale, unit, flags);
4690Sstevel@tonic-gate if (ret)
4700Sstevel@tonic-gate return (0);
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate if (width < minwidth)
4730Sstevel@tonic-gate width = minwidth;
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate /*
4760Sstevel@tonic-gate * Convert first number to width and modifier.
4770Sstevel@tonic-gate * This is done for the following reasons:
4780Sstevel@tonic-gate * 1. In case first number is hecadecimal. This will convert
4790Sstevel@tonic-gate * it to decimal
4800Sstevel@tonic-gate * 2. In case the first number has < the minimum number of
4810Sstevel@tonic-gate * columns.
4820Sstevel@tonic-gate * 3. The first number is missing an optional unit string.
4830Sstevel@tonic-gate * 4. Fix casing of modifier and unit.
4840Sstevel@tonic-gate */
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate ret = scaledtoscaled(scaled, width, modifier,
4870Sstevel@tonic-gate scaledA, NULL, NULL, scale, unit, flags);
4880Sstevel@tonic-gate if (ret)
4890Sstevel@tonic-gate return (0);
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate /* convert second number to width and modifier matching first number */
4920Sstevel@tonic-gate ret = uint64toscaled(uint64, width, modifier,
4930Sstevel@tonic-gate scaledB, NULL, NULL, scale, unit, flags);
4940Sstevel@tonic-gate if (ret)
4950Sstevel@tonic-gate return (0);
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate /* numbers are equal if strings match */
4980Sstevel@tonic-gate return ((strncmp(scaledA, scaledB, strlen(scaledA)) == 0) &&
4990Sstevel@tonic-gate (strlen(scaledA) == strlen(scaledB)));
5000Sstevel@tonic-gate }
501