/*
* スタックマシン?になっていればいいのだけれど・・・
*
* 1行目:
* 使う変数名列挙
* 変数名はアルファベット(A-Z)1文字で定義される
* (大文字小文字は区別されない、重複定義は許されない)
* アルファベット以外の文字は無視される
* 2行目以降:
* 変数への代入式 or 変数出力コマンド を 1行単位で書く
* 変数代入式は 変数名= で開始される
* 代入式右辺は 整数0-9 変数名A-Z 演算子*+-/ で構成され
* 上記以外の文字は許されない
* 編集出力コマンドは @変数名 で記述される
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/*
* 命令コード
*
* POP1 ... 1回目のpopで得られる値
* POP2 ... 2回目のpopで得られる値
*/
#define CMD_END (0) /* プログラムの終わり */
#define CMD_PUSH (1) /* 次のコードを値としてpushする */
#define CMD_LOAD (2) /* POP1のアドレスの変数の値をpushする */
#define CMD_PRINT (3) /* POP1の値を出力する */
#define CMD_ADD (4) /* POP2+POP1の結果をpushする */
#define CMD_SUB (5) /* POP2-POP1の結果をpushする */
#define CMD_MUL (6) /* POP2*POP1の結果をpushする */
#define CMD_DIV (7) /* POP2/POP1の結果をpushする */
#define CMD_STORE (8) /* POP1の値をPOP2のアドレスの変数へ格納する */
char cmd[][9] = {"END", "PUSH", "LOAD", "PRINT", "ADD",
"SUB", "MUL", "DIV", "STORE"};
/*
* 構文解析遷移状態
*/
#define TERM_DEF (0) /* 変数定義 */
#define TERM_TOP (1) /* 行頭 */
#define TERM_PRT (2) /* 出力変数名の読み込み */
#define TERM_SET (3) /* 代入文字=の読み込み */
#define TERM_NUM (4) /* 数字の読み込み */
#define TERM_SYB (5) /* 演算子の読み込み */
#define TERM_EXP (6) /* 式の開始の読み込み */
#define TERM_LF (99) /* 行末文字の読み込み*/
/*
* プログラム終了コード
*/
#define EXST_SUCCESS (0) /* 成功 */
#define EXST_RTERR (1) /* 実行時エラー */
#define EXST_NFEND (2) /* 終了命令なくプログラムの終了 */
#define SYNTAX_ERR (0)
int func1(FILE*,int[]); /* ソースコードをコンパイルする */
void func2(int[], int); /* コンパイルされたコードを出力する */
int func3(int[], int); /* コンパイルされたコードを実行する */
int main(void)
{
int p[1000] = {0};
int c, r;
c = func1(stdin, p);
if (c == SYNTAX_ERR)
{
return 0;
}
r = func3(p, c);
switch (r)
{
case EXST_SUCCESS:
{
break;
}
case EXST_RTERR:
{
break;
}
case EXST_NFEND:
{
printf("Not found END command\n"); break;
}
}
func2(p, c);
return 0;
}
int func1(FILE *file, int p[])
{
int w[100];
int v[30] = {0};
int c, i = 0, bi = 0, j, wi = 0;
int t = TERM_DEF;
int vr = 0, nm;
while ((c
= getc(file
)) != EOF
) {
switch (t)
{
case TERM_DEF:
{
if (c == '\n')
{
if (i == 0)
{
return SYNTAX_ERR;
}
p[bi++] = i;
for (j = 0; j < i; j++)
{
p[bi++] = 0;
}
t = TERM_TOP;
}
{
if (v[vr] != 0)
{
printf("term: %d, %c\n", t
, c
); return SYNTAX_ERR;
}
v[vr] = ++i;
}
break;
}
case TERM_TOP:
{
if (c == '@')
{
t = TERM_PRT;
}
{
if (v[vr] == 0)
{
printf("term: %d, char '%c'\n", t
, c
); return SYNTAX_ERR;
}
p[bi++] = CMD_PUSH;
p[bi++] = v[vr];
t = TERM_SET;
}
else
{
printf("term: %d, char '%c'\n", t
, c
); return SYNTAX_ERR;
}
break;
}
case TERM_PRT:
{
{
if (v[vr] == 0)
{
printf("term: %d, char '%c'\n", t
, c
); return SYNTAX_ERR;
}
p[bi++] = CMD_PUSH;
p[bi++] = v[vr];
p[bi++] = CMD_LOAD;
p[bi++] = CMD_PRINT;
t = TERM_LF;
}
else
{
printf("term: %d, char '%c'\n", t
, c
); return SYNTAX_ERR;
}
break;
}
case TERM_SET:
{
if (c == '=')
{
t = TERM_EXP;
}
else
{
printf("term: %d, char '%c'\n", t
, c
); return SYNTAX_ERR;
}
break;
}
case TERM_EXP:
{
{
if (v[vr] == 0)
{
printf("term: %d, char '%c'\n", t
, c
); return SYNTAX_ERR;
}
p[bi++] = CMD_PUSH;
p[bi++] = v[vr];
p[bi++] = CMD_LOAD;
t = TERM_SYB;
}
{
nm = c - '0';
t = TERM_NUM;
}
else
{
printf("term: %d, char '%c'\n", t
, c
); return SYNTAX_ERR;
}
break;
}
case TERM_SYB:
{
switch (c)
{
case '+':
case '-':
{
while (wi > 0)
{
p[bi++] = w[wi--];
}
w[++wi] = c == '+' ? CMD_ADD : CMD_SUB;
t = TERM_EXP;
break;
}
case '*':
case '/':
{
while (w[wi] == '*' || w[wi] == '/')
{
p[bi++] = w[wi--];
}
w[++wi] = c == '*' ? CMD_MUL : CMD_DIV;
t = TERM_EXP;
break;
}
case '\n':
{
while (wi > 0)
{
p[bi++] = w[wi--];
}
p[bi++] = CMD_STORE;
t = TERM_TOP;
break;
}
default:
{
printf("term: %d, char '%c'\n", t
, c
); return SYNTAX_ERR;
}
}
break;
}
case TERM_NUM:
{
{
nm = nm * 10 + (c - '0');
}
else
{
p[bi++] = CMD_PUSH;
p[bi++] = nm;
switch (c)
{
case '+':
case '-':
{
while (wi > 0)
{
p[bi++] = w[wi--];
}
w[++wi] = c == '+' ? CMD_ADD : CMD_SUB;
t = TERM_EXP;
break;
}
case '*':
case '/':
{
while (w[wi] == '*' || w[wi] == '/')
{
p[bi++] = w[wi--];
}
w[++wi] = c == '*' ? CMD_MUL : CMD_DIV;
t = TERM_EXP;
break;
}
case '\n':
{
while (wi > 0)
{
p[bi++] = w[wi--];
}
p[bi++] = CMD_STORE;
t = TERM_TOP;
break;
}
default:
{
printf("term: %d, char '%c'\n", t
, c
); return SYNTAX_ERR;
}
}
}
break;
}
case TERM_LF:
{
if (c == '\n')
{
t = TERM_TOP;
}
else
{
printf("term: %d, char '%c'\n", t
, c
); return SYNTAX_ERR;
}
break;
}
}
}
switch (t)
{
case TERM_NUM:
{
p[bi++] = CMD_PUSH;
p[bi++] = nm;
}
case TERM_SYB:
{
while (wi > 0)
{
p[bi++] = w[wi--];
}
break;
}
case TERM_LF:
case TERM_TOP:
{
break;
}
default:
{
return SYNTAX_ERR;
}
}
p[bi++] = CMD_END;
return bi;
}
void func2(int p[], int c)
{
int i;
int t = 0;
int n;
n = p[0];
printf("%03d VAR COUNT: %d\n", 0, n
); for (i = 0; i < n; i++)
{
printf("%03d VAR AREA: %d\n", i
+ 1, i
+ 1); }
for (i = n + 1; i < c; i++)
{
if (t)
{
printf("%03d DATA: %d\n", i
, p
[i
]); t = 0;
}
else
{
printf("%03d CMD: %s\n", i
, cmd
[p
[i
]]); if (p[i] == CMD_PUSH)
{
t = 1;
}
}
}
}
int func3(int p[], int c)
{
int s[1000];
int si = 0;
int i;
for (i = p[0] + 1; i < c; i++)
{
switch (p[i])
{
case CMD_END:
{
return EXST_SUCCESS;
}
case CMD_PUSH:
{
s[++si] = p[++i];
break;
}
case CMD_LOAD:
{
s[si] = p[s[si]];
break;
}
case CMD_STORE:
{
p[s[si - 1]] = s[si];
si -= 2;
break;
}
case CMD_ADD:
{
s[si - 1] += s[si];
si--;
break;
}
case CMD_SUB:
{
s[si - 1] -= s[si];
si--;
break;
}
case CMD_MUL:
{
s[si - 1] *= s[si];
si--;
break;
}
case CMD_DIV:
{
s[si - 1] /= s[si];
si--;
break;
}
case CMD_PRINT:
{
break;
}
default:
{
return EXST_RTERR;
}
}
}
return EXST_NFEND;
}
LyoKICog44K544K/44OD44Kv44Oe44K344Oz77yf44Gr44Gq44Gj44Gm44GE44KM44Gw44GE44GE44Gu44Gg44GR44KM44Gp44O744O744O7CiAqCiAqIDHooYznm646CiAqCQnkvb/jgYblpInmlbDlkI3liJfmjJkKICogCQnlpInmlbDlkI3jga/jgqLjg6vjg5XjgqHjg5njg4Pjg4goQS1aKe+8keaWh+Wtl+OBp+Wumue+qeOBleOCjOOCiwogKgkJKOWkp+aWh+Wtl+Wwj+aWh+Wtl+OBr+WMuuWIpeOBleOCjOOBquOBhOOAgemHjeikh+Wumue+qeOBr+ioseOBleOCjOOBquOBhCkKICoJCeOCouODq+ODleOCoeODmeODg+ODiOS7peWkluOBruaWh+Wtl+OBr+eEoeimluOBleOCjOOCiwogKiAy6KGM55uu5Lul6ZmNOgogKgkJ5aSJ5pWw44G444Gu5Luj5YWl5byPIG9yIOWkieaVsOWHuuWKm+OCs+ODnuODs+ODiSDjgpIgMeihjOWNmOS9jeOBp+abuOOBjwogKgkJ5aSJ5pWw5Luj5YWl5byP44GvIOWkieaVsOWQjT0g44Gn6ZaL5aeL44GV44KM44KLCiAqICAgICAgCeS7o+WFpeW8j+WPs+i+uuOBryDmlbTmlbAwLTkg5aSJ5pWw5ZCNQS1aIOa8lOeul+WtkCorLS8g44Gn5qeL5oiQ44GV44KMCiAqICAgICAgCeS4iuiomOS7peWkluOBruaWh+Wtl+OBr+ioseOBleOCjOOBquOBhAogKiAgICAgIOe3qOmbhuWHuuWKm+OCs+ODnuODs+ODieOBryBA5aSJ5pWw5ZCNIOOBp+iomOi/sOOBleOCjOOCiwogKi8KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPGN0eXBlLmg+CgovKgogKiDlkb3ku6TjgrPjg7zjg4kKICoKICogUE9QMSAuLi4gMeWbnuebruOBrnBvcOOBp+W+l+OCieOCjOOCi+WApAogKiBQT1AyIC4uLiAy5Zue55uu44GucG9w44Gn5b6X44KJ44KM44KL5YCkCiAqLwojZGVmaW5lIENNRF9FTkQJCSgwKQkvKiDjg5fjg63jgrDjg6njg6Djga7ntYLjgo/jgoogKi8KI2RlZmluZSBDTURfUFVTSCAgCSgxKSAvKiDmrKHjga7jgrPjg7zjg4njgpLlgKTjgajjgZfjgaZwdXNo44GZ44KLICovCiNkZWZpbmUgQ01EX0xPQUQgIAkoMikgLyogUE9QMeOBruOCouODieODrOOCueOBruWkieaVsOOBruWApOOCknB1c2jjgZnjgosgKi8KI2RlZmluZSBDTURfUFJJTlQgCSgzKSAvKiBQT1Ax44Gu5YCk44KS5Ye65Yqb44GZ44KLICovCiNkZWZpbmUgQ01EX0FERAkJKDQpIC8qIFBPUDIrUE9QMeOBrue1kOaenOOCknB1c2jjgZnjgosgKi8KI2RlZmluZSBDTURfU1VCCQkoNSkgLyogUE9QMi1QT1Ax44Gu57WQ5p6c44KScHVzaOOBmeOCiyAqLwojZGVmaW5lIENNRF9NVUwJCSg2KSAvKiBQT1AyKlBPUDHjga7ntZDmnpzjgpJwdXNo44GZ44KLICovCiNkZWZpbmUgQ01EX0RJVgkJKDcpIC8qIFBPUDIvUE9QMeOBrue1kOaenOOCknB1c2jjgZnjgosgKi8KI2RlZmluZSBDTURfU1RPUkUJKDgpIC8qIFBPUDHjga7lgKTjgpJQT1Ay44Gu44Ki44OJ44Os44K544Gu5aSJ5pWw44G45qC857SN44GZ44KLICovCgpjaGFyIGNtZFtdWzldID0geyJFTkQiLCAiUFVTSCIsICJMT0FEIiwgIlBSSU5UIiwgIkFERCIsCgkiU1VCIiwgIk1VTCIsICJESVYiLCAiU1RPUkUifTsKCi8qCiAqIOani+aWh+ino+aekOmBt+enu+eKtuaFiwogKi8KI2RlZmluZSBURVJNX0RFRiAgCSgwKSAvKiDlpInmlbDlrprnvqkgKi8KI2RlZmluZSBURVJNX1RPUCAgCSgxKSAvKiDooYzpoK0gKi8KI2RlZmluZSBURVJNX1BSVCAgCSgyKSAvKiDlh7rlipvlpInmlbDlkI3jga7oqq3jgb/ovrzjgb8gKi8KI2RlZmluZSBURVJNX1NFVCAgCSgzKSAvKiDku6PlhaXmloflrZc944Gu6Kqt44G/6L6844G/ICovCiNkZWZpbmUgVEVSTV9OVU0JKDQpIC8qIOaVsOWtl+OBruiqreOBv+i+vOOBvyAqLwojZGVmaW5lIFRFUk1fU1lCCSg1KSAvKiDmvJTnrpflrZDjga7oqq3jgb/ovrzjgb8gKi8KI2RlZmluZSBURVJNX0VYUAkoNikgLyog5byP44Gu6ZaL5aeL44Gu6Kqt44G/6L6844G/ICovCiNkZWZpbmUgVEVSTV9MRiAgIAkoOTkpIC8qIOihjOacq+aWh+Wtl+OBruiqreOBv+i+vOOBvyovCgovKgogKiDjg5fjg63jgrDjg6njg6DntYLkuobjgrPjg7zjg4kKICovCiNkZWZpbmUgRVhTVF9TVUNDRVNTCSgwKSAvKiDmiJDlip8gKi8KI2RlZmluZSBFWFNUX1JURVJSCQkoMSkgLyog5a6f6KGM5pmC44Ko44Op44O8ICovCiNkZWZpbmUgRVhTVF9ORkVORAkJKDIpIC8qIOe1guS6huWRveS7pOOBquOBj+ODl+ODreOCsOODqeODoOOBrue1guS6hiAqLwoKI2RlZmluZSBTWU5UQVhfRVJSICgwKQoKaW50IGZ1bmMxKEZJTEUqLGludFtdKTsJLyog44K944O844K544Kz44O844OJ44KS44Kz44Oz44OR44Kk44Or44GZ44KLICovCnZvaWQgZnVuYzIoaW50W10sIGludCk7CS8qIOOCs+ODs+ODkeOCpOODq+OBleOCjOOBn+OCs+ODvOODieOCkuWHuuWKm+OBmeOCiyAqLwppbnQgZnVuYzMoaW50W10sIGludCk7CS8qIOOCs+ODs+ODkeOCpOODq+OBleOCjOOBn+OCs+ODvOODieOCkuWun+ihjOOBmeOCiyAqLyAKCmludCBtYWluKHZvaWQpCnsKCWludCBwWzEwMDBdID0gezB9OwoJaW50IGMsIHI7CgkKCWMgPSBmdW5jMShzdGRpbiwgcCk7CgoJaWYgKGMgPT0gU1lOVEFYX0VSUikKCXsKCQlwcmludGYoIlN5bnRheCBFcnJvclxuIik7CgkJcmV0dXJuIDA7Cgl9CglwcmludGYoIi0tUmVzdWx0LS1cbiIpOwoJciA9IGZ1bmMzKHAsIGMpOwoJcHJpbnRmKCItLUV4aXQgU3RhdHVzLS1cbiIpOwoJc3dpdGNoIChyKQoJewoJCWNhc2UgRVhTVF9TVUNDRVNTOgoJCXsKCQkJcHJpbnRmKCJTdWNjZXNzXG4iKTsKCQkJYnJlYWs7CgkJfQoJCWNhc2UgRVhTVF9SVEVSUjoKCQl7CgkJCXByaW50ZigiUnVudGltZSBFcnJvclxuIik7CgkJCWJyZWFrOwoJCX0KCQljYXNlIEVYU1RfTkZFTkQ6CgkJewoJCQlwcmludGYoIk5vdCBmb3VuZCBFTkQgY29tbWFuZFxuIik7CgkJCWJyZWFrOwoJCX0KCX0KCXByaW50ZigiLS1Qcm9ncmFtIENvZGUtLVxuIik7CglmdW5jMihwLCBjKTsKCQoJcmV0dXJuIDA7Cn0KCmludCBmdW5jMShGSUxFICpmaWxlLCBpbnQgcFtdKQp7CglpbnQgd1sxMDBdOwoJaW50IHZbMzBdID0gezB9OwoJaW50IGMsIGkgPSAwLCBiaSA9IDAsIGosIHdpID0gMDsKCWludCB0ID0gVEVSTV9ERUY7CglpbnQgdnIgPSAwLCBubTsKCXdoaWxlICgoYyA9IGdldGMoZmlsZSkpICE9IEVPRikKCXsKCQlzd2l0Y2ggKHQpCgkJewoJCQljYXNlIFRFUk1fREVGOgoJCQl7CgkJCQlpZiAoYyA9PSAnXG4nKQoJCQkJewoJCQkJCWlmIChpID09IDApCgkJCQkJewoJCQkJCQlwcmludGYoInRlcm06ICVkXG4iLCB0KTsKCQkJCQkJcmV0dXJuIFNZTlRBWF9FUlI7CgkJCQkJfQoJCQkJCXBbYmkrK10gPSBpOwoJCQkJCWZvciAoaiA9IDA7IGogPCBpOyBqKyspCgkJCQkJewoJCQkJCQlwW2JpKytdID0gMDsKCQkJCQl9CgkJCQkJdCA9IFRFUk1fVE9QOwoJCQkJfQoJCQkJZWxzZSBpZiAoaXNhbHBoYShjKSkKCQkJCXsKCQkJCQl2ciA9IHRvdXBwZXIoYykgLSAnQSc7CgkJCQkJaWYgKHZbdnJdICE9IDApCgkJCQkJewoJCQkJCQlwcmludGYoInRlcm06ICVkLCAlY1xuIiwgdCwgYyk7CgkJCQkJCXJldHVybiBTWU5UQVhfRVJSOwoJCQkJCX0KCQkJCQl2W3ZyXSA9ICsraTsKCQkJCX0KCQkJCWJyZWFrOwoJCQl9CgkJCWNhc2UgVEVSTV9UT1A6CQoJCQl7CgkJCQlpZiAoYyA9PSAnQCcpCgkJCQl7CgkJCQkJdCA9IFRFUk1fUFJUOwoJCQkJfQoJCQkJZWxzZSBpZiAoaXNhbHBoYShjKSkKCQkJCXsKCQkJCQl2ciA9IHRvdXBwZXIoYykgLSAnQSc7CgkJCQkJaWYgKHZbdnJdID09IDApCgkJCQkJewoJCQkJCQlwcmludGYoInRlcm06ICVkLCBjaGFyICclYydcbiIsIHQsIGMpOwoJCQkJCQlyZXR1cm4gU1lOVEFYX0VSUjsKCQkJCQl9CgkJCQkJcFtiaSsrXSA9IENNRF9QVVNIOwoJCQkJCXBbYmkrK10gPSB2W3ZyXTsKCQkJCQl0ID0gVEVSTV9TRVQ7CgkJCQl9CgkJCQllbHNlCgkJCQl7CgkJCQkJcHJpbnRmKCJ0ZXJtOiAlZCwgY2hhciAnJWMnXG4iLCB0LCBjKTsKCQkJCQlyZXR1cm4gU1lOVEFYX0VSUjsKCQkJCX0KCQkJCWJyZWFrOwoJCQl9CgkJCWNhc2UgVEVSTV9QUlQ6CgkJCXsKCQkJCWlmIChpc2FscGhhKGMpKQoJCQkJewoJCQkJCXZyID0gdG91cHBlcihjKSAtICdBJzsKCQkJCQlpZiAodlt2cl0gPT0gMCkKCQkJCQl7CgkJCQkJCXByaW50ZigidGVybTogJWQsIGNoYXIgJyVjJ1xuIiwgdCwgYyk7CgkJCQkJCXJldHVybiBTWU5UQVhfRVJSOwoJCQkJCX0KCQkJCQlwW2JpKytdID0gQ01EX1BVU0g7CgkJCQkJcFtiaSsrXSA9IHZbdnJdOwoJCQkJCXBbYmkrK10gPSBDTURfTE9BRDsKCQkJCQlwW2JpKytdID0gQ01EX1BSSU5UOwoJCQkJCXQgPSBURVJNX0xGOwoJCQkJfQoJCQkJZWxzZQoJCQkJewoJCQkJCXByaW50ZigidGVybTogJWQsIGNoYXIgJyVjJ1xuIiwgdCwgYyk7CgkJCQkJcmV0dXJuIFNZTlRBWF9FUlI7CgkJCQl9CgkJCQlicmVhazsKCQkJfQoJCQljYXNlIFRFUk1fU0VUOgoJCQl7CgkJCQlpZiAoYyA9PSAnPScpCgkJCQl7CgkJCQkJdCA9IFRFUk1fRVhQOwoJCQkJfQoJCQkJZWxzZQoJCQkJewoJCQkJCXByaW50ZigidGVybTogJWQsIGNoYXIgJyVjJ1xuIiwgdCwgYyk7CgkJCQkJcmV0dXJuIFNZTlRBWF9FUlI7CgkJCQl9CgkJCQlicmVhazsKCQkJfQoJCQljYXNlIFRFUk1fRVhQOgoJCQl7CgkJCQlpZiAoaXNhbHBoYShjKSkKCQkJCXsKCQkJCQl2ciA9IHRvdXBwZXIoYykgLSAnQSc7CgkJCQkJaWYgKHZbdnJdID09IDApCgkJCQkJewoJCQkJCQlwcmludGYoInRlcm06ICVkLCBjaGFyICclYydcbiIsIHQsIGMpOwoJCQkJCQlyZXR1cm4gU1lOVEFYX0VSUjsKCQkJCQl9CgkJCQkJcFtiaSsrXSA9IENNRF9QVVNIOwoJCQkJCXBbYmkrK10gPSB2W3ZyXTsKCQkJCQlwW2JpKytdID0gQ01EX0xPQUQ7CgkJCQkJdCA9IFRFUk1fU1lCOwoJCQkJfQoJCQkJZWxzZSBpZiAoaXNkaWdpdChjKSkKCQkJCXsKCQkJCQlubSA9IGMgLSAnMCc7CgkJCQkJdCA9IFRFUk1fTlVNOwoJCQkJfQoJCQkJZWxzZQoJCQkJewoJCQkJCXByaW50ZigidGVybTogJWQsIGNoYXIgJyVjJ1xuIiwgdCwgYyk7CgkJCQkJcmV0dXJuIFNZTlRBWF9FUlI7CgkJCQl9CgkJCQlicmVhazsKCQkJfQoJCQljYXNlIFRFUk1fU1lCOgoJCQl7CgkJCQlzd2l0Y2ggKGMpCgkJCQl7CgkJCQkJY2FzZSAnKyc6CgkJCQkJY2FzZSAnLSc6CgkJCQkJewoJCQkJCQl3aGlsZSAod2kgPiAwKQoJCQkJCQl7CgkJCQkJCQlwW2JpKytdID0gd1t3aS0tXTsKCQkJCQkJfQoJCQkJCQl3Wysrd2ldID0gYyA9PSAnKycgPyBDTURfQUREIDogQ01EX1NVQjsKCQkJCQkJdCA9IFRFUk1fRVhQOwoJCQkJCQlicmVhazsKCQkJCQl9CgkJCQkJY2FzZSAnKic6CgkJCQkJY2FzZSAnLyc6CgkJCQkJewoJCQkJCQl3aGlsZSAod1t3aV0gPT0gJyonIHx8IHdbd2ldID09ICcvJykKCQkJCQkJewoJCQkJCQkJcFtiaSsrXSA9IHdbd2ktLV07CgkJCQkJCX0KCQkJCQkJd1srK3dpXSA9IGMgPT0gJyonID8gQ01EX01VTCA6IENNRF9ESVY7CgkJCQkJCXQgPSBURVJNX0VYUDsKCQkJCQkJYnJlYWs7CgkJCQkJfQoJCQkJCWNhc2UgJ1xuJzoKCQkJCQl7CgkJCQkJCXdoaWxlICh3aSA+IDApCgkJCQkJCXsKCQkJCQkJCXBbYmkrK10gPSB3W3dpLS1dOwoJCQkJCQl9CgkJCQkJCXBbYmkrK10gPSBDTURfU1RPUkU7CgkJCQkJCXQgPSBURVJNX1RPUDsKCQkJCQkJYnJlYWs7CgkJCQkJfQoJCQkJCWRlZmF1bHQ6CgkJCQkJewoJCQkJCQlwcmludGYoInRlcm06ICVkLCBjaGFyICclYydcbiIsIHQsIGMpOwoJCQkJCQlyZXR1cm4gU1lOVEFYX0VSUjsKCQkJCQl9CgkJCQl9CgkJCQlicmVhazsKCQkJfQoJCQljYXNlIFRFUk1fTlVNOgoJCQl7CgkJCQlpZiAoaXNkaWdpdChjKSkKCQkJCXsKCQkJCQlubSA9IG5tICogMTAgKyAoYyAtICcwJyk7CgkJCQl9CgkJCQllbHNlCgkJCQl7CgkJCQkJcFtiaSsrXSA9IENNRF9QVVNIOwoJCQkJCXBbYmkrK10gPSBubTsKCQkJCQlzd2l0Y2ggKGMpCgkJCQkJewoJCQkJCQljYXNlICcrJzoKCQkJCQkJY2FzZSAnLSc6CgkJCQkJCXsKCQkJCQkJCXdoaWxlICh3aSA+IDApCgkJCQkJCQl7CgkJCQkJCQkJcFtiaSsrXSA9IHdbd2ktLV07CgkJCQkJCQl9CgkJCQkJCQl3Wysrd2ldID0gYyA9PSAnKycgPyBDTURfQUREIDogQ01EX1NVQjsKCQkJCQkJCXQgPSBURVJNX0VYUDsKCQkJCQkJCWJyZWFrOwoJCQkJCQl9CgkJCQkJCWNhc2UgJyonOgoJCQkJCQljYXNlICcvJzoKCQkJCQkJewoJCQkJCQkJd2hpbGUgKHdbd2ldID09ICcqJyB8fCB3W3dpXSA9PSAnLycpCgkJCQkJCQl7CgkJCQkJCQkJcFtiaSsrXSA9IHdbd2ktLV07CgkJCQkJCQl9CgkJCQkJCQl3Wysrd2ldID0gYyA9PSAnKicgPyBDTURfTVVMIDogQ01EX0RJVjsKCQkJCQkJCXQgPSBURVJNX0VYUDsKCQkJCQkJCWJyZWFrOwoJCQkJCQl9CgkJCQkJCWNhc2UgJ1xuJzoKCQkJCQkJewoJCQkJCQkJd2hpbGUgKHdpID4gMCkKCQkJCQkJCXsKCQkJCQkJCQlwW2JpKytdID0gd1t3aS0tXTsKCQkJCQkJCX0KCQkJCQkJCXBbYmkrK10gPSBDTURfU1RPUkU7CgkJCQkJCQl0ID0gVEVSTV9UT1A7CgkJCQkJCQlicmVhazsKCQkJCQkJfQoJCQkJCQlkZWZhdWx0OgoJCQkJCQl7CgkJCQkJCQlwcmludGYoInRlcm06ICVkLCBjaGFyICclYydcbiIsIHQsIGMpOwoJCQkJCQkJcmV0dXJuIFNZTlRBWF9FUlI7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCQlicmVhazsKCQkJfQoJCQljYXNlIFRFUk1fTEY6CgkJCXsKCQkJCWlmIChjID09ICdcbicpCgkJCQl7CgkJCQkJdCA9IFRFUk1fVE9QOwoJCQkJfQoJCQkJZWxzZQoJCQkJewoJCQkJCXByaW50ZigidGVybTogJWQsIGNoYXIgJyVjJ1xuIiwgdCwgYyk7CgkJCQkJcmV0dXJuIFNZTlRBWF9FUlI7CgkJCQl9CgkJCQlicmVhazsKCQkJfQoJCX0KCgl9CgkKCXN3aXRjaCAodCkKCXsKCQljYXNlIFRFUk1fTlVNOgoJCXsKCQkJcFtiaSsrXSA9IENNRF9QVVNIOwoJCQlwW2JpKytdID0gbm07CgkJfQoJCWNhc2UgVEVSTV9TWUI6CgkJewoJCQl3aGlsZSAod2kgPiAwKQoJCQl7CgkJCQlwW2JpKytdID0gd1t3aS0tXTsKCQkJfQoJCQlicmVhazsKCQl9CgkJY2FzZSBURVJNX0xGOgoJCWNhc2UgVEVSTV9UT1A6CgkJewoJCQlicmVhazsKCQl9CgkJZGVmYXVsdDoKCQl7CgkJCXJldHVybiBTWU5UQVhfRVJSOwoJCX0KCX0KCQoJcFtiaSsrXSA9IENNRF9FTkQ7CgkKCXJldHVybiBiaTsKfQoKdm9pZCBmdW5jMihpbnQgcFtdLCBpbnQgYykKewoJaW50IGk7CglpbnQgdCA9IDA7CglpbnQgbjsKCW4gPSBwWzBdOwoJcHJpbnRmKCIlMDNkIFZBUiBDT1VOVDogJWRcbiIsIDAsIG4pOwoJZm9yIChpID0gMDsgaSA8IG47IGkrKykKCXsKCQlwcmludGYoIiUwM2QgVkFSIEFSRUE6ICVkXG4iLCBpICsgMSwgaSArIDEpOwkKCX0KCQoJZm9yIChpID0gbiArIDE7IGkgPCBjOyBpKyspCgl7CgkJaWYgKHQpCgkJewoJCQlwcmludGYoIiUwM2QgREFUQTogJWRcbiIsIGksIHBbaV0pOwoJCQl0ID0gMDsJCgkJfQoJCWVsc2UKCQl7CgkJCXByaW50ZigiJTAzZCBDTUQ6ICVzXG4iLCBpLCBjbWRbcFtpXV0pOwoJCQlpZiAocFtpXSA9PSBDTURfUFVTSCkKCQkJewoJCQkJdCA9IDE7CgkJCX0KCQl9Cgl9Cn0KCmludCBmdW5jMyhpbnQgcFtdLCBpbnQgYykKewoJaW50IHNbMTAwMF07CglpbnQgc2kgPSAwOwoJaW50IGk7Cglmb3IgKGkgPSBwWzBdICsgMTsgaSA8IGM7IGkrKykKCXsKCQlzd2l0Y2ggKHBbaV0pCgkJewoJCQljYXNlIENNRF9FTkQ6CgkJCXsKCQkJCXJldHVybiBFWFNUX1NVQ0NFU1M7CgkJCX0KCQkJY2FzZSBDTURfUFVTSDoKCQkJewoJCQkJc1srK3NpXSA9IHBbKytpXTsKCQkJCWJyZWFrOwoJCQl9CgkJCWNhc2UgQ01EX0xPQUQ6CgkJCXsKCQkJCXNbc2ldID0gcFtzW3NpXV07CgkJCQlicmVhazsKCQkJfQoJCQljYXNlIENNRF9TVE9SRToKCQkJewoJCQkJcFtzW3NpIC0gMV1dID0gc1tzaV07CgkJCQlzaSAtPSAyOwoJCQkJYnJlYWs7CgkJCX0KCQkJY2FzZSBDTURfQUREOgoJCQl7CgkJCQlzW3NpIC0gMV0gKz0gc1tzaV07CgkJCQlzaS0tOwoJCQkJYnJlYWs7CgkJCX0KCQkJY2FzZSBDTURfU1VCOgoJCQl7CgkJCQlzW3NpIC0gMV0gLT0gc1tzaV07CgkJCQlzaS0tOwoJCQkJYnJlYWs7CgkJCX0KCQkJY2FzZSBDTURfTVVMOgoJCQl7CgkJCQlzW3NpIC0gMV0gKj0gc1tzaV07CgkJCQlzaS0tOwoJCQkJYnJlYWs7CgkJCX0KCQkJY2FzZSBDTURfRElWOgoJCQl7CgkJCQlzW3NpIC0gMV0gLz0gc1tzaV07CgkJCQlzaS0tOwoJCQkJYnJlYWs7CgkJCX0KCQkJY2FzZSBDTURfUFJJTlQ6CgkJCXsKCQkJCXByaW50ZigiJWRcbiIsIHNbc2ktLV0pOwoJCQkJYnJlYWs7CgkJCX0KCQkJZGVmYXVsdDoKCQkJewoJCQkJcmV0dXJuIEVYU1RfUlRFUlI7CgkJCX0KCQl9Cgl9CglyZXR1cm4gRVhTVF9ORkVORDsKfQo=