#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <ctype.h>

#define TABLE_SIZE  256

#define MAXLEN 1024             /* Max message as defined for TNPP */

typedef int boolean;

static unsigned table[TABLE_SIZE];

void initcrc16(void)
{
  unsigned i, index, entry;
  boolean carry;

  for (index = 0; index < TABLE_SIZE; ++index) {
    entry = index;

    for (i = 0; i < 8; ++i) {
      carry = entry & 1;  /* is bit zero set? */
      entry >>= 1;

      if ( carry )
	entry ^= 0xa001;
    }

    table[index] = entry;
  }
}
void crc16_update(char *buf, unsigned count, unsigned *crc16)
{
  unsigned i;
  unsigned char index;  /* 8-bit value so as to restrict range */

  for (i = 0; i < count; ++i) {
    index = buf[i] ^ *crc16;
    *crc16 >>= 8;
    *crc16 ^= table[index];
  }
}

void crc(char c, unsigned *crc16)
{
  unsigned char index;  /* 8-bit value so as to restrict range */

    index = c ^ *crc16;
    *crc16 >>= 8;
    *crc16 ^= table[index];
}

void crcput( char c , FILE *out , unsigned *crc16 ) {
	fputc( c , out );
	crc( c , crc16 );
	}

void crcputs( char *s , FILE *out , unsigned *crc16 ) {
	while (*s) crcput( *(s++) , out , crc16 );
	}
 /*              Soh   DestInSourSn    Stx    Etx */
char messxx[] = "\x01" "000007A21200" "\x02" "\x03";

char mess0[] = "\x01" "010107010500" "\x02" "\x03";

 /*              Soh   DestInSourSn    Stx   TFId--------M------------    Etx */
char mess1[] = "\x01" "010107010701" "\x02" "BA1997000   This is TNPP #2!  "/* Line'" "\x0a" "And a line`"  "\x0a" "Bell and RT" /* "\0x0d" "Is VT" /* "\x0b" "And a FF~" "\x0c" "And thats it"*/ "\x03";

 /*              Soh   DestInSourSn    Stx   TFId--------M------------    Etx */
char mess4[] = "\x01" "010107010702" "\x02" "B@1997000   This is TNPP #2! Line\x1a\x4a And a line"  "\x1a\x4a" "FF" "\x1a\x4c" /* "Is VT"  "\x1a\x4b" "And a FF" "\x1a\x4c"*/ "And thats it" "\x03";

 /*              Soh   DestInSourSn    Stx   TFId--------M------------    Etx */
char mess5[] = "\x01" "312103A21201" "\x02" "B@7777046   This is TNPP #1! Line\x1a\x4a And a line"  "\x1a\x4a" /* "Is VT"  "\x1a\x4b" "And a FF" "\x1a\x4c"*/ "And thats it" "\x03";
					    /*2718607*/
 /*              Soh   DestInSourSn    Stx   BTCDZFC-------M------------    Etx */
char mess2[] = "\x01" "010107627601" "\x02" "ApA@@C14101137This is TNPP CAP!" "\x03";
					    /*2718607*/
char mess3[] = "\x01" "000002000100\x02\x03" ;

char mess[MAXLEN+1];

void dohelp(void) {
	cprintf( "Usage: TNPP [-?] [-T] infile outfile header block\r\n");
	cprintf( "  -?   Displays this help screen\r\n");
	cprintf( "  -T   Uses transparent CRC calculation\r\n");
	cprintf( "\r\n");
	cprintf( "header has the format ddddiissssnn\r\n");
	cprintf( "           DDDD is the destination address\r\n");
	cprintf( "           II   is the inertia\r\n");
	cprintf( "           SSSS is the source address\r\n");
	cprintf( "           NN   is the packet serial number\r\n");
	cprintf( "block  has the format Bfiiiiiiiiii\r\n");
	cprintf( "           F    is the function ('@' for default)\r\n");
	cprintf( "           i... is the 10 digit ID code, left justified, speace padded\r\n");
	}

int main(int argc, char **argv) {
	FILE *in,*out;
	int arg;
	int c;
	unsigned crc16;
	int transflag=0;

/*      initcrc16();
	crc16=0;

	crcputs( mess0 , stdout , &crc16 );
	printf( "%02X%02X" , crc16 & 0xff , crc16 >> 8 );  */

	cprintf( "**** TNPP, Version 1.1, (c)1995 Joshua M. Levine\r\n");
	arg=1;
	while ( arg<argc && argv[arg][0]=='-' ) {
		switch (toupper(argv[arg][1])) {
			case '?':
				dohelp();
				return(1);

			case 'T':
				cprintf("Using TRANSPARENT CRC calculations.\r\n");
				transflag=1;
				break;

			default:
				cprintf("Unknown switch:%c\r\n",argv[arg][1]);
				cprintf("Try TNPP -? for help\r\n");
				return(1);
			}
		arg++;
		}
	if (arg+4 > argc ) {
		cprintf("Not enough arguments. Try TNPP -? for help.\r\n");
		return(3);
		}

	in=fopen( argv[arg] , "rb");
	if (!in) {
		cprintf( "Could not open infile : %s\r\n", argv[arg] );
		return(2);
		}
	arg++;
	out=fopen( argv[arg] , "wb");
	if (!out) {
		cprintf( "Could not open outfile : %s\r\n", argv[arg] );
		return(3);
		}
	arg++;
	initcrc16();
	crc16=0;

	crcput( 0x01 , out , &crc16 );                  /* SOH */
	crcputs( argv[arg] , out , &crc16 );            /* Header */
	arg++;
	crcput( 0x02 , out , &crc16 );                  /* STX */
	crcputs( argv[arg] , out , &crc16 );            /* Block */
	while ( (c=getc(in)) != EOF  ) {
		if ( !isprint( c ) ) {
			if (c < 0x20 ) {
				crcput( 0x1a   , out , &crc16 );        /* SUB */
				crcput( c+0x40 , out , &crc16 );
				}
			else {
				cprintf("Unknown char : %X\r\n",c);
				}
			}
		else {
			crcput( c , out , &crc16 );
			}
		}
	crcput( 0x17 , out , &crc16 );			/* ETB */
	crcput( 0x03 , out , &crc16 );                  /* ETX */
	if (transflag) {
		fprintf( out , "%02X%02X" , crc16 & 0xff , crc16 >> 8 );
		}
	else {
		fwrite( &crc16 , sizeof( crc16 ) , 1 , out );
		}
	fclose( out );
	fclose ( in );
	return(0);
	}