Subversion Repositories HelenOS

Rev

Rev 3728 | Rev 3730 | 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. /** Move memory block with possible overlapping. */
  193. void *memmove(void *dst, const void *src, size_t n)
  194. {
  195.     uint8_t *dp, *sp;
  196.  
  197.     /* Nothing to do? */
  198.     if (src == dst)
  199.         return dst;
  200.  
  201.     /* Non-overlapping? */
  202.     if (dst >= src + n || src >= dst + n) {
  203.         return memcpy(dst, src, n);
  204.     }
  205.  
  206.     /* Which direction? */
  207.     if (src > dst) {
  208.         /* Forwards. */
  209.         sp = src;
  210.         dp = dst;
  211.  
  212.         while (n-- != 0)
  213.             *dp++ = *sp++;
  214.     } else {
  215.         /* Backwards. */
  216.         sp = src + (n - 1);
  217.         dp = dst + (n - 1);
  218.  
  219.         while (n-- != 0)
  220.             *dp-- = *sp--;
  221.     }
  222.  
  223.     return dst;
  224. }
  225.  
  226. /** Compare two memory areas.
  227.  *
  228.  * @param s1        Pointer to the first area to compare.
  229.  * @param s2        Pointer to the second area to compare.
  230.  * @param len       Size of the first area in bytes. Both areas must have
  231.  *          the same length.
  232.  * @return      If len is 0, return zero. If the areas match, return
  233.  *          zero. Otherwise return non-zero.
  234.  */
  235. int bcmp(const char *s1, const char *s2, size_t len)
  236. {
  237.     for (; len && *s1++ == *s2++; len--)
  238.         ;
  239.     return len;
  240. }
  241.  
  242. /** Count the number of characters in the string, not including terminating 0.
  243.  *
  244.  * @param str       String.
  245.  * @return      Number of characters in string.
  246.  */
  247. size_t strlen(const char *str)
  248. {
  249.     size_t counter = 0;
  250.  
  251.     while (str[counter] != 0)
  252.         counter++;
  253.  
  254.     return counter;
  255. }
  256.  
  257. int strcmp(const char *a, const char *b)
  258. {
  259.     int c = 0;
  260.    
  261.     while (a[c] && b[c] && (!(a[c] - b[c])))
  262.         c++;
  263.    
  264.     return (a[c] - b[c]);
  265. }
  266.  
  267. int strncmp(const char *a, const char *b, size_t n)
  268. {
  269.     size_t c = 0;
  270.  
  271.     while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
  272.         c++;
  273.    
  274.     return ( c < n ? a[c] - b[c] : 0);
  275.    
  276. }
  277.  
  278. int stricmp(const char *a, const char *b)
  279. {
  280.     int c = 0;
  281.    
  282.     while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
  283.         c++;
  284.    
  285.     return (tolower(a[c]) - tolower(b[c]));
  286. }
  287.  
  288. /** Return pointer to the first occurence of character c in string.
  289.  *
  290.  * @param str       Scanned string.
  291.  * @param c     Searched character (taken as one byte).
  292.  * @return      Pointer to the matched character or NULL if it is not
  293.  *          found in given string.
  294.  */
  295. char *strchr(const char *str, int c)
  296. {
  297.     while (*str != '\0') {
  298.         if (*str == (char) c)
  299.             return (char *) str;
  300.         str++;
  301.     }
  302.  
  303.     return NULL;
  304. }
  305.  
  306. /** Return pointer to the last occurence of character c in string.
  307.  *
  308.  * @param str       Scanned string.
  309.  * @param c     Searched character (taken as one byte).
  310.  * @return      Pointer to the matched character or NULL if it is not
  311.  *          found in given string.
  312.  */
  313. char *strrchr(const char *str, int c)
  314. {
  315.     char *retval = NULL;
  316.  
  317.     while (*str != '\0') {
  318.         if (*str == (char) c)
  319.             retval = (char *) str;
  320.         str++;
  321.     }
  322.  
  323.     return (char *) retval;
  324. }
  325.  
  326. /** Convert string to a number.
  327.  * Core of strtol and strtoul functions.
  328.  *
  329.  * @param nptr      Pointer to string.
  330.  * @param endptr    If not NULL, function stores here pointer to the first
  331.  *          invalid character.
  332.  * @param base      Zero or number between 2 and 36 inclusive.
  333.  * @param sgn       It's set to 1 if minus found.
  334.  * @return      Result of conversion.
  335.  */
  336. static unsigned long
  337. _strtoul(const char *nptr, char **endptr, int base, char *sgn)
  338. {
  339.     unsigned char c;
  340.     unsigned long result = 0;
  341.     unsigned long a, b;
  342.     const char *str = nptr;
  343.     const char *tmpptr;
  344.    
  345.     while (isspace(*str))
  346.         str++;
  347.    
  348.     if (*str == '-') {
  349.         *sgn = 1;
  350.         ++str;
  351.     } else if (*str == '+')
  352.         ++str;
  353.    
  354.     if (base) {
  355.         if ((base == 1) || (base > 36)) {
  356.             /* FIXME: set errno to EINVAL */
  357.             return 0;
  358.         }
  359.         if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
  360.             (str[1] == 'X'))) {
  361.             str += 2;
  362.         }
  363.     } else {
  364.         base = 10;
  365.        
  366.         if (*str == '0') {
  367.             base = 8;
  368.             if ((str[1] == 'X') || (str[1] == 'x'))  {
  369.                 base = 16;
  370.                 str += 2;
  371.             }
  372.         }
  373.     }
  374.    
  375.     tmpptr = str;
  376.  
  377.     while (*str) {
  378.         c = *str;
  379.         c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
  380.             (c <= '9' ? c - '0' : 0xff)));
  381.         if (c > base) {
  382.             break;
  383.         }
  384.        
  385.         a = (result & 0xff) * base + c;
  386.         b = (result >> 8) * base + (a >> 8);
  387.        
  388.         if (b > (ULONG_MAX >> 8)) {
  389.             /* overflow */
  390.             /* FIXME: errno = ERANGE*/
  391.             return ULONG_MAX;
  392.         }
  393.    
  394.         result = (b << 8) + (a & 0xff);
  395.         ++str;
  396.     }
  397.    
  398.     if (str == tmpptr) {
  399.         /*
  400.          * No number was found => first invalid character is the first
  401.          * character of the string.
  402.          */
  403.         /* FIXME: set errno to EINVAL */
  404.         str = nptr;
  405.         result = 0;
  406.     }
  407.    
  408.     if (endptr)
  409.         *endptr = (char *) str;
  410.  
  411.     if (nptr == str) {
  412.         /*FIXME: errno = EINVAL*/
  413.         return 0;
  414.     }
  415.  
  416.     return result;
  417. }
  418.  
  419. /** Convert initial part of string to long int according to given base.
  420.  * The number may begin with an arbitrary number of whitespaces followed by
  421.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  422.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  423.  * and the number begin with a zero, number will be taken as octal one (as with
  424.  * base 8). Otherwise the base 0 is taken as decimal.
  425.  *
  426.  * @param nptr      Pointer to string.
  427.  * @param endptr    If not NULL, function stores here pointer to the first
  428.  *          invalid character.
  429.  * @param base      Zero or number between 2 and 36 inclusive.
  430.  * @return      Result of conversion.
  431.  */
  432. long int strtol(const char *nptr, char **endptr, int base)
  433. {
  434.     char sgn = 0;
  435.     unsigned long number = 0;
  436.    
  437.     number = _strtoul(nptr, endptr, base, &sgn);
  438.  
  439.     if (number > LONG_MAX) {
  440.         if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
  441.             /* FIXME: set 0 to errno */
  442.             return number;     
  443.         }
  444.         /* FIXME: set ERANGE to errno */
  445.         return (sgn ? LONG_MIN : LONG_MAX);
  446.     }
  447.    
  448.     return (sgn ? -number : number);
  449. }
  450.  
  451.  
  452. /** Convert initial part of string to unsigned long according to given base.
  453.  * The number may begin with an arbitrary number of whitespaces followed by
  454.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  455.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  456.  * and the number begin with a zero, number will be taken as octal one (as with
  457.  * base 8). Otherwise the base 0 is taken as decimal.
  458.  *
  459.  * @param nptr      Pointer to string.
  460.  * @param endptr    If not NULL, function stores here pointer to the first
  461.  *          invalid character
  462.  * @param base      Zero or number between 2 and 36 inclusive.
  463.  * @return      Result of conversion.
  464.  */
  465. unsigned long strtoul(const char *nptr, char **endptr, int base)
  466. {
  467.     char sgn = 0;
  468.     unsigned long number = 0;
  469.    
  470.     number = _strtoul(nptr, endptr, base, &sgn);
  471.  
  472.     return (sgn ? -number : number);
  473. }
  474.  
  475. char *strcpy(char *dest, const char *src)
  476. {
  477.     char *orig = dest;
  478.    
  479.     while ((*(dest++) = *(src++)))
  480.         ;
  481.     return orig;
  482. }
  483.  
  484. char *strncpy(char *dest, const char *src, size_t n)
  485. {
  486.     char *orig = dest;
  487.    
  488.     while ((*(dest++) = *(src++)) && --n)
  489.         ;
  490.     return orig;
  491. }
  492.  
  493. char *strcat(char *dest, const char *src)
  494. {
  495.     char *orig = dest;
  496.     while (*dest++)
  497.         ;
  498.     --dest;
  499.     while ((*dest++ = *src++))
  500.         ;
  501.     return orig;
  502. }
  503.  
  504. char * strdup(const char *s1)
  505. {
  506.     size_t len = strlen(s1) + 1;
  507.     void *ret = malloc(len);
  508.  
  509.     if (ret == NULL)
  510.         return (char *) NULL;
  511.  
  512.     return (char *) memcpy(ret, s1, len);
  513. }
  514.  
  515. /* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
  516. char * strtok_r(char *s, const char *delim, char **last)
  517. {
  518.     char *spanp, *tok;
  519.     int c, sc;
  520.  
  521.     if (s == NULL && (s = *last) == NULL)
  522.         return (NULL);
  523.  
  524. cont:
  525.     c = *s++;
  526.     for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
  527.         if (c == sc)
  528.             goto cont;
  529.     }
  530.  
  531.     if (c == 0) {       /* no non-delimiter characters */
  532.         *last = NULL;
  533.         return (NULL);
  534.     }
  535.  
  536.     tok = s - 1;
  537.  
  538.     for (;;) {
  539.         c = *s++;
  540.         spanp = (char *)delim;
  541.         do {
  542.             if ((sc = *spanp++) == c) {
  543.                 if (c == 0)
  544.                     s = NULL;
  545.                 else
  546.                     s[-1] = '\0';
  547.                 *last = s;
  548.                 return (tok);
  549.             }
  550.         } while (sc != 0);
  551.     }
  552. }
  553.  
  554. /* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
  555. char * strtok(char *s, const char *delim)
  556. {
  557.     static char *last;
  558.  
  559.     return (strtok_r(s, delim, &last));
  560. }
  561.  
  562. /** @}
  563.  */
  564.