/* pdats.c jha 5/93 ** release 1.0 eej 6/93 ** release 1.1 eej 5/94 ** ** Produces PDATS format compressed traces from ** any of the following: DAS, dinero, Schieber, ** GreenStamp, and straight binary with or without ** time stamps. Employs repeat records. ** ** Copyright 1994 Eric E. Johnson, Jiheng Ha ** ** Permission to use, copy, modify, and distribute this ** software and its documentation for any purpose and without ** fee is hereby granted, provided that the above copyright ** notice appears in all copies. The authors make no ** representations about the suitability of this software ** for any purpose. It is provided "as is" without expressed ** or implied warranty. */ #include #include #include #include "das_pack.h" #define true 1 #define false 0 #define LIM 10 /* increased from 8 to allow for 0x... notation */ #define SEEK_SET 0 unsigned long StoredAddr[8],CurrentTS; unsigned long OffsetOflo = 0; char token[LIM],token2[LIM],token3[LIM]; int numchar, numchar2, numchar3; int das,UncompBin,HasTS,fbyte,sbyte; char Schieber; /******************************************************************/ knowsize(offset) long offset; { if((offset >= -128) && ( offset <= 127)) return 1; if((offset >= -32768) && ( offset <= 32767)) return 2; if((offset >= -8388608) && ( offset <= 8388607)) return 3; if((offset >= -2147483648) && (offset <= 2147483647)) return 4; OffsetOflo++; return 4; } /******************************************************************/ unsigned long t1[LIM/2],t2[LIM/2],t[LIM]; unsigned long char2int(token,numchar,hexdec) char token[],hexdec; int numchar; { unsigned long c,k,mask; int i,j; unsigned long ReturnValue; ReturnValue=0; for(i=0;i=0;i--,j--) t[j]=token[i]; for(i=0;i='A' && t[i]<='F') t[i]-=55; else t[i]-=48; } if(hexdec=='x'){ for(i=0,j=0;i> ((LIM/2-1-j)*8)); } } else exit(-1); } return ReturnValue; } /******************************************************************/ /* */ /* This program compresses Das, Schieber, GreenStamp, Dinero */ /* and Binary format traces using Repeated scheme. */ /* */ /******************************************************************/ main(argc,argv) int argc; char *argv[]; { int c,i; if (UncompBin = (fbyte=getchar())==0xff){ switch (sbyte=getchar()) { case 2: HasTS=true; case 0: break; default: fprintf(stderr,"pdats: File already in PDATS format.\n"); exit(0); } } if (das = (fbyte == 0x2e)) { fseek(stdin,0,SEEK_SET); HasTS = true; } c=initial(); /******************************************/ /* N - Uncompressed binary format */ /* S - Schieber format */ /* D - Dinero format */ /* G - Green Stamp format */ /* A - DAS format */ /******************************************/ switch(c){ case 'B': /* uncompressed binary */ if(HasTS) binary_w_TS(); else binary_no_TS(); break; case 'A': /* DAS format */ DAS_format(); break; case 'S': /* Schieber format */ case 'D': /* dinero format */ ASCII_no_TS(); break; case 'G': /* GreenStamp format */ GreenStamp(); break; default: fprintf(stderr, "pdats: Unknown file format\n"); exit(-1); } if (OffsetOflo) fprintf(stderr, "pdats: offset overflowed %ld times\n", OffsetOflo); } /*******************************************************************/ gettoken(token,numchar) char token[LIM]; int *numchar; { int c,i; while((c=getchar())==' ' || c=='\n') ; islower(c) ? (token[0]=toupper(c)) : (token[0]=c); for(i=1;(c=getchar())!=' ' && c!=EOF && c!='\n';i++) islower(c) ? (token[i]=toupper(c)) : (token[i]=c); *numchar=i; return(c); } /**********************************************************************/ initial() /* initialize globals and write PDATS file header */ { int c, i, format; Schieber=false; for(i=0;i<8;i++){ StoredAddr[i]= 0; } CurrentTS=0; putchar(0xff); /* PDATS flag */ if (das) { putchar(format = 3); return ('A'); } else format=1; if(UncompBin){ if(HasTS) format |= 2; putchar(format); return('B'); } /**** must be ASCII format; count fields to determine which ****/ if((c=gettoken(token2,&numchar2))=='\n'){ /**** 2 FIELD ****/ putchar(format); return('D'); /* dinero */ } else{ if((c=gettoken(token3,&numchar3))=='\n'){ /**** 3 FIELD ****/ format |= 2; putchar(format); return('G'); /* GreenStamp */ } else{ gettoken(token,&numchar); if((c=gettoken(token,&numchar))=='\n'){ /**** 5 FIELD ****/ putchar(format); Schieber=true; return('S'); } else{ fprintf(stderr, "Unknown file format\n"); exit(-1); } } } } /********************************************************************/ DAS_format(){ int OffsetSize1,OffsetSize2,NumByteTS1,NumByteTS2,i,j,c,NumRep; int PrevType,NewType; unsigned long TempAddr,PrevAddr,NewAddr,TempTS,PrevTS,NewTS; unsigned long *NextAddrptr,*NextTSptr; char tokenA[LIM]; int numcharA,*typeptr; unsigned long numref, RefCount; numref=get_size(stdin); next_ref(stdin); RefCount=1; NewType= current_ref.type; NewAddr= current_ref.address; NewTS= current_ref.time; for(;;){ PrevType=NewType; PrevAddr=NewAddr; PrevTS=NewTS; TempAddr=PrevAddr; TempTS=PrevTS; NumRep=1; for(;;){ next_ref(stdin); if(++RefCount >= numref){ handleoffT(PrevType,PrevAddr,PrevTS,NumRep); return(0); /* This omits last reference! */ } else{ NewType= current_ref.type; NewAddr= current_ref.address; NewTS= current_ref.time; } if(PrevType==NewType && (PrevAddr-StoredAddr[PrevType])==(NewAddr-TempAddr) && (PrevTS-CurrentTS)==(NewTS-TempTS)){ NumRep++; TempAddr=NewAddr; TempTS=NewTS; continue; } else{ handleoffT(PrevType,PrevAddr,PrevTS,NumRep); break; } } } } /***************************************************************/ binary_w_TS(){ int OffsetSize1,OffsetSize2,NumByteTS1,NumByteTS2,i,j,c,NumRep; int PrevType,NewType; unsigned long TempAddr,PrevAddr,NewAddr,TempTS,PrevTS,NewTS; char tokenA[LIM]; int numcharA; NewType= (c=getchar()) & 0x07; NewAddr=0; NewTS=0; for(i=4;i>0;i--) NewAddr |= (c=getchar())<< 8*(i-1); for(i=4;i>0;i--) NewTS |= (c=getchar())<< 8*(i-1); for(;;){ PrevType=NewType; PrevAddr=NewAddr; PrevTS=NewTS; TempAddr=PrevAddr; TempTS=PrevTS; NumRep=1; for(;;){ if((c=getchar())==EOF){ handleoffT(PrevType,PrevAddr,PrevTS,NumRep); return(0); } else{ NewType= c & 0x07; NewAddr=0; NewTS=0; for(i=4;i>0;i--) NewAddr |= (c=getchar())<< 8*(i-1); for(i=4;i>0;i--) NewTS |= (c=getchar())<< 8*(i-1); } if(PrevType==NewType && (PrevAddr-StoredAddr[PrevType])==(NewAddr-TempAddr) && (PrevTS-CurrentTS)==(NewTS-TempTS)){ NumRep++; TempAddr=NewAddr; TempTS=NewTS; continue; } else{ handleoffT(PrevType,PrevAddr,PrevTS,NumRep); break; } } } } /********************************************************************/ binary_no_TS(){ int OffsetSize1,OffsetSize2,i,j,c,NumRep; int PrevType,NewType; unsigned long TempAddr,PrevAddr,NewAddr; char tokenA[LIM]; int numcharA; NewType= (c=getchar()) & 0x07; NewAddr=0; for(i=4;i>0;i--) NewAddr |= (c=getchar())<< 8*(i-1); for(;;){ PrevType=NewType; PrevAddr=NewAddr; TempAddr=PrevAddr; NumRep=1; for(;;){ if((c=getchar())==EOF){ handleoff(PrevType,PrevAddr,NumRep); return(0); } else{ NewType= c & 0x07; NewAddr=0; for(i=4;i>0;i--) NewAddr |= (c=getchar())<< 8*(i-1); } if(PrevType==NewType && (PrevAddr-StoredAddr[PrevType])==(NewAddr-TempAddr)){ NumRep++; TempAddr=NewAddr; continue; } else{ handleoff(PrevType,PrevAddr,NumRep); break; } } } } /********************************************************************/ GreenStamp(){ int OffsetSize1,OffsetSize2,NumByteTS1,NumByteTS2,i,j,c,NumRep; int PrevType,NewType; unsigned long TempAddr,PrevAddr,NewAddr,TempTS,PrevTS,NewTS; char tokenA[LIM]; int numcharA; NewType=fbyte-48; NewAddr = char2int(token2,numchar2,'x'); NewTS = char2int(token3,numchar3,'d'); for(;;){ PrevType=NewType; PrevAddr=NewAddr; PrevTS=NewTS; TempAddr=PrevAddr; TempTS=PrevTS; NumRep=1; for(;;){ if((c=getset2T(&NewType,&NewAddr,&NewTS,tokenA,&numcharA))==EOF){ handleoffT(PrevType,PrevAddr,PrevTS,NumRep); return(0); } if(PrevType==NewType && (PrevAddr-StoredAddr[PrevType])==(NewAddr-TempAddr) && (PrevTS-CurrentTS)==(NewTS-TempTS)) { NumRep++; TempAddr=NewAddr; TempTS=NewTS; continue; } else{ handleoffT(PrevType,PrevAddr,PrevTS,NumRep); break; } } } } /********************************************************************/ ASCII_no_TS(){ int OffsetSize1,OffsetSize2,i,j,c,NumRep; int PrevType,NewType; unsigned long TempAddr,PrevAddr,NewAddr; char tokenA[LIM]; int numcharA; NewType=fbyte-48; NewAddr = char2int(token2,numchar2,'x'); for(;;){ PrevType=NewType; PrevAddr=NewAddr; TempAddr=PrevAddr; NumRep=1; for(;;){ if((c=getset2(&NewType,&NewAddr,tokenA,&numcharA))==EOF){ handleoff(PrevType,PrevAddr,NumRep); return(0); } if(PrevType==NewType && (PrevAddr-StoredAddr[PrevType])==(NewAddr-TempAddr)) { NumRep++; TempAddr=NewAddr; continue; } else{ handleoff(PrevType,PrevAddr,NumRep); break; } } } } /****************************************************************/ handleoff(PrevType,PrevAddr,TotalReps) int PrevType,TotalReps; unsigned long PrevAddr; { int HeaderByte,OffsetSize,i,j,c, NumRep; long addroff; HeaderByte=PrevType; addroff=PrevAddr-StoredAddr[PrevType]; StoredAddr[PrevType] += TotalReps * addroff; OffsetSize=knowsize(addroff); if(addroff==4) ; /* address code = '00' */ else if((OffsetSize==1) || (OffsetSize==2)) HeaderByte |= ((j=OffsetSize) <<5); else HeaderByte |= ((j=3) <<5); while (NumRep = (TotalReps > 255) ? 255 : TotalReps) { TotalReps -= NumRep; if(NumRep==1) putchar(HeaderByte); else { putchar(HeaderByte | (c=1 <<7)); putchar(NumRep); } if (NumRep > 255) { fprintf(stderr, "Repetitions overflow: %d\n", NumRep); exit (-47); } if(addroff !=4){ if(OffsetSize==1 || OffsetSize==2) for(i=OffsetSize-1;i>=0;i--){ c=(addroff >> 8*i) & 0xFF; putchar(c); } else for(i=3;i>=0;i--){ c=(addroff >> 8*i) & 0xFF; putchar(c); } } } } /****************************************************************/ getset2(typeptr,NextAddrptr,tokenA,numcharA) int *typeptr; unsigned long *NextAddrptr; char tokenA[]; int *numcharA; { int i; if(gettoken(token,&numchar)==EOF) return(EOF); *typeptr=token[0]-48; gettoken(tokenA,&numcharA); *NextAddrptr = char2int(tokenA,numcharA,'x'); if(Schieber) for(i=0;i<=2;i++) gettoken(token,&numchar); } /****************************************************************/ handleoffT(type,NextAddr,NextTS, TotalReps) int type, TotalReps; unsigned long NextAddr,NextTS; { int HeaderByte,OffsetSize,NumByteTS,i,j,c, NumRep; long addroff,tsoff; HeaderByte=type; addroff=NextAddr-StoredAddr[type]; StoredAddr[type] += TotalReps * addroff; tsoff=NextTS-CurrentTS; CurrentTS += TotalReps * tsoff; OffsetSize=knowsize(addroff); NumByteTS=knowsize(tsoff); if(addroff==4) ; /* address code = '00' */ else if((OffsetSize==1) || (OffsetSize==2)) HeaderByte |= ((j=OffsetSize) <<5); else HeaderByte |= ((j=3) <<5); if(tsoff==1) HeaderByte |= ((i=1)<<3); else HeaderByte |= ((i=NumByteTS+1)<<3); while (NumRep = (TotalReps > 255) ? 255 : TotalReps) { TotalReps -= NumRep; if(NumRep==1) putchar(HeaderByte); else{ putchar(HeaderByte | (c=1 << 7)); putchar(NumRep); } if (NumRep > 255) { fprintf(stderr, "Repetitions overflow: %d\n", NumRep); exit (-48); } if(addroff !=4){ if(OffsetSize==1 || OffsetSize==2) for(i=OffsetSize-1;i>=0;i--){ c=(addroff >> 8*i) & 0xFF; putchar(c); } else for(i=3;i>=0;i--){ c=(addroff >> 8*i) & 0xFF; putchar(c); } } if(tsoff >1){ for(i=NumByteTS-1;i>=0;i--){ c=(tsoff >> 8*i) & 0xFF; putchar(c); } } } } /****************************************************************/ getset2T(typeptr,NextAddrptr,NextTSptr,tokenA,numcharA) int *typeptr; unsigned long *NextAddrptr,*NextTSptr; char tokenA[]; int *numcharA; { if(gettoken(token,&numchar)==EOF) return(EOF); *typeptr=token[0]-48; gettoken(tokenA,&numcharA); *NextAddrptr = char2int(tokenA,numcharA,'x'); gettoken(token,&numchar); *NextTSptr = char2int(token,numchar,'d'); }