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