fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. typedef struct label {
  6. char *name;
  7. short address;
  8. } Label;
  9.  
  10. typedef struct code {
  11. short opcode;
  12. short operand;
  13. int line_no;
  14. } Code;
  15.  
  16. enum { NOP, BEGIN, CALL, END, EXECUTE };
  17.  
  18. struct op {
  19. const char name[8];
  20. short code;
  21. } op_table[] = {
  22. { "BEGIN" , BEGIN },
  23. { "CALL" , CALL },
  24. { "END" , END },
  25. { "EXECUTE", EXECUTE },
  26. };
  27.  
  28. #define MEMSIZE 32767
  29. #define STACKSIZE 256
  30.  
  31. int lbl_count = 0;
  32. Label label[MEMSIZE];
  33. Code code[MEMSIZE];
  34. int stack[STACKSIZE];
  35. int sp = -1;
  36. int pc;
  37.  
  38. void print_stack(void);
  39. char *my_strdup(char *s);
  40.  
  41. int main(void){
  42. FILE *fp = stdin;//fopen("code.prg", "r");
  43. char line[128];
  44. int i;
  45. pc = 1;
  46.  
  47. //convert code
  48. while(fgets(line, sizeof line, fp)){
  49. int no;
  50. char opname[8], operand[16];
  51. int ret_scnf = sscanf(line, "%d %7s %15s", &no, opname, operand);
  52. struct op *op = bsearch(opname, op_table,
  53. sizeof(op_table)/ sizeof(*op_table), sizeof(*op_table),
  54. (int (*)(const void *, const void *))strcmp);
  55. if(!op){
  56. printf("unknown code\n");
  57. continue;
  58. }
  59. switch(op->code){
  60. case BEGIN:
  61. if(ret_scnf != 3){
  62. printf("%s : A name is necessary.\n", line);
  63. continue;
  64. }
  65. for(i = 0; i < lbl_count; ++i){
  66. if(strcmp(operand, label[i].name) == 0)
  67. break;
  68. }
  69. if(i != lbl_count){//found
  70. int wpc = label[i].address;
  71. label[i].address = pc;
  72. while(wpc < 0){//Follow the label address link
  73. int next = code[-wpc].operand;
  74. code[-wpc].operand = pc;
  75. if(next != wpc){
  76. wpc = next;
  77. } else {
  78. break;
  79. }
  80. }
  81. } else {//not found
  82. label[lbl_count].name = my_strdup(operand);//ret_scnf == 3
  83. label[lbl_count++].address = pc;
  84. }
  85. code[pc].operand = pc;
  86. break;
  87. case CALL:
  88. if(ret_scnf != 3){
  89. printf("%s : A name is necessary.\n", line);
  90. continue;
  91. }
  92. for(i = 0; i < lbl_count; ++i){
  93. if(strcmp(operand, label[i].name) == 0)
  94. break;
  95. }
  96. if(i != lbl_count){//found
  97. code[pc].operand = label[i].address;
  98. if(label[i].address < 0){
  99. label[i].address = -pc;
  100. }
  101. } else {//not found
  102. label[lbl_count].address = code[pc].operand = -pc;
  103. label[lbl_count++].name = my_strdup(operand);
  104. }
  105. break;
  106. case END:
  107. case EXECUTE:
  108. code[pc].operand = pc;//no operand
  109. break;
  110. }
  111. code[pc].line_no = no;
  112. code[pc++].opcode = op->code;
  113. }
  114. fclose(fp);
  115. //check unresolve and set start address
  116. pc = 0;
  117. for(i = 0; i < lbl_count; ++i){
  118. if(label[i].address < 0){
  119. printf("%s %d\n", label[i].name, label[i].address);
  120. printf("There are unresolved references.\n");
  121. exit(EXIT_FAILURE);
  122. }
  123. if(strcmp(label[i].name, "Main")==0)
  124. pc = label[i].address;
  125. free(label[i].name);
  126. }
  127. if(!pc){
  128. printf("'Main' does not exist.\n");
  129. exit(EXIT_FAILURE);
  130. }
  131. //execute code
  132. sp = -1;
  133. int end = 0;
  134. while(!end){
  135. Code curr = code[pc];
  136. printf("%d", curr.line_no);
  137. switch(curr.opcode){
  138. case BEGIN:
  139. case EXECUTE:
  140. ++pc;
  141. break;
  142. case CALL:
  143. stack[++sp] = pc;
  144. print_stack();
  145. pc = curr.operand;
  146. break;
  147. case END:
  148. if(sp == -1){
  149. printf(" --- END ---");
  150. end = 1;
  151. } else {
  152. pc = stack[sp--] + 1;//+1 : back to next statement
  153. print_stack();
  154. }
  155. }
  156. printf("\n");
  157. }
  158. }
  159.  
  160. void print_stack(void){
  161. printf(" Stack = ");
  162. for(int i = sp; i >= 0; --i){
  163. if(i != sp)
  164. printf(" ");
  165. printf("%d", stack[i]);
  166. }
  167. }
  168.  
  169. char *my_strdup(char *s){
  170. char *r = malloc(strlen(s)+1);
  171. if(r)
  172. strcpy(r, s);
  173. return r;
  174. }
Success #stdin #stdout 0s 10192KB
stdin
1 BEGIN Fun1  
2  CALL Fun2 
3  EXECUTE 
4 END  
5 BEGIN Fun2  
6  EXECUTE 
7 END  
8 BEGIN Main  
9  EXECUTE 
10  CALL Fun1 
11 END   
stdout
8
9
10 Stack = 10
1
2 Stack = 2 10
5
6
7 Stack = 10
3
4 Stack = 
11  --- END ---