"Fossies" - the Fresh Open Source Software Archive

Member "xombrero-1.6.4/netbsd/netbsd.c" (17 Feb 2015, 8446 Bytes) of package /linux/www/old/xombrero-1.6.4.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "netbsd.c" see the Fossies "Dox" file reference documentation.

    1 /*  $OpenBSD: fmt_scaled.c,v 1.10 2009/06/20 15:00:04 martynas Exp $    */
    2 
    3 /*
    4  * Copyright (c) 2001, 2002, 2003 Ian F. Darwin.  All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * fmt_scaled: Format numbers scaled for human comprehension
   31  * scan_scaled: Scan numbers in this format.
   32  *
   33  * "Human-readable" output uses 4 digits max, and puts a unit suffix at
   34  * the end.  Makes output compact and easy-to-read esp. on huge disks.
   35  * Formatting code was originally in OpenBSD "df", converted to library routine.
   36  * Scanning code written for OpenBSD libutil.
   37  */
   38 
   39 #include <stdio.h>
   40 #include <stdlib.h>
   41 #include <errno.h>
   42 #include <string.h>
   43 #include <ctype.h>
   44 #include <limits.h>
   45 
   46 #include "util.h"
   47 
   48 typedef enum {
   49     NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6
   50 } unit_type;
   51 
   52 /* These three arrays MUST be in sync!  XXX make a struct */
   53 static unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA };
   54 static char scale_chars[] = "BKMGTPE";
   55 static long long scale_factors[] = {
   56     1LL,
   57     1024LL,
   58     1024LL*1024,
   59     1024LL*1024*1024,
   60     1024LL*1024*1024*1024,
   61     1024LL*1024*1024*1024*1024,
   62     1024LL*1024*1024*1024*1024*1024,
   63 };
   64 #define SCALE_LENGTH (sizeof(units)/sizeof(units[0]))
   65 
   66 #define MAX_DIGITS (SCALE_LENGTH * 3)   /* XXX strlen(sprintf("%lld", -1)? */
   67 
   68 /* Convert the given input string "scaled" into numeric in "result".
   69  * Return 0 on success, -1 and errno set on error.
   70  */
   71 int
   72 scan_scaled(char *scaled, long long *result)
   73 {
   74     char *p = scaled;
   75     int sign = 0;
   76     unsigned int i, ndigits = 0, fract_digits = 0;
   77     long long scale_fact = 1, whole = 0, fpart = 0;
   78 
   79     /* Skip leading whitespace */
   80     while (isascii((unsigned char)*p) &&
   81           isspace((unsigned char)*p))
   82         ++p;
   83 
   84     /* Then at most one leading + or - */
   85     while (*p == '-' || *p == '+') {
   86         if (*p == '-') {
   87             if (sign) {
   88                 errno = EINVAL;
   89                 return -1;
   90             }
   91             sign = -1;
   92             ++p;
   93         } else if (*p == '+') {
   94             if (sign) {
   95                 errno = EINVAL;
   96                 return -1;
   97             }
   98             sign = +1;
   99             ++p;
  100         }
  101     }
  102 
  103     /* Main loop: Scan digits, find decimal point, if present.
  104      * We don't allow exponentials, so no scientific notation
  105      * (but note that E for Exa might look like e to some!).
  106      * Advance 'p' to end, to get scale factor.
  107      */
  108     for (; isascii((unsigned char)*p) &&
  109             (isdigit((unsigned char)*p) || *p=='.'); ++p) {
  110         if (*p == '.') {
  111             if (fract_digits > 0) { /* oops, more than one '.' */
  112                 errno = EINVAL;
  113                 return -1;
  114             }
  115             fract_digits = 1;
  116             continue;
  117         }
  118 
  119         i = (*p) - '0';         /* whew! finally a digit we can use */
  120         if (fract_digits > 0) {
  121             if (fract_digits >= MAX_DIGITS-1)
  122                 /* ignore extra fractional digits */
  123                 continue;
  124             fract_digits++;     /* for later scaling */
  125             fpart *= 10;
  126             fpart += i;
  127         } else {                /* normal digit */
  128             if (++ndigits >= MAX_DIGITS) {
  129                 errno = ERANGE;
  130                 return -1;
  131             }
  132             whole *= 10;
  133             whole += i;
  134         }
  135     }
  136 
  137     if (sign) {
  138         whole *= sign;
  139         fpart *= sign;
  140     }
  141 
  142     /* If no scale factor given, we're done. fraction is discarded. */
  143     if (!*p) {
  144         *result = whole;
  145         return 0;
  146     }
  147 
  148     /* Validate scale factor, and scale whole and fraction by it. */
  149     for (i = 0; i < SCALE_LENGTH; i++) {
  150 
  151         /* Are we there yet? */
  152         if (*p == scale_chars[i] ||
  153             *p == tolower((unsigned char)scale_chars[i])) {
  154 
  155             /* If it ends with alphanumerics after the scale char, bad. */
  156             if (isalnum((unsigned char)*(p+1))) {
  157                 errno = EINVAL;
  158                 return -1;
  159             }
  160             scale_fact = scale_factors[i];
  161 
  162             /* scale whole part */
  163             whole *= scale_fact;
  164 
  165             /* truncate fpart so it does't overflow.
  166              * then scale fractional part.
  167              */
  168             while (fpart >= LLONG_MAX / scale_fact) {
  169                 fpart /= 10;
  170                 fract_digits--;
  171             }
  172             fpart *= scale_fact;
  173             if (fract_digits > 0) {
  174                 for (i = 0; i < fract_digits -1; i++)
  175                     fpart /= 10;
  176             }
  177             whole += fpart;
  178             *result = whole;
  179             return 0;
  180         }
  181     }
  182     errno = ERANGE;
  183     return -1;
  184 }
  185 
  186 /* Format the given "number" into human-readable form in "result".
  187  * Result must point to an allocated buffer of length FMT_SCALED_STRSIZE.
  188  * Return 0 on success, -1 and errno set if error.
  189  */
  190 int
  191 fmt_scaled(long long number, char *result)
  192 {
  193     long long abval, fract = 0;
  194     unsigned int i;
  195     unit_type unit = NONE;
  196 
  197     abval = llabs(number);
  198 
  199     /* Not every negative long long has a positive representation.
  200      * Also check for numbers that are just too darned big to format
  201      */
  202     if (abval < 0 || abval / 1024 >= scale_factors[SCALE_LENGTH-1]) {
  203         errno = ERANGE;
  204         return -1;
  205     }
  206 
  207     /* scale whole part; get unscaled fraction */
  208     for (i = 0; i < SCALE_LENGTH; i++) {
  209         if (abval/1024 < scale_factors[i]) {
  210             unit = units[i];
  211             fract = (i == 0) ? 0 : abval % scale_factors[i];
  212             number /= scale_factors[i];
  213             if (i > 0)
  214                 fract /= scale_factors[i - 1];
  215             break;
  216         }
  217     }
  218 
  219     fract = (10 * fract + 512) / 1024;
  220     /* if the result would be >= 10, round main number */
  221     if (fract == 10) {
  222         if (number >= 0)
  223             number++;
  224         else
  225             number--;
  226         fract = 0;
  227     }
  228 
  229     if (number == 0)
  230         strlcpy(result, "0B", FMT_SCALED_STRSIZE);
  231     else if (unit == NONE || number >= 100 || number <= -100) {
  232         if (fract >= 5) {
  233             if (number >= 0)
  234                 number++;
  235             else
  236                 number--;
  237         }
  238         (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c",
  239             number, scale_chars[unit]);
  240     } else
  241         (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c",
  242             number, fract, scale_chars[unit]);
  243 
  244     return 0;
  245 }
  246 
  247 /*  $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $    */
  248 
  249 /*
  250  * Copyright (c) 2004 Ted Unangst and Todd Miller
  251  * All rights reserved.
  252  *
  253  * Permission to use, copy, modify, and distribute this software for any
  254  * purpose with or without fee is hereby granted, provided that the above
  255  * copyright notice and this permission notice appear in all copies.
  256  *
  257  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  258  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  259  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  260  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  261  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  262  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  263  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  264  */
  265 
  266 #include <errno.h>
  267 #include <limits.h>
  268 #include <stdlib.h>
  269 
  270 #define INVALID     1
  271 #define TOOSMALL    2
  272 #define TOOLARGE    3
  273 
  274 long long
  275 strtonum(const char *numstr, long long minval, long long maxval,
  276     const char **errstrp)
  277 {
  278     long long ll = 0;
  279     char *ep;
  280     int error = 0;
  281     struct errval {
  282         const char *errstr;
  283         int err;
  284     } ev[4] = {
  285         { NULL,     0 },
  286         { "invalid",    EINVAL },
  287         { "too small",  ERANGE },
  288         { "too large",  ERANGE },
  289     };
  290 
  291     ev[0].err = errno;
  292     errno = 0;
  293     if (minval > maxval)
  294         error = INVALID;
  295     else {
  296         ll = strtoll(numstr, &ep, 10);
  297         if (numstr == ep || *ep != '\0')
  298             error = INVALID;
  299         else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
  300             error = TOOSMALL;
  301         else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
  302             error = TOOLARGE;
  303     }
  304     if (errstrp != NULL)
  305         *errstrp = ev[error].errstr;
  306     errno = ev[error].err;
  307     if (error)
  308         ll = 0;
  309 
  310     return (ll);
  311 }