Subversion Repositories HelenOS

Rev

Rev 3271 | Rev 3427 | 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 *) dst;
  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 *) dst;
  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 *) dst;
  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. int strncmp(const char *a, const char *b, size_t n)
  152. {
  153.     size_t c = 0;
  154.  
  155.     while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
  156.         c++;
  157.    
  158.     return ( c < n ? a[c] - b[c] : 0);
  159.    
  160. }
  161.  
  162. int stricmp(const char *a, const char *b)
  163. {
  164.     int c = 0;
  165.    
  166.     while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
  167.         c++;
  168.    
  169.     return (tolower(a[c]) - tolower(b[c]));
  170. }
  171.  
  172. /** Return pointer to the first occurence of character c in string.
  173.  *
  174.  * @param str       Scanned string.
  175.  * @param c     Searched character (taken as one byte).
  176.  * @return      Pointer to the matched character or NULL if it is not
  177.  *          found in given string.
  178.  */
  179. char *strchr(const char *str, int c)
  180. {
  181.     while (*str != '\0') {
  182.         if (*str == (char) c)
  183.             return (char *) str;
  184.         str++;
  185.     }
  186.  
  187.     return NULL;
  188. }
  189.  
  190. /** Return pointer to the last occurence of character c in string.
  191.  *
  192.  * @param str       Scanned string.
  193.  * @param c     Searched character (taken as one byte).
  194.  * @return      Pointer to the matched character or NULL if it is not
  195.  *          found in given string.
  196.  */
  197. char *strrchr(const char *str, int c)
  198. {
  199.     char *retval = NULL;
  200.  
  201.     while (*str != '\0') {
  202.         if (*str == (char) c)
  203.             retval = (char *) str;
  204.         str++;
  205.     }
  206.  
  207.     return (char *) retval;
  208. }
  209.  
  210. /** Convert string to a number.
  211.  * Core of strtol and strtoul functions.
  212.  *
  213.  * @param nptr      Pointer to string.
  214.  * @param endptr    If not NULL, function stores here pointer to the first
  215.  *          invalid character.
  216.  * @param base      Zero or number between 2 and 36 inclusive.
  217.  * @param sgn       It's set to 1 if minus found.
  218.  * @return      Result of conversion.
  219.  */
  220. static unsigned long
  221. _strtoul(const char *nptr, char **endptr, int base, char *sgn)
  222. {
  223.     unsigned char c;
  224.     unsigned long result = 0;
  225.     unsigned long a, b;
  226.     const char *str = nptr;
  227.     const char *tmpptr;
  228.    
  229.     while (isspace(*str))
  230.         str++;
  231.    
  232.     if (*str == '-') {
  233.         *sgn = 1;
  234.         ++str;
  235.     } else if (*str == '+')
  236.         ++str;
  237.    
  238.     if (base) {
  239.         if ((base == 1) || (base > 36)) {
  240.             /* FIXME: set errno to EINVAL */
  241.             return 0;
  242.         }
  243.         if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
  244.             (str[1] == 'X'))) {
  245.             str += 2;
  246.         }
  247.     } else {
  248.         base = 10;
  249.        
  250.         if (*str == '0') {
  251.             base = 8;
  252.             if ((str[1] == 'X') || (str[1] == 'x'))  {
  253.                 base = 16;
  254.                 str += 2;
  255.             }
  256.         }
  257.     }
  258.    
  259.     tmpptr = str;
  260.  
  261.     while (*str) {
  262.         c = *str;
  263.         c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
  264.             (c <= '9' ? c - '0' : 0xff)));
  265.         if (c > base) {
  266.             break;
  267.         }
  268.        
  269.         a = (result & 0xff) * base + c;
  270.         b = (result >> 8) * base + (a >> 8);
  271.        
  272.         if (b > (ULONG_MAX >> 8)) {
  273.             /* overflow */
  274.             /* FIXME: errno = ERANGE*/
  275.             return ULONG_MAX;
  276.         }
  277.    
  278.         result = (b << 8) + (a & 0xff);
  279.         ++str;
  280.     }
  281.    
  282.     if (str == tmpptr) {
  283.         /*
  284.          * No number was found => first invalid character is the first
  285.          * character of the string.
  286.          */
  287.         /* FIXME: set errno to EINVAL */
  288.         str = nptr;
  289.         result = 0;
  290.     }
  291.    
  292.     if (endptr)
  293.         *endptr = (char *) str;
  294.  
  295.     if (nptr == str) {
  296.         /*FIXME: errno = EINVAL*/
  297.         return 0;
  298.     }
  299.  
  300.     return result;
  301. }
  302.  
  303. /** Convert initial part of string to long int according to given base.
  304.  * The number may begin with an arbitrary number of whitespaces followed by
  305.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  306.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  307.  * and the number begin with a zero, number will be taken as octal one (as with
  308.  * base 8). Otherwise the base 0 is taken as decimal.
  309.  *
  310.  * @param nptr      Pointer to string.
  311.  * @param endptr    If not NULL, function stores here pointer to the first
  312.  *          invalid character.
  313.  * @param base      Zero or number between 2 and 36 inclusive.
  314.  * @return      Result of conversion.
  315.  */
  316. long int strtol(const char *nptr, char **endptr, int base)
  317. {
  318.     char sgn = 0;
  319.     unsigned long number = 0;
  320.    
  321.     number = _strtoul(nptr, endptr, base, &sgn);
  322.  
  323.     if (number > LONG_MAX) {
  324.         if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
  325.             /* FIXME: set 0 to errno */
  326.             return number;     
  327.         }
  328.         /* FIXME: set ERANGE to errno */
  329.         return (sgn ? LONG_MIN : LONG_MAX);
  330.     }
  331.    
  332.     return (sgn ? -number : number);
  333. }
  334.  
  335.  
  336. /** Convert initial part of string to unsigned long according to given base.
  337.  * The number may begin with an arbitrary number of whitespaces followed by
  338.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  339.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  340.  * and the number begin with a zero, number will be taken as octal one (as with
  341.  * base 8). Otherwise the base 0 is taken as decimal.
  342.  *
  343.  * @param nptr      Pointer to string.
  344.  * @param endptr    If not NULL, function stores here pointer to the first
  345.  *          invalid character
  346.  * @param base      Zero or number between 2 and 36 inclusive.
  347.  * @return      Result of conversion.
  348.  */
  349. unsigned long strtoul(const char *nptr, char **endptr, int base)
  350. {
  351.     char sgn = 0;
  352.     unsigned long number = 0;
  353.    
  354.     number = _strtoul(nptr, endptr, base, &sgn);
  355.  
  356.     return (sgn ? -number : number);
  357. }
  358.  
  359. char *strcpy(char *dest, const char *src)
  360. {
  361.     char *orig = dest;
  362.    
  363.     while ((*(dest++) = *(src++)))
  364.         ;
  365.     return orig;
  366. }
  367.  
  368. char *strncpy(char *dest, const char *src, size_t n)
  369. {
  370.     char *orig = dest;
  371.    
  372.     while ((*(dest++) = *(src++)) && --n)
  373.         ;
  374.     return orig;
  375. }
  376.  
  377. char *strcat(char *dest, const char *src)
  378. {
  379.     char *orig = dest;
  380.     while (*dest++)
  381.         ;
  382.     --dest;
  383.     while ((*dest++ = *src++))
  384.         ;
  385.     return orig;
  386. }
  387.  
  388. char * strdup(const char *s1)
  389. {
  390.     size_t len = strlen(s1) + 1;
  391.     void *ret = malloc(len);
  392.  
  393.     if (ret == NULL)
  394.         return (char *) NULL;
  395.  
  396.     return (char *) memcpy(ret, s1, len);
  397. }
  398.  
  399. /** @}
  400.  */
  401.