training

Code I wrote during training
git clone git://git.bitsmanent.org/training
Log | Files | Refs | README

esimpletron.c (9799B)


      1 /* Exercise 7.29 */
      2 
      3 /* The Extended Simpletron (and LMS) implementation */
      4 
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 #include <math.h>
      9 
     10 #define MEMSIZE 1000
     11 #define MAXWORD 7
     12 
     13 /* Input/Output */
     14 #define READ   10
     15 #define WRITE  11
     16 #define NEWLINE 12
     17 #define SREAD 13
     18 #define SWRITE 14
     19 
     20 /* Loading/Storing */
     21 #define LOAD  20
     22 #define STORE 21
     23 
     24 /* Arithmetical */
     25 #define ADD      30
     26 #define SUBTRACT 31
     27 #define DIVIDE   32
     28 #define MULTIPLY 33
     29 #define REST     34
     30 #define POWER    35
     31 
     32 /* Reference and control */
     33 #define BRANCH     40
     34 #define BRANCHNEG  41
     35 #define BRANCHZERO 42
     36 #define HALT       43
     37 
     38 int checkword(int word, int size);
     39 void dump(float acc, int icounter, float mem[]);
     40 int r_htoi(const char string[]);
     41 char * p_itoh(int num, char str[], int z);
     42 
     43 int main(void)
     44 {
     45    char s_mem[MAXWORD] = { 0 };
     46    float memory[MEMSIZE] = { 0 }, accumulator = 0;
     47 
     48    int operationCode = 0, instructionRegister = 0, operand = 0;
     49    int i, j, k, err = 0;
     50    float t_val = 0, f_tmp;
     51 
     52    printf("*** Welcome to the Simpletron! ***\n"
     53 	  "*** Please enter your program one instruction ***\n"
     54 	  "*** (or data word) at a time. I will type the ***\n"
     55 	  "*** location number and a question mark (?).  ***\n"
     56 	  "*** You then type the word for that location. ***\n"
     57 	  "*** Use the sentinel -999999 to stop entering ***\n"
     58 	  "*** your program. ***\n");
     59 
     60    for(i = 0; i < MEMSIZE; i++) {
     61       while(1) {
     62          printf("%.2d ?? ", i);
     63          scanf("%s", s_mem);
     64 
     65 	 memory[i] = r_htoi(s_mem);
     66 
     67 	 if(memory[i] == -999999) {
     68 	    memory[i] = 0;
     69 	    i = MEMSIZE; /* Terminate the for loop */
     70 	    break;
     71 	 }
     72 
     73 	 if(s_mem[0] != '+') {
     74 	    printf("*** Invalid instruction: %s\n", s_mem);
     75 	    printf("*** Please use '+' or exit.\n");
     76 	    continue;
     77 	 }
     78 
     79 	 if( checkword((int)memory[i], MEMSIZE) ) {
     80 	    printf("*** Invalid instruction: +%.0f\n"
     81 		   "*** Please retype it or exit.\n", memory[i]);
     82 	 }
     83 	 else
     84 	    break;
     85 
     86       } /* end while */
     87    } /* end for (i) */
     88 
     89    printf("*** Program loading completed ***\n"
     90 	  "*** Program execution begins  ***\n");
     91 
     92    for(i = 0; i < MEMSIZE; i++) {
     93       instructionRegister = (int)memory[i];
     94 
     95       operationCode = 
     96 	 instructionRegister / (instructionRegister <= 9999 ? 100 : 1000);
     97       operand =
     98 	 instructionRegister % (instructionRegister <= 9999 ? 100 : 1000);
     99 
    100       /* this is required because after the switch()
    101       statement the 'i' counter is incremented of 1. */
    102       if(operationCode >= BRANCH)
    103          --operand;
    104 
    105       switch(operationCode) {
    106 	 case READ:
    107 	    printf("\nInsert a word: ");
    108             scanf("%f", &memory[operand]);
    109 
    110 	    break;
    111 	 case WRITE:
    112 	    printf("\nMemory location: %.2d\nWord: %.2f\n",
    113 	       operand, memory[operand]);
    114 
    115 	    break;
    116 	 case NEWLINE:
    117 	    printf("\n");
    118 	    break;
    119 	 case SREAD:
    120 	    /* If this instruction is used then HALT is required */
    121 	    printf("\nInsert a string: ");
    122 	    scanf("%s", s_mem);
    123 
    124 	    if(strlen(s_mem) > 3) {
    125 	       err = 3;
    126 	       break;
    127 	    }
    128 
    129 	    for(j = 0; (unsigned)j < strlen(s_mem); j++) {
    130 	       if((int)s_mem[j] > 99) {
    131 		  err = 4;
    132 		  t_val = j;
    133 		  break;
    134 	       }
    135 	    }
    136 	    memory[operand] = 0;
    137 
    138 	    for(j = strlen(s_mem), k = 1; j >= 0; k *= 100, j--)
    139 	       memory[operand] += s_mem[j] * k;
    140 
    141             for(t_val = 0.1, k = 1; k < memory[operand]; t_val *= 0.10, k *= 10) ;
    142 	    t_val /= 0.10;
    143 
    144 	    memory[operand] *= t_val;
    145 	    memory[operand] += strlen(s_mem);
    146 
    147 	    break;
    148 	 case SWRITE:
    149 	    printf("\nMemory location: %.0f\nWord: ", memory[operand]);
    150 	    for(j = (int)memory[operand], t_val = 100; j ; t_val *= 100, j--) { 
    151 	       f_tmp = memory[operand] * t_val;
    152 	       k = (int)f_tmp % 100;
    153 	       printf("%c", k);
    154 	    }
    155 	    printf("\n");
    156 
    157 	    break;
    158 	 case LOAD:
    159 	    accumulator = memory[operand];
    160 	    break;
    161 	 case STORE:
    162 	    memory[operand] = accumulator;
    163 	    break;
    164 
    165 	 case ADD:
    166 	    accumulator += memory[operand];
    167 
    168 	    break;
    169 	 case SUBTRACT:
    170 	    accumulator -= memory[operand];
    171 
    172 	    break;
    173 	 case DIVIDE:
    174 	    if( !memory[operand] )
    175 	       err = 2;
    176 	    else
    177 	       accumulator /= memory[operand];
    178 
    179 	    break;
    180 	 case MULTIPLY:
    181 	    accumulator *= memory[operand];
    182 
    183 	    break;
    184 	 case REST:
    185 	    accumulator = (int)accumulator % (int)memory[operand];
    186 
    187 	    break;
    188 
    189 	 case POWER:
    190 	    accumulator = pow(accumulator, memory[operand]);
    191 	    break;
    192 
    193 	 case BRANCH:
    194 	    i = operand;
    195 	    break;
    196 	 case BRANCHNEG:
    197 	    if(accumulator < 0)
    198 	       i = operand;
    199 
    200 	    break;
    201 	 case BRANCHZERO:
    202 	    if(!accumulator)
    203 	       i = operand;
    204 
    205             break;
    206 
    207 	 case HALT:
    208 	    i = MEMSIZE; /* terminate the for loop */
    209 	    /* dump(accumulator, i, memory); */
    210 
    211             break;
    212 	 case 0:
    213 	    break;
    214 
    215 	 default:
    216 	    printf("*** unknown error: %d\n", instructionRegister);
    217 	    dump(accumulator, i, memory);
    218 	    printf("\nAre'nt you using HALT (+4300)?\n");
    219 	    exit(-1);
    220       }
    221 
    222       if(accumulator > MEMSIZE * MEMSIZE - 1 ||
    223          accumulator < MEMSIZE * -MEMSIZE + 1)
    224          err = 1;
    225 
    226       if(err) { /* Error messages manager */
    227 	 printf("\n*** ");
    228 	 switch(err) {
    229 	    case 1:
    230                printf("Out of the accumulator limit"); 
    231 	       break;
    232 	    case 2:
    233 	       printf("Attempt to divide by zero");
    234 	       break;
    235 	    case 3:
    236 	       printf("You can put max 3 numbers for memory location");
    237 	       break;
    238 	    case 4:
    239 	       printf("This ASCII code is too long: %d (%c)",
    240 		  s_mem[(int)t_val], s_mem[(int)t_val]);
    241 	 }
    242 
    243 	 printf(" ***\n");
    244 	 
    245          printf("*** Simpletron execution abnormally terminated ***\n");
    246          dump(accumulator, i, memory);
    247          exit(-1);
    248       }
    249 
    250    } /* end for (i) */
    251 
    252    /* dump(accumulator, i, memory); */
    253    printf("\n*** Simpletron execution terminated ***\n");
    254 
    255    return 0;
    256 } /* E0F main */
    257 
    258 /* Check if a "word" is correct */
    259 int checkword(int word, int size)
    260 {
    261    if( word < 0 || word >= MEMSIZE * MEMSIZE ||
    262        word % (word <= 9999 ? 100 : 1000) >= size ) {
    263       return 1;
    264    }
    265 
    266    switch(word / (word <= 9999 ? 100 : 1000)) {
    267       case READ:
    268       case WRITE:
    269       case NEWLINE:
    270       case SREAD:
    271       case SWRITE:
    272       case LOAD:
    273       case STORE:
    274       case ADD:
    275       case SUBTRACT:
    276       case DIVIDE:
    277       case MULTIPLY:
    278       case REST:
    279       case POWER:
    280       case BRANCH:
    281       case BRANCHNEG:
    282       case BRANCHZERO:
    283       case HALT:
    284       case 0:
    285          break;
    286       default:
    287 	 return 1;
    288 
    289    } /* end switch (word) */
    290 
    291    return 0;
    292 
    293 } /* eof checkword() */
    294 
    295 /* Show a dump of the current memory state */
    296 void dump(float acc, int icounter, float mem[])
    297 {
    298    int i, j;
    299    char string[6] = { 0 };
    300 
    301    printf("\nREGISTERS:\n");
    302 
    303    printf("accumulator\t\t%c%s\n", acc < 0 ? '-' : '+', p_itoh(acc, string, 4));
    304    printf("instructionCounter\t%s\n", p_itoh(icounter, string, 2));
    305 
    306    printf("instructionRegister\t%c%s\n", mem[icounter] < 0 ? '-' : '+',
    307       p_itoh(mem[icounter] < 0 ? -mem[icounter] : mem[icounter], string, 4));
    308 
    309    printf("operationCode\t\t%s\n", p_itoh(mem[icounter] / 100, string, 2));
    310    printf("operand\t\t\t%s\n", p_itoh((int)mem[icounter] % 100, string, 2));
    311 
    312    printf("\nMEMORY:\n");
    313 
    314    /* Print the header */
    315    printf("%3c", ' ');
    316    for(i = 0; i < 10; i++)
    317       printf("%5d ", i);
    318    printf("\n");
    319 
    320    for(i = 0; i < MEMSIZE; i += 10) {
    321       printf("%.3d", i);
    322       for(j = i; j < i+10; j++) {
    323 	 printf(" %c%s", mem[j] < 0 ? '-' : '+',
    324 	   p_itoh(mem[j] < 0 ? -mem[j] : mem[j], string, 4));
    325       }
    326       printf("\n");
    327    }
    328 
    329 } /* eof dump() */
    330 
    331 int r_htoi(const char string[])
    332 {
    333    int i, num = 0, n = 1;
    334    char s[1] = { 0 };
    335 
    336    for(i = strlen(string) - 1; i >= 0; i--) {
    337       if(string[i] >= 'A' && string[i] <= 'F')
    338          n *= 10;
    339 
    340       n *= 10;
    341    }
    342 
    343    n /= 10;
    344 
    345    for(i = 0; i < 7; n /= 10, i++) {
    346 
    347       if(string[i] >= 'A' && string[i] <= 'F') {
    348          num += 1 * n;
    349          n /= 10;
    350       }
    351 
    352       switch(string[i])
    353       {  
    354          case 'A':
    355 	 case 'a':
    356             /* 0 */
    357             break;
    358          case 'B':
    359 	 case 'b':
    360             num += 1 * n;
    361             break;
    362          case 'C':
    363 	 case 'c':
    364             num += 2 * n;
    365             break;
    366          case 'D':
    367 	 case 'd':
    368             num += 3 * n;
    369             break;
    370          case 'E':
    371 	 case 'e':
    372             num += 4 * n;
    373             break;
    374          case 'F':
    375 	 case 'f':
    376             num += 5 * n;
    377             break;
    378          default:
    379             *s = string[i];
    380             if(string[0] == '-')
    381                num -= atoi(s) * n;
    382             else
    383                num += atoi(s) * n;
    384       } /* end switch */
    385 
    386    }
    387 
    388    return num;
    389 }
    390 
    391 char * p_itoh(int num, char str[], int z)
    392 {
    393    int i, idx = 0;
    394 
    395    if(num > 0) {
    396       if(num <= 9) i = 1;
    397       else if(num <= 99) i = 10;
    398       else if(num <= 999) i = 100;
    399       else if(num <= 9999) i = 1000;
    400       else if(num <= 99999) i = 10000;
    401       else {
    402 	 printf("error in p_itoh(): unknown range: %d\n", num);
    403 	    printf("\nAre'nt you using HALT (+4300)?\n");
    404 	 exit(-1);
    405       }
    406    }
    407    else if(!num) {
    408       for(i = 0; i < (int)sizeof(str); i++) {
    409 	 if(i < z) str[i] = '0';
    410 	 else str[i] = ' ';
    411       }
    412       return str;
    413    }
    414    else {
    415       printf("Negative numbers are not allowed!\n");
    416       return 0;
    417    }
    418 
    419    for( ; i ; idx++, i /= 10) {
    420 
    421       if( (num / i % 10) == 1 ) {
    422 
    423          i /= 10;
    424 	 if(!i) break;
    425          switch(num / i % 10) {
    426 	    case 0:
    427 	       str[idx] = 'A';
    428 	       break;
    429 	    case 1:
    430 	       str[idx] = 'B';
    431 	       break;
    432 	    case 2:
    433 	       str[idx] = 'C';
    434 	       break;
    435 	    case 3:
    436 	       str[idx] = 'D';
    437 	       break;
    438 	    case 4:
    439 	       str[idx] = 'E';
    440 	       break;
    441             case 5:
    442 	       str[idx] = 'F';
    443 	       break;
    444 	    default:
    445 	       str[idx] = (char)(num / i % 10) + '0';
    446 	       i *= 10;
    447 	 }
    448       }
    449 
    450       else {
    451 	 str[idx] = (char)(num / i % 10) + '0';
    452       }
    453    } /* end for (i) */
    454 
    455    return str;
    456 }
    457