www.pudn.com > doc2pdf-0_7_1.rar > printablecodec.c


// Code obtained from John Walkers qprint project
// 
// http://www.fourmilab.ch/webtools/qprint
// 
// Some minor modifications made by Matt Peterson


#include  
#include  
#include  
#include  
#include  
#include  

#define TRUE 1
#define FALSE 0
#define LINELEN 72
#define MAXINLINE 256 
#define ASCII_HORIZONTAL_TAB 9
#define ASCII_LINE_FEED 10
#define ASCII_CARRIAGE_RETURN 13
#define ASCII_SPACE 32
#define ASCII_0 48
#define ASCII_EQUAL_SIGN 61
#define ASCII_A 65
#define ASCII_LOWER_CASE_A 97 


#define Character_is_printable_ISO_8859(c) (((((c) >=0x20) &&((c) <=0x7E) ) ||((c) >=0xA1) ) )  \

typedef unsigned char byte;

static FILE*fi;

static FILE*fo;

typedef enum
{
    Rule_1,Rule_2,Rule_3,Rule_4,Rule_EBCDIC
}
character_encoding_rule;

static character_encoding_rule character_class[256];

static int current_line_length= 0;

static int pending_white_space= 0;

#if (SIZEOF_UNSIGNED_LONG == 8) || (SIZEOF_UNSIGNED_LONG_LONG == 0)
    typedef unsigned long file_address_type;
    #define FILE_ADDRESS_FORMAT_LENGTH "l"
#else
    typedef unsigned long long file_address_type;
    #define FILE_ADDRESS_FORMAT_LENGTH "ll"
#endif

static file_address_type decode_input_stream_position= 0;
static long decode_errors= 0;
static int decoding= FALSE;
static int encoding= FALSE;
static int binary_input= FALSE;
static int errcheck= TRUE;
static int EBCDIC_out= FALSE;
static int paranoid= FALSE;

static int read_decode_character(void);

static int hex_to_nybble(int ch);

static void output_line_break(void)
{
    static char line_break[3]= {ASCII_CARRIAGE_RETURN,ASCII_LINE_FEED,0};

    fputs(line_break,fo);
    current_line_length= 0;
}

static void check_line_length(int chars_required)
{
    if ((current_line_length+chars_required)>=(LINELEN-1))
    {
        putc(ASCII_EQUAL_SIGN,fo);
        output_line_break();
    }
    current_line_length+= chars_required;
}

static void emit_literally(int ch)
{
    check_line_length(1);
    putc(ch,fo);
}

static void emit_hex_encoded(int ch)
{
    static char hex[16]= {ASCII_0,ASCII_0+1,ASCII_0+2,ASCII_0+3,
        ASCII_0+4,ASCII_0+5,ASCII_0+6,
        ASCII_0+7,ASCII_0+8,ASCII_0+9,
        ASCII_A,ASCII_A+1,ASCII_A+2,ASCII_A+3,
        ASCII_A+4,ASCII_A+5};

    check_line_length(3);
    putc(ASCII_EQUAL_SIGN,fo);
    putc(hex[(ch>>4)&0xF],fo);
    putc(hex[ch&0xF],fo);
}

static void encode(void)
{
    int i,ch;

    for (i= 0;i<=255;i++)
    {
        character_class[i]= Rule_1;
    }

    for (i= 33;i<=60;i++)
    {
        character_class[i]= Rule_2;
    }

    for (i= 62;i<=126;i++)
    {
        character_class[i]= Rule_2;
    }

    character_class[ASCII_HORIZONTAL_TAB]= Rule_3;
    character_class[ASCII_SPACE]= Rule_3;
    character_class[ASCII_LINE_FEED]= Rule_4;
    character_class[ASCII_CARRIAGE_RETURN]= Rule_4;
    character_class[33]= 
    character_class[34]= 
    character_class[35]= 
    character_class[36]= 
    character_class[64]= 
    character_class[91]= 
    character_class[92]= 
    character_class[93]= 
    character_class[94]= 
    character_class[96]= 
    character_class[123]= 
    character_class[124]= 
    character_class[125]= 
    character_class[126]= Rule_EBCDIC;

    while ((ch= getc(fi))!=EOF)
    {
        switch (character_class[ch])
        {
        case Rule_1:
            if (pending_white_space!=0)
            {
                emit_literally(pending_white_space);
                pending_white_space= 0;
            }
            emit_hex_encoded(ch);
            break;

        case Rule_2:
            if (pending_white_space!=0)
            {
                emit_literally(pending_white_space);
                pending_white_space= 0;
            }
            if (paranoid)
            {
                emit_hex_encoded(ch);
            }
            else
            {
                emit_literally(ch);
            }
            break;

        case Rule_3:
            if (paranoid)
            {
                emit_hex_encoded(ch);
            }
            else
            {
                if (pending_white_space!=0)
                {
                    emit_literally(pending_white_space);
                    pending_white_space= 0;
                }
                pending_white_space= ch;
            }
            break;

        case Rule_4:
            if (binary_input)
            {
                if (pending_white_space!=0)
                {
                    emit_literally(pending_white_space);
                    pending_white_space= 0;
                }
                emit_hex_encoded(ch);
            }
            else
            {
                {
                    int chn= getc(fi);

                    if (chn!=EOF)
                    {
                        if ((chn==ASCII_LINE_FEED)||(chn==ASCII_CARRIAGE_RETURN))
                        {
                            if (chn==ch)
                            {
                                ungetc(chn,fi);
                            }
                        }
                        else
                        {
                            ungetc(chn,fi);
                        }
                    }
                }
                
                if (pending_white_space!=0)
                {
                    emit_hex_encoded(pending_white_space);
                    pending_white_space= 0;
                }
                output_line_break();
            }
            break;

        case Rule_EBCDIC:
            if (pending_white_space!=0)
            {
                emit_literally(pending_white_space);
                pending_white_space= 0;
            }
            if (EBCDIC_out||paranoid)
            {
                emit_hex_encoded(ch);
            }
            else
            {
                emit_literally(ch);
            }
            break;
        }
    }
    
    if (pending_white_space!=0)
    {
        emit_literally(pending_white_space);
        pending_white_space= 0;
    }

    if (current_line_length> 0)
    {
        putc(ASCII_EQUAL_SIGN,fo);
        output_line_break();
    }
}

static int is_end_of_line_sequence(int ch)
{
    if(ch == EOF) 
	{ 
		return TRUE; 
	} 
	 
	if ((ch==ASCII_CARRIAGE_RETURN)||(ch==ASCII_LINE_FEED))
    {
        int chn= getc(fi);

        if (chn!=EOF)
        {
            if ((chn==ASCII_LINE_FEED)||(chn==ASCII_CARRIAGE_RETURN))
            {
                if (chn==ch)
                {
                    ungetc(chn,fi);
                }
            }
            else
            {
                ungetc(chn,fi);
            }
        }
        
        return TRUE;
    }

    return FALSE;
}


static void decode(void)
{
    int ch,ch1,ch2;

    while ((ch= read_decode_character())!=EOF)
    {
        switch (ch)
        {
        
        case ASCII_EQUAL_SIGN:
            ch1= read_decode_character();
            while (((ch1==ASCII_SPACE)||(ch1==ASCII_HORIZONTAL_TAB)))
            {
                ch1= read_decode_character();
                if (is_end_of_line_sequence(ch1))
                {
                    break;
                }
                if (!((ch1==ASCII_SPACE)||(ch1==ASCII_HORIZONTAL_TAB)))
                {
                    if (errcheck)
                    {
                        if (('a'==0x61) &&
                            Character_is_printable_ISO_8859(ch1))
                        {

                            fprintf(stderr,
                                    "Error: invalid character \"%c\" in soft line break sequence at byte %"
                                    FILE_ADDRESS_FORMAT_LENGTH
                                    "u (0x%"
                                    FILE_ADDRESS_FORMAT_LENGTH
                                    "X) of input.\n",
                                    ch1,decode_input_stream_position-1,
                                    decode_input_stream_position-1);
                        }
                        else
                        {


                            fprintf(stderr,
                                    "Error: invalid character \"0x%02X\" in soft line break sequence at byte %"
                                    FILE_ADDRESS_FORMAT_LENGTH
                                    "u (0x%"
                                    FILE_ADDRESS_FORMAT_LENGTH
                                    "X) of input.\n",
                                    ch1,decode_input_stream_position-1,
                                    decode_input_stream_position-1);
                        }
                    }
                    decode_errors++;
                    ch1= ASCII_SPACE;
                }
            }
            
            if (is_end_of_line_sequence(ch1))
            {
                ch= EOF;
            }
            else
            {
                int n1,n2;

                n1= hex_to_nybble(ch1);
                ch2= read_decode_character();
                n2= hex_to_nybble(ch2);
                if (n1==EOF||n2==EOF)
                {
                    if (errcheck)
                    {
                        if (('a'==0x61) &&
                            Character_is_printable_ISO_8859(ch1)&&
                            Character_is_printable_ISO_8859(ch2))
                        {
                            fprintf(stderr,
                                    "Error: bad equal sign escape \"=%c%c\" at byte %"
                                    FILE_ADDRESS_FORMAT_LENGTH
                                    "u (0x%"
                                    FILE_ADDRESS_FORMAT_LENGTH
                                    "X) of input.\n",
                                    ch1,ch2,decode_input_stream_position-3,
                                    decode_input_stream_position-3);
                        }
                        else
                        {
                            fprintf(stderr,
                                    "Error: bad equal sign escape \"= 0x%02X 0x%02X\" at byte %"
                                    FILE_ADDRESS_FORMAT_LENGTH
                                    "u (0x%"
                                    FILE_ADDRESS_FORMAT_LENGTH
                                    "X) of input.\n",
                                    ch1,ch2,decode_input_stream_position-3,
                                    decode_input_stream_position-3);
                        }
                    }
                    decode_errors++;
                }
                ch= (n1<<4)|n2;
            }
            
            if (ch!=EOF)
            {
                putc(ch,fo);
            }
            break;

        case ASCII_CARRIAGE_RETURN:
        case ASCII_LINE_FEED:
            {
                int chn= getc(fi);

                if (chn!=EOF)
                {
                    if ((chn==ASCII_LINE_FEED)||(chn==ASCII_CARRIAGE_RETURN))
                    {
                        if (chn==ch)
                        {
                            ungetc(chn,fi);
                        }
                    }
                    else
                    {
                        ungetc(chn,fi);
                    }
                }
            }
            putc('\n',fo);
            break;

        default:
            putc(ch,fo);
            break;
        }
    }
}

static int read_decode_character(void)
{
    int ch;

    ch= getc(fi);
    if (ch!=EOF)
    {
        decode_input_stream_position++;
    }
    return ch;
}

static int hex_to_nybble(int ch)
{
    if ((ch>=ASCII_0)&&(ch<=(ASCII_0+9)))
    {
        return ch-'0';
    }
    else if ((ch>=ASCII_A)&&(ch<=(ASCII_A+5)))
    {
        return 10+(ch-ASCII_A);
    }
    else if ((ch>=ASCII_LOWER_CASE_A)&&(ch<=(ASCII_LOWER_CASE_A+5)))
    {
        return 10+(ch-ASCII_LOWER_CASE_A);
    }
    return EOF;
}


// returns zero on success
int decode_quoted_printable(const char* infilename, const char* outfilename)
{
    fi = fopen(infilename,"r");
    if(fi == NULL)
    {
        return -1;
    }

    fo = fopen(outfilename,"w");
    if(fo == NULL)
    {
        return -1;
    }

    decode(); 
 
	fclose(fi); 
	fclose(fo); 

    return 0;
}