/* string.c: ANSI draft (X3J11 Oct 86) library code, section 4.11 */
/* Copyright (C) Codemist Ltd., 1988                              */
/* Copyright (C) Advanced Risc Machines Ltd., 1991                */
/* version 3a */

#pragma -s1			/* Turn OFF stack checking */

typedef unsigned int size_t;

#define _chararg int            /* arg spec for char when ANSI says int */
#define _copywords 1            /* do fast cpy/cmp if word aligned      */

/* The following magic check was designed by A. Mycroft. It yields a     */
/* nonzero value if the argument w has a zero byte in it somewhere. The  */
/* messy constants have been unfolded a bit in this code so that they    */
/* get preloaded into registers before relevant loops.                   */

#ifdef _copywords
#  define ONES_WORD   0x01010101
#  define EIGHTS_WORD (ones_word << 7)
#  define nullbyte_prologue_() \
      int ones_word = ONES_WORD;
#  define word_has_nullbyte(w) (((w) - ones_word) & ~(w) & EIGHTS_WORD)
#endif

void *memcpy(void *a, const void *b, size_t n)
/* copy memory (upwards) - it is an error for args to overlap. */
/* Relies on sizeof(int)=sizeof(void *) and byte addressing.   */
{
#ifdef _copywords
    /* do it fast if word aligned ... */
    if ((((int)a | (int)b | (int)n) & 3) == 0)
    { int *wa,*wb;
      n >>= 2;
      for (wa = (int *)a, wb = (int *)b; n-- > 0;) *wa++ = *wb++;
    }
    else
#endif
    { char *ca,*cb;
      for (ca = (char *)a, cb = (char *)b; n-- > 0;) *ca++ = *cb++;
    }
    return a;
}

int strcmp(const char *a, const char *b) /* lexical comparison on strings */
{
#ifdef _copywords
    if ((((int)a | (int)b) & 3) == 0)
    {   int w1, w2;
        nullbyte_prologue_();
        do {
            w1 = *(int *)a, a += 4;
            w2 = *(int *)b, b += 4;
        } while (w1 == w2 && !word_has_nullbyte(w1));
#ifdef BYTESEX_EVEN
        for (;;)
        {   char c1 = w1 & 0xff, c2 = w2 & 0xff;
            int d = c1 - c2;
            if (d != 0) return d;
            if (c1 == 0) return 0;
            w1 = w1 >> 8; w2 = w2 >> 8;
        }
#else
        for (;;)
        {   char c1 = (w1 >> 24) & 0xff, c2 = (w2 >> 24) & 0xff;
            int d = c1 - c2;
            if (d != 0) return d;
            if (c1 == 0) return 0;
            w1 = w1 << 8; w2 = w2 << 8;
        }
#endif
    }
#endif
    for (;;)
    {   char c1 = *a++, c2 = *b++;
        int d = c1 - c2;
        if (d != 0) return d;
        if (c1 == 0) return 0;     /* no need to check c2 */
    }
}

char *strcpy(char *a, const char *b)                 /* copy from b to a */
{   char *p = a;
#ifdef _copywords
    if ((((int)p | (int)b) & 3) == 0)
    {   int w;
        nullbyte_prologue_()
        while (w = *(int *)b, b += 4, !word_has_nullbyte(w))
            *(int *)p = w, p += 4;
/* This next piece of code relies on knowledge of the order of bytes     */
/* within a word.                                                        */
#ifdef BYTESEX_EVEN
        for (;;)
        {   if ((*p++ = w) == 0) return a;
            w >>= 8;
        }
#else
        for (;;)
/* I rather assume that shifts are fast operations here.                 */
        {   if ((*p++ = (w >> 24)) == 0) return a;
            w <<= 8;
        }
#endif
    }
#endif
    while ((*p++ = *b++) != 0);
    return a;
}

/* end string.c */
