Subversion Repositories HelenOS

Rev

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

  1. /*
  2.  * Copyright (c) 2005 Martin Decky
  3.  * Copyright (C) 1998 by Wes Peters <wes@softweyr.com>
  4.  * Copyright (c) 1988, 1993 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * - Redistributions of source code must retain the above copyright
  12.  *   notice, this list of conditions and the following disclaimer.
  13.  * - Redistributions in binary form must reproduce the above copyright
  14.  *   notice, this list of conditions and the following disclaimer in the
  15.  *   documentation and/or other materials provided with the distribution.
  16.  * - The name of the author may not be used to endorse or promote products
  17.  *   derived from this software without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  */
  30.  
  31. /** @addtogroup libc
  32.  * @{
  33.  */
  34. /** @file
  35.  */
  36.  
  37. #include <string.h>
  38. #include <unistd.h>
  39. #include <ctype.h>
  40. #include <limits.h>
  41. #include <align.h>
  42. #include <sys/types.h>
  43. #include <malloc.h>
  44.  
  45. /* Dummy implementation of mem/ functions */
  46.  
  47. void *memset(void *s, int c, size_t n)
  48. {
  49.     char *os = s;
  50.    
  51.     while (n--)
  52.         *(os++) = c;
  53.    
  54.     return s;
  55. }
  56.  
  57. struct along {
  58.     unsigned long n;
  59. } __attribute__ ((packed));
  60.  
  61. static void *unaligned_memcpy(void *dst, const void *src, size_t n)
  62. {
  63.     int i, j;
  64.     struct along *adst = dst;
  65.     const struct along *asrc = src;
  66.  
  67.     for (i = 0; i < n / sizeof(unsigned long); i++)
  68.         adst[i].n = asrc[i].n;
  69.        
  70.     for (j = 0; j < n % sizeof(unsigned long); j++)
  71.         ((unsigned char *) (((unsigned long *) dst) + i))[j] =
  72.             ((unsigned char *) (((unsigned long *) src) + i))[j];
  73.        
  74.     return (char *) dst;
  75. }
  76.  
  77. void *memcpy(void *dst, const void *src, size_t n)
  78. {
  79.     int i, j;
  80.  
  81.     if (((long) dst & (sizeof(long) - 1)) ||
  82.         ((long) src & (sizeof(long) - 1)))
  83.         return unaligned_memcpy(dst, src, n);
  84.  
  85.     for (i = 0; i < n / sizeof(unsigned long); i++)
  86.         ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
  87.        
  88.     for (j = 0; j < n % sizeof(unsigned long); j++)
  89.         ((unsigned char *) (((unsigned long *) dst) + i))[j] =
  90.             ((unsigned char *) (((unsigned long *) src) + i))[j];
  91.        
  92.     return (char *) dst;
  93. }
  94.  
  95. void *memmove(void *dst, const void *src, size_t n)
  96. {
  97.     int i, j;
  98.    
  99.     if (src > dst)
  100.         return memcpy(dst, src, n);
  101.  
  102.     for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
  103.         ((unsigned char *) ((unsigned long *) dst))[j] =
  104.             ((unsigned char *) ((unsigned long *) src))[j];
  105.  
  106.     for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
  107.         ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
  108.        
  109.     return (char *) dst;
  110. }
  111.  
  112. /** Compare two memory areas.
  113.  *
  114.  * @param s1        Pointer to the first area to compare.
  115.  * @param s2        Pointer to the second area to compare.
  116.  * @param len       Size of the first area in bytes. Both areas must have
  117.  *          the same length.
  118.  * @return      If len is 0, return zero. If the areas match, return
  119.  *          zero. Otherwise return non-zero.
  120.  */
  121. int bcmp(const char *s1, const char *s2, size_t len)
  122. {
  123.     for (; len && *s1++ == *s2++; len--)
  124.         ;
  125.     return len;
  126. }
  127.  
  128. /** Count the number of characters in the string, not including terminating 0.
  129.  *
  130.  * @param str       String.
  131.  * @return      Number of characters in string.
  132.  */
  133. size_t strlen(const char *str)
  134. {
  135.     size_t counter = 0;
  136.  
  137.     while (str[counter] != 0)
  138.         counter++;
  139.  
  140.     return counter;
  141. }
  142.  
  143. int strcmp(const char *a, const char *b)
  144. {
  145.     int c = 0;
  146.    
  147.     while (a[c] && b[c] && (!(a[c] - b[c])))
  148.         c++;
  149.    
  150.     return (a[c] - b[c]);
  151. }
  152.  
  153. int strncmp(const char *a, const char *b, size_t n)
  154. {
  155.     size_t c = 0;
  156.  
  157.     while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
  158.         c++;
  159.    
  160.     return ( c < n ? a[c] - b[c] : 0);
  161.    
  162. }
  163.  
  164. int stricmp(const char *a, const char *b)
  165. {
  166.     int c = 0;
  167.    
  168.     while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
  169.         c++;
  170.    
  171.     return (tolower(a[c]) - tolower(b[c]));
  172. }
  173.  
  174. /** Return pointer to the first occurence of character c in string.
  175.  *
  176.  * @param str       Scanned string.
  177.  * @param c     Searched character (taken as one byte).
  178.  * @return      Pointer to the matched character or NULL if it is not
  179.  *          found in given string.
  180.  */
  181. char *strchr(const char *str, int c)
  182. {
  183.     while (*str != '\0') {
  184.         if (*str == (char) c)
  185.             return (char *) str;
  186.         str++;
  187.     }
  188.  
  189.     return NULL;
  190. }
  191.  
  192. /** Return pointer to the last occurence of character c in string.
  193.  *
  194.  * @param str       Scanned string.
  195.  * @param c     Searched character (taken as one byte).
  196.  * @return      Pointer to the matched character or NULL if it is not
  197.  *          found in given string.
  198.  */
  199. char *strrchr(const char *str, int c)
  200. {
  201.     char *retval = NULL;
  202.  
  203.     while (*str != '\0') {
  204.         if (*str == (char) c)
  205.             retval = (char *) str;
  206.         str++;
  207.     }
  208.  
  209.     return (char *) retval;
  210. }
  211.  
  212. /** Convert string to a number.
  213.  * Core of strtol and strtoul functions.
  214.  *
  215.  * @param nptr      Pointer to string.
  216.  * @param endptr    If not NULL, function stores here pointer to the first
  217.  *          invalid character.
  218.  * @param base      Zero or number between 2 and 36 inclusive.
  219.  * @param sgn       It's set to 1 if minus found.
  220.  * @return      Result of conversion.
  221.  */
  222. static unsigned long
  223. _strtoul(const char *nptr, char **endptr, int base, char *sgn)
  224. {
  225.     unsigned char c;
  226.     unsigned long result = 0;
  227.     unsigned long a, b;
  228.     const char *str = nptr;
  229.     const char *tmpptr;
  230.    
  231.     while (isspace(*str))
  232.         str++;
  233.    
  234.     if (*str == '-') {
  235.         *sgn = 1;
  236.         ++str;
  237.     } else if (*str == '+')
  238.         ++str;
  239.    
  240.     if (base) {
  241.         if ((base == 1) || (base > 36)) {
  242.             /* FIXME: set errno to EINVAL */
  243.             return 0;
  244.         }
  245.         if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
  246.             (str[1] == 'X'))) {
  247.             str += 2;
  248.         }
  249.     } else {
  250.         base = 10;
  251.        
  252.         if (*str == '0') {
  253.             base = 8;
  254.             if ((str[1] == 'X') || (str[1] == 'x'))  {
  255.                 base = 16;
  256.                 str += 2;
  257.             }
  258.         }
  259.     }
  260.    
  261.     tmpptr = str;
  262.  
  263.     while (*str) {
  264.         c = *str;
  265.         c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
  266.             (c <= '9' ? c - '0' : 0xff)));
  267.         if (c > base) {
  268.             break;
  269.         }
  270.        
  271.         a = (result & 0xff) * base + c;
  272.         b = (result >> 8) * base + (a >> 8);
  273.        
  274.         if (b > (ULONG_MAX >> 8)) {
  275.             /* overflow */
  276.             /* FIXME: errno = ERANGE*/
  277.             return ULONG_MAX;
  278.         }
  279.    
  280.         result = (b << 8) + (a & 0xff);
  281.         ++str;
  282.     }
  283.    
  284.     if (str == tmpptr) {
  285.         /*
  286.          * No number was found => first invalid character is the first
  287.          * character of the string.
  288.          */
  289.         /* FIXME: set errno to EINVAL */
  290.         str = nptr;
  291.         result = 0;
  292.     }
  293.    
  294.     if (endptr)
  295.         *endptr = (char *) str;
  296.  
  297.     if (nptr == str) {
  298.         /*FIXME: errno = EINVAL*/
  299.         return 0;
  300.     }
  301.  
  302.     return result;
  303. }
  304.  
  305. /** Convert initial part of string to long int according to given base.
  306.  * The number may begin with an arbitrary number of whitespaces followed by
  307.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  308.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  309.  * and the number begin with a zero, number will be taken as octal one (as with
  310.  * base 8). Otherwise the base 0 is taken as decimal.
  311.  *
  312.  * @param nptr      Pointer to string.
  313.  * @param endptr    If not NULL, function stores here pointer to the first
  314.  *          invalid character.
  315.  * @param base      Zero or number between 2 and 36 inclusive.
  316.  * @return      Result of conversion.
  317.  */
  318. long int strtol(const char *nptr, char **endptr, int base)
  319. {
  320.     char sgn = 0;
  321.     unsigned long number = 0;
  322.    
  323.     number = _strtoul(nptr, endptr, base, &sgn);
  324.  
  325.     if (number > LONG_MAX) {
  326.         if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
  327.             /* FIXME: set 0 to errno */
  328.             return number;     
  329.         }
  330.         /* FIXME: set ERANGE to errno */
  331.         return (sgn ? LONG_MIN : LONG_MAX);
  332.     }
  333.    
  334.     return (sgn ? -number : number);
  335. }
  336.  
  337.  
  338. /** Convert initial part of string to unsigned long according to given base.
  339.  * The number may begin with an arbitrary number of whitespaces followed by
  340.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  341.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  342.  * and the number begin with a zero, number will be taken as octal one (as with
  343.  * base 8). Otherwise the base 0 is taken as decimal.
  344.  *
  345.  * @param nptr      Pointer to string.
  346.  * @param endptr    If not NULL, function stores here pointer to the first
  347.  *          invalid character
  348.  * @param base      Zero or number between 2 and 36 inclusive.
  349.  * @return      Result of conversion.
  350.  */
  351. unsigned long strtoul(const char *nptr, char **endptr, int base)
  352. {
  353.     char sgn = 0;
  354.     unsigned long number = 0;
  355.    
  356.     number = _strtoul(nptr, endptr, base, &sgn);
  357.  
  358.     return (sgn ? -number : number);
  359. }
  360.  
  361. char *strcpy(char *dest, const char *src)
  362. {
  363.     char *orig = dest;
  364.    
  365.     while ((*(dest++) = *(src++)))
  366.         ;
  367.     return orig;
  368. }
  369.  
  370. char *strncpy(char *dest, const char *src, size_t n)
  371. {
  372.     char *orig = dest;
  373.    
  374.     while ((*(dest++) = *(src++)) && --n)
  375.         ;
  376.     return orig;
  377. }
  378.  
  379. char *strcat(char *dest, const char *src)
  380. {
  381.     char *orig = dest;
  382.     while (*dest++)
  383.         ;
  384.     --dest;
  385.     while ((*dest++ = *src++))
  386.         ;
  387.     return orig;
  388. }
  389.  
  390. char * strdup(const char *s1)
  391. {
  392.     size_t len = strlen(s1) + 1;
  393.     void *ret = malloc(len);
  394.  
  395.     if (ret == NULL)
  396.         return (char *) NULL;
  397.  
  398.     return (char *) memcpy(ret, s1, len);
  399. }
  400.  
  401. /* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
  402. char * strtok_r(char *s, const char *delim, char **last)
  403. {
  404.     char *spanp, *tok;
  405.     int c, sc;
  406.  
  407.     if (s == NULL && (s = *last) == NULL)
  408.         return (NULL);
  409.  
  410. cont:
  411.     c = *s++;
  412.     for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
  413.         if (c == sc)
  414.             goto cont;
  415.     }
  416.  
  417.     if (c == 0) {       /* no non-delimiter characters */
  418.         *last = NULL;
  419.         return (NULL);
  420.     }
  421.  
  422.     tok = s - 1;
  423.  
  424.     for (;;) {
  425.         c = *s++;
  426.         spanp = (char *)delim;
  427.         do {
  428.             if ((sc = *spanp++) == c) {
  429.                 if (c == 0)
  430.                     s = NULL;
  431.                 else
  432.                     s[-1] = '\0';
  433.                 *last = s;
  434.                 return (tok);
  435.             }
  436.         } while (sc != 0);
  437.     }
  438. }
  439.  
  440. /* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
  441. char * strtok(char *s, const char *delim)
  442. {
  443.     static char *last;
  444.  
  445.     return (strtok_r(s, delim, &last));
  446. }
  447.  
  448. /** @}
  449.  */
  450.