#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define LENGTH(x) (sizeof(x) / sizeof(x[0]))
int hasPar ( char * ) ; //Überprüft, ob Klammern im String sind und gibt Position der ersten Klammer zurück
char * subStr ( char * , char * , int , int ) ; //Funktion, die Substring zurückgibt
double calcStr( char * ) ; //Wertet Terme ohne Klammern aus
double calc ( char * ) ; //Rekursive Berechnung des Terms
int main( /*int argc, char *argv[]*/ ) {
char * s/*, c*/ ;
double ergebnis;
do {
puts ( "Taschenrechner. Ignoriert alles, au\xe1 " "er 0-9,.,+,-,*,/,^,(,)" ) ;
scanf ( "%99[^\n ]" , s
) ; //[^\n] bedeutet, dass alle Zeichen außer Zeilenumbruch eingelesen werden sollen
printf ( "Erkannter Ausdruck:\n %s\n " , s
) ;
ergebnis= calc( s) ;
printf ( "Berechnetes Ergebnis:\n %f\n " , ergebnis
) ;
//if (getc(stdin) == 'c') {break;}
} while ( 0 ) ;
return 0 ;
}
/*************************************
* Überprüfen, ob Klammern im Term sind
* gibt Position der ersten Klammer
* oder -1 zurück
**************************************/
int hasPar ( char * s) {
for ( unsigned int k
= 0 ; k
< strlen ( s
) ; k
++ ) { //k verwendet, da mit i Interferenzen mit calc() aufgetreten sind if ( s[ k] == '(' ) {
return k;
}
}
return ( - 1 ) ;
}
/*****************************************************
* Funktion, die Substring zurückgibt
* s: Ursprungsstring
* offset: Position, an der Substring beginnt
* len: Länge des Substrings
* t: Variable, in der Substring gespeichert wird
******************************************************/
char * subStr ( char * dest, char * src, int offset, int len) {
if ( offset+ len > input_len ) { //Wenn Substring größer sein sollte als Usprungsstring oder Substring Null Zeichen enthalten soll
return NULL;
} else if ( len <= 0 ) {
dest[ 0 ] = '\0 ' ;
}
strncpy ( dest
, src
+ offset
, len
) ; //len Zeichen werden aus s ab offset in t kopiert dest[ len] = '\0 ' ;
return dest;
}
/*****************************************************
* Wertet Terme ohne Klammern aus
******************************************************/
double calcStr ( char * s) {
char * t, * t_first;
int len_s
= strlen ( s
) , len_first
= 0 ; t
= calloc ( len_s
, sizeof ( char ) ) ; //Kopie von s zum Arbeiten erstellen, Schritt 1 strcpy ( t
, s
) ; //Kopie von s zum Arbeiten erstellen, Schritt 2
//ACHTUNG: REIHENFOLGE WICHTIG FÜR KORREKTE ANWENDUNG VON RECHENREGELN
if ( t[ 0 ] != '+' ) { //+ als unärer Operator
t_first
= strtok ( t
, "+" ) ; //String auf + prüfen, Nach Ausführung von strtok: t_first: String bis exklusiv + len_first
= strlen ( t_first
) ; //Länge des Ergebnisstrings berechnen zum Vergleich mit Länge des Ursprungsstrings if ( len_first != len_s) { //Wenn Länge gleich, dann ist hier auch der Inhalt gleich, also kein Plus enthalten
switch ( t_first[ len_first- 1 ] ) { //Wenn + unär, also vor dem + ein anderes OpSym
case '+' :
t[ len_first- 1 ] = '\0 ' ;
return calcStr( t) + ( calcStr( s+ len_first) ) ;
case '-' :
t[ len_first- 1 ] = '\0 ' ;
return calcStr( t) - ( calcStr( s+ len_first) ) ;
case '*' :
t[ len_first- 1 ] = '\0 ' ;
return calcStr( t) * ( calcStr( s+ len_first) ) ;
case '/' :
t[ len_first- 1 ] = '\0 ' ;
return calcStr( t) / ( calcStr( s+ len_first) ) ;
case '^' :
t[ len_first- 1 ] = '\0 ' ;
return pow ( calcStr
( t
) , ( calcStr
( s
+ len_first
) ) ) ; default :
return calcStr( t_first) + ( calcStr( s+ len_first+ 1 ) ) ; //Rekursives Aufrufen der Strings links und rechts des Operationszeichens
}
}
}
strcpy ( t
, s
) ; //da t bei Überprüfung auf + verändert wurde, Wiederherstellung der Arbeitskopie aus Ursprungsstring if ( t[ 0 ] != '-' ) { //- als unärer Operator
t_first
= strtok ( t
, "-" ) ; //analog oben if ( len_first != len_s) {
switch ( t_first[ len_first- 1 ] ) {
case '+' :
t[ len_first- 1 ] = '\0 ' ;
return calcStr( t) + ( calcStr( s+ len_first) ) ;
case '-' :
t[ len_first- 1 ] = '\0 ' ;
return calcStr( t) - ( calcStr( s+ len_first) ) ;
case '*' :
t[ len_first- 1 ] = '\0 ' ;
return calcStr( t) * ( calcStr( s+ len_first) ) ;
case '/' :
t[ len_first- 1 ] = '\0 ' ;
return calcStr( t) / ( calcStr( s+ len_first) ) ;
case '^' :
t[ len_first- 1 ] = '\0 ' ;
return pow ( calcStr
( t
) , ( calcStr
( s
+ len_first
) ) ) ; default :
return calcStr( t_first) + ( calcStr( s+ len_first+ 1 ) ) ; //Rekursives Aufrufen der Strings links und rechts des Operationszeichens
}
}
}
if ( len_first != len_s) {
return calcStr( t_first) * ( calcStr( s+ len_first+ 1 ) ) ;
}
if ( len_first != len_s) {
return calcStr( t_first) * ( 1 / calcStr( s+ len_first+ 1 ) ) ;
}
if ( len_first != len_s) {
if ( t_first[ len_first- 1 ] == 'e' ) {
if ( t_first[ 0 ] == '-' ) {
return ( - 1 ) * exp ( calcStr
( s
+ len_first
+ 1 ) ) ; } else if ( t_first[ 0 ] == '+' ) {
return exp ( calcStr
( s
+ len_first
+ 1 ) ) ; } else {
return pow ( calcStr
( t_first
) , ( calcStr
( s
+ len_first
+ 1 ) ) ) ; }
}
}
return atof ( s
) ; //String ist bei keinem Operationszeichen zerfallen => String ist Zahl ; atof castet string zu double (aus stdlib.h)
}
/****************************************************
* Funktion zur Verschachtelten Berechnung des Terms
****************************************************/
double calc ( char * s) {
double result_d= 0 .;
char * t, * result_str;
int check= 1 , i= hasPar( s) , j= 0 ;
if ( i == ( - 1 ) ) {
return calcStr( s) ;
} else {
j= ++ i; //j=++i ist Position des Chars nach der ersten öffnenden Klammer
while ( check > 0 ) {
if ( s[ i] == '(' ) {
check++;
} else if ( s[ i] == ')' ) {
check--;
}
i++;
} //Bestimmen der Länge der "obersten" Klammer, i ist Position des ersten Zeichens nach der Klammer
t
= calloc ( strlen ( s
) , sizeof ( char ) ) ; //Hilfsstring, Länge: s[0 bis j-1] + Puffer für Nachkommastellen result_str
= calloc ( strlen ( s
) , sizeof ( char ) ) ; //Hilfsstring, Länge s[j bis i-2] + Puffer für Nachkommastellen result_d= calc( subStr( result_str, s, j, i- j- 1 ) ) ; //Trennung auf zwei Zeilen zur besseren Lesbarkeit der verschachtelten Funktionsaufrufe
sprintf ( result_str
, "%-.16f" , result_d
) ; //casten des errechneten Double-Ergebnisses zurück in *char !!!ACHTUNG!!! Präzision nicht auf 16 stellen, da sonst undefiniertes Verhalten erzeugt wird return calcStr
( strcat ( subStr
( t
, s
, 0 , j
- 1 ) , strcat ( result_str
, s
+ i
) ) ) ; //rekursiver Aufruf: calc( s[bis j-2] ## s[j bis i-2] ## s[i bis Ende]) //##: Konkatenation }
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8Y3R5cGUuaD4KI2luY2x1ZGUgPG1hdGguaD4KI2RlZmluZSBMRU5HVEgoeCkgIChzaXplb2YoeCkgLyBzaXplb2YoeFswXSkpCgppbnQgaGFzUGFyIChjaGFyICopOyAvL8OcYmVycHLDvGZ0LCBvYiBLbGFtbWVybiBpbSBTdHJpbmcgc2luZCB1bmQgZ2lidCBQb3NpdGlvbiBkZXIgZXJzdGVuIEtsYW1tZXIgenVyw7xjawpjaGFyKiBzdWJTdHIgKGNoYXIqICwgY2hhciogLCBpbnQgLCBpbnQgKTsgLy9GdW5rdGlvbiwgZGllIFN1YnN0cmluZyB6dXLDvGNrZ2lidApkb3VibGUgY2FsY1N0cihjaGFyICopOyAvL1dlcnRldCBUZXJtZSBvaG5lIEtsYW1tZXJuIGF1cwpkb3VibGUgY2FsYyAoY2hhciAqKTsgLy9SZWt1cnNpdmUgQmVyZWNobnVuZyBkZXMgVGVybXMKCgppbnQgbWFpbigvKmludCBhcmdjLCBjaGFyICphcmd2W10qLykgewoJY2hhciAqcy8qLCBjKi87Cglkb3VibGUgZXJnZWJuaXM7CgoJZG8gewoJCXB1dHMoIlRhc2NoZW5yZWNobmVyLiBJZ25vcmllcnQgYWxsZXMsIGF1XHhlMSIiZXIgMC05LC4sKywtLCosLyxeLCgsKSIpOwoKCQlmZmx1c2goc3RkaW4pOwoJCXM9IGNhbGxvYygxMDAsMSk7CgkJc2NhbmYoIiU5OVteXG5dIiwgcyk7IC8vW15cbl0gYmVkZXV0ZXQsIGRhc3MgYWxsZSBaZWljaGVuIGF1w59lciBaZWlsZW51bWJydWNoIGVpbmdlbGVzZW4gd2VyZGVuIHNvbGxlbgoJCQoJCXByaW50ZigiRXJrYW5udGVyIEF1c2RydWNrOlxuJXNcbiIsIHMpOwoJCQoJCWVyZ2VibmlzPSBjYWxjKHMpOwkKCQlwcmludGYoIkJlcmVjaG5ldGVzIEVyZ2VibmlzOlxuJWZcbiIsIGVyZ2VibmlzKTsKCQkKCgkJcHV0cygiRXJmb2xnISIpOzsKCQlmcmVlKHMpOwoJCWZmbHVzaChzdGRpbik7CgkJLy9pZiAoZ2V0YyhzdGRpbikgPT0gJ2MnKSB7YnJlYWs7fQoJfSB3aGlsZSAoMCk7CgkKCXJldHVybiAwOwp9CgoKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiogw5xiZXJwcsO8ZmVuLCBvYiBLbGFtbWVybiBpbSBUZXJtIHNpbmQKKiBnaWJ0IFBvc2l0aW9uIGRlciBlcnN0ZW4gS2xhbW1lcgoqIG9kZXIgLTEgenVyw7xjawoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KaW50IGhhc1BhciAoY2hhciAqcykgewoJZm9yICh1bnNpZ25lZCBpbnQgaz0wOyBrPHN0cmxlbihzKTsgaysrKSB7IC8vayB2ZXJ3ZW5kZXQsIGRhIG1pdCBpIEludGVyZmVyZW56ZW4gbWl0IGNhbGMoKSBhdWZnZXRyZXRlbiBzaW5kCgkJaWYgKCBzW2tdID09ICcoJyApIHsKCQkJcmV0dXJuIGs7CgkJfQoJfQoKCXJldHVybiAoLTEpOwp9CgoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiogRnVua3Rpb24sIGRpZSBTdWJzdHJpbmcgenVyw7xja2dpYnQKKiBzOiBVcnNwcnVuZ3NzdHJpbmcKKiBvZmZzZXQ6IFBvc2l0aW9uLCBhbiBkZXIgU3Vic3RyaW5nIGJlZ2lubnQKKiBsZW46IEzDpG5nZSBkZXMgU3Vic3RyaW5ncwoqIHQ6IFZhcmlhYmxlLCBpbiBkZXIgU3Vic3RyaW5nIGdlc3BlaWNoZXJ0IHdpcmQKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpjaGFyKiBzdWJTdHIgKGNoYXIqIGRlc3QsIGNoYXIqIHNyYywgaW50IG9mZnNldCwgaW50IGxlbikgewoJaW50IGlucHV0X2xlbiA9IHN0cmxlbiAoc3JjKTsKCglpZiAoIG9mZnNldCtsZW4gPiBpbnB1dF9sZW4gKSB7IC8vV2VubiBTdWJzdHJpbmcgZ3LDtsOfZXIgc2VpbiBzb2xsdGUgYWxzIFVzcHJ1bmdzc3RyaW5nIG9kZXIgU3Vic3RyaW5nIE51bGwgWmVpY2hlbiBlbnRoYWx0ZW4gc29sbAoJCXJldHVybiBOVUxMOwoJfSBlbHNlIGlmIChsZW4gPD0gMCkgewoJCWRlc3RbMF09ICdcMCc7Cgl9CgoJc3RybmNweShkZXN0LCBzcmMgKyBvZmZzZXQsIGxlbik7IC8vbGVuIFplaWNoZW4gd2VyZGVuIGF1cyBzIGFiIG9mZnNldCBpbiB0IGtvcGllcnQKCWRlc3RbbGVuXT0gJ1wwJzsKCXJldHVybiBkZXN0Owp9CgoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiogV2VydGV0IFRlcm1lIG9obmUgS2xhbW1lcm4gYXVzCioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KZG91YmxlIGNhbGNTdHIgKGNoYXIgKnMpIHsKCWNoYXIgKnQsICp0X2ZpcnN0OwoJaW50IGxlbl9zPSBzdHJsZW4ocyksIGxlbl9maXJzdD0wOwoJdD0gY2FsbG9jKGxlbl9zLCBzaXplb2YoY2hhcikpOyAvL0tvcGllIHZvbiBzIHp1bSBBcmJlaXRlbiBlcnN0ZWxsZW4sIFNjaHJpdHQgMQoJc3RyY3B5KHQscyk7IC8vS29waWUgdm9uIHMgenVtIEFyYmVpdGVuIGVyc3RlbGxlbiwgU2Nocml0dCAyCgoJLy9BQ0hUVU5HOiBSRUlIRU5GT0xHRSBXSUNIVElHIEbDnFIgS09SUkVLVEUgQU5XRU5EVU5HIFZPTiBSRUNIRU5SRUdFTE4KCglpZih0WzBdICE9ICcrJykgeyAvLysgYWxzIHVuw6RyZXIgT3BlcmF0b3IKCQl0X2ZpcnN0PSBzdHJ0b2sodCwiKyIpOyAvL1N0cmluZyBhdWYgKyBwcsO8ZmVuLCBOYWNoIEF1c2bDvGhydW5nIHZvbiBzdHJ0b2s6IHRfZmlyc3Q6IFN0cmluZyBiaXMgZXhrbHVzaXYgKwoJCWxlbl9maXJzdD1zdHJsZW4odF9maXJzdCk7IC8vTMOkbmdlIGRlcyBFcmdlYm5pc3N0cmluZ3MgYmVyZWNobmVuIHp1bSBWZXJnbGVpY2ggbWl0IEzDpG5nZSBkZXMgVXJzcHJ1bmdzc3RyaW5ncwoJCWlmIChsZW5fZmlyc3QgIT0gbGVuX3MpIHsgLy9XZW5uIEzDpG5nZSBnbGVpY2gsIGRhbm4gaXN0IGhpZXIgYXVjaCBkZXIgSW5oYWx0IGdsZWljaCwgYWxzbyBrZWluIFBsdXMgZW50aGFsdGVuCgkJCXN3aXRjaCAoIHRfZmlyc3RbbGVuX2ZpcnN0LTFdICkgeyAvL1dlbm4gKyB1bsOkciwgYWxzbyB2b3IgZGVtICsgZWluIGFuZGVyZXMgT3BTeW0KCQkJCWNhc2UgJysnOgoJCQkJCXRbbGVuX2ZpcnN0LTFdPSAnXDAnOwoJCQkJCXJldHVybiBjYWxjU3RyKHQpICsgKGNhbGNTdHIocytsZW5fZmlyc3QpKTsKCQkJCWNhc2UgJy0nOgoJCQkJCXRbbGVuX2ZpcnN0LTFdPSAnXDAnOwoJCQkJCXJldHVybiBjYWxjU3RyKHQpIC0gKGNhbGNTdHIocytsZW5fZmlyc3QpKTsKCQkJCWNhc2UgJyonOgoJCQkJCXRbbGVuX2ZpcnN0LTFdPSAnXDAnOwoJCQkJCXJldHVybiBjYWxjU3RyKHQpICogKGNhbGNTdHIocytsZW5fZmlyc3QpKTsKCQkJCWNhc2UgJy8nOgoJCQkJCXRbbGVuX2ZpcnN0LTFdPSAnXDAnOwoJCQkJCXJldHVybiBjYWxjU3RyKHQpIC8gKGNhbGNTdHIocytsZW5fZmlyc3QpKTsKCQkJCWNhc2UgJ14nOgoJCQkJCXRbbGVuX2ZpcnN0LTFdPSAnXDAnOwoJCQkJCXJldHVybiBwb3coY2FsY1N0cih0KSwgKGNhbGNTdHIocytsZW5fZmlyc3QpKSk7CgkJCQlkZWZhdWx0OgoJCQkJCXJldHVybiBjYWxjU3RyKHRfZmlyc3QpICsgKGNhbGNTdHIocytsZW5fZmlyc3QrMSkpOyAvL1Jla3Vyc2l2ZXMgQXVmcnVmZW4gZGVyIFN0cmluZ3MgbGlua3MgdW5kIHJlY2h0cyBkZXMgT3BlcmF0aW9uc3plaWNoZW5zCgkJCX0KCQl9Cgl9CgoJc3RyY3B5KHQscyk7IC8vZGEgdCBiZWkgw5xiZXJwcsO8ZnVuZyBhdWYgKyB2ZXLDpG5kZXJ0IHd1cmRlLCBXaWVkZXJoZXJzdGVsbHVuZyBkZXIgQXJiZWl0c2tvcGllIGF1cyBVcnNwcnVuZ3NzdHJpbmcKCWlmKHRbMF0gIT0gJy0nKSB7IC8vLSBhbHMgdW7DpHJlciBPcGVyYXRvcgoJCXRfZmlyc3Q9IHN0cnRvayh0LCItIik7IC8vYW5hbG9nIG9iZW4KCQlsZW5fZmlyc3Q9c3RybGVuKHRfZmlyc3QpOyAKCQlpZiAobGVuX2ZpcnN0ICE9IGxlbl9zKSB7CgkJCXN3aXRjaCAoIHRfZmlyc3RbbGVuX2ZpcnN0LTFdICkgewoJCQkJY2FzZSAnKyc6CgkJCQkJdFtsZW5fZmlyc3QtMV09ICdcMCc7CgkJCQkJcmV0dXJuIGNhbGNTdHIodCkgKyAoY2FsY1N0cihzK2xlbl9maXJzdCkpOwoJCQkJY2FzZSAnLSc6CgkJCQkJdFtsZW5fZmlyc3QtMV09ICdcMCc7CgkJCQkJcmV0dXJuIGNhbGNTdHIodCkgLSAoY2FsY1N0cihzK2xlbl9maXJzdCkpOwoJCQkJY2FzZSAnKic6CgkJCQkJdFtsZW5fZmlyc3QtMV09ICdcMCc7CgkJCQkJcmV0dXJuIGNhbGNTdHIodCkgKiAoY2FsY1N0cihzK2xlbl9maXJzdCkpOwoJCQkJY2FzZSAnLyc6CgkJCQkJdFtsZW5fZmlyc3QtMV09ICdcMCc7CgkJCQkJcmV0dXJuIGNhbGNTdHIodCkgLyAoY2FsY1N0cihzK2xlbl9maXJzdCkpOwoJCQkJY2FzZSAnXic6CgkJCQkJdFtsZW5fZmlyc3QtMV09ICdcMCc7CgkJCQkJcmV0dXJuIHBvdyhjYWxjU3RyKHQpLCAoY2FsY1N0cihzK2xlbl9maXJzdCkpKTsKCQkJCWRlZmF1bHQ6CgkJCQkJcmV0dXJuIGNhbGNTdHIodF9maXJzdCkgKyAoY2FsY1N0cihzK2xlbl9maXJzdCsxKSk7IC8vUmVrdXJzaXZlcyBBdWZydWZlbiBkZXIgU3RyaW5ncyBsaW5rcyB1bmQgcmVjaHRzIGRlcyBPcGVyYXRpb25zemVpY2hlbnMKCQkJfQoJCX0KCX0KCglzdHJjcHkodCxzKTsKCXRfZmlyc3Q9IHN0cnRvayh0LCIqIik7CglsZW5fZmlyc3Q9c3RybGVuKHRfZmlyc3QpOwoJaWYgKGxlbl9maXJzdCAhPSBsZW5fcykgewoJCXJldHVybiBjYWxjU3RyKHRfZmlyc3QpICogKGNhbGNTdHIocytsZW5fZmlyc3QrMSkpOwoJfQoKCXN0cmNweSh0LHMpOyAvL2FuYWxvZwoJdF9maXJzdD0gc3RydG9rKHQsIi8iKTsKCWxlbl9maXJzdD1zdHJsZW4odF9maXJzdCk7CglpZiAobGVuX2ZpcnN0ICE9IGxlbl9zKSB7CgkJcmV0dXJuIGNhbGNTdHIodF9maXJzdCkgKiAoMSAvIGNhbGNTdHIocytsZW5fZmlyc3QrMSkpOwoJfQoJCglzdHJjcHkodCxzKTsKCXRfZmlyc3Q9IHN0cnRvayh0LCJeIik7CglsZW5fZmlyc3Q9c3RybGVuKHRfZmlyc3QpOwoJaWYgKGxlbl9maXJzdCAhPSBsZW5fcykgewoJCWlmICh0X2ZpcnN0W2xlbl9maXJzdC0xXT09J2UnKSB7CgkJCWlmICh0X2ZpcnN0WzBdPT0nLScpIHsKCQkJCXJldHVybiAoLTEpKmV4cChjYWxjU3RyKHMrbGVuX2ZpcnN0KzEpKTsKCQkJfSBlbHNlIGlmICh0X2ZpcnN0WzBdPT0nKycpIHsKCQkJCXJldHVybiBleHAoY2FsY1N0cihzK2xlbl9maXJzdCsxKSk7CgkJCX0gZWxzZSB7CgkJCQlyZXR1cm4gcG93KGNhbGNTdHIodF9maXJzdCksIChjYWxjU3RyKHMrbGVuX2ZpcnN0KzEpKSk7CgkJCX0KCQl9Cgl9CgoJcmV0dXJuIGF0b2Yocyk7IC8vU3RyaW5nIGlzdCBiZWkga2VpbmVtIE9wZXJhdGlvbnN6ZWljaGVuIHplcmZhbGxlbiA9PiBTdHJpbmcgaXN0IFphaGwgOyBhdG9mIGNhc3RldCBzdHJpbmcgenUgZG91YmxlIChhdXMgc3RkbGliLmgpCgp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiBGdW5rdGlvbiB6dXIgVmVyc2NoYWNodGVsdGVuIEJlcmVjaG51bmcgZGVzIFRlcm1zCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpkb3VibGUgY2FsYyAoY2hhciAqcykgewoJZG91YmxlIHJlc3VsdF9kPTAuOwoJY2hhciAqdCwgKnJlc3VsdF9zdHI7CglpbnQgY2hlY2s9MSwgaT1oYXNQYXIocyksIGo9MDsKCWlmICggaSA9PSAoLTEpICkgewoJCXJldHVybiBjYWxjU3RyKHMpOwoJfSBlbHNlIHsKCQlqPSArK2k7IC8vaj0rK2kgaXN0IFBvc2l0aW9uIGRlcyBDaGFycyBuYWNoIGRlciBlcnN0ZW4gw7ZmZm5lbmRlbiBLbGFtbWVyCgkJd2hpbGUgKGNoZWNrID4gMCkgewoJCQlpZiAoc1tpXSA9PSAnKCcpIHsKCQkJCWNoZWNrKys7CgkJCX0gZWxzZSBpZiAoc1tpXSA9PSAnKScpIHsKCQkJCWNoZWNrLS07CgkJCX0KCQkJaSsrOwoJCX0JLy9CZXN0aW1tZW4gZGVyIEzDpG5nZSBkZXIgIm9iZXJzdGVuIiBLbGFtbWVyLCBpIGlzdCBQb3NpdGlvbiBkZXMgZXJzdGVuIFplaWNoZW5zIG5hY2ggZGVyIEtsYW1tZXIKCgkJdD0gY2FsbG9jKHN0cmxlbihzKSwgc2l6ZW9mKGNoYXIpKTsgLy9IaWxmc3N0cmluZywgTMOkbmdlOiBzWzAgYmlzIGotMV0gKyBQdWZmZXIgZsO8ciBOYWNoa29tbWFzdGVsbGVuCgkJcmVzdWx0X3N0cj0gY2FsbG9jKHN0cmxlbihzKSwgc2l6ZW9mKGNoYXIpKTsgLy9IaWxmc3N0cmluZywgTMOkbmdlIHNbaiBiaXMgaS0yXSArIFB1ZmZlciBmw7xyIE5hY2hrb21tYXN0ZWxsZW4KCQlyZXN1bHRfZD0gY2FsYyggc3ViU3RyKHJlc3VsdF9zdHIsIHMsIGosIGktai0xKSk7IC8vVHJlbm51bmcgYXVmIHp3ZWkgWmVpbGVuIHp1ciBiZXNzZXJlbiBMZXNiYXJrZWl0IGRlciB2ZXJzY2hhY2h0ZWx0ZW4gRnVua3Rpb25zYXVmcnVmZQoJCXNwcmludGYocmVzdWx0X3N0ciwgIiUtLjE2ZiIsIHJlc3VsdF9kKTsgLy9jYXN0ZW4gZGVzIGVycmVjaG5ldGVuIERvdWJsZS1FcmdlYm5pc3NlcyB6dXLDvGNrIGluICpjaGFyICEhIUFDSFRVTkchISEgUHLDpHppc2lvbiBuaWNodCBhdWYgMTYgc3RlbGxlbiwgZGEgc29uc3QgdW5kZWZpbmllcnRlcyBWZXJoYWx0ZW4gZXJ6ZXVndCB3aXJkCgkJcmV0dXJuIGNhbGNTdHIoIHN0cmNhdCggc3ViU3RyKHQsIHMsIDAsIGotMSksIHN0cmNhdCggcmVzdWx0X3N0ciwgcytpKSkpOyAvL3Jla3Vyc2l2ZXIgQXVmcnVmOiBjYWxjKCBzW2JpcyBqLTJdICMjIHNbaiBiaXMgaS0yXSAjIyBzW2kgYmlzIEVuZGVdKSAvLyMjOiBLb25rYXRlbmF0aW9uCgl9Cn0K