Subversion Repositories HelenOS

Rev

Rev 1866 | Rev 2072 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2005 Martin Decky
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - 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.  * - 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. /** @addtogroup libc
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <string.h>
  36. #include <unistd.h>
  37. #include <ctype.h>
  38. #include <limits.h>
  39. #include <align.h>
  40.  
  41.  
  42. /* Dummy implementation of mem/ functions */
  43.  
  44. void *memset(void *s, int c, size_t n)
  45. {
  46.     char *os = s;
  47.    
  48.     while (n--)
  49.         *(os++) = c;
  50.    
  51.     return s;
  52. }
  53.  
  54. struct along {
  55.     unsigned long n;
  56. } __attribute__ ((packed));
  57.  
  58. static void *unaligned_memcpy(void *dst, const void *src, size_t n)
  59. {
  60.     int i, j;
  61.     struct along *adst = dst;
  62.     const struct along *asrc = src;
  63.  
  64.     for (i = 0; i < n / sizeof(unsigned long); i++)
  65.         adst[i].n = asrc[i].n;
  66.        
  67.     for (j = 0; j < n % sizeof(unsigned long); j++)
  68.         ((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j];
  69.        
  70.     return (char *) src;
  71. }
  72.  
  73. void *memcpy(void *dst, const void *src, size_t n)
  74. {
  75.     int i, j;
  76.  
  77.     if (((long) dst & (sizeof(long) - 1)) || ((long) src & (sizeof(long) - 1)))
  78.         return unaligned_memcpy(dst, src, n);
  79.  
  80.     for (i = 0; i < n / sizeof(unsigned long); i++)
  81.         ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
  82.        
  83.     for (j = 0; j < n % sizeof(unsigned long); j++)
  84.         ((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j];
  85.        
  86.     return (char *) src;
  87. }
  88.  
  89. void *memmove(void *dst, const void *src, size_t n)
  90. {
  91.     int i, j;
  92.    
  93.     if (src > dst)
  94.         return memcpy(dst, src, n);
  95.  
  96.     for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
  97.         ((unsigned char *) ((unsigned long *) dst))[j] = ((unsigned char *) ((unsigned long *) src))[j];
  98.  
  99.     for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
  100.         ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
  101.        
  102.     return (char *) src;
  103. }
  104.  
  105.  
  106. /** Count the number of characters in the string, not including terminating 0.
  107.  * @param str string
  108.  * @return number of characters in string.
  109.  */
  110. size_t strlen(const char *str)
  111. {
  112.     size_t counter = 0;
  113.  
  114.     while (str[counter] != 0)
  115.         counter++;
  116.  
  117.     return counter;
  118. }
  119.  
  120. int strcmp(const char *a, const char *b)
  121. {
  122.     int c = 0;
  123.    
  124.     while (a[c] && b[c] && (!(a[c] - b[c])))
  125.         c++;
  126.    
  127.     return (a[c] - b[c]);
  128.    
  129. }
  130.  
  131.  
  132. /** Return pointer to the first occurence of character c in string
  133.  * @param str scanned string
  134.  * @param c searched character (taken as one byte)
  135.  * @return pointer to the matched character or NULL if it is not found in given string.
  136.  */
  137. char *strchr(const char *str, int c)
  138. {
  139.     while (*str != '\0') {
  140.         if (*str == (char) c)
  141.             return (char *) str;
  142.         str++;
  143.     }
  144.  
  145.     return NULL;
  146. }
  147.  
  148. /** Return pointer to the last occurence of character c in string
  149.  * @param str scanned string
  150.  * @param c searched character (taken as one byte)
  151.  * @return pointer to the matched character or NULL if it is not found in given string.
  152.  */
  153. char *strrchr(const char *str, int c)
  154. {
  155.     char *retval = NULL;
  156.  
  157.     while (*str != '\0') {
  158.         if (*str == (char) c)
  159.             retval = (char *) str;
  160.         str++;
  161.     }
  162.  
  163.     return (char *) retval;
  164. }
  165.  
  166. /** Convert string to a number.
  167.  * Core of strtol and strtoul functions.
  168.  * @param nptr pointer to string
  169.  * @param endptr if not NULL, function stores here pointer to the first invalid character
  170.  * @param base zero or number between 2 and 36 inclusive
  171.  * @param sgn its set to 1 if minus found
  172.  * @return result of conversion.
  173.  */
  174. static unsigned long _strtoul(const char *nptr, char **endptr, int base, char *sgn)
  175. {
  176.     unsigned char c;
  177.     unsigned long result = 0;
  178.     unsigned long a, b;
  179.     const char *str = nptr;
  180.     const char *tmpptr;
  181.    
  182.     while (isspace(*str))
  183.         str++;
  184.    
  185.     if (*str == '-') {
  186.         *sgn = 1;
  187.         ++str;
  188.     } else if (*str == '+')
  189.         ++str;
  190.    
  191.     if (base) {
  192.         if ((base == 1) || (base > 36)) {
  193.             /* FIXME: set errno to EINVAL */
  194.             return 0;
  195.         }
  196.         if ((base == 16) && (*str == '0') && ((str[1] == 'x') || (str[1] == 'X'))) {
  197.             str += 2;
  198.         }
  199.     } else {
  200.         base = 10;
  201.        
  202.         if (*str == '0') {
  203.             base = 8;
  204.             if ((str[1] == 'X') || (str[1] == 'x'))  {
  205.                 base = 16;
  206.                 str += 2;
  207.             }
  208.         }
  209.     }
  210.    
  211.     tmpptr = str;
  212.  
  213.     while (*str) {
  214.         c = *str;
  215.         c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 : (c <= '9' ? c - '0' : 0xff)));
  216.         if (c > base) {
  217.             break;
  218.         }
  219.        
  220.         a = (result & 0xff) * base + c;
  221.         b = (result >> 8) * base + (a >> 8);
  222.        
  223.         if (b > (ULONG_MAX >> 8)) {
  224.             /* overflow */
  225.             /* FIXME: errno = ERANGE*/
  226.             return ULONG_MAX;
  227.         }
  228.    
  229.         result = (b << 8) + (a & 0xff);
  230.         ++str;
  231.     }
  232.    
  233.     if (str == tmpptr) {
  234.         /* no number was found => first invalid character is the first character of the string */
  235.         /* FIXME: set errno to EINVAL */
  236.         str = nptr;
  237.         result = 0;
  238.     }
  239.    
  240.     if (endptr)
  241.         *endptr = (char *) str;
  242.  
  243.     if (nptr == str) {
  244.         /*FIXME: errno = EINVAL*/
  245.         return 0;
  246.     }
  247.  
  248.     return result;
  249. }
  250.  
  251. /** Convert initial part of string to long int according to given base.
  252.  * The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
  253.  * If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
  254.  * If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
  255.  * Otherwise the base 0 is taken as decimal.
  256.  * @param nptr pointer to string
  257.  * @param endptr if not NULL, function stores here pointer to the first invalid character
  258.  * @param base zero or number between 2 and 36 inclusive
  259.  * @return result of conversion.
  260.  */
  261. long int strtol(const char *nptr, char **endptr, int base)
  262. {
  263.     char sgn = 0;
  264.     unsigned long number = 0;
  265.    
  266.     number = _strtoul(nptr, endptr, base, &sgn);
  267.  
  268.     if (number > LONG_MAX) {
  269.         if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
  270.             /* FIXME: set 0 to errno */
  271.             return number;     
  272.         }
  273.         /* FIXME: set ERANGE to errno */
  274.         return (sgn ? LONG_MIN : LONG_MAX);
  275.     }
  276.    
  277.     return (sgn ? -number : number);
  278. }
  279.  
  280.  
  281. /** Convert initial part of string to unsigned long according to given base.
  282.  * The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
  283.  * If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
  284.  * If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
  285.  * Otherwise the base 0 is taken as decimal.
  286.  * @param nptr pointer to string
  287.  * @param endptr if not NULL, function stores here pointer to the first invalid character
  288.  * @param base zero or number between 2 and 36 inclusive
  289.  * @return result of conversion.
  290.  */
  291. unsigned long strtoul(const char *nptr, char **endptr, int base)
  292. {
  293.     char sgn = 0;
  294.     unsigned long number = 0;
  295.    
  296.     number = _strtoul(nptr, endptr, base, &sgn);
  297.  
  298.     return (sgn ? -number : number);
  299. }
  300.  
  301. char *strcpy(char *dest, const char *src)
  302. {
  303.     char *orig = dest;
  304.    
  305.     while ((*(dest++) = *(src++)));
  306.     return orig;
  307. }
  308.  
  309. char *strncpy(char *dest, const char *src, size_t n)
  310. {
  311.     char *orig = dest;
  312.    
  313.     while ((*(dest++) = *(src++)) && --n);
  314.     return orig;
  315. }
  316.  
  317. /** @}
  318.  */
  319.