training

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

esimpletron2.c (11529B)


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