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