Subversion Repositories HelenOS

Rev

Rev 3427 | Rev 3728 | 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. /** Copy memory block. */
  78. void *memcpy(void *dst, const void *src, size_t n)
  79. {
  80.     size_t i;
  81.     size_t mod, fill;
  82.     size_t word_size;
  83.     size_t n_words;
  84.  
  85.     const unsigned long *srcw;
  86.     unsigned long *dstw;
  87.     const uint8_t *srcb;
  88.     uint8_t *dstb;
  89.  
  90.     word_size = sizeof(unsigned long);
  91.  
  92.     /*
  93.      * Are source and destination addresses congruent modulo word_size?
  94.      * If not, use unaligned_memcpy().
  95.      */
  96.  
  97.     if (((uintptr_t) dst & (word_size - 1)) !=
  98.         ((uintptr_t) src & (word_size - 1)))
  99.         return unaligned_memcpy(dst, src, n);
  100.  
  101.     /*
  102.      * mod is the address modulo word size. fill is the length of the
  103.      * initial buffer segment before the first word boundary.
  104.      * If the buffer is very short, use unaligned_memcpy(), too.
  105.      */
  106.  
  107.     mod = (uintptr_t) dst & (word_size - 1);
  108.     fill = word_size - mod;
  109.     if (fill > n) fill = n;
  110.  
  111.     /* Copy the initial segment. */
  112.  
  113.     srcb = src;
  114.     dstb = dst;
  115.  
  116.     i = fill;
  117.     while (i-- > 0)
  118.         *dstb++ = *srcb++;
  119.  
  120.     /* Compute remaining length. */
  121.  
  122.     n -= fill;
  123.     if (n == 0) return dst;
  124.  
  125.     /* Pointers to aligned segment. */
  126.  
  127.     dstw = (unsigned long *) dstb;
  128.     srcw = (const unsigned long *) srcb;
  129.  
  130.     n_words = n / word_size;    /* Number of whole words to copy. */
  131.     n -= n_words * word_size;   /* Remaining bytes at the end. */
  132.  
  133.     /* "Fast" copy. */
  134.     i = n_words;
  135.     while (i-- > 0)
  136.         *dstw++ = *srcw++;
  137.  
  138.     /*
  139.      * Copy the rest.
  140.      */
  141.  
  142.     srcb = (const uint8_t *) srcw;
  143.     dstb = (uint8_t *) dstw;
  144.  
  145.     i = n;
  146.     while (i-- > 0)
  147.         *dstb++ = *srcb++;
  148.  
  149.     return dst;
  150. }
  151.  
  152. void *memmove(void *dst, const void *src, size_t n)
  153. {
  154.     int i, j;
  155.    
  156.     if (src > dst)
  157.         return memcpy(dst, src, n);
  158.  
  159.     for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
  160.         ((unsigned char *) ((unsigned long *) dst))[j] =
  161.             ((unsigned char *) ((unsigned long *) src))[j];
  162.  
  163.     for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
  164.         ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
  165.        
  166.     return (char *) dst;
  167. }
  168.  
  169. /** Compare two memory areas.
  170.  *
  171.  * @param s1        Pointer to the first area to compare.
  172.  * @param s2        Pointer to the second area to compare.
  173.  * @param len       Size of the first area in bytes. Both areas must have
  174.  *          the same length.
  175.  * @return      If len is 0, return zero. If the areas match, return
  176.  *          zero. Otherwise return non-zero.
  177.  */
  178. int bcmp(const char *s1, const char *s2, size_t len)
  179. {
  180.     for (; len && *s1++ == *s2++; len--)
  181.         ;
  182.     return len;
  183. }
  184.  
  185. /** Count the number of characters in the string, not including terminating 0.
  186.  *
  187.  * @param str       String.
  188.  * @return      Number of characters in string.
  189.  */
  190. size_t strlen(const char *str)
  191. {
  192.     size_t counter = 0;
  193.  
  194.     while (str[counter] != 0)
  195.         counter++;
  196.  
  197.     return counter;
  198. }
  199.  
  200. int strcmp(const char *a, const char *b)
  201. {
  202.     int c = 0;
  203.    
  204.     while (a[c] && b[c] && (!(a[c] - b[c])))
  205.         c++;
  206.    
  207.     return (a[c] - b[c]);
  208. }
  209.  
  210. int strncmp(const char *a, const char *b, size_t n)
  211. {
  212.     size_t c = 0;
  213.  
  214.     while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
  215.         c++;
  216.    
  217.     return ( c < n ? a[c] - b[c] : 0);
  218.    
  219. }
  220.  
  221. int stricmp(const char *a, const char *b)
  222. {
  223.     int c = 0;
  224.    
  225.     while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
  226.         c++;
  227.    
  228.     return (tolower(a[c]) - tolower(b[c]));
  229. }
  230.  
  231. /** Return pointer to the first occurence of character c in string.
  232.  *
  233.  * @param str       Scanned string.
  234.  * @param c     Searched character (taken as one byte).
  235.  * @return      Pointer to the matched character or NULL if it is not
  236.  *          found in given string.
  237.  */
  238. char *strchr(const char *str, int c)
  239. {
  240.     while (*str != '\0') {
  241.         if (*str == (char) c)
  242.             return (char *) str;
  243.         str++;
  244.     }
  245.  
  246.     return NULL;
  247. }
  248.  
  249. /** Return pointer to the last occurence of character c in string.
  250.  *
  251.  * @param str       Scanned string.
  252.  * @param c     Searched character (taken as one byte).
  253.  * @return      Pointer to the matched character or NULL if it is not
  254.  *          found in given string.
  255.  */
  256. char *strrchr(const char *str, int c)
  257. {
  258.     char *retval = NULL;
  259.  
  260.     while (*str != '\0') {
  261.         if (*str == (char) c)
  262.             retval = (char *) str;
  263.         str++;
  264.     }
  265.  
  266.     return (char *) retval;
  267. }
  268.  
  269. /** Convert string to a number.
  270.  * Core of strtol and strtoul functions.
  271.  *
  272.  * @param nptr      Pointer to string.
  273.  * @param endptr    If not NULL, function stores here pointer to the first
  274.  *          invalid character.
  275.  * @param base      Zero or number between 2 and 36 inclusive.
  276.  * @param sgn       It's set to 1 if minus found.
  277.  * @return      Result of conversion.
  278.  */
  279. static unsigned long
  280. _strtoul(const char *nptr, char **endptr, int base, char *sgn)
  281. {
  282.     unsigned char c;
  283.     unsigned long result = 0;
  284.     unsigned long a, b;
  285.     const char *str = nptr;
  286.     const char *tmpptr;
  287.    
  288.     while (isspace(*str))
  289.         str++;
  290.    
  291.     if (*str == '-') {
  292.         *sgn = 1;
  293.         ++str;
  294.     } else if (*str == '+')
  295.         ++str;
  296.    
  297.     if (base) {
  298.         if ((base == 1) || (base > 36)) {
  299.             /* FIXME: set errno to EINVAL */
  300.             return 0;
  301.         }
  302.         if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
  303.             (str[1] == 'X'))) {
  304.             str += 2;
  305.         }
  306.     } else {
  307.         base = 10;
  308.        
  309.         if (*str == '0') {
  310.             base = 8;
  311.             if ((str[1] == 'X') || (str[1] == 'x'))  {
  312.                 base = 16;
  313.                 str += 2;
  314.             }
  315.         }
  316.     }
  317.    
  318.     tmpptr = str;
  319.  
  320.     while (*str) {
  321.         c = *str;
  322.         c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
  323.             (c <= '9' ? c - '0' : 0xff)));
  324.         if (c > base) {
  325.             break;
  326.         }
  327.        
  328.         a = (result & 0xff) * base + c;
  329.         b = (result >> 8) * base + (a >> 8);
  330.        
  331.         if (b > (ULONG_MAX >> 8)) {
  332.             /* overflow */
  333.             /* FIXME: errno = ERANGE*/
  334.             return ULONG_MAX;
  335.         }
  336.    
  337.         result = (b << 8) + (a & 0xff);
  338.         ++str;
  339.     }
  340.    
  341.     if (str == tmpptr) {
  342.         /*
  343.          * No number was found => first invalid character is the first
  344.          * character of the string.
  345.          */
  346.         /* FIXME: set errno to EINVAL */
  347.         str = nptr;
  348.         result = 0;
  349.     }
  350.    
  351.     if (endptr)
  352.         *endptr = (char *) str;
  353.  
  354.     if (nptr == str) {
  355.         /*FIXME: errno = EINVAL*/
  356.         return 0;
  357.     }
  358.  
  359.     return result;
  360. }
  361.  
  362. /** Convert initial part of string to long int according to given base.
  363.  * The number may begin with an arbitrary number of whitespaces followed by
  364.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  365.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  366.  * and the number begin with a zero, number will be taken as octal one (as with
  367.  * base 8). Otherwise the base 0 is taken as decimal.
  368.  *
  369.  * @param nptr      Pointer to string.
  370.  * @param endptr    If not NULL, function stores here pointer to the first
  371.  *          invalid character.
  372.  * @param base      Zero or number between 2 and 36 inclusive.
  373.  * @return      Result of conversion.
  374.  */
  375. long int strtol(const char *nptr, char **endptr, int base)
  376. {
  377.     char sgn = 0;
  378.     unsigned long number = 0;
  379.    
  380.     number = _strtoul(nptr, endptr, base, &sgn);
  381.  
  382.     if (number > LONG_MAX) {
  383.         if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
  384.             /* FIXME: set 0 to errno */
  385.             return number;     
  386.         }
  387.         /* FIXME: set ERANGE to errno */
  388.         return (sgn ? LONG_MIN : LONG_MAX);
  389.     }
  390.    
  391.     return (sgn ? -number : number);
  392. }
  393.  
  394.  
  395. /** Convert initial part of string to unsigned long according to given base.
  396.  * The number may begin with an arbitrary number of whitespaces followed by
  397.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  398.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  399.  * and the number begin with a zero, number will be taken as octal one (as with
  400.  * base 8). Otherwise the base 0 is taken as decimal.
  401.  *
  402.  * @param nptr      Pointer to string.
  403.  * @param endptr    If not NULL, function stores here pointer to the first
  404.  *          invalid character
  405.  * @param base      Zero or number between 2 and 36 inclusive.
  406.  * @return      Result of conversion.
  407.  */
  408. unsigned long strtoul(const char *nptr, char **endptr, int base)
  409. {
  410.     char sgn = 0;
  411.     unsigned long number = 0;
  412.    
  413.     number = _strtoul(nptr, endptr, base, &sgn);
  414.  
  415.     return (sgn ? -number : number);
  416. }
  417.  
  418. char *strcpy(char *dest, const char *src)
  419. {
  420.     char *orig = dest;
  421.    
  422.     while ((*(dest++) = *(src++)))
  423.         ;
  424.     return orig;
  425. }
  426.  
  427. char *strncpy(char *dest, const char *src, size_t n)
  428. {
  429.     char *orig = dest;
  430.    
  431.     while ((*(dest++) = *(src++)) && --n)
  432.         ;
  433.     return orig;
  434. }
  435.  
  436. char *strcat(char *dest, const char *src)
  437. {
  438.     char *orig = dest;
  439.     while (*dest++)
  440.         ;
  441.     --dest;
  442.     while ((*dest++ = *src++))
  443.         ;
  444.     return orig;
  445. }
  446.  
  447. char * strdup(const char *s1)
  448. {
  449.     size_t len = strlen(s1) + 1;
  450.     void *ret = malloc(len);
  451.  
  452.     if (ret == NULL)
  453.         return (char *) NULL;
  454.  
  455.     return (char *) memcpy(ret, s1, len);
  456. }
  457.  
  458. /* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
  459. char * strtok_r(char *s, const char *delim, char **last)
  460. {
  461.     char *spanp, *tok;
  462.     int c, sc;
  463.  
  464.     if (s == NULL && (s = *last) == NULL)
  465.         return (NULL);
  466.  
  467. cont:
  468.     c = *s++;
  469.     for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
  470.         if (c == sc)
  471.             goto cont;
  472.     }
  473.  
  474.     if (c == 0) {       /* no non-delimiter characters */
  475.         *last = NULL;
  476.         return (NULL);
  477.     }
  478.  
  479.     tok = s - 1;
  480.  
  481.     for (;;) {
  482.         c = *s++;
  483.         spanp = (char *)delim;
  484.         do {
  485.             if ((sc = *spanp++) == c) {
  486.                 if (c == 0)
  487.                     s = NULL;
  488.                 else
  489.                     s[-1] = '\0';
  490.                 *last = s;
  491.                 return (tok);
  492.             }
  493.         } while (sc != 0);
  494.     }
  495. }
  496.  
  497. /* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
  498. char * strtok(char *s, const char *delim)
  499. {
  500.     static char *last;
  501.  
  502.     return (strtok_r(s, delim, &last));
  503. }
  504.  
  505. /** @}
  506.  */
  507.