#define BORDER_CHARS            1

U8   *buf;
I64       size, mp_not_done_flags;
CDoc *doc;

U0 PDNormalize()
{
        U8 *r = MAlloc(size+2*BORDER_CHARS), *src = buf, *dst = r;
        I64 ch;

        *dst++ = '['; //Border
        while (size--)
        {
                ch = *src++;
                if ('a' <= ch <= 'z') //lower is most common so do first
                        *dst++ = ch;
                else if ('A' <= ch <= 'Z')
                        *dst++ = ch + 'a' - 'A'; //Convert to lower
        }
        *dst++ = ']'; //Border
        Free(buf);
        buf = r;
        size = dst - r - 2 * BORDER_CHARS;
}

U0 PDAnswer(U8 *a, I64 len)
{
        DocLock(doc);
        a -= (len - 1) / 2;
        DocPrint(doc, "CPU%02X Len:%2d ", Gs->num, len);
        while (len--)
                DocPrint(doc, "%C", *a++); //%C is toupper char
        DocPrint(doc, "\n");
        DocUnlock(doc);
}

U0 MPPalindrome(I64 dummy=0)
{
        no_warn dummy;
        U8 *src = buf + BORDER_CHARS + size * Gs->num / mp_count, *f, *b;
        I64 len, best = 0, my_size = (size + mp_count - 1) / mp_count;
        while (my_size--)
        {

                //Odd
                f = src + 1;
                b = src - 1;
                while (*f == *b)
                {
                        f++;
                        b--;
                }
                len = f - b + 1 - 2;
                if (len > best)
                {
                        best = len;
                        PDAnswer(src, len);
                }

                //Even
                f = src + 1;
                b = src;
                while (*f == *b)
                {
                        f++;
                        b--;
                }
                len = f - b + 1 - 2;
                if (len > best)
                {
                        best = len;
                        PDAnswer(src, len);
                }

                src++;
        }
        LBtr(&mp_not_done_flags, Gs->num);
}

U0 Palindrome(U8 *filename)
{
        I64 i;
        F64 t0 = tS;

        buf = FileRead(filename, &size);
        PDNormalize;

        doc = DocPut;
        mp_not_done_flags = 1 << mp_count - 1;
        for (i = 0; i < mp_count; i++)
                JobQueue(&MPPalindrome, NULL, i);
        while (mp_not_done_flags)
                Yield;

        Free(buf);
        "Time:%9.5f\n", tS - t0;
}

Palindrome(BIBLE_FILENAME);