/*  pdt2din.c           jha    5/93  */
/*             revised  eej    6/93  */
/*                                   */
/*  converts PDATS trace to dinero   */

#include <stdio.h>

unsigned int CurrentAddr[8],NextAddr,CurrentTS,NextTS;
long addroff,tsoff;

main()
{
    int c;

    if((c=getchar())!=0xff){
	fprintf(stderr, "pdt2din: file not in PDATS format\n");
	exit(-1);
    }
    initial();
    switch (c=getchar()) {
      case 3:         /* time stamps, w/repeats  */
      case 2:         /* time stamps, no repeats */
	uncompTR();
	break;
      case 1:         /* no time stamps, w/repeats  */
      case 0:         /* no time stamps, no repeats */
	uncompR();
	break;
      default:
	fprintf(stderr, "pdt2din: unrecognized format\n");
	exit(-2);
    }
}

/**************************************************************/

uncompTR()    /* TYPE, ADDRESS, and TIME STAMPS */
{
    int i,j,c,type,tscode,addrcode,NumRep;

    while((c=getchar())!=EOF){
	type= c & 7;
	tscode = (c & 0x18) >>3;
	addrcode = (c & 0x60) >>5;
	if(c & 0x80)         /*** repeated ***/
	  NumRep = getchar();
	else
	  NumRep=1;

	if(addrcode==0)
	  addroff=4;
	else if(addrcode==1 || addrcode==2) {
	    addroff=0;
	    for(i=addrcode;i>0;i--)
	      addroff |= getchar() << ((i-1) << 3);
	    if(c=negnum(addroff,addrcode))
	      addroff= sign_extend(addroff,addrcode);
	}
	else fread((char *) &addroff, 4, 1, stdin);

	if (tscode < 2) tsoff = tscode;
	else{
	    tsoff = 0;
	    for(i=tscode-1;i>0;i--)
	      tsoff |= getchar() << ((i-1) << 3);
	}
	for(;NumRep>0;NumRep--){
	    NextAddr = (CurrentAddr[type] += addroff);
	    NextTS = (CurrentTS += tsoff);
	    printf("%d %x %d\n",type,NextAddr,NextTS);
	}
    }
}

/**************************************************************/

uncompR()
{
    register int i,c,type,addrcode,NumRep;

    while((c=getchar())!=EOF){ 
	type= c & 7;
	addrcode = (c & 0x60) >>5; 
	if(c & 0x80)         /*** repeated ***/
	  NumRep=getchar();
	else
	  NumRep=1;

	if(addrcode==0)
	  addroff=4;
	else if(addrcode==1 || addrcode==2) {
	    addroff=0; 
	    for(i=addrcode;i>0;i--)
	      addroff |= getchar() << ((i-1) << 3);
	    if(negnum(addroff,addrcode))
	      addroff= sign_extend(addroff,addrcode);
	}
	else fread((char *) &addroff, 4, 1, stdin);

	for(;NumRep>0;NumRep--){
	    NextAddr = (CurrentAddr[type] += addroff);
	    printf("%d %x\n",type,NextAddr);
	}
    }
}
/********************************************************************/
initial()
{
    int i;
    for(i=0;i<=7;i++)
      CurrentAddr[i]=0;
    CurrentTS=0;
}
/*********************************************************************/
negnum(num,size)
unsigned long num;
char size;
{
    if(size==1) return (num & 0x80);
    else if(size==2) return (num & 0x8000);
    else if(size==3) return (num & 0x800000);
    else{
	fprintf(stderr, "size can't be greater than 3 byte\n");
	exit(-1);
    } 
}
/****************************************************************/
#define neg1 0xffffff00
#define neg2 0xffff0000
#define neg3 0xff000000

sign_extend(num,size)
long num;
char size;
{
    if(size==1) return (num | neg1);
    if(size==2) return (num | neg2);
    if(size==3) return (num | neg3);
    else{
	fprintf(stderr, "size can't be greater than 3\n");
	exit(-1);
    }
}
