summaryrefslogtreecommitdiffstats
path: root/llvm/runtime/GCCLibraries/libc/string.c
blob: f697dd4d19ade2010546a6ac02a3bef08c796611 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//===-- string.c - String functions for the LLVM libc Library -----*- C -*-===//
// 
// A lot of this code is ripped gratuitously from glibc and libiberty.
//
//===----------------------------------------------------------------------===//

#include <stdlib.h>
void *malloc(unsigned);
void free(void *);

unsigned strlen(const char *Str) {
  int Count = 0;
  while (*Str) { ++Count; ++Str; }
  return Count;
}

char *strdup(const char *str) {
  int Len = strlen(str);
  char *Result = (char*)malloc((Len+1)*sizeof(char));
  memcpy(Result, str, Len+1);
  return Result;
}

char *strcpy(char *s1, const char *s2) {
  while ((*s1++ = *s2++));
  return s1;
}


/* Compare S1 and S2, returning less than, equal to or
   greater than zero if S1 is lexicographically less than,
   equal to or greater than S2.  */
int strcmp (const char *p1, const char *p2) {
  register const unsigned char *s1 = (const unsigned char *) p1;
  register const unsigned char *s2 = (const unsigned char *) p2;
  unsigned char c1, c2;

  do
    {
      c1 = (unsigned char) *s1++;
      c2 = (unsigned char) *s2++;
      if (c1 == '\0')
        return c1 - c2;
    }
  while (c1 == c2);

  return c1 - c2;
}

// http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/generic/?cvsroot=glibc

typedef unsigned int op_t;
#define OPSIZ 4

void *memset (void *dstpp, int c, size_t len) {
  long long int dstp = (long long int) dstpp;

  if (len >= 8)
    {
      size_t xlen;
      op_t cccc;

      cccc = (unsigned char) c;
      cccc |= cccc << 8;
      cccc |= cccc << 16;
      if (OPSIZ > 4)
        /* Do the shift in two steps to avoid warning if long has 32 bits.  */
        cccc |= (cccc << 16) << 16;

      /* There are at least some bytes to set.
         No need to test for LEN == 0 in this alignment loop.  */
      while (dstp % OPSIZ != 0)
        {
          ((unsigned char *) dstp)[0] = c;
          dstp += 1;
          len -= 1;
        }

      /* Write 8 `op_t' per iteration until less than 8 `op_t' remain.  */
      xlen = len / (OPSIZ * 8);
      while (xlen > 0)
        {
          ((op_t *) dstp)[0] = cccc;
          ((op_t *) dstp)[1] = cccc;
          ((op_t *) dstp)[2] = cccc;
          ((op_t *) dstp)[3] = cccc;
          ((op_t *) dstp)[4] = cccc;
          ((op_t *) dstp)[5] = cccc;
          ((op_t *) dstp)[6] = cccc;
          ((op_t *) dstp)[7] = cccc;
          dstp += 8 * OPSIZ;
          xlen -= 1;
        }
      len %= OPSIZ * 8;

      /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain.  */
      xlen = len / OPSIZ;
      while (xlen > 0)
        {
          ((op_t *) dstp)[0] = cccc;
          dstp += OPSIZ;
          xlen -= 1;
        }
      len %= OPSIZ;
    }

  /* Write the last few bytes.  */
  while (len > 0)
    {
      ((unsigned char *) dstp)[0] = c;
      dstp += 1;
      len -= 1;
    }

  return dstpp;
}

void *memcpy(void *dstpp, const void *srcpp, size_t len) {
  char *dstp = (char*)dstpp;
  char *srcp = (char*) srcpp;
  unsigned i;

  for (i = 0; i < len; ++i)
    dstp[i] = srcp[i];

  return dstpp;
}
OpenPOWER on IntegriCloud