#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAXLEN 256
#define TBLSIZE 65535
typedef enum {UNKNOWN, END, INT, ID, ADDSUB, MULDIV, ASSIGN,
LPAREN, RPAREN, ENDFILE} TokenSet;
typedef enum {MISPAREN, NOTNUMID, NOTFOUND, RUNOUT} ErrorType;
typedef struct {
char name[MAXLEN];
int val;
} Symbol;
typedef struct _Node {
char lexeme[MAXLEN];
TokenSet data;
int val;
struct _Node *left, *right;
} BTNode;
Symbol table[TBLSIZE];
extern Symbol table[TBLSIZE];
int r[8][2];
int idx = 0;
extern int getval(void);
extern int setval(char *str, int val);
extern int match (TokenSet token);
extern int evaluateTree(BTNode *root);
extern void printPrefix(BTNode *root);
extern void advance(void);
extern void freeTree(BTNode *root);
extern void statement(void);
extern void error(ErrorType errorNum);
extern BTNode* makeNode(TokenSet tok, const char *lexe);
extern BTNode* factor(void);
extern BTNode* term(void);
extern BTNode* term_tail(BTNode *left);
extern BTNode* expr(void);
extern BTNode* expr_tail(BTNode *left);
static TokenSet getToken(void);
static TokenSet lookahead = UNKNOWN;
extern char* getLexeme(void);
static char lexeme[MAXLEN];
int sbcount = 0;
/*
Something like Python
>> y = 2
>> z = 2
>> x = 3*y + 4/(2*z)
*/
/*
the only type: integer
everything is an expression
statement := END | expr END
expr := term expr_tail
expr_tail := ADDSUB term expr_tail | NIL
term := factor term_tail
term_tail := MULDIV factor term_tail | NIL
factor := INT | ADDSUB INT | ADDSUB ID | ID ASSIGN expr | ID | LPAREN expr RPAREN
*/
int main() {
while (1) {
statement();
}
return 0;
}
/*statement := ENDFILE | END | expr END*/
void statement(void) {
BTNode* retp;
if (match(ENDFILE)) {
} else if (match(END)) {
advance();
} else {
retp = expr();
if (match(END)) {
printf("%d\n", evaluateTree
(retp
)); printPrefix
(retp
); printf("\n"); freeTree(retp);
advance();
}
}
}
void advance(void) {
lookahead = getToken();
}
/* expr := term expr_tail*/
BTNode* expr(void) {
BTNode *node;
node = term();
return expr_tail(node);
}
/* expr_tail := ADDSUB term expr_tail | NIL*/
BTNode* expr_tail(BTNode *left) {
BTNode *node;
if (match(ADDSUB)) {
node = makeNode(ADDSUB, getLexeme());
advance();
node->left = left;
node->right = term();
return expr_tail(node);
}
else
return left;
}
TokenSet getToken(void) {
int i;
char c;
while ((c
= fgetc(stdin
)) == ' ' || c
== '\t'); // ©ø≤§™≈•’¶r§∏
lexeme[0] = c;
i = 1;
lexeme[i] = c;
++i;
}
lexeme[i] = '\0';
return INT;
} else if (c == '+' || c == '-') {
lexeme[0] = c;
lexeme[1] = '\0';
return ADDSUB;
} else if (c == '*' || c == '/') {
lexeme[0] = c;
lexeme[1] = '\0';
return MULDIV;
} else if (c == '\n') {
lexeme[0] = '\0';
return END;
} else if (c == '=') {
return ASSIGN;
} else if (c == '(') {
return LPAREN;
} else if (c == ')') {
return RPAREN;
} else if (isalpha(c
) || c
== '_') { lexeme[0] = c;
i = 1;
lexeme[i] = c;
++i;
}
lexeme[i] = '\0';
return ID;
} else if (c == EOF)
return ENDFILE;
else
return UNKNOWN;
}
int match(TokenSet token) {
if (lookahead == UNKNOWN) advance();
return token == lookahead;
}
char* getLexeme(void) {
return lexeme;
}
int evaluateTree(BTNode *root) {
int retval = 0, lv, rv;
if (root != NULL) {
switch (root->data) {
case ID:
if (strcmp(root
->lexeme
, "x") == 0) else if (strcmp(root
->lexeme
, "y") == 0) else if (strcmp(root
->lexeme
, "z") == 0) break;
case INT:
retval = root->val;
r[idx][0] = root->val;
r[idx][1] = -1;
printf("MOV r%d %d\n", idx
, r
[idx
][0]); idx++;
break;
case ASSIGN:
/*if (strcmp(root->right->lexeme, "x") == 0)
printf("MOV [0] r%d\n", idx);
else if (strcmp(root->right->lexeme, "y") == 0)
printf("MOV [4] r%d\n", idx);
else if (strcmp(root->right->lexeme, "z") == 0)
printf("MOV [8] r%d\n", idx);*/
case ADDSUB:
if (strcmp(root
->lexeme
, "+") == 0) { //printf("",);
}
case MULDIV:
lv = evaluateTree(root->left);
rv = evaluateTree(root->right);
if (strcmp(root
->lexeme
, "+") == 0) { retval = lv + rv;
}
else if (strcmp(root
->lexeme
, "-") == 0) { retval = lv - rv;
}
else if (strcmp(root
->lexeme
, "*") == 0) { retval = lv * rv;
}
else if (strcmp(root
->lexeme
, "/") == 0) { retval = lv / rv;
}
else if (strcmp(root
->lexeme
, "=") == 0) { retval = setval(root->left->lexeme, rv);
}
break;
default:
retval = 0;
}
}
return retval;
}
/* print a tree by pre-order. */
void printPrefix(BTNode *root) {
if (root != NULL) {
printPrefix(root->left);
printPrefix(root->right);
}
}
int getval(void) {
int i, retval, found;
if (match(INT))
retval
= atoi(getLexeme
()); else if (match(ID)) {
i = 0; found = 0; retval = 0;
while (i < sbcount && !found) {
if (strcmp(getLexeme
(), table
[i
].
name)==0) { retval = table[i].val;
found = 1;
break;
} else
i++;
}
if (!found) {
if (sbcount < TBLSIZE) {
strcpy(table
[sbcount
].
name, getLexeme
()); table[sbcount].val = 0;
sbcount++;
} else
error(RUNOUT);
}
}
return retval;
}
int setval(char *str, int val) {
int i, retval;
i = 0;
while (i < sbcount) {
if (strcmp(str
, table
[i
].
name) == 0) { table[i].val = val;
retval = val;
break;
} else
i++;
}
return retval;
}
/* create a node without any child.*/
BTNode* makeNode(TokenSet tok, const char *lexe){
BTNode
*node
= (BTNode
*) malloc(sizeof(BTNode
)); node->data = tok;
node->val = 0;
node->left = NULL;
node->right = NULL;
return node;
}
/* clean a tree.*/
void freeTree(BTNode *root) {
if (root != NULL) {
freeTree(root->left);
freeTree(root->right);
}
}
/*factor := INT | ADDSUB INT | ADDSUB ID | ID ASSIGN expr | ID | LPAREN expr RPAREN*/
BTNode* factor(void) {
BTNode* retp = NULL;
char tmpstr[MAXLEN];
if (match(INT)) {
retp = makeNode(INT, getLexeme());
retp->val = getval();
advance();
} else if (match(ID)) {
BTNode* left = makeNode(ID, getLexeme());
left->val = getval();
advance();
if (match(ASSIGN)) {
retp = makeNode(ASSIGN, getLexeme());
advance();
retp->right = expr();
retp->left = left;
} else
retp = left;
} else if (match(ADDSUB)) {
advance();
if (match(ID) || match(INT)) {
retp = makeNode(ADDSUB, tmpstr);
if (match(ID))
retp->right = makeNode(ID, getLexeme());
else
retp->right = makeNode(INT, getLexeme());
retp->right->val = getval();
retp->left = makeNode(INT, "0");
retp->left->val = 0;
advance();
} else
error(NOTNUMID);
} else if (match(LPAREN)) {
advance();
retp = expr();
if (match(RPAREN))
advance();
else
error(MISPAREN);
} else
error(NOTNUMID);
return retp;
}
/* term := factor term_tail*/
BTNode* term(void) {
BTNode *node;
node = factor();
return term_tail(node);
}
/*term_tail := MULDIV factor term_tail | NIL*/
BTNode* term_tail(BTNode *left) {
BTNode *node;
if (match(MULDIV)) {
node = makeNode(MULDIV, getLexeme());
advance();
node->left = left;
node->right = factor();
return term_tail(node);
}
else
return left;
}
void error(ErrorType errorNum) {
switch (errorNum) {
case MISPAREN:
fprintf(stderr
, "Mismatched parenthesis\n"); break;
case NOTNUMID:
fprintf(stderr
, "Number or identifier expected\n"); break;
case NOTFOUND:
fprintf(stderr
, "%s not defined\n", getLexeme
()); break;
case RUNOUT:
fprintf(stderr
, "Out of memory\n"); }
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPGN0eXBlLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KCiNkZWZpbmUgTUFYTEVOIDI1NgojZGVmaW5lIFRCTFNJWkUgNjU1MzUKCnR5cGVkZWYgZW51bSB7VU5LTk9XTiwgRU5ELCBJTlQsIElELCBBRERTVUIsIE1VTERJViwgQVNTSUdOLAogICAgTFBBUkVOLCBSUEFSRU4sIEVOREZJTEV9IFRva2VuU2V0Owp0eXBlZGVmIGVudW0ge01JU1BBUkVOLCBOT1ROVU1JRCwgTk9URk9VTkQsIFJVTk9VVH0gRXJyb3JUeXBlOwoKdHlwZWRlZiBzdHJ1Y3QgewogICAgY2hhciBuYW1lW01BWExFTl07CiAgICBpbnQgdmFsOwp9IFN5bWJvbDsKCnR5cGVkZWYgc3RydWN0IF9Ob2RlIHsKICAgIGNoYXIgbGV4ZW1lW01BWExFTl07CiAgICBUb2tlblNldCBkYXRhOwogICAgaW50IHZhbDsKICAgIHN0cnVjdCBfTm9kZSAqbGVmdCwgKnJpZ2h0Owp9IEJUTm9kZTsKClN5bWJvbCB0YWJsZVtUQkxTSVpFXTsKZXh0ZXJuIFN5bWJvbCB0YWJsZVtUQkxTSVpFXTsKCmludCByWzhdWzJdOwppbnQgaWR4ID0gMDsKCmV4dGVybiBpbnQgZ2V0dmFsKHZvaWQpOwpleHRlcm4gaW50IHNldHZhbChjaGFyICpzdHIsIGludCB2YWwpOwpleHRlcm4gaW50IG1hdGNoIChUb2tlblNldCB0b2tlbik7CmV4dGVybiBpbnQgZXZhbHVhdGVUcmVlKEJUTm9kZSAqcm9vdCk7CmV4dGVybiB2b2lkIHByaW50UHJlZml4KEJUTm9kZSAqcm9vdCk7CmV4dGVybiB2b2lkIGFkdmFuY2Uodm9pZCk7CmV4dGVybiB2b2lkIGZyZWVUcmVlKEJUTm9kZSAqcm9vdCk7CmV4dGVybiB2b2lkIHN0YXRlbWVudCh2b2lkKTsKZXh0ZXJuIHZvaWQgZXJyb3IoRXJyb3JUeXBlIGVycm9yTnVtKTsKZXh0ZXJuIEJUTm9kZSogbWFrZU5vZGUoVG9rZW5TZXQgdG9rLCBjb25zdCBjaGFyICpsZXhlKTsKZXh0ZXJuIEJUTm9kZSogZmFjdG9yKHZvaWQpOwpleHRlcm4gQlROb2RlKiB0ZXJtKHZvaWQpOwpleHRlcm4gQlROb2RlKiB0ZXJtX3RhaWwoQlROb2RlICpsZWZ0KTsKZXh0ZXJuIEJUTm9kZSogZXhwcih2b2lkKTsKZXh0ZXJuIEJUTm9kZSogZXhwcl90YWlsKEJUTm9kZSAqbGVmdCk7CnN0YXRpYyBUb2tlblNldCBnZXRUb2tlbih2b2lkKTsKc3RhdGljIFRva2VuU2V0IGxvb2thaGVhZCA9IFVOS05PV047CmV4dGVybiBjaGFyKiBnZXRMZXhlbWUodm9pZCk7CnN0YXRpYyBjaGFyIGxleGVtZVtNQVhMRU5dOwppbnQgc2Jjb3VudCA9IDA7Ci8qCiBTb21ldGhpbmcgbGlrZSBQeXRob24KID4+IHkgPSAyCiA+PiB6ID0gMgogPj4geCA9IDMqeSArIDQvKDIqeikKIAogKi8KCi8qCiB0aGUgb25seSB0eXBlOiBpbnRlZ2VyCiBldmVyeXRoaW5nIGlzIGFuIGV4cHJlc3Npb24KIHN0YXRlbWVudCAgIDo9IEVORCB8IGV4cHIgRU5ECiBleHByICAgICAgICA6PSB0ZXJtIGV4cHJfdGFpbAogZXhwcl90YWlsICAgOj0gQUREU1VCIHRlcm0gZXhwcl90YWlsIHwgTklMCiB0ZXJtICAgICAgICA6PSBmYWN0b3IgdGVybV90YWlsCiB0ZXJtX3RhaWwgOj0gTVVMRElWIGZhY3RvciB0ZXJtX3RhaWwgfCBOSUwKIGZhY3RvciAgICAgIDo9IElOVCB8IEFERFNVQiBJTlQgfCBBRERTVUIgSUQgfCBJRCBBU1NJR04gZXhwciB8IElEIHwgTFBBUkVOIGV4cHIgUlBBUkVOCiAqLwoKaW50IG1haW4oKSB7CiAgICBwcmludGYoIj4+ICIpOwogICAgd2hpbGUgKDEpIHsKICAgICAgICBzdGF0ZW1lbnQoKTsKICAgIH0KICAgIHJldHVybiAwOwp9CgovKnN0YXRlbWVudCAgIDo9IEVOREZJTEUgfCBFTkQgfCBleHByIEVORCovCnZvaWQgc3RhdGVtZW50KHZvaWQpIHsKICAgIEJUTm9kZSogcmV0cDsKICAgIAogICAgaWYgKG1hdGNoKEVOREZJTEUpKSB7CiAgICAgICAgZXhpdCgwKTsKICAgIH0gZWxzZSBpZiAobWF0Y2goRU5EKSkgewogICAgICAgIHByaW50ZigiPj4gIik7CiAgICAgICAgYWR2YW5jZSgpOwogICAgfSBlbHNlIHsKICAgICAgICByZXRwID0gZXhwcigpOwogICAgICAgIGlmIChtYXRjaChFTkQpKSB7CiAgICAgICAgICAgIAogICAgICAgICAgICBwcmludGYoIiVkXG4iLCBldmFsdWF0ZVRyZWUocmV0cCkpOwogICAgICAgICAgICBwcmludFByZWZpeChyZXRwKTsgcHJpbnRmKCJcbiIpOwogICAgICAgICAgICBmcmVlVHJlZShyZXRwKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIHByaW50ZigiPj4gIik7CiAgICAgICAgICAgIGFkdmFuY2UoKTsKICAgICAgICB9CiAgICB9Cn0KCnZvaWQgYWR2YW5jZSh2b2lkKSB7CiAgICBsb29rYWhlYWQgPSBnZXRUb2tlbigpOwp9CgovKiAgZXhwciAgICAgICAgOj0gdGVybSBleHByX3RhaWwqLwpCVE5vZGUqIGV4cHIodm9pZCkgewogICAgQlROb2RlICpub2RlOwogICAgCiAgICBub2RlID0gdGVybSgpOwogICAgCiAgICByZXR1cm4gZXhwcl90YWlsKG5vZGUpOwp9Ci8qICBleHByX3RhaWwgICA6PSBBRERTVUIgdGVybSBleHByX3RhaWwgfCBOSUwqLwpCVE5vZGUqIGV4cHJfdGFpbChCVE5vZGUgKmxlZnQpIHsKICAgIEJUTm9kZSAqbm9kZTsKICAgIAogICAgaWYgKG1hdGNoKEFERFNVQikpIHsKICAgICAgICBub2RlID0gbWFrZU5vZGUoQUREU1VCLCBnZXRMZXhlbWUoKSk7CiAgICAgICAgYWR2YW5jZSgpOwogICAgICAgIAogICAgICAgIG5vZGUtPmxlZnQgPSBsZWZ0OwogICAgICAgIG5vZGUtPnJpZ2h0ID0gdGVybSgpOwogICAgICAgIAogICAgICAgIHJldHVybiBleHByX3RhaWwobm9kZSk7CiAgICB9CiAgICBlbHNlCiAgICAgICAgcmV0dXJuIGxlZnQ7Cn0KClRva2VuU2V0IGdldFRva2VuKHZvaWQpIHsKICAgIGludCBpOwogICAgY2hhciBjOwogICAgCiAgICB3aGlsZSAoKGMgPSBmZ2V0YyhzdGRpbikpID09ICcgJyB8fCBjID09ICdcdCcpOyAgLy8gwqnDuOKJpMKn4oSi4omI4oCi4oCZwrZywqfiiI8KICAgIAogICAgaWYgKGlzZGlnaXQoYykpIHsKICAgICAgICBsZXhlbWVbMF0gPSBjOwogICAgICAgIGMgPSBmZ2V0YyhzdGRpbik7CiAgICAgICAgaSA9IDE7CiAgICAgICAgd2hpbGUgKGlzZGlnaXQoYykgJiYgaSA8IE1BWExFTikgewogICAgICAgICAgICBsZXhlbWVbaV0gPSBjOwogICAgICAgICAgICArK2k7CiAgICAgICAgICAgIGMgPSBmZ2V0YyhzdGRpbik7CiAgICAgICAgfQogICAgICAgIHVuZ2V0YyhjLCBzdGRpbik7CiAgICAgICAgbGV4ZW1lW2ldID0gJ1wwJzsKICAgICAgICByZXR1cm4gSU5UOwogICAgfSBlbHNlIGlmIChjID09ICcrJyB8fCBjID09ICctJykgewogICAgICAgIGxleGVtZVswXSA9IGM7CiAgICAgICAgbGV4ZW1lWzFdID0gJ1wwJzsKICAgICAgICByZXR1cm4gQUREU1VCOwogICAgfSBlbHNlIGlmIChjID09ICcqJyB8fCBjID09ICcvJykgewogICAgICAgIGxleGVtZVswXSA9IGM7CiAgICAgICAgbGV4ZW1lWzFdID0gJ1wwJzsKICAgICAgICByZXR1cm4gTVVMRElWOwogICAgfSBlbHNlIGlmIChjID09ICdcbicpIHsKICAgICAgICBsZXhlbWVbMF0gPSAnXDAnOwogICAgICAgIHJldHVybiBFTkQ7CiAgICB9IGVsc2UgaWYgKGMgPT0gJz0nKSB7CiAgICAgICAgc3RyY3B5KGxleGVtZSwgIj0iKTsKICAgICAgICByZXR1cm4gQVNTSUdOOwogICAgfSBlbHNlIGlmIChjID09ICcoJykgewogICAgICAgIHN0cmNweShsZXhlbWUsICIoIik7CiAgICAgICAgcmV0dXJuIExQQVJFTjsKICAgIH0gZWxzZSBpZiAoYyA9PSAnKScpIHsKICAgICAgICBzdHJjcHkobGV4ZW1lLCAiKSIpOwogICAgICAgIHJldHVybiBSUEFSRU47CiAgICB9IGVsc2UgaWYgKGlzYWxwaGEoYykgfHwgYyA9PSAnXycpIHsKICAgICAgICBsZXhlbWVbMF0gPSBjOwogICAgICAgIGMgPSBmZ2V0YyhzdGRpbik7CiAgICAgICAgaSA9IDE7CiAgICAgICAgd2hpbGUgKGlzYWxwaGEoYykgfHwgaXNkaWdpdChjKSB8fCBjID09ICdfJykgewogICAgICAgICAgICBsZXhlbWVbaV0gPSBjOwogICAgICAgICAgICArK2k7CiAgICAgICAgICAgIGMgPSBmZ2V0YyhzdGRpbik7CiAgICAgICAgfQogICAgICAgIHVuZ2V0YyhjLCBzdGRpbik7CiAgICAgICAgbGV4ZW1lW2ldID0gJ1wwJzsKICAgICAgICByZXR1cm4gSUQ7CiAgICB9IGVsc2UgaWYgKGMgPT0gRU9GKQogICAgICAgIHJldHVybiBFTkRGSUxFOwogICAgZWxzZQogICAgICAgIHJldHVybiBVTktOT1dOOwp9CgppbnQgbWF0Y2goVG9rZW5TZXQgdG9rZW4pIHsKICAgIGlmIChsb29rYWhlYWQgPT0gVU5LTk9XTikgYWR2YW5jZSgpOwogICAgcmV0dXJuIHRva2VuID09IGxvb2thaGVhZDsKfQoKY2hhciogZ2V0TGV4ZW1lKHZvaWQpIHsKICAgIHJldHVybiBsZXhlbWU7Cn0KCmludCBldmFsdWF0ZVRyZWUoQlROb2RlICpyb290KSB7CiAgICBpbnQgcmV0dmFsID0gMCwgbHYsIHJ2OwogICAgaWYgKHJvb3QgIT0gTlVMTCkgewogICAgICAgIHN3aXRjaCAocm9vdC0+ZGF0YSkgewogICAgICAgICAgICBjYXNlIElEOgogICAgICAgICAgICAgICAgaWYgKHN0cmNtcChyb290LT5sZXhlbWUsICJ4IikgPT0gMCkKICAgICAgICAgICAgICAgICAgICBwcmludGYoIk1PViByJWQgWzBdXG4iLCBpZHgpOwogICAgICAgICAgICAgICAgZWxzZSBpZiAoc3RyY21wKHJvb3QtPmxleGVtZSwgInkiKSA9PSAwKQogICAgICAgICAgICAgICAgICAgIHByaW50ZigiTU9WIHIlZCBbNF1cbiIsIGlkeCk7CiAgICAgICAgICAgICAgICBlbHNlIGlmIChzdHJjbXAocm9vdC0+bGV4ZW1lLCAieiIpID09IDApCiAgICAgICAgICAgICAgICAgICAgcHJpbnRmKCJNT1YgciVkIFs4XVxuIiwgaWR4KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIElOVDoKICAgICAgICAgICAgICAgIHJldHZhbCA9IHJvb3QtPnZhbDsKICAgICAgICAgICAgICAgIHJbaWR4XVswXSA9IHJvb3QtPnZhbDsKICAgICAgICAgICAgICAgIHJbaWR4XVsxXSA9IC0xOwogICAgICAgICAgICAgICAgcHJpbnRmKCJNT1YgciVkICVkXG4iLCBpZHgsIHJbaWR4XVswXSk7CiAgICAgICAgICAgICAgICBpZHgrKzsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIEFTU0lHTjoKICAgICAgICAgICAgICAgIC8qaWYgKHN0cmNtcChyb290LT5yaWdodC0+bGV4ZW1lLCAieCIpID09IDApCiAgICAgICAgICAgICAgICAgcHJpbnRmKCJNT1YgWzBdIHIlZFxuIiwgaWR4KTsKICAgICAgICAgICAgICAgICBlbHNlIGlmIChzdHJjbXAocm9vdC0+cmlnaHQtPmxleGVtZSwgInkiKSA9PSAwKQogICAgICAgICAgICAgICAgIHByaW50ZigiTU9WIFs0XSByJWRcbiIsIGlkeCk7CiAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc3RyY21wKHJvb3QtPnJpZ2h0LT5sZXhlbWUsICJ6IikgPT0gMCkKICAgICAgICAgICAgICAgICBwcmludGYoIk1PViBbOF0gciVkXG4iLCBpZHgpOyovCiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgY2FzZSBBRERTVUI6CiAgICAgICAgICAgICAgICBpZiAoc3RyY21wKHJvb3QtPmxleGVtZSwgIisiKSA9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgLy9wcmludGYoIiIsKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgY2FzZSBNVUxESVY6CiAgICAgICAgICAgICAgICBsdiA9IGV2YWx1YXRlVHJlZShyb290LT5sZWZ0KTsKICAgICAgICAgICAgICAgIHJ2ID0gZXZhbHVhdGVUcmVlKHJvb3QtPnJpZ2h0KTsKICAgICAgICAgICAgICAgIGlmIChzdHJjbXAocm9vdC0+bGV4ZW1lLCAiKyIpID09IDApIHsKICAgICAgICAgICAgICAgICAgICByZXR2YWwgPSBsdiArIHJ2OwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSBpZiAoc3RyY21wKHJvb3QtPmxleGVtZSwgIi0iKSA9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dmFsID0gbHYgLSBydjsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgaWYgKHN0cmNtcChyb290LT5sZXhlbWUsICIqIikgPT0gMCkgewogICAgICAgICAgICAgICAgICAgIHJldHZhbCA9IGx2ICogcnY7CiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIGlmIChzdHJjbXAocm9vdC0+bGV4ZW1lLCAiLyIpID09IDApIHsKICAgICAgICAgICAgICAgICAgICByZXR2YWwgPSBsdiAvIHJ2OwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSBpZiAoc3RyY21wKHJvb3QtPmxleGVtZSwgIj0iKSA9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dmFsID0gc2V0dmFsKHJvb3QtPmxlZnQtPmxleGVtZSwgcnYpOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICByZXR2YWwgPSAwOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXR2YWw7Cn0KCgovKiBwcmludCBhIHRyZWUgYnkgcHJlLW9yZGVyLiAqLwp2b2lkIHByaW50UHJlZml4KEJUTm9kZSAqcm9vdCkgewogICAgaWYgKHJvb3QgIT0gTlVMTCkgewogICAgICAgIHByaW50ZigiJXMgIiwgcm9vdC0+bGV4ZW1lKTsKICAgICAgICBwcmludFByZWZpeChyb290LT5sZWZ0KTsKICAgICAgICBwcmludFByZWZpeChyb290LT5yaWdodCk7CiAgICB9Cn0KCmludCBnZXR2YWwodm9pZCkgewogICAgaW50IGksIHJldHZhbCwgZm91bmQ7CiAgICAKICAgIGlmIChtYXRjaChJTlQpKQogICAgICAgIHJldHZhbCA9IGF0b2koZ2V0TGV4ZW1lKCkpOwogICAgZWxzZSBpZiAobWF0Y2goSUQpKSB7CiAgICAgICAgaSA9IDA7IGZvdW5kID0gMDsgcmV0dmFsID0gMDsKICAgICAgICB3aGlsZSAoaSA8IHNiY291bnQgJiYgIWZvdW5kKSB7CiAgICAgICAgICAgIGlmIChzdHJjbXAoZ2V0TGV4ZW1lKCksIHRhYmxlW2ldLm5hbWUpPT0wKSB7CiAgICAgICAgICAgICAgICByZXR2YWwgPSB0YWJsZVtpXS52YWw7CiAgICAgICAgICAgICAgICBmb3VuZCA9IDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgICBpKys7CiAgICAgICAgfQogICAgICAgIGlmICghZm91bmQpIHsKICAgICAgICAgICAgaWYgKHNiY291bnQgPCBUQkxTSVpFKSB7CiAgICAgICAgICAgICAgICBzdHJjcHkodGFibGVbc2Jjb3VudF0ubmFtZSwgZ2V0TGV4ZW1lKCkpOwogICAgICAgICAgICAgICAgdGFibGVbc2Jjb3VudF0udmFsID0gMDsKICAgICAgICAgICAgICAgIHNiY291bnQrKzsKICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgICBlcnJvcihSVU5PVVQpOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXR2YWw7Cn0KCmludCBzZXR2YWwoY2hhciAqc3RyLCBpbnQgdmFsKSB7CiAgICBpbnQgaSwgcmV0dmFsOwogICAgaSA9IDA7CiAgICB3aGlsZSAoaSA8IHNiY291bnQpIHsKICAgICAgICBpZiAoc3RyY21wKHN0ciwgdGFibGVbaV0ubmFtZSkgPT0gMCkgewogICAgICAgICAgICB0YWJsZVtpXS52YWwgPSB2YWw7CiAgICAgICAgICAgIHJldHZhbCA9IHZhbDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfSBlbHNlCiAgICAgICAgICAgIGkrKzsKICAgIH0KICAgIHJldHVybiByZXR2YWw7Cn0KLyogY3JlYXRlIGEgbm9kZSB3aXRob3V0IGFueSBjaGlsZC4qLwpCVE5vZGUqIG1ha2VOb2RlKFRva2VuU2V0IHRvaywgY29uc3QgY2hhciAqbGV4ZSl7CiAgICBCVE5vZGUgKm5vZGUgPSAoQlROb2RlKikgbWFsbG9jKHNpemVvZihCVE5vZGUpKTsKICAgIHN0cmNweShub2RlLT5sZXhlbWUsIGxleGUpOwogICAgbm9kZS0+ZGF0YSA9IHRvazsKICAgIG5vZGUtPnZhbCA9IDA7CiAgICBub2RlLT5sZWZ0ID0gTlVMTDsKICAgIG5vZGUtPnJpZ2h0ID0gTlVMTDsKICAgIHJldHVybiBub2RlOwp9Ci8qIGNsZWFuIGEgdHJlZS4qLwp2b2lkIGZyZWVUcmVlKEJUTm9kZSAqcm9vdCkgewogICAgaWYgKHJvb3QgIT0gTlVMTCkgewogICAgICAgIGZyZWVUcmVlKHJvb3QtPmxlZnQpOwogICAgICAgIGZyZWVUcmVlKHJvb3QtPnJpZ2h0KTsKICAgICAgICBmcmVlKHJvb3QpOwogICAgfQp9Ci8qZmFjdG9yIDo9IElOVCB8IEFERFNVQiBJTlQgfCBBRERTVUIgSUQgfCBJRCBBU1NJR04gZXhwciB8IElEIHwgTFBBUkVOIGV4cHIgUlBBUkVOKi8KQlROb2RlKiBmYWN0b3Iodm9pZCkgewogICAgQlROb2RlKiByZXRwID0gTlVMTDsKICAgIGNoYXIgdG1wc3RyW01BWExFTl07CiAgICAKICAgIGlmIChtYXRjaChJTlQpKSB7CiAgICAgICAgcmV0cCA9IG1ha2VOb2RlKElOVCwgZ2V0TGV4ZW1lKCkpOwogICAgICAgIHJldHAtPnZhbCA9IGdldHZhbCgpOwogICAgICAgIGFkdmFuY2UoKTsKICAgIH0gZWxzZSBpZiAobWF0Y2goSUQpKSB7CiAgICAgICAgQlROb2RlKiBsZWZ0ID0gbWFrZU5vZGUoSUQsIGdldExleGVtZSgpKTsKICAgICAgICBsZWZ0LT52YWwgPSBnZXR2YWwoKTsKICAgICAgICBzdHJjcHkodG1wc3RyLCBnZXRMZXhlbWUoKSk7CiAgICAgICAgYWR2YW5jZSgpOwogICAgICAgIGlmIChtYXRjaChBU1NJR04pKSB7CiAgICAgICAgICAgIHJldHAgPSBtYWtlTm9kZShBU1NJR04sIGdldExleGVtZSgpKTsKICAgICAgICAgICAgYWR2YW5jZSgpOwogICAgICAgICAgICByZXRwLT5yaWdodCA9IGV4cHIoKTsKICAgICAgICAgICAgcmV0cC0+bGVmdCA9IGxlZnQ7CiAgICAgICAgfSBlbHNlCiAgICAgICAgICAgIHJldHAgPSBsZWZ0OwogICAgfSBlbHNlIGlmIChtYXRjaChBRERTVUIpKSB7CiAgICAgICAgc3RyY3B5KHRtcHN0ciwgZ2V0TGV4ZW1lKCkpOwogICAgICAgIGFkdmFuY2UoKTsKICAgICAgICBpZiAobWF0Y2goSUQpIHx8IG1hdGNoKElOVCkpIHsKICAgICAgICAgICAgcmV0cCA9IG1ha2VOb2RlKEFERFNVQiwgdG1wc3RyKTsKICAgICAgICAgICAgaWYgKG1hdGNoKElEKSkKICAgICAgICAgICAgICAgIHJldHAtPnJpZ2h0ID0gbWFrZU5vZGUoSUQsIGdldExleGVtZSgpKTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgcmV0cC0+cmlnaHQgPSBtYWtlTm9kZShJTlQsIGdldExleGVtZSgpKTsKICAgICAgICAgICAgcmV0cC0+cmlnaHQtPnZhbCA9IGdldHZhbCgpOwogICAgICAgICAgICByZXRwLT5sZWZ0ID0gbWFrZU5vZGUoSU5ULCAiMCIpOwogICAgICAgICAgICByZXRwLT5sZWZ0LT52YWwgPSAwOwogICAgICAgICAgICBhZHZhbmNlKCk7CiAgICAgICAgfSBlbHNlCiAgICAgICAgICAgIGVycm9yKE5PVE5VTUlEKTsKICAgIH0gZWxzZSBpZiAobWF0Y2goTFBBUkVOKSkgewogICAgICAgIGFkdmFuY2UoKTsKICAgICAgICByZXRwID0gZXhwcigpOwogICAgICAgIGlmIChtYXRjaChSUEFSRU4pKQogICAgICAgICAgICBhZHZhbmNlKCk7CiAgICAgICAgZWxzZQogICAgICAgICAgICBlcnJvcihNSVNQQVJFTik7CiAgICB9IGVsc2UKICAgICAgICBlcnJvcihOT1ROVU1JRCk7CiAgICByZXR1cm4gcmV0cDsKfQovKiAgdGVybSAgICAgICAgOj0gZmFjdG9yIHRlcm1fdGFpbCovCkJUTm9kZSogdGVybSh2b2lkKSB7CiAgICBCVE5vZGUgKm5vZGU7CiAgICBub2RlID0gZmFjdG9yKCk7CiAgICAKICAgIHJldHVybiB0ZXJtX3RhaWwobm9kZSk7Cn0KLyp0ZXJtX3RhaWwgOj0gTVVMRElWIGZhY3RvciB0ZXJtX3RhaWwgfCBOSUwqLwpCVE5vZGUqIHRlcm1fdGFpbChCVE5vZGUgKmxlZnQpIHsKICAgIEJUTm9kZSAqbm9kZTsKICAgIAogICAgaWYgKG1hdGNoKE1VTERJVikpIHsKICAgICAgICBub2RlID0gbWFrZU5vZGUoTVVMRElWLCBnZXRMZXhlbWUoKSk7CiAgICAgICAgYWR2YW5jZSgpOwogICAgICAgIAogICAgICAgIG5vZGUtPmxlZnQgPSBsZWZ0OwogICAgICAgIG5vZGUtPnJpZ2h0ID0gZmFjdG9yKCk7CiAgICAgICAgCiAgICAgICAgcmV0dXJuIHRlcm1fdGFpbChub2RlKTsKICAgIH0KICAgIGVsc2UKICAgICAgICByZXR1cm4gbGVmdDsKfQoKdm9pZCBlcnJvcihFcnJvclR5cGUgZXJyb3JOdW0pIHsKICAgIHN3aXRjaCAoZXJyb3JOdW0pIHsKICAgICAgICBjYXNlIE1JU1BBUkVOOgogICAgICAgICAgICBmcHJpbnRmKHN0ZGVyciwgIk1pc21hdGNoZWQgcGFyZW50aGVzaXNcbiIpOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIE5PVE5VTUlEOgogICAgICAgICAgICBmcHJpbnRmKHN0ZGVyciwgIk51bWJlciBvciBpZGVudGlmaWVyIGV4cGVjdGVkXG4iKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBOT1RGT1VORDoKICAgICAgICAgICAgZnByaW50ZihzdGRlcnIsICIlcyBub3QgZGVmaW5lZFxuIiwgZ2V0TGV4ZW1lKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFJVTk9VVDoKICAgICAgICAgICAgZnByaW50ZihzdGRlcnIsICJPdXQgb2YgbWVtb3J5XG4iKTsKICAgIH0KICAgIGV4aXQoMCk7Cn0K