#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#define POINT_NUM1 inputNum1+outputNum1+wireNum1
#define POINT_NUM2 inputNum2+outputNum2+wireNum2
int inputNum1,outputNum1,wireNum1;
int inputNum2,outputNum2,wireNum2;
FILE *out;
typedef struct tPoint{
char type;
char *name;
int value;
int level;
struct tPoint *incone;
struct tPoint *gateInput;
struct tPoint *gateOutput;
}Point;
Point *pointG1,*pointG2;
typedef struct tHashTable{
char valid;
char *data;
struct tHashTable *next;
}HashTable;
int HashTable_CollisoinMax;
HashTable *h1,*h2;
int strGetHashKey(char *str , int gSeq);
void initialize();
void readCircuit(char **);
void buildGraph();
void resourceRelease();
int main(int argc , char **argv){
initialize();
out
= fopen (argv
[3],"w");
readCircuit(argv);
printf("i,o,w=%d,%d,%d\n",inputNum1
,outputNum1
,wireNum1
); printf("i,o,w=%d,%d,%d\n",inputNum2
,outputNum2
,wireNum2
); buildGraph();
resourceRelease();
// fclose(out);
}
void initialize(){
inputNum1=0; outputNum1=0; wireNum1=0;
inputNum2=0; outputNum2=0; wireNum2=0;
HashTable_CollisoinMax=0;
}
void readCircuit(char **argv){
char str
[10000],key
[10],strcat[5000000],*token
; int w_now,in_now,gate_o,edgeType;
int i,j,k;
FILE *in1,*in2;
in1
= fopen (argv
[1],"r"); in2
= fopen (argv
[2],"r"); out
= fopen (argv
[3],"w"); if(in1==NULL || in2==NULL)
{
}
else{
/*------------------1pass of input1----------------------------------*/
i=0; j=0; k=0;
//fprintf(out,"nowline:%s , length=%d\n",str,strlen(str));
while(str[i]==' ' || str[i]=='\t' || str[i]=='\n') i++; //Note 過濾tab用\t
while((str[i]!=' ') && (str[i]!='\n') ){
key[k]=str[i];
i++; k++;
}
key[k]='\0';
//fprintf(out,"+--key=%s\n",key);
do{
// fprintf(out," filter:%s %d %d\n",str,str[strlen(str)-1],'\n');
fgets(str
,10000,in1
); //換行字元不會中斷此函式 }while(str
[strlen(str
)-2]!=';'); }
}
else if(key
[0]=='/' && key
[1]=='/') { fprintf(out
,"comment\n"); ;continue;} else if(key
[0]=='\0') { fprintf(out
,"blank line\n");continue;} else if(strcmp(key
,"endmodule")==0) break; else{
do{
//fprintf(out,"muti? %c\n",str[strlen(str)-2]);
while(str[i]==' ') i++;
while(str[i]!='\n'){
i++; j++;
}
//fprintf(out," filter:%s",str);
fgets(str
,10000,in1
); //換行字元不會中斷此函式 i=0;
}while(str
[strlen(str
)-2]!=';'); while(str[i]==' ') i++;
while(str[i]!='\n'){
i++; j++;
}
}
else{ // single line
while(str[i]==' ') i++;
while(str[i]!=';'){
i++; j++;
}
}
//fprintf(out,"Multi-Line Merged/single str:\n%s\n",strcat);
while(token!=NULL){
inputNum1++;
}
}
else if(strcmp(key
,"output")==0){ while(token!=NULL){
outputNum1++;
}
}
else if(strcmp(key
,"wire")==0){ while(token!=NULL){
//fprintf(out,"token=%s\n",token);
wireNum1++;
}
}
else{
// printf("this key word \"%s\" is invalid\n",key);
}
}
}//end read line
fprintf(out
,"-------First pass of in1 Done--------------\n"); /*------------------1pass of input2----------------------------------*/
i=0; j=0; k=0;
//fprintf(out,"nowline:%s , length=%d\n",str,strlen(str));
while(str[i]==' ' || str[i]=='\t' || str[i]=='\n') i++; //Note 過濾tab用\t
while((str[i]!=' ') && (str[i]!='\n') ){
key[k]=str[i];
i++; k++;
}
key[k]='\0';
//fprintf(out,"+--key=%s\n",key);
do{
// fprintf(out," filter:%s %d %d\n",str,str[strlen(str)-1],'\n');
fgets(str
,10000,in2
); //換行字元不會中斷此函式 }while(str
[strlen(str
)-2]!=';'); }
}
else if(key
[0]=='/' && key
[1]=='/') { fprintf(out
,"comment\n"); ;continue;} else if(key
[0]=='\0') { fprintf(out
,"blank line\n");continue;} else if(strcmp(key
,"endmodule")==0) break; else{
do{
//fprintf(out,"muti? %c\n",str[strlen(str)-2]);
while(str[i]==' ') i++;
while(str[i]!='\n'){
i++; j++;
}
//fprintf(out," filter:%s",str);
fgets(str
,10000,in2
); //換行字元不會中斷此函式 i=0;
}while(str
[strlen(str
)-2]!=';'); while(str[i]==' ') i++;
while(str[i]!='\n'){
i++; j++;
}
}
else{ // single line
while(str[i]==' ') i++;
while(str[i]!=';'){
i++; j++;
}
}
//fprintf(out,"Multi-Line Merged/single str:\n%s\n",strcat);
while(token!=NULL){
inputNum2++;
}
}
else if(strcmp(key
,"output")==0){ while(token!=NULL){
outputNum2++;
}
}
else if(strcmp(key
,"wire")==0){ while(token!=NULL){
//fprintf(out,"token=%s\n",token);
wireNum2++;
}
}
else{
// printf("this key word \"%s\" is invalid\n",key);
}
}
}//end read line
fprintf(out
,"-------First pass of in2 Done--------------\n");
}//valid FILE ptr
}
void buildGraph(){
int i;
pointG1
= (Point
*)malloc((POINT_NUM1
+2)*sizeof(Point
)); for(i=0;i<POINT_NUM1+2;i++){
(pointG1+i)->type ='e';
(pointG1+i)->value=0;
(pointG1+i)->level=-1;
(pointG1+i)->incone=NULL;
(pointG1+i)->gateInput=NULL;
(pointG1+i)->gateOutput=NULL;
}
printf("part1,pNUm1=%d\n",POINT_NUM1
); h1
= (HashTable
*)malloc(POINT_NUM1
*sizeof(HashTable
)); for(i=0;i<POINT_NUM1;i++){
printf("part3,i=%d,%d\n",i
,POINT_NUM1
); (h1+i)->valid ='i';
(h1+i)->data=NULL;
(h1+i)->next=NULL;
}
}
void resourceRelease(){
}
int strGetHashKey(char *str , int gSeq){
int i,x=0;
for(i
=0;i
<strlen(str
);i
++) x
=x
+str
[i
]; x = (gSeq==1)? x%POINT_NUM1 : POINT_NUM2;
return x;
}
I2luY2x1ZGU8c3RkaW8uaD4KI2luY2x1ZGU8c3RkbGliLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPG1hdGguaD4KI2luY2x1ZGUgPHRpbWUuaD4KI2RlZmluZSBQT0lOVF9OVU0xIGlucHV0TnVtMStvdXRwdXROdW0xK3dpcmVOdW0xCiNkZWZpbmUgUE9JTlRfTlVNMiBpbnB1dE51bTIrb3V0cHV0TnVtMit3aXJlTnVtMgoKCmludCBpbnB1dE51bTEsb3V0cHV0TnVtMSx3aXJlTnVtMTsKaW50IGlucHV0TnVtMixvdXRwdXROdW0yLHdpcmVOdW0yOwpGSUxFICpvdXQ7Cgp0eXBlZGVmIHN0cnVjdCB0UG9pbnR7CgljaGFyIHR5cGU7CgljaGFyICpuYW1lOwoJaW50IHZhbHVlOwoJaW50IGxldmVsOwoJc3RydWN0IHRQb2ludCAqaW5jb25lOwoJc3RydWN0IHRQb2ludCAqZ2F0ZUlucHV0OwoJc3RydWN0IHRQb2ludCAqZ2F0ZU91dHB1dDsKfVBvaW50OwpQb2ludCAqcG9pbnRHMSwqcG9pbnRHMjsKCnR5cGVkZWYgc3RydWN0IHRIYXNoVGFibGV7CgljaGFyIHZhbGlkOwoJY2hhciAqZGF0YTsKCXN0cnVjdCB0SGFzaFRhYmxlICpuZXh0Owp9SGFzaFRhYmxlOwppbnQgSGFzaFRhYmxlX0NvbGxpc29pbk1heDsKSGFzaFRhYmxlICpoMSwqaDI7CgppbnQgc3RyR2V0SGFzaEtleShjaGFyICpzdHIgLCBpbnQgZ1NlcSk7CgoKdm9pZCBpbml0aWFsaXplKCk7CnZvaWQgcmVhZENpcmN1aXQoY2hhciAqKik7CnZvaWQgYnVpbGRHcmFwaCgpOwp2b2lkIHJlc291cmNlUmVsZWFzZSgpOwoKaW50IG1haW4oaW50IGFyZ2MgLCBjaGFyICoqYXJndil7Cglpbml0aWFsaXplKCk7CglvdXQgPSBmb3BlbiAoYXJndlszXSwidyIpOwoJIAoJcmVhZENpcmN1aXQoYXJndik7CgkKCXByaW50ZigiaSxvLHc9JWQsJWQsJWRcbiIsaW5wdXROdW0xLG91dHB1dE51bTEsd2lyZU51bTEpOwoJcHJpbnRmKCJpLG8sdz0lZCwlZCwlZFxuIixpbnB1dE51bTIsb3V0cHV0TnVtMix3aXJlTnVtMik7CglidWlsZEdyYXBoKCk7CglyZXNvdXJjZVJlbGVhc2UoKTsJCgkKLy8JZmNsb3NlKG91dCk7Cn0Kdm9pZCBpbml0aWFsaXplKCl7CQoJaW5wdXROdW0xPTA7ICBvdXRwdXROdW0xPTA7ICB3aXJlTnVtMT0wOyAKCWlucHV0TnVtMj0wOyAgb3V0cHV0TnVtMj0wOyAgd2lyZU51bTI9MDsgCQoJSGFzaFRhYmxlX0NvbGxpc29pbk1heD0wOwp9CnZvaWQgcmVhZENpcmN1aXQoY2hhciAqKmFyZ3YpewoJCgkKICAgIGNoYXIgc3RyWzEwMDAwXSxrZXlbMTBdLHN0cmNhdFs1MDAwMDAwXSwqdG9rZW47CiAgICBpbnQgd19ub3csaW5fbm93LGdhdGVfbyxlZGdlVHlwZTsKICAgIGludCBpLGosazsKICAgIEZJTEUgKmluMSwqaW4yOwogICAgCiAgICBpbjEgPSBmb3BlbiAoYXJndlsxXSwiciIpOwogICAgaW4yID0gZm9wZW4gKGFyZ3ZbMl0sInIiKTsgCiAgICBvdXQgPSBmb3BlbiAoYXJndlszXSwidyIpOwogICAgaWYoaW4xPT1OVUxMIHx8IGluMj09TlVMTCkKICAgIHsKICAgICAgICBwZXJyb3IoIkVycm9yIG9wZW5pbmcgZmlsZSIpOwogICAgfQogICAgZWxzZXsKICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tMXBhc3Mgb2YgaW5wdXQxLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCiAgICAgICAgd2hpbGUoIWZlb2YoaW4xKSl7CgogICAgICAgICAgIGZnZXRzKHN0ciwxMDAwMCxpbjEpOwogICAgICAgICAgIGk9MDsgaj0wOyBrPTA7ICAgICAgICAgICAKLy9mcHJpbnRmKG91dCwibm93bGluZTolcyAsIGxlbmd0aD0lZFxuIixzdHIsc3RybGVuKHN0cikpOyAgICAgICAgICAgICAgIAogICAgICAgICAgIHdoaWxlKHN0cltpXT09JyAnIHx8IHN0cltpXT09J1x0JyB8fCBzdHJbaV09PSdcbicpIGkrKzsgIC8vTm90ZSDpgY7mv750YWLnlKhcdCAKICAgICAgICAgICB3aGlsZSgoc3RyW2ldIT0nICcpICYmIChzdHJbaV0hPSdcbicpICl7CiAgICAgICAgICAgICAgICBrZXlba109c3RyW2ldOwogICAgICAgICAgICAgICAgaSsrOyBrKys7ICAKICAgICAgICAgICB9IAogICAgICAgICAgIGtleVtrXT0nXDAnOwovL2ZwcmludGYob3V0LCIrLS1rZXk9JXNcbiIsa2V5KTsgICAgICAgICAKICAgICAgICAgICBpZihzdHJjbXAoa2V5LCJtb2R1bGUiKT09MCl7CiAgICAgICAgICAgICAgICBpZihzdHJbc3RybGVuKHN0ciktMl0hPSc7Jyl7CiAgICAgICAgICAgICAgICAgICAgZG97Ci8vICAgICAgICAgICAgICAgICAgICAgICAgZnByaW50ZihvdXQsIiAgICAgZmlsdGVyOiVzICVkICVkXG4iLHN0cixzdHJbc3RybGVuKHN0ciktMV0sJ1xuJyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZnZXRzKHN0ciwxMDAwMCxpbjEpOyAgICAgICAgICAgIC8v5o+b6KGM5a2X5YWD5LiN5pyD5Lit5pa35q2k5Ye95byPIAogICAgICAgICAgICAgICAgICAgIH13aGlsZShzdHJbc3RybGVuKHN0ciktMl0hPSc7Jyk7ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgfQoJCSAgIGVsc2UgaWYoa2V5WzBdPT0nLycgJiYga2V5WzFdPT0nLycpIHsgIGZwcmludGYob3V0LCJjb21tZW50XG4iKTsgO2NvbnRpbnVlO30KCQkgICBlbHNlIGlmKGtleVswXT09J1wwJykgeyAgIGZwcmludGYob3V0LCJibGFuayBsaW5lXG4iKTtjb250aW51ZTt9CiAgICAgICAgICAgZWxzZSBpZihzdHJjbXAoa2V5LCJlbmRtb2R1bGUiKT09MCkgYnJlYWs7CiAgICAgICAgICAgZWxzZXsgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGlmKHN0cltzdHJsZW4oc3RyKS0yXSE9JzsnKXsKCQkJCQogICAgICAgICAgICAgICAgICAgIGRvewovL2ZwcmludGYob3V0LCJtdXRpPyAlY1xuIixzdHJbc3RybGVuKHN0ciktMl0pOyAKICAgICAgICAgICAgICAgICAgICAgd2hpbGUoc3RyW2ldPT0nICcpIGkrKzsKICAgICAgICAgICAgICAgICAgICAgd2hpbGUoc3RyW2ldIT0nXG4nKXsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJjYXRbal09c3RyW2ldOyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGkrKzsgaisrOyAKICAgICAgICAgICAgICAgICAgICAgfSAKLy9mcHJpbnRmKG91dCwiICAgICBmaWx0ZXI6JXMiLHN0cik7CiAgICAgICAgICAgICAgICAgICAgICAgIGZnZXRzKHN0ciwxMDAwMCxpbjEpOyAgICAgICAgICAgIC8v5o+b6KGM5a2X5YWD5LiN5pyD5Lit5pa35q2k5Ye95byPIAogICAgICAgICAgICAgICAgICAgICAgICBpPTA7IAogICAgICAgICAgICAgICAgICAgIH13aGlsZShzdHJbc3RybGVuKHN0ciktMl0hPSc7Jyk7IAogICAgICAgICAgICAgICAgICAgICB3aGlsZShzdHJbaV09PScgJykgaSsrOwogICAgICAgICAgICAgICAgICAgICB3aGlsZShzdHJbaV0hPSdcbicpeyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmNhdFtqXT1zdHJbaV07IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaSsrOyBqKys7IAogICAgICAgICAgICAgICAgICAgICB9ICAKICAgICAgICAgICAgICAgICAgICAgc3RyY2F0W2pdPSdcMCc7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNleyAvLyBzaW5nbGUgbGluZSAKICAgICAgICAgICAgICAgICAgICB3aGlsZShzdHJbaV09PScgJykgaSsrOwogICAgICAgICAgICAgICAgICAgIHdoaWxlKHN0cltpXSE9JzsnKXsKICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmNhdFtqXT0gc3RyW2ldOwogICAgICAgICAgICAgICAgICAgICAgICAgaSsrOyBqKys7IAogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdHJjYXRbal09J1wwJzsgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgfSAgICAgICAgICAgICAgICAgICAgCi8vZnByaW50ZihvdXQsIk11bHRpLUxpbmUgTWVyZ2VkL3NpbmdsZSBzdHI6XG4lc1xuIixzdHJjYXQpOwogICAgICAgICAgICAKICAgICAgICAgICAgICAgaWYoc3RyY21wKGtleSwiaW5wdXQiKT09MCl7CiAgICAgICAgICAgICAgICAgICAgdG9rZW4gPSBzdHJ0b2soc3RyY2F0LCIgLFx0OyIpOwogICAgICAgICAgICAgICAgICAgIHdoaWxlKHRva2VuIT1OVUxMKXsKICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW4gPSBzdHJ0b2soTlVMTCwiICxcdDsiKTsKICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXROdW0xKys7CiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICBlbHNlIGlmKHN0cmNtcChrZXksIm91dHB1dCIpPT0wKXsKICAgICAgICAgICAgICAgICAgICB0b2tlbiA9IHN0cnRvayhzdHJjYXQsIiAsXHQ7Iik7CiAgICAgICAgICAgICAgICAgICAgd2hpbGUodG9rZW4hPU5VTEwpewogICAgICAgICAgICAgICAgICAgICAgICB0b2tlbiA9IHN0cnRvayhOVUxMLCIgLFx0OyIpOwogICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXROdW0xKys7CiAgICAgICAgICAgICAgICAgICAgfSAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgZWxzZSBpZihzdHJjbXAoa2V5LCJ3aXJlIik9PTApewogICAgICAgICAgICAgICAgICAgIHRva2VuID0gc3RydG9rKHN0cmNhdCwiICxcdDsiKTsKICAgICAgICAgICAgICAgICAgICB3aGlsZSh0b2tlbiE9TlVMTCl7Ci8vZnByaW50ZihvdXQsInRva2VuPSVzXG4iLHRva2VuKTsKICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW4gPSBzdHJ0b2soTlVMTCwiICxcdDsiKTsKICAgICAgICAgICAgICAgICAgICAgICAgd2lyZU51bTErKzsKICAgICAgICAgICAgICAgICAgICB9ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICBlbHNlewoJCQkJICAgCi8vCQkJCSAgcHJpbnRmKCJ0aGlzIGtleSB3b3JkIFwiJXNcIiBpcyBpbnZhbGlkXG4iLGtleSk7CgkJCSAgIH0gICAgICAKICAgICAgICAgICB9ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgCiAgICAgICAgfS8vZW5kIHJlYWQgbGluZSAKZnByaW50ZihvdXQsIi0tLS0tLS1GaXJzdCBwYXNzIG9mIGluMSBEb25lLS0tLS0tLS0tLS0tLS1cbiIpOwkJCiAvKi0tLS0tLS0tLS0tLS0tLS0tLTFwYXNzIG9mIGlucHV0Mi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwogICAgICAgIHdoaWxlKCFmZW9mKGluMikpewoKICAgICAgICAgICBmZ2V0cyhzdHIsMTAwMDAsaW4yKTsKICAgICAgICAgICBpPTA7IGo9MDsgaz0wOyAgICAgICAgICAgCi8vZnByaW50ZihvdXQsIm5vd2xpbmU6JXMgLCBsZW5ndGg9JWRcbiIsc3RyLHN0cmxlbihzdHIpKTsgICAgICAgICAgICAgICAKICAgICAgICAgICB3aGlsZShzdHJbaV09PScgJyB8fCBzdHJbaV09PSdcdCcgfHwgc3RyW2ldPT0nXG4nKSBpKys7ICAvL05vdGUg6YGO5r++dGFi55SoXHQgCiAgICAgICAgICAgd2hpbGUoKHN0cltpXSE9JyAnKSAmJiAoc3RyW2ldIT0nXG4nKSApewogICAgICAgICAgICAgICAga2V5W2tdPXN0cltpXTsKICAgICAgICAgICAgICAgIGkrKzsgaysrOyAgCiAgICAgICAgICAgfSAKICAgICAgICAgICBrZXlba109J1wwJzsKLy9mcHJpbnRmKG91dCwiKy0ta2V5PSVzXG4iLGtleSk7ICAgICAgICAgCiAgICAgICAgICAgaWYoc3RyY21wKGtleSwibW9kdWxlIik9PTApewogICAgICAgICAgICAgICAgaWYoc3RyW3N0cmxlbihzdHIpLTJdIT0nOycpewogICAgICAgICAgICAgICAgICAgIGRvewovLyAgICAgICAgICAgICAgICAgICAgICAgIGZwcmludGYob3V0LCIgICAgIGZpbHRlcjolcyAlZCAlZFxuIixzdHIsc3RyW3N0cmxlbihzdHIpLTFdLCdcbicpOwogICAgICAgICAgICAgICAgICAgICAgICBmZ2V0cyhzdHIsMTAwMDAsaW4yKTsgICAgICAgICAgICAvL+aPm+ihjOWtl+WFg+S4jeacg+S4reaWt+atpOWHveW8jyAKICAgICAgICAgICAgICAgICAgICB9d2hpbGUoc3RyW3N0cmxlbihzdHIpLTJdIT0nOycpOyAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgfQogICAgICAgICAgIH0KCQkgICBlbHNlIGlmKGtleVswXT09Jy8nICYmIGtleVsxXT09Jy8nKSB7ICBmcHJpbnRmKG91dCwiY29tbWVudFxuIik7IDtjb250aW51ZTt9CgkJICAgZWxzZSBpZihrZXlbMF09PSdcMCcpIHsgICBmcHJpbnRmKG91dCwiYmxhbmsgbGluZVxuIik7Y29udGludWU7fQogICAgICAgICAgIGVsc2UgaWYoc3RyY21wKGtleSwiZW5kbW9kdWxlIik9PTApIGJyZWFrOwogICAgICAgICAgIGVsc2V7ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBpZihzdHJbc3RybGVuKHN0ciktMl0hPSc7Jyl7CgkJCQkKICAgICAgICAgICAgICAgICAgICBkb3sKLy9mcHJpbnRmKG91dCwibXV0aT8gJWNcbiIsc3RyW3N0cmxlbihzdHIpLTJdKTsgCiAgICAgICAgICAgICAgICAgICAgIHdoaWxlKHN0cltpXT09JyAnKSBpKys7CiAgICAgICAgICAgICAgICAgICAgIHdoaWxlKHN0cltpXSE9J1xuJyl7IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyY2F0W2pdPXN0cltpXTsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpKys7IGorKzsgCiAgICAgICAgICAgICAgICAgICAgIH0gCi8vZnByaW50ZihvdXQsIiAgICAgZmlsdGVyOiVzIixzdHIpOwogICAgICAgICAgICAgICAgICAgICAgICBmZ2V0cyhzdHIsMTAwMDAsaW4yKTsgICAgICAgICAgICAvL+aPm+ihjOWtl+WFg+S4jeacg+S4reaWt+atpOWHveW8jyAKICAgICAgICAgICAgICAgICAgICAgICAgaT0wOyAKICAgICAgICAgICAgICAgICAgICB9d2hpbGUoc3RyW3N0cmxlbihzdHIpLTJdIT0nOycpOyAKICAgICAgICAgICAgICAgICAgICAgd2hpbGUoc3RyW2ldPT0nICcpIGkrKzsKICAgICAgICAgICAgICAgICAgICAgd2hpbGUoc3RyW2ldIT0nXG4nKXsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJjYXRbal09c3RyW2ldOyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGkrKzsgaisrOyAKICAgICAgICAgICAgICAgICAgICAgfSAgCiAgICAgICAgICAgICAgICAgICAgIHN0cmNhdFtqXT0nXDAnOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZXsgLy8gc2luZ2xlIGxpbmUgCiAgICAgICAgICAgICAgICAgICAgd2hpbGUoc3RyW2ldPT0nICcpIGkrKzsKICAgICAgICAgICAgICAgICAgICB3aGlsZShzdHJbaV0hPSc7Jyl7CiAgICAgICAgICAgICAgICAgICAgICAgICBzdHJjYXRbal09IHN0cltpXTsKICAgICAgICAgICAgICAgICAgICAgICAgIGkrKzsgaisrOyAKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RyY2F0W2pdPSdcMCc7ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgICAgIAovL2ZwcmludGYob3V0LCJNdWx0aS1MaW5lIE1lcmdlZC9zaW5nbGUgc3RyOlxuJXNcbiIsc3RyY2F0KTsKICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGlmKHN0cmNtcChrZXksImlucHV0Iik9PTApewogICAgICAgICAgICAgICAgICAgIHRva2VuID0gc3RydG9rKHN0cmNhdCwiICxcdDsiKTsKICAgICAgICAgICAgICAgICAgICB3aGlsZSh0b2tlbiE9TlVMTCl7CiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuID0gc3RydG9rKE5VTEwsIiAsXHQ7Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0TnVtMisrOwogICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgZWxzZSBpZihzdHJjbXAoa2V5LCJvdXRwdXQiKT09MCl7CiAgICAgICAgICAgICAgICAgICAgdG9rZW4gPSBzdHJ0b2soc3RyY2F0LCIgLFx0OyIpOwogICAgICAgICAgICAgICAgICAgIHdoaWxlKHRva2VuIT1OVUxMKXsKICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW4gPSBzdHJ0b2soTlVMTCwiICxcdDsiKTsKICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0TnVtMisrOwogICAgICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgIGVsc2UgaWYoc3RyY21wKGtleSwid2lyZSIpPT0wKXsKICAgICAgICAgICAgICAgICAgICB0b2tlbiA9IHN0cnRvayhzdHJjYXQsIiAsXHQ7Iik7CiAgICAgICAgICAgICAgICAgICAgd2hpbGUodG9rZW4hPU5VTEwpewovL2ZwcmludGYob3V0LCJ0b2tlbj0lc1xuIix0b2tlbik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuID0gc3RydG9rKE5VTEwsIiAsXHQ7Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIHdpcmVOdW0yKys7CiAgICAgICAgICAgICAgICAgICAgfSAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgZWxzZXsKCQkJCSAgIAovLwkJCQkgIHByaW50ZigidGhpcyBrZXkgd29yZCBcIiVzXCIgaXMgaW52YWxpZFxuIixrZXkpOwoJCQkgICB9ICAgICAgCiAgICAgICAgICAgfSAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgIAogICAgICAgIH0vL2VuZCByZWFkIGxpbmUgCmZwcmludGYob3V0LCItLS0tLS0tRmlyc3QgcGFzcyBvZiBpbjIgRG9uZS0tLS0tLS0tLS0tLS0tXG4iKTsJCQoJCgl9Ly92YWxpZCBGSUxFIHB0cgoJZmNsb3NlKGluMSk7CglmY2xvc2UoaW4yKTsKCWZjbG9zZShvdXQpOwp9Cgp2b2lkIGJ1aWxkR3JhcGgoKXsKCWludCBpOwoJcG9pbnRHMSA9IChQb2ludCAqKW1hbGxvYygoUE9JTlRfTlVNMSsyKSpzaXplb2YoUG9pbnQpKTsKCWZvcihpPTA7aTxQT0lOVF9OVU0xKzI7aSsrKXsKCQkocG9pbnRHMStpKS0+dHlwZSA9J2UnOwoJCShwb2ludEcxK2kpLT52YWx1ZT0wOwoJCShwb2ludEcxK2kpLT5sZXZlbD0tMTsKCQkocG9pbnRHMStpKS0+aW5jb25lPU5VTEw7CgkJKHBvaW50RzEraSktPmdhdGVJbnB1dD1OVUxMOwoJCShwb2ludEcxK2kpLT5nYXRlT3V0cHV0PU5VTEw7CQkKCX0KCXByaW50ZigicGFydDEscE5VbTE9JWRcbiIsUE9JTlRfTlVNMSk7CgloMSA9IChIYXNoVGFibGUgKiltYWxsb2MoUE9JTlRfTlVNMSpzaXplb2YoSGFzaFRhYmxlKSk7CglwcmludGYoInBhcnQyXG4iKTsKCWZvcihpPTA7aTxQT0lOVF9OVU0xO2krKyl7CgkJcHJpbnRmKCJwYXJ0MyxpPSVkLCVkXG4iLGksUE9JTlRfTlVNMSk7CgkJKGgxK2kpLT52YWxpZCA9J2knOwoJCShoMStpKS0+ZGF0YT1OVUxMOwoJCShoMStpKS0+bmV4dD1OVUxMOwoJfQoJcHJpbnRmKCJwYXJ0NFxuIik7Cn0Kdm9pZCByZXNvdXJjZVJlbGVhc2UoKXsKCQoJZnJlZShwb2ludEcxKTsgZnJlZShwb2ludEcyKTsKCWZyZWUoaDEpOyBmcmVlKGgyKTsKfQoKaW50IHN0ckdldEhhc2hLZXkoY2hhciAqc3RyICwgaW50IGdTZXEpewoJaW50IGkseD0wOwoJZm9yKGk9MDtpPHN0cmxlbihzdHIpO2krKykgeD14K3N0cltpXTsKCXggPSAoZ1NlcT09MSk/IHglUE9JTlRfTlVNMSA6IFBPSU5UX05VTTI7CglyZXR1cm4geDsKfQ==