/*
Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)

Permission to use, copy, modify, and distribute this material 
for any purpose and without fee is hereby granted, provided 
that the above copyright notice and this permission notice 
appear in all copies, and that the name of Bellcore not be 
used in advertising or publicity pertaining to this 
material without the specific, prior written permission 
of an authorized representative of Bellcore.  BELLCORE 
MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY 
OF THIS MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS", 
WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
*/

#include <ctype.h>
#include <string.h>
#include "iso646.h"
#define Char unsigned char

#define NA 100
#define NU 101
#define HT 102
#define LF 103
#define CR 104
#define SP 105
#define EQ 106

static Char basis_base[] =
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static Char index_base[256] = begin
    NU,NA,NA,NA, NA,NA,NA,NA, NA,HT,LF,NA, NA,CR,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    SP,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,62, NA,NA,NA,63,
    52,53,54,55, 56,57,58,59, 60,61,NA,NA, NA,EQ,NA,NA,
    NA, 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,NA, NA,NA,NA,NA,
    NA,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,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA
end;

void
base4(c1, c2, c3, pads, out)
Char c1,c2,c3,*out;
int pads;
begin
    *out++ =      basis_base[c1>>2];
    *out++ =      basis_base[((c1 & 0x3)<< 4) | ((int)(c2 & 0xF0) >> 4)];
    if (pads == 2) *out++ = '=';
    else *out++ = basis_base[((c2 & 0xF) << 2) | ((int)(c3 & 0xC0) >>6)];
    if (pads)      *out++ = '=';
    else *out++ = basis_base[c3 & 0x3F];
end

Char c1, c2;

Char *
binc2base(in, out, pos) 
Char in, *out; int pos;
begin
    int nbr= pos%3;
    switch(nbr) begin
	case 0: c1= in; break;
	case 1: c2= in; break;
	case 2: base4(c1,c2,in,0, out); out+=4;
		if (pos==53) begin
    		    *out++ = '\n';
		    *out++ = '\0';
		    return NULL;
		end
    end
    return out;
end

void
bincl2base(out, pos) 
Char *out; int pos;
begin
    int nbr= pos%3;
    if (nbr) begin
	if (nbr == 1) c2=0;
	base4(c1,c2,0,3-nbr, out);
    	out += 4;
    end
    *out++ = '\n';
    *out++ = '\0';
end

Char *
base2bin(in, out)
Char *in, *out;
begin
    Char c1, c2, c3, c4, *outmax=out+72;
    while (out < outmax and (c1 = index_base[*in++]) < NA ) begin
        c2 = index_base[*in++];
        *out++ =((c1<<2) | ((int)(c2&0x30)>>4));
	if ((c3 = index_base[*in++])<NA) *out++ = ((c2&017) << 4) | ((int)(c3&0x3C) >> 2);
	if ((c4 = index_base[*in++])<NA) *out++ = ((c3&0x03)<<6) | c4;
    end
    return out;
end

static Char basis_qp[] = "0123456789ABCDEF";
static Char index1_qp[256] = begin
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
     0,16,32,48,    64,80,96,112,   128,144,NA,NA, NA,NA,NA,NA,
    NA,160,176,192, 208,224,240,NA, NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,160,176,192, 208,224,240,NA, NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA,
    NA,NA,NA,NA,    NA,NA,NA,NA,    NA,NA,NA,NA,   NA,NA,NA,NA
end;

static Char index2_qp[256] = begin
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
     0, 1, 2, 3,  4, 5, 6, 7,  8, 9,NA,NA, NA,NA,NA,NA,
    NA,10,11,12, 13,14,15,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,10,11,12, 13,14,15,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA,
    NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA, NA,NA,NA,NA
end;

Char *
bin2qp(in, out, inmax) 
register Char *in, *out, *inmax;
begin
    register Char c, *outbeg= out, *outmax= out+72;
    if (strncmp((char *)in,"From ",5) == 0) begin  /* avoid sendmail ">From " */
	strncpy((char *)out,"=46rom ",7);
        in += 5; out += 7; 
    end else if (*in == '.') begin  /* avoid single period bug */
	strcpy((char *)out,"=2E");  /* hex for "." */
	in++; out +=3;
    end
    while (in<inmax) begin
        c= *in++;
        if ((c < 32 and c != '\t') or c == '=' or c >= 127) begin
            *out++ = '=';
            *out++ = basis_qp[c>>4];
            *out++ = basis_qp[c&15];
        end else *out++ = c;
        if (out > outmax and in < inmax) begin
            *out++ = '=';
            *out++ = '\n';
            *out++ = '\0';
            return in;
        end
    end
    if (out != outbeg and ((c=*(out-1)) == ' ' or c == '\t')) begin
        *(out-1) = '='; /* protect trailing space and tab */
        *out++ = basis_qp[c>>4];
        *out++ = basis_qp[c&15];
    end
    *out++ = '\n';
    *out++ = '\0';
    return in;
end

Char *
qp2bin(in, out) 
Char *in, *out;
begin
    Char c;
    while ((c = *in++) != 0) begin
	if (c == '=') begin
	    if ((c = *in++) != 0) *out++ = index1_qp[c] + index2_qp[*in++];
	    else return out; /* end of qp line */
	end else *out++ = c;
    end
    *out++ = '\n';
    *out = '\0';
    return out;
end
