cynix

x86 UNIX-like OS
git clone git://git.2f30.org/cynix
Log | Files | Refs | README | LICENSE

stdlib.c (3609B)


      1 /*
      2  *  libc/stdlib.c
      3  *
      4  *  Copyright (C) 2009 stateless
      5  */
      6 
      7 #include <stdlib.h>
      8 #include <ctype.h>
      9 #include <errno.h>
     10 
     11 void
     12 itoa(long int num, char *buffer, int base)
     13 {
     14 	static char hex[] = "0123456789abcdef";
     15 	char *ptr = buffer, tmp, *beg = buffer;
     16 	int rem;
     17 	unsigned int uns;
     18 
     19 	if (base == 'x') {
     20 		unsigned long n = num;
     21 		do {
     22 			rem = n % 16;
     23 			*ptr++ = hex[rem];
     24 			n /= 16;
     25 		} while (n); *ptr = '\0'; --ptr;
     26 	} else {
     27 		if (base == 'd' && num < 0) {
     28 			*ptr++ = '-'; num = -num;
     29 			++beg;
     30 		}
     31 		uns = (unsigned int)num;
     32 		do {
     33 			rem = uns % 10;
     34 			*ptr++ = rem + '0';
     35 			uns /= 10;
     36 		} while (uns); *ptr = '\0'; --ptr;
     37 	}
     38 	while (ptr >= beg) {
     39 		tmp = *beg;
     40 		*beg = *ptr;
     41 		*ptr = tmp;
     42 		--ptr;
     43 		++beg;
     44 	}
     45 }
     46 
     47 /*
     48  * Copyright (c) 1990 Regents of the University of California.
     49  * All rights reserved.
     50  *
     51  * Redistribution and use in source and binary forms, with or without
     52  * modification, are permitted provided that the following conditions
     53  * are met:
     54  * 1. Redistributions of source code must retain the above copyright
     55  *    notice, this list of conditions and the following disclaimer.
     56  * 2. Redistributions in binary form must reproduce the above copyright
     57  *    notice, this list of conditions and the following disclaimer in the
     58  *    documentation and/or other materials provided with the distribution.
     59  * 3. Neither the name of the University nor the names of its contributors
     60  *    may be used to endorse or promote products derived from this software
     61  *    without specific prior written permission.
     62  *
     63  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     66  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     73  * SUCH DAMAGE.
     74  */
     75 
     76 /*
     77  * Convert a string to an unsigned long integer.
     78  *
     79  * Ignores `locale' stuff.  Assumes that the upper and lower case
     80  * alphabets and digits are each contiguous.
     81  */
     82 unsigned long
     83 strtoul(const char *nptr, char **endptr, int base)
     84 {
     85 	const char *s;
     86 	unsigned long acc, cutoff;
     87 	int c;
     88 	int neg, any, cutlim;
     89 
     90 	/*
     91 	 * See strtol for comments as to the logic used.
     92 	 */
     93 	s = nptr;
     94 	do {
     95 		c = (unsigned char) * s++;
     96 	} while (isspace(c));
     97 	if (c == '-') {
     98 		neg = 1;
     99 		c = *s++;
    100 	} else {
    101 		neg = 0;
    102 		if (c == '+')
    103 			c = *s++;
    104 	}
    105 	if ((base == 0 || base == 16) &&
    106 			c == '0' && (*s == 'x' || *s == 'X')) {
    107 		c = s[1];
    108 		s += 2;
    109 		base = 16;
    110 	}
    111 	if (base == 0)
    112 		base = c == '0' ? 8 : 10;
    113 
    114 	cutoff = 0xffffffff / (unsigned long)base;
    115 	cutlim = 0xffffffff % (unsigned long)base;
    116 	for (acc = 0, any = 0;; c = (unsigned char) * s++) {
    117 		if (isdigit(c))
    118 			c -= '0';
    119 		else if (isalpha(c))
    120 			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
    121 		else
    122 			break;
    123 		if (c >= base)
    124 			break;
    125 		if (any < 0)
    126 			continue;
    127 		if (acc > cutoff || (acc == cutoff && c > cutlim)) {
    128 			any = -1;
    129 			acc = 0xffffffff;
    130 			errno = ERANGE;
    131 		} else {
    132 			any = 1;
    133 			acc *= (unsigned long)base;
    134 			acc += c;
    135 		}
    136 	}
    137 	if (neg && any > 0)
    138 		acc = -acc;
    139 	if (endptr != 0)
    140 		*endptr = (char *) (any ? s - 1 : nptr);
    141 	return (acc);
    142 }
    143