Subversion Repositories HelenOS

Rev

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