#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct label {
char *name;
short address;
} Label;
typedef struct code {
short opcode;
short operand;
int line_no;
} Code;
enum { NOP, BEGIN, CALL, END, EXECUTE };
struct op {
const char name[8];
short code;
} op_table[] = {
{ "BEGIN" , BEGIN },
{ "CALL" , CALL },
{ "END" , END },
{ "EXECUTE", EXECUTE },
};
#define MEMSIZE 32767
#define STACKSIZE 256
int lbl_count = 0;
Label label[MEMSIZE];
Code code[MEMSIZE];
int stack[STACKSIZE];
int sp = -1;
int pc;
void print_stack(void);
char *my_strdup(char *s);
int main(void){
FILE *fp = stdin;//fopen("code.prg", "r");
char line[128];
int i;
pc = 1;
//convert code
while(fgets(line
, sizeof line
, fp
)){ int no;
char opname[8], operand[16];
int ret_scnf
= sscanf(line
, "%d %7s %15s", &no
, opname
, operand
); struct op
*op
= bsearch(opname
, op_table
, sizeof(op_table)/ sizeof(*op_table), sizeof(*op_table),
(int (*)(const void *, const void *))strcmp); if(!op){
continue;
}
switch(op->code){
case BEGIN:
if(ret_scnf != 3){
printf("%s : A name is necessary.\n", line
); continue;
}
for(i = 0; i < lbl_count; ++i){
if(strcmp(operand
, label
[i
].
name) == 0) break;
}
if(i != lbl_count){//found
int wpc = label[i].address;
label[i].address = pc;
while(wpc < 0){//Follow the label address link
int next = code[-wpc].operand;
code[-wpc].operand = pc;
if(next != wpc){
wpc = next;
} else {
break;
}
}
} else {//not found
label[lbl_count].name = my_strdup(operand);//ret_scnf == 3
label[lbl_count++].address = pc;
}
code[pc].operand = pc;
break;
case CALL:
if(ret_scnf != 3){
printf("%s : A name is necessary.\n", line
); continue;
}
for(i = 0; i < lbl_count; ++i){
if(strcmp(operand
, label
[i
].
name) == 0) break;
}
if(i != lbl_count){//found
code[pc].operand = label[i].address;
if(label[i].address < 0){
label[i].address = -pc;
}
} else {//not found
label[lbl_count].address = code[pc].operand = -pc;
label[lbl_count++].name = my_strdup(operand);
}
break;
case END:
case EXECUTE:
code[pc].operand = pc;//no operand
break;
}
code[pc].line_no = no;
code[pc++].opcode = op->code;
}
//check unresolve and set start address
pc = 0;
for(i = 0; i < lbl_count; ++i){
if(label[i].address < 0){
printf("%s %d\n", label
[i
].
name, label
[i
].
address); printf("There are unresolved references.\n"); }
if(strcmp(label
[i
].
name, "Main")==0) pc = label[i].address;
}
if(!pc){
printf("'Main' does not exist.\n"); }
//execute code
sp = -1;
int end = 0;
while(!end){
Code curr = code[pc];
switch(curr.opcode){
case BEGIN:
case EXECUTE:
++pc;
break;
case CALL:
stack[++sp] = pc;
print_stack();
pc = curr.operand;
break;
case END:
if(sp == -1){
end = 1;
} else {
pc = stack[sp--] + 1;//+1 : back to next statement
print_stack();
}
}
}
}
void print_stack(void){
for(int i = sp; i >= 0; --i){
if(i != sp)
}
}
char *my_strdup(char *s){
if(r)
return r;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKdHlwZWRlZiBzdHJ1Y3QgbGFiZWwgewoJY2hhciAqbmFtZTsKCXNob3J0IGFkZHJlc3M7Cn0gTGFiZWw7Cgp0eXBlZGVmIHN0cnVjdCBjb2RlIHsKCXNob3J0IG9wY29kZTsKCXNob3J0IG9wZXJhbmQ7CglpbnQgbGluZV9ubzsKfSBDb2RlOwoKZW51bSB7IE5PUCwgQkVHSU4sIENBTEwsIEVORCwgRVhFQ1VURSB9OwoKc3RydWN0IG9wIHsKCWNvbnN0IGNoYXIgbmFtZVs4XTsKCXNob3J0IGNvZGU7Cn0gb3BfdGFibGVbXSA9IHsKCXsgIkJFR0lOIiAgLCBCRUdJTiB9LAoJeyAiQ0FMTCIgICAsIENBTEwgfSwKCXsgIkVORCIgICAgLCBFTkQgfSwKCXsgIkVYRUNVVEUiLCBFWEVDVVRFIH0sCn07CgojZGVmaW5lIE1FTVNJWkUgMzI3NjcKI2RlZmluZSBTVEFDS1NJWkUgMjU2CgppbnQgbGJsX2NvdW50ID0gMDsKTGFiZWwgbGFiZWxbTUVNU0laRV07CkNvZGUgICBjb2RlW01FTVNJWkVdOwppbnQgICBzdGFja1tTVEFDS1NJWkVdOwppbnQgc3AgPSAtMTsKaW50IHBjOwoKdm9pZCBwcmludF9zdGFjayh2b2lkKTsKY2hhciAqbXlfc3RyZHVwKGNoYXIgKnMpOwoKaW50IG1haW4odm9pZCl7CglGSUxFICpmcCA9IHN0ZGluOy8vZm9wZW4oImNvZGUucHJnIiwgInIiKTsKCWNoYXIgbGluZVsxMjhdOwoJaW50IGk7CglwYyA9IDE7CgoJLy9jb252ZXJ0IGNvZGUKCXdoaWxlKGZnZXRzKGxpbmUsIHNpemVvZiBsaW5lLCBmcCkpewoJCWludCBubzsKCQljaGFyIG9wbmFtZVs4XSwgb3BlcmFuZFsxNl07CgkJaW50IHJldF9zY25mID0gc3NjYW5mKGxpbmUsICIlZCAlN3MgJTE1cyIsICZubywgb3BuYW1lLCBvcGVyYW5kKTsKCQlzdHJ1Y3Qgb3AgKm9wID0gYnNlYXJjaChvcG5hbWUsIG9wX3RhYmxlLAoJCQlzaXplb2Yob3BfdGFibGUpLyBzaXplb2YoKm9wX3RhYmxlKSwgc2l6ZW9mKCpvcF90YWJsZSksCgkJCShpbnQgKCopKGNvbnN0IHZvaWQgKiwgY29uc3Qgdm9pZCAqKSlzdHJjbXApOwoJCWlmKCFvcCl7CgkJCXByaW50ZigidW5rbm93biBjb2RlXG4iKTsKCQkJY29udGludWU7CgkJfQoJCXN3aXRjaChvcC0+Y29kZSl7CgkJY2FzZSBCRUdJTjoKCQkJaWYocmV0X3NjbmYgIT0gMyl7CgkJCQlwcmludGYoIiVzIDogQSBuYW1lIGlzIG5lY2Vzc2FyeS5cbiIsIGxpbmUpOwoJCQkJY29udGludWU7CgkJCX0KCQkJZm9yKGkgPSAwOyBpIDwgbGJsX2NvdW50OyArK2kpewoJCQkJaWYoc3RyY21wKG9wZXJhbmQsIGxhYmVsW2ldLm5hbWUpID09IDApCgkJCQkJYnJlYWs7CgkJCX0KCQkJaWYoaSAhPSBsYmxfY291bnQpey8vZm91bmQKCQkJCWludCB3cGMgPSBsYWJlbFtpXS5hZGRyZXNzOwoJCQkJbGFiZWxbaV0uYWRkcmVzcyA9IHBjOwoJCQkJd2hpbGUod3BjIDwgMCl7Ly9Gb2xsb3cgdGhlIGxhYmVsIGFkZHJlc3MgbGluawoJCQkJCWludCBuZXh0ID0gY29kZVstd3BjXS5vcGVyYW5kOwoJCQkJCWNvZGVbLXdwY10ub3BlcmFuZCA9IHBjOwoJCQkJCWlmKG5leHQgIT0gd3BjKXsKCQkJCQkJd3BjID0gbmV4dDsKCQkJCQl9IGVsc2UgewoJCQkJCQlicmVhazsKCQkJCQl9CgkJCQl9CgkJCX0gZWxzZSB7Ly9ub3QgZm91bmQKCQkJCWxhYmVsW2xibF9jb3VudF0ubmFtZSA9IG15X3N0cmR1cChvcGVyYW5kKTsvL3JldF9zY25mID09IDMKCQkJCWxhYmVsW2xibF9jb3VudCsrXS5hZGRyZXNzID0gcGM7CgkJCX0KCQkJY29kZVtwY10ub3BlcmFuZCA9IHBjOwoJCQlicmVhazsKCQljYXNlIENBTEw6CgkJCWlmKHJldF9zY25mICE9IDMpewoJCQkJcHJpbnRmKCIlcyA6IEEgbmFtZSBpcyBuZWNlc3NhcnkuXG4iLCBsaW5lKTsKCQkJCWNvbnRpbnVlOwoJCQl9CgkJCWZvcihpID0gMDsgaSA8IGxibF9jb3VudDsgKytpKXsKCQkJCWlmKHN0cmNtcChvcGVyYW5kLCBsYWJlbFtpXS5uYW1lKSA9PSAwKQoJCQkJCWJyZWFrOwoJCQl9CgkJCWlmKGkgIT0gbGJsX2NvdW50KXsvL2ZvdW5kCgkJCQljb2RlW3BjXS5vcGVyYW5kID0gbGFiZWxbaV0uYWRkcmVzczsKCQkJCWlmKGxhYmVsW2ldLmFkZHJlc3MgPCAwKXsKCQkJCQlsYWJlbFtpXS5hZGRyZXNzID0gLXBjOwoJCQkJfQoJCQl9IGVsc2Ugey8vbm90IGZvdW5kCgkJCQlsYWJlbFtsYmxfY291bnRdLmFkZHJlc3MgPSBjb2RlW3BjXS5vcGVyYW5kID0gLXBjOwoJCQkJbGFiZWxbbGJsX2NvdW50KytdLm5hbWUgPSBteV9zdHJkdXAob3BlcmFuZCk7CgkJCX0KCQkJYnJlYWs7CgkJY2FzZSBFTkQ6CgkJY2FzZSBFWEVDVVRFOgoJCQljb2RlW3BjXS5vcGVyYW5kID0gcGM7Ly9ubyBvcGVyYW5kCgkJCWJyZWFrOwoJCX0KCQljb2RlW3BjXS5saW5lX25vID0gbm87CgkJY29kZVtwYysrXS5vcGNvZGUgPSBvcC0+Y29kZTsKCX0KCWZjbG9zZShmcCk7CgkvL2NoZWNrIHVucmVzb2x2ZSBhbmQgc2V0IHN0YXJ0IGFkZHJlc3MKCXBjID0gMDsKCWZvcihpID0gMDsgaSA8IGxibF9jb3VudDsgKytpKXsKCQlpZihsYWJlbFtpXS5hZGRyZXNzIDwgMCl7CgkJCXByaW50ZigiJXMgJWRcbiIsIGxhYmVsW2ldLm5hbWUsIGxhYmVsW2ldLmFkZHJlc3MpOwoJCQlwcmludGYoIlRoZXJlIGFyZSB1bnJlc29sdmVkIHJlZmVyZW5jZXMuXG4iKTsKCQkJZXhpdChFWElUX0ZBSUxVUkUpOwoJCX0KCQlpZihzdHJjbXAobGFiZWxbaV0ubmFtZSwgIk1haW4iKT09MCkKCQkJcGMgPSBsYWJlbFtpXS5hZGRyZXNzOwoJCWZyZWUobGFiZWxbaV0ubmFtZSk7Cgl9CglpZighcGMpewoJCXByaW50ZigiJ01haW4nIGRvZXMgbm90IGV4aXN0LlxuIik7CgkJZXhpdChFWElUX0ZBSUxVUkUpOwoJfQoJLy9leGVjdXRlIGNvZGUKCXNwID0gLTE7CglpbnQgZW5kID0gMDsKCXdoaWxlKCFlbmQpewoJCUNvZGUgY3VyciA9IGNvZGVbcGNdOwoJCXByaW50ZigiJWQiLCBjdXJyLmxpbmVfbm8pOwoJCXN3aXRjaChjdXJyLm9wY29kZSl7CgkJY2FzZSBCRUdJTjoKCQljYXNlIEVYRUNVVEU6CgkJCSsrcGM7CgkJCWJyZWFrOwoJCWNhc2UgQ0FMTDoKCQkJc3RhY2tbKytzcF0gPSBwYzsKCQkJcHJpbnRfc3RhY2soKTsKCQkJcGMgPSBjdXJyLm9wZXJhbmQ7CgkJCWJyZWFrOwoJCWNhc2UgRU5EOgoJCQlpZihzcCA9PSAtMSl7CgkJCQlwcmludGYoIiAgLS0tIEVORCAtLS0iKTsKCQkJCWVuZCA9IDE7CgkJCX0gZWxzZSB7CgkJCQlwYyA9IHN0YWNrW3NwLS1dICsgMTsvLysxIDogYmFjayB0byBuZXh0IHN0YXRlbWVudAoJCQkJcHJpbnRfc3RhY2soKTsKCQkJfQoJCX0KCQlwcmludGYoIlxuIik7Cgl9Cn0KCnZvaWQgcHJpbnRfc3RhY2sodm9pZCl7CglwcmludGYoIiBTdGFjayA9ICIpOwoJZm9yKGludCBpID0gc3A7IGkgPj0gMDsgLS1pKXsKCQlpZihpICE9IHNwKQoJCQlwcmludGYoIiAiKTsKCQlwcmludGYoIiVkIiwgc3RhY2tbaV0pOwoJfQp9CgpjaGFyICpteV9zdHJkdXAoY2hhciAqcyl7CgljaGFyICpyID0gbWFsbG9jKHN0cmxlbihzKSsxKTsKCWlmKHIpCgkJc3RyY3B5KHIsIHMpOwoJcmV0dXJuIHI7Cn0=