ietf-822
[Top] [All Lists]

MU conversion program bug fix

1993-01-16 13:47:20
Sorry, but there was a bug in the MU program I sent recently.  (I
forgot about the possibility of a MU character straddling an input
block boundary.)

Here is a version that is fixed and cleaned up:

/*

SYNOPSIS

    int  runetomu(unsigned char *m, Rune *r)

    int  mutorune(Rune *r, unsigned char *m)


DESCRIPTION

    These routines convert between a MU byte stream and runes.

    Runetomu converts one rune at r to a MU character of at most 4 bytes
    starting at m and returns the number of bytes written.  If m is NULL,
    runetomu returns the number of bytes that would have been written if m
    was not NULL.

    Mutorune converts a MU character of at most 4 bytes starting at m to
    one rune at r and returns the number of bytes converted.  If the bytes
    are not exactly in MU format, mutorune will copy the first byte to r
    and return 1.  If r is NULL, mutorune returns the number of bytes that
    would have been converted if r was not NULL.

*/


#include <stdio.h>

typedef unsigned short Rune;

static unsigned char encode[] =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static unsigned int decode[] = {
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
        64,  0,  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, 64, 64, 64, 64, 64,
        64, 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, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};

int
runetomu(m, r)
        unsigned char   *m;
        Rune            *r;
{
        Rune            rune;

        if (!r) return 0;

        rune = *r;

        if (rune == '=')
        {
                if (m)
                {
                        *m++ = '=';
                        *m   = '=';
                }
                return 2;
        }
        else if (rune & 0xff80)
        {
                if (m)
                {
                        *m++ = '=';
                        *m++ = encode[rune >> 10];
                        *m++ = encode[(rune >> 4) & 0x3f];
                        *m   = encode[(rune << 2) & 0x3f];
                }
                return 4;
        }

        if (m) *m = rune;
        return 1;
}

int
mutorune(r, m)
        Rune            *r;
        unsigned char   *m;
{
        unsigned int    part1, part2, part3;

        if (!m) return 0;

        if (*m != '=')
        {
                if (r) *r = *m;
                return 1;
        }
        else if (!(*(m+1)))     /* premature NULL terminator */
        {
                if (r) *r = *m;
                return 1;
        }
        else if (*(m+1) == '=')
        {
                if (r) *r = '=';
                return 2;
        }
        else if
        (
                (!(*(m+2))) ||  /* premature NULL terminator */
                (!(*(m+3)))
        )
        {
                if (r) *r = *m;
                return 1;
        }

        part1 = decode[*(m+1)];
        part2 = decode[*(m+2)];
        part3 = decode[*(m+3)];

        if
        (
                (part1 != 64) &&
                (part2 != 64) &&
                (part3 != 64)
        )
        {
                if (r) *r = (part1 << 10) | (part2 << 4) | (part3 >> 2);
                return 4;
        }

        if (r) *r = *m;
        return 1;
}

#ifndef muLIBRARY
int
main(argc, argv)
        int     argc;
        char    *argv[];
{
        extern char     *strrchr();
        char            *name;
        int             nread;
        unsigned char   in [256];
        unsigned char   out[512];

        if (name = strrchr(argv[0], '/')) name++;
        else name = argv[0];

        if (!strcmp(name, "unitomu"))
        {
                while ((nread = fread(in, 1, sizeof(in), stdin)) > 0)
                {
                        unsigned char   *out_ptr = out;
                        int             i;

                        for (i = 0; i < nread - 1; i += 2)
                        {
                                Rune    rune;

                                rune = (in[i] << 8) | in[i+1];
                                out_ptr += runetomu(out_ptr, &rune);
                        }
                        if (i < nread)
                        {
                                fprintf(stderr, "%s: warning: Unicode file has 
odd number of bytes (last one ignored)\n", name);
                                exit(1);
                        }
                        (void) fwrite(out, 1, out_ptr - out, stdout);
                }
        }
        else
        {
                int     left;

                left = 0;
                while
                (
                        ((nread = fread(&in[left], 1,
                                sizeof(in) - left, stdin)) > 0)
                     || (left > 0)
                )
                {
                        int     in_index, out_index;

                        nread = nread + left;
                        out_index = 0;
                        for (in_index = 0; in_index < nread; )
                        {
                                Rune    rune;

                                in_index += mutorune(&rune, &in[in_index]);
                                out[out_index++] = rune >> 8;
                                out[out_index++] = rune & 0xff;
                                if ((left = sizeof(in) - in_index) < 5)
                                {
                                        (void) memcpy(in, &in[in_index], left);
                                        break;
                                }
                                else
                                {
                                        left = 0;
                                }
                        }
                        (void) fwrite(out, 1, out_index, stdout);
                }
        }

        return 0;
}
#endif


<Prev in Thread] Current Thread [Next in Thread>