Subversion Repositories HelenOS

Rev

Rev 3238 | Rev 3271 | 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. #include <sys/types.h>
  41. #include <malloc.h>
  42.  
  43. /* Dummy implementation of mem/ functions */
  44.  
  45. void *memset(void *s, int c, size_t n)
  46. {
  47.     char *os = s;
  48.    
  49.     while (n--)
  50.         *(os++) = c;
  51.    
  52.     return s;
  53. }
  54.  
  55. struct along {
  56.     unsigned long n;
  57. } __attribute__ ((packed));
  58.  
  59. static void *unaligned_memcpy(void *dst, const void *src, size_t n)
  60. {
  61.     int i, j;
  62.     struct along *adst = dst;
  63.     const struct along *asrc = src;
  64.  
  65.     for (i = 0; i < n / sizeof(unsigned long); i++)
  66.         adst[i].n = asrc[i].n;
  67.        
  68.     for (j = 0; j < n % sizeof(unsigned long); j++)
  69.         ((unsigned char *) (((unsigned long *) dst) + i))[j] =
  70.             ((unsigned char *) (((unsigned long *) src) + i))[j];
  71.        
  72.     return (char *) src;
  73. }
  74.  
  75. void *memcpy(void *dst, const void *src, size_t n)
  76. {
  77.     int i, j;
  78.  
  79.     if (((long) dst & (sizeof(long) - 1)) ||
  80.         ((long) src & (sizeof(long) - 1)))
  81.         return unaligned_memcpy(dst, src, n);
  82.  
  83.     for (i = 0; i < n / sizeof(unsigned long); i++)
  84.         ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
  85.        
  86.     for (j = 0; j < n % sizeof(unsigned long); j++)
  87.         ((unsigned char *) (((unsigned long *) dst) + i))[j] =
  88.             ((unsigned char *) (((unsigned long *) src) + i))[j];
  89.        
  90.     return (char *) src;
  91. }
  92.  
  93. void *memmove(void *dst, const void *src, size_t n)
  94. {
  95.     int i, j;
  96.    
  97.     if (src > dst)
  98.         return memcpy(dst, src, n);
  99.  
  100.     for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
  101.         ((unsigned char *) ((unsigned long *) dst))[j] =
  102.             ((unsigned char *) ((unsigned long *) src))[j];
  103.  
  104.     for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
  105.         ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
  106.        
  107.     return (char *) src;
  108. }
  109.  
  110. /** Compare two memory areas.
  111.  *
  112.  * @param s1        Pointer to the first area to compare.
  113.  * @param s2        Pointer to the second area to compare.
  114.  * @param len       Size of the first area in bytes. Both areas must have
  115.  *          the same length.
  116.  * @return      If len is 0, return zero. If the areas match, return
  117.  *          zero. Otherwise return non-zero.
  118.  */
  119. int bcmp(const char *s1, const char *s2, size_t len)
  120. {
  121.     for (; len && *s1++ == *s2++; len--)
  122.         ;
  123.     return len;
  124. }
  125.  
  126. /** Count the number of characters in the string, not including terminating 0.
  127.  *
  128.  * @param str       String.
  129.  * @return      Number of characters in string.
  130.  */
  131. size_t strlen(const char *str)
  132. {
  133.     size_t counter = 0;
  134.  
  135.     while (str[counter] != 0)
  136.         counter++;
  137.  
  138.     return counter;
  139. }
  140.  
  141. int strcmp(const char *a, const char *b)
  142. {
  143.     int c = 0;
  144.    
  145.     while (a[c] && b[c] && (!(a[c] - b[c])))
  146.         c++;
  147.    
  148.     return (a[c] - b[c]);
  149.    
  150. }
  151.  
  152. int strncmp(const char *a, const char *b, size_t n)
  153. {
  154.     size_t c = 0;
  155.  
  156.     while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
  157.         c++;
  158.    
  159.     return ( c < n ? a[c] - b[c] : 0);
  160.    
  161. }
  162.  
  163. /** Return pointer to the first occurence of character c in string.
  164.  *
  165.  * @param str       Scanned string.
  166.  * @param c     Searched character (taken as one byte).
  167.  * @return      Pointer to the matched character or NULL if it is not
  168.  *          found in given string.
  169.  */
  170. char *strchr(const char *str, int c)
  171. {
  172.     while (*str != '\0') {
  173.         if (*str == (char) c)
  174.             return (char *) str;
  175.         str++;
  176.     }
  177.  
  178.     return NULL;
  179. }
  180.  
  181. /** Return pointer to the last occurence of character c in string.
  182.  *
  183.  * @param str       Scanned string.
  184.  * @param c     Searched character (taken as one byte).
  185.  * @return      Pointer to the matched character or NULL if it is not
  186.  *          found in given string.
  187.  */
  188. char *strrchr(const char *str, int c)
  189. {
  190.     char *retval = NULL;
  191.  
  192.     while (*str != '\0') {
  193.         if (*str == (char) c)
  194.             retval = (char *) str;
  195.         str++;
  196.     }
  197.  
  198.     return (char *) retval;
  199. }
  200.  
  201. /** Convert string to a number.
  202.  * Core of strtol and strtoul functions.
  203.  *
  204.  * @param nptr      Pointer to string.
  205.  * @param endptr    If not NULL, function stores here pointer to the first
  206.  *          invalid character.
  207.  * @param base      Zero or number between 2 and 36 inclusive.
  208.  * @param sgn       It's set to 1 if minus found.
  209.  * @return      Result of conversion.
  210.  */
  211. static unsigned long
  212. _strtoul(const char *nptr, char **endptr, int base, char *sgn)
  213. {
  214.     unsigned char c;
  215.     unsigned long result = 0;
  216.     unsigned long a, b;
  217.     const char *str = nptr;
  218.     const char *tmpptr;
  219.    
  220.     while (isspace(*str))
  221.         str++;
  222.    
  223.     if (*str == '-') {
  224.         *sgn = 1;
  225.         ++str;
  226.     } else if (*str == '+')
  227.         ++str;
  228.    
  229.     if (base) {
  230.         if ((base == 1) || (base > 36)) {
  231.             /* FIXME: set errno to EINVAL */
  232.             return 0;
  233.         }
  234.         if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
  235.             (str[1] == 'X'))) {
  236.             str += 2;
  237.         }
  238.     } else {
  239.         base = 10;
  240.        
  241.         if (*str == '0') {
  242.             base = 8;
  243.             if ((str[1] == 'X') || (str[1] == 'x'))  {
  244.                 base = 16;
  245.                 str += 2;
  246.             }
  247.         }
  248.     }
  249.    
  250.     tmpptr = str;
  251.  
  252.     while (*str) {
  253.         c = *str;
  254.         c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
  255.             (c <= '9' ? c - '0' : 0xff)));
  256.         if (c > base) {
  257.             break;
  258.         }
  259.        
  260.         a = (result & 0xff) * base + c;
  261.         b = (result >> 8) * base + (a >> 8);
  262.        
  263.         if (b > (ULONG_MAX >> 8)) {
  264.             /* overflow */
  265.             /* FIXME: errno = ERANGE*/
  266.             return ULONG_MAX;
  267.         }
  268.    
  269.         result = (b << 8) + (a & 0xff);
  270.         ++str;
  271.     }
  272.    
  273.     if (str == tmpptr) {
  274.         /*
  275.          * No number was found => first invalid character is the first
  276.          * character of the string.
  277.          */
  278.         /* FIXME: set errno to EINVAL */
  279.         str = nptr;
  280.         result = 0;
  281.     }
  282.    
  283.     if (endptr)
  284.         *endptr = (char *) str;
  285.  
  286.     if (nptr == str) {
  287.         /*FIXME: errno = EINVAL*/
  288.         return 0;
  289.     }
  290.  
  291.     return result;
  292. }
  293.  
  294. /** Convert initial part of string to long int according to given base.
  295.  * The number may begin with an arbitrary number of whitespaces followed by
  296.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  297.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  298.  * and the number begin with a zero, number will be taken as octal one (as with
  299.  * base 8). Otherwise the base 0 is taken as decimal.
  300.  *
  301.  * @param nptr      Pointer to string.
  302.  * @param endptr    If not NULL, function stores here pointer to the first
  303.  *          invalid character.
  304.  * @param base      Zero or number between 2 and 36 inclusive.
  305.  * @return      Result of conversion.
  306.  */
  307. long int strtol(const char *nptr, char **endptr, int base)
  308. {
  309.     char sgn = 0;
  310.     unsigned long number = 0;
  311.    
  312.     number = _strtoul(nptr, endptr, base, &sgn);
  313.  
  314.     if (number > LONG_MAX) {
  315.         if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
  316.             /* FIXME: set 0 to errno */
  317.             return number;     
  318.         }
  319.         /* FIXME: set ERANGE to errno */
  320.         return (sgn ? LONG_MIN : LONG_MAX);
  321.     }
  322.    
  323.     return (sgn ? -number : number);
  324. }
  325.  
  326.  
  327. /** Convert initial part of string to unsigned long according to given base.
  328.  * The number may begin with an arbitrary number of whitespaces followed by
  329.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  330.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  331.  * and the number begin with a zero, number will be taken as octal one (as with
  332.  * base 8). Otherwise the base 0 is taken as decimal.
  333.  *
  334.  * @param nptr      Pointer to string.
  335.  * @param endptr    If not NULL, function stores here pointer to the first
  336.  *          invalid character
  337.  * @param base      Zero or number between 2 and 36 inclusive.
  338.  * @return      Result of conversion.
  339.  */
  340. unsigned long strtoul(const char *nptr, char **endptr, int base)
  341. {
  342.     char sgn = 0;
  343.     unsigned long number = 0;
  344.    
  345.     number = _strtoul(nptr, endptr, base, &sgn);
  346.  
  347.     return (sgn ? -number : number);
  348. }
  349.  
  350. char *strcpy(char *dest, const char *src)
  351. {
  352.     char *orig = dest;
  353.    
  354.     while ((*(dest++) = *(src++)))
  355.         ;
  356.     return orig;
  357. }
  358.  
  359. char *strncpy(char *dest, const char *src, size_t n)
  360. {
  361.     char *orig = dest;
  362.    
  363.     while ((*(dest++) = *(src++)) && --n)
  364.         ;
  365.     return orig;
  366. }
  367.  
  368. char *strcat(char *dest, const char *src)
  369. {
  370.     char *orig = dest;
  371.     while (*dest++)
  372.         ;
  373.     --dest;
  374.     while ((*dest++ = *src++))
  375.         ;
  376.     return orig;
  377. }
  378.  
  379. char * strdup(const char *s1)
  380. {
  381.     size_t len = strlen(s1) + 1;
  382.     void *ret = malloc(len);
  383.  
  384.     if (ret == NULL)
  385.         return (char *) NULL;
  386.  
  387.     return (char *) memcpy(ret, s1, len);
  388. }
  389.  
  390. /** @}
  391.  */
  392.