/ c4.c
c4.c
1 // c4.c - C in four functions 2 3 // char, int, and pointer types 4 // if, while, return, and expression statements 5 // just enough features to allow self-compilation and a bit more 6 7 // Written by Robert Swierczek 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <memory.h> 12 #include <unistd.h> 13 #include <fcntl.h> 14 15 char *p, *lp, // current position in source code 16 *data; // data/bss pointer 17 18 int *e, *le, // current position in emitted code 19 *id, // currently parsed identifier 20 *sym, // symbol table (simple list of identifiers) 21 tk, // current token 22 ival, // current token value 23 ty, // current expression type 24 loc, // local variable offset 25 line, // current line number 26 src, // print source and assembly flag 27 debug; // print executed instructions 28 29 // tokens and classes (operators last and in precedence order) 30 enum { 31 Num = 128, Fun, Sys, Glo, Loc, Id, 32 Char, Else, Enum, If, Int, Return, Sizeof, While, 33 Assign, Cond, Lor, Lan, Or, Xor, And, Eq, Ne, Lt, Gt, Le, Ge, Shl, Shr, Add, Sub, Mul, Div, Mod, Inc, Dec, Brak 34 }; 35 36 // opcodes 37 enum { LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH , 38 OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD , 39 OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,EXIT }; 40 41 // types 42 enum { CHAR, INT, PTR }; 43 44 // identifier offsets (since we can't create an ident struct) 45 enum { Tk, Hash, Name, Class, Type, Val, HClass, HType, HVal, Idsz }; 46 47 void next() 48 { 49 char *pp; 50 51 while (tk = *p) { 52 ++p; 53 if (tk == '\n') { 54 if (src) { 55 printf("%d: %.*s", line, p - lp, lp); 56 lp = p; 57 while (le < e) { 58 printf("%8.4s", &"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ," 59 "OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ," 60 "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,EXIT,"[*++le * 5]); 61 if (*le <= ADJ) printf(" %d\n", *++le); else printf("\n"); 62 } 63 } 64 ++line; 65 } 66 else if (tk == '#') { 67 while (*p != 0 && *p != '\n') ++p; 68 } 69 else if ((tk >= 'a' && tk <= 'z') || (tk >= 'A' && tk <= 'Z') || tk == '_') { 70 pp = p - 1; 71 while ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_') 72 tk = tk * 147 + *p++; 73 tk = (tk << 6) + (p - pp); 74 id = sym; 75 while (id[Tk]) { 76 if (tk == id[Hash] && !memcmp((char *)id[Name], pp, p - pp)) { tk = id[Tk]; return; } 77 id = id + Idsz; 78 } 79 id[Name] = (int)pp; 80 id[Hash] = tk; 81 tk = id[Tk] = Id; 82 return; 83 } 84 else if (tk >= '0' && tk <= '9') { 85 if (ival = tk - '0') { while (*p >= '0' && *p <= '9') ival = ival * 10 + *p++ - '0'; } 86 else if (*p == 'x' || *p == 'X') { 87 while ((tk = *++p) && ((tk >= '0' && tk <= '9') || (tk >= 'a' && tk <= 'f') || (tk >= 'A' && tk <= 'F'))) 88 ival = ival * 16 + (tk & 15) + (tk >= 'A' ? 9 : 0); 89 } 90 else { while (*p >= '0' && *p <= '7') ival = ival * 8 + *p++ - '0'; } 91 tk = Num; 92 return; 93 } 94 else if (tk == '/') { 95 if (*p == '/') { 96 ++p; 97 while (*p != 0 && *p != '\n') ++p; 98 } 99 else { 100 tk = Div; 101 return; 102 } 103 } 104 else if (tk == '\'' || tk == '"') { 105 pp = data; 106 while (*p != 0 && *p != tk) { 107 if ((ival = *p++) == '\\') { 108 if ((ival = *p++) == 'n') ival = '\n'; 109 } 110 if (tk == '"') *data++ = ival; 111 } 112 ++p; 113 if (tk == '"') ival = (int)pp; else tk = Num; 114 return; 115 } 116 else if (tk == '=') { if (*p == '=') { ++p; tk = Eq; } else tk = Assign; return; } 117 else if (tk == '+') { if (*p == '+') { ++p; tk = Inc; } else tk = Add; return; } 118 else if (tk == '-') { if (*p == '-') { ++p; tk = Dec; } else tk = Sub; return; } 119 else if (tk == '!') { if (*p == '=') { ++p; tk = Ne; } return; } 120 else if (tk == '<') { if (*p == '=') { ++p; tk = Le; } else if (*p == '<') { ++p; tk = Shl; } else tk = Lt; return; } 121 else if (tk == '>') { if (*p == '=') { ++p; tk = Ge; } else if (*p == '>') { ++p; tk = Shr; } else tk = Gt; return; } 122 else if (tk == '|') { if (*p == '|') { ++p; tk = Lor; } else tk = Or; return; } 123 else if (tk == '&') { if (*p == '&') { ++p; tk = Lan; } else tk = And; return; } 124 else if (tk == '^') { tk = Xor; return; } 125 else if (tk == '%') { tk = Mod; return; } 126 else if (tk == '*') { tk = Mul; return; } 127 else if (tk == '[') { tk = Brak; return; } 128 else if (tk == '?') { tk = Cond; return; } 129 else if (tk == '~' || tk == ';' || tk == '{' || tk == '}' || tk == '(' || tk == ')' || tk == ']' || tk == ',' || tk == ':') return; 130 } 131 } 132 133 void expr(int lev) 134 { 135 int t, *d; 136 137 if (!tk) { printf("%d: unexpected eof in expression\n", line); exit(-1); } 138 else if (tk == Num) { *++e = IMM; *++e = ival; next(); ty = INT; } 139 else if (tk == '"') { 140 *++e = IMM; *++e = ival; next(); 141 while (tk == '"') next(); 142 data = (char *)((int)data + sizeof(int) & -sizeof(int)); ty = PTR; 143 } 144 else if (tk == Sizeof) { 145 next(); if (tk == '(') next(); else { printf("%d: open paren expected in sizeof\n", line); exit(-1); } 146 ty = INT; if (tk == Int) next(); else if (tk == Char) { next(); ty = CHAR; } 147 while (tk == Mul) { next(); ty = ty + PTR; } 148 if (tk == ')') next(); else { printf("%d: close paren expected in sizeof\n", line); exit(-1); } 149 *++e = IMM; *++e = (ty == CHAR) ? sizeof(char) : sizeof(int); 150 ty = INT; 151 } 152 else if (tk == Id) { 153 d = id; next(); 154 if (tk == '(') { 155 next(); 156 t = 0; 157 while (tk != ')') { expr(Assign); *++e = PSH; ++t; if (tk == ',') next(); } 158 next(); 159 if (d[Class] == Sys) *++e = d[Val]; 160 else if (d[Class] == Fun) { *++e = JSR; *++e = d[Val]; } 161 else { printf("%d: bad function call\n", line); exit(-1); } 162 if (t) { *++e = ADJ; *++e = t; } 163 ty = d[Type]; 164 } 165 else if (d[Class] == Num) { *++e = IMM; *++e = d[Val]; ty = INT; } 166 else { 167 if (d[Class] == Loc) { *++e = LEA; *++e = loc - d[Val]; } 168 else if (d[Class] == Glo) { *++e = IMM; *++e = d[Val]; } 169 else { printf("%d: undefined variable\n", line); exit(-1); } 170 *++e = ((ty = d[Type]) == CHAR) ? LC : LI; 171 } 172 } 173 else if (tk == '(') { 174 next(); 175 if (tk == Int || tk == Char) { 176 t = (tk == Int) ? INT : CHAR; next(); 177 while (tk == Mul) { next(); t = t + PTR; } 178 if (tk == ')') next(); else { printf("%d: bad cast\n", line); exit(-1); } 179 expr(Inc); 180 ty = t; 181 } 182 else { 183 expr(Assign); 184 if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); } 185 } 186 } 187 else if (tk == Mul) { 188 next(); expr(Inc); 189 if (ty > INT) ty = ty - PTR; else { printf("%d: bad dereference\n", line); exit(-1); } 190 *++e = (ty == CHAR) ? LC : LI; 191 } 192 else if (tk == And) { 193 next(); expr(Inc); 194 if (*e == LC || *e == LI) --e; else { printf("%d: bad address-of\n", line); exit(-1); } 195 ty = ty + PTR; 196 } 197 else if (tk == '!') { next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = 0; *++e = EQ; ty = INT; } 198 else if (tk == '~') { next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = -1; *++e = XOR; ty = INT; } 199 else if (tk == Add) { next(); expr(Inc); ty = INT; } 200 else if (tk == Sub) { 201 next(); *++e = IMM; 202 if (tk == Num) { *++e = -ival; next(); } else { *++e = -1; *++e = PSH; expr(Inc); *++e = MUL; } 203 ty = INT; 204 } 205 else if (tk == Inc || tk == Dec) { 206 t = tk; next(); expr(Inc); 207 if (*e == LC) { *e = PSH; *++e = LC; } 208 else if (*e == LI) { *e = PSH; *++e = LI; } 209 else { printf("%d: bad lvalue in pre-increment\n", line); exit(-1); } 210 *++e = PSH; 211 *++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char); 212 *++e = (t == Inc) ? ADD : SUB; 213 *++e = (ty == CHAR) ? SC : SI; 214 } 215 else { printf("%d: bad expression\n", line); exit(-1); } 216 217 while (tk >= lev) { // "precedence climbing" or "Top Down Operator Precedence" method 218 t = ty; 219 if (tk == Assign) { 220 next(); 221 if (*e == LC || *e == LI) *e = PSH; else { printf("%d: bad lvalue in assignment\n", line); exit(-1); } 222 expr(Assign); *++e = ((ty = t) == CHAR) ? SC : SI; 223 } 224 else if (tk == Cond) { 225 next(); 226 *++e = BZ; d = ++e; 227 expr(Assign); 228 if (tk == ':') next(); else { printf("%d: conditional missing colon\n", line); exit(-1); } 229 *d = (int)(e + 3); *++e = JMP; d = ++e; 230 expr(Cond); 231 *d = (int)(e + 1); 232 } 233 else if (tk == Lor) { next(); *++e = BNZ; d = ++e; expr(Lan); *d = (int)(e + 1); ty = INT; } 234 else if (tk == Lan) { next(); *++e = BZ; d = ++e; expr(Or); *d = (int)(e + 1); ty = INT; } 235 else if (tk == Or) { next(); *++e = PSH; expr(Xor); *++e = OR; ty = INT; } 236 else if (tk == Xor) { next(); *++e = PSH; expr(And); *++e = XOR; ty = INT; } 237 else if (tk == And) { next(); *++e = PSH; expr(Eq); *++e = AND; ty = INT; } 238 else if (tk == Eq) { next(); *++e = PSH; expr(Lt); *++e = EQ; ty = INT; } 239 else if (tk == Ne) { next(); *++e = PSH; expr(Lt); *++e = NE; ty = INT; } 240 else if (tk == Lt) { next(); *++e = PSH; expr(Shl); *++e = LT; ty = INT; } 241 else if (tk == Gt) { next(); *++e = PSH; expr(Shl); *++e = GT; ty = INT; } 242 else if (tk == Le) { next(); *++e = PSH; expr(Shl); *++e = LE; ty = INT; } 243 else if (tk == Ge) { next(); *++e = PSH; expr(Shl); *++e = GE; ty = INT; } 244 else if (tk == Shl) { next(); *++e = PSH; expr(Add); *++e = SHL; ty = INT; } 245 else if (tk == Shr) { next(); *++e = PSH; expr(Add); *++e = SHR; ty = INT; } 246 else if (tk == Add) { 247 next(); *++e = PSH; expr(Mul); 248 if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; } 249 *++e = ADD; 250 } 251 else if (tk == Sub) { 252 next(); *++e = PSH; expr(Mul); 253 if (t > PTR && t == ty) { *++e = SUB; *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = DIV; ty = INT; } 254 else if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; *++e = SUB; } 255 else *++e = SUB; 256 } 257 else if (tk == Mul) { next(); *++e = PSH; expr(Inc); *++e = MUL; ty = INT; } 258 else if (tk == Div) { next(); *++e = PSH; expr(Inc); *++e = DIV; ty = INT; } 259 else if (tk == Mod) { next(); *++e = PSH; expr(Inc); *++e = MOD; ty = INT; } 260 else if (tk == Inc || tk == Dec) { 261 if (*e == LC) { *e = PSH; *++e = LC; } 262 else if (*e == LI) { *e = PSH; *++e = LI; } 263 else { printf("%d: bad lvalue in post-increment\n", line); exit(-1); } 264 *++e = PSH; *++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char); 265 *++e = (tk == Inc) ? ADD : SUB; 266 *++e = (ty == CHAR) ? SC : SI; 267 *++e = PSH; *++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char); 268 *++e = (tk == Inc) ? SUB : ADD; 269 next(); 270 } 271 else if (tk == Brak) { 272 next(); *++e = PSH; expr(Assign); 273 if (tk == ']') next(); else { printf("%d: close bracket expected\n", line); exit(-1); } 274 if (t > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; } 275 else if (t < PTR) { printf("%d: pointer type expected\n", line); exit(-1); } 276 *++e = ADD; 277 *++e = ((ty = t - PTR) == CHAR) ? LC : LI; 278 } 279 else { printf("%d: compiler error tk=%d\n", line, tk); exit(-1); } 280 } 281 } 282 283 void stmt() 284 { 285 int *a, *b; 286 287 if (tk == If) { 288 next(); 289 if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); } 290 expr(Assign); 291 if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); } 292 *++e = BZ; b = ++e; 293 stmt(); 294 if (tk == Else) { 295 *b = (int)(e + 3); *++e = JMP; b = ++e; 296 next(); 297 stmt(); 298 } 299 *b = (int)(e + 1); 300 } 301 else if (tk == While) { 302 next(); 303 a = e + 1; 304 if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); } 305 expr(Assign); 306 if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); } 307 *++e = BZ; b = ++e; 308 stmt(); 309 *++e = JMP; *++e = (int)a; 310 *b = (int)(e + 1); 311 } 312 else if (tk == Return) { 313 next(); 314 if (tk != ';') expr(Assign); 315 *++e = LEV; 316 if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); } 317 } 318 else if (tk == '{') { 319 next(); 320 while (tk != '}') stmt(); 321 next(); 322 } 323 else if (tk == ';') { 324 next(); 325 } 326 else { 327 expr(Assign); 328 if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); } 329 } 330 } 331 332 int main(int argc, char **argv) 333 { 334 int fd, bt, ty, poolsz, *idmain; 335 int *pc, *sp, *bp, a, cycle; // vm registers 336 int i, *t; // temps 337 338 --argc; ++argv; 339 if (argc > 0 && **argv == '-' && (*argv)[1] == 's') { src = 1; --argc; ++argv; } 340 if (argc > 0 && **argv == '-' && (*argv)[1] == 'd') { debug = 1; --argc; ++argv; } 341 if (argc < 1) { printf("usage: c4 [-s] [-d] file ...\n"); return -1; } 342 343 if ((fd = open(*argv, 0)) < 0) { printf("could not open(%s)\n", *argv); return -1; } 344 345 poolsz = 256*1024; // arbitrary size 346 if (!(sym = malloc(poolsz))) { printf("could not malloc(%d) symbol area\n", poolsz); return -1; } 347 if (!(le = e = malloc(poolsz))) { printf("could not malloc(%d) text area\n", poolsz); return -1; } 348 if (!(data = malloc(poolsz))) { printf("could not malloc(%d) data area\n", poolsz); return -1; } 349 if (!(sp = malloc(poolsz))) { printf("could not malloc(%d) stack area\n", poolsz); return -1; } 350 351 memset(sym, 0, poolsz); 352 memset(e, 0, poolsz); 353 memset(data, 0, poolsz); 354 355 p = "char else enum if int return sizeof while " 356 "open read close printf malloc free memset memcmp exit void main"; 357 i = Char; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table 358 i = OPEN; while (i <= EXIT) { next(); id[Class] = Sys; id[Type] = INT; id[Val] = i++; } // add library to symbol table 359 next(); id[Tk] = Char; // handle void type 360 next(); idmain = id; // keep track of main 361 362 if (!(lp = p = malloc(poolsz))) { printf("could not malloc(%d) source area\n", poolsz); return -1; } 363 if ((i = read(fd, p, poolsz-1)) <= 0) { printf("read() returned %d\n", i); return -1; } 364 p[i] = 0; 365 close(fd); 366 367 // parse declarations 368 line = 1; 369 next(); 370 while (tk) { 371 bt = INT; // basetype 372 if (tk == Int) next(); 373 else if (tk == Char) { next(); bt = CHAR; } 374 else if (tk == Enum) { 375 next(); 376 if (tk != '{') next(); 377 if (tk == '{') { 378 next(); 379 i = 0; 380 while (tk != '}') { 381 if (tk != Id) { printf("%d: bad enum identifier %d\n", line, tk); return -1; } 382 next(); 383 if (tk == Assign) { 384 next(); 385 if (tk != Num) { printf("%d: bad enum initializer\n", line); return -1; } 386 i = ival; 387 next(); 388 } 389 id[Class] = Num; id[Type] = INT; id[Val] = i++; 390 if (tk == ',') next(); 391 } 392 next(); 393 } 394 } 395 while (tk != ';' && tk != '}') { 396 ty = bt; 397 while (tk == Mul) { next(); ty = ty + PTR; } 398 if (tk != Id) { printf("%d: bad global declaration\n", line); return -1; } 399 if (id[Class]) { printf("%d: duplicate global definition\n", line); return -1; } 400 next(); 401 id[Type] = ty; 402 if (tk == '(') { // function 403 id[Class] = Fun; 404 id[Val] = (int)(e + 1); 405 next(); i = 0; 406 while (tk != ')') { 407 ty = INT; 408 if (tk == Int) next(); 409 else if (tk == Char) { next(); ty = CHAR; } 410 while (tk == Mul) { next(); ty = ty + PTR; } 411 if (tk != Id) { printf("%d: bad parameter declaration\n", line); return -1; } 412 if (id[Class] == Loc) { printf("%d: duplicate parameter definition\n", line); return -1; } 413 id[HClass] = id[Class]; id[Class] = Loc; 414 id[HType] = id[Type]; id[Type] = ty; 415 id[HVal] = id[Val]; id[Val] = i++; 416 next(); 417 if (tk == ',') next(); 418 } 419 next(); 420 if (tk != '{') { printf("%d: bad function definition\n", line); return -1; } 421 loc = ++i; 422 next(); 423 while (tk == Int || tk == Char) { 424 bt = (tk == Int) ? INT : CHAR; 425 next(); 426 while (tk != ';') { 427 ty = bt; 428 while (tk == Mul) { next(); ty = ty + PTR; } 429 if (tk != Id) { printf("%d: bad local declaration\n", line); return -1; } 430 if (id[Class] == Loc) { printf("%d: duplicate local definition\n", line); return -1; } 431 id[HClass] = id[Class]; id[Class] = Loc; 432 id[HType] = id[Type]; id[Type] = ty; 433 id[HVal] = id[Val]; id[Val] = ++i; 434 next(); 435 if (tk == ',') next(); 436 } 437 next(); 438 } 439 *++e = ENT; *++e = i - loc; 440 while (tk != '}') stmt(); 441 *++e = LEV; 442 id = sym; // unwind symbol table locals 443 while (id[Tk]) { 444 if (id[Class] == Loc) { 445 id[Class] = id[HClass]; 446 id[Type] = id[HType]; 447 id[Val] = id[HVal]; 448 } 449 id = id + Idsz; 450 } 451 } 452 else { 453 id[Class] = Glo; 454 id[Val] = (int)data; 455 data = data + sizeof(int); 456 } 457 if (tk == ',') next(); 458 } 459 next(); 460 } 461 462 if (!(pc = (int *)idmain[Val])) { printf("main() not defined\n"); return -1; } 463 if (src) return 0; 464 465 // setup stack 466 bp = sp = (int *)((int)sp + poolsz); 467 *--sp = EXIT; // call exit if main returns 468 *--sp = PSH; t = sp; 469 *--sp = argc; 470 *--sp = (int)argv; 471 *--sp = (int)t; 472 473 // run... 474 cycle = 0; 475 while (1) { 476 i = *pc++; ++cycle; 477 if (debug) { 478 printf("%d> %.4s", cycle, 479 &"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ," 480 "OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ," 481 "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,EXIT,"[i * 5]); 482 if (i <= ADJ) printf(" %d\n", *pc); else printf("\n"); 483 } 484 if (i == LEA) a = (int)(bp + *pc++); // load local address 485 else if (i == IMM) a = *pc++; // load global address or immediate 486 else if (i == JMP) pc = (int *)*pc; // jump 487 else if (i == JSR) { *--sp = (int)(pc + 1); pc = (int *)*pc; } // jump to subroutine 488 else if (i == BZ) pc = a ? pc + 1 : (int *)*pc; // branch if zero 489 else if (i == BNZ) pc = a ? (int *)*pc : pc + 1; // branch if not zero 490 else if (i == ENT) { *--sp = (int)bp; bp = sp; sp = sp - *pc++; } // enter subroutine 491 else if (i == ADJ) sp = sp + *pc++; // stack adjust 492 else if (i == LEV) { sp = bp; bp = (int *)*sp++; pc = (int *)*sp++; } // leave subroutine 493 else if (i == LI) a = *(int *)a; // load int 494 else if (i == LC) a = *(char *)a; // load char 495 else if (i == SI) *(int *)*sp++ = a; // store int 496 else if (i == SC) a = *(char *)*sp++ = a; // store char 497 else if (i == PSH) *--sp = a; // push 498 499 else if (i == OR) a = *sp++ | a; 500 else if (i == XOR) a = *sp++ ^ a; 501 else if (i == AND) a = *sp++ & a; 502 else if (i == EQ) a = *sp++ == a; 503 else if (i == NE) a = *sp++ != a; 504 else if (i == LT) a = *sp++ < a; 505 else if (i == GT) a = *sp++ > a; 506 else if (i == LE) a = *sp++ <= a; 507 else if (i == GE) a = *sp++ >= a; 508 else if (i == SHL) a = *sp++ << a; 509 else if (i == SHR) a = *sp++ >> a; 510 else if (i == ADD) a = *sp++ + a; 511 else if (i == SUB) a = *sp++ - a; 512 else if (i == MUL) a = *sp++ * a; 513 else if (i == DIV) a = *sp++ / a; 514 else if (i == MOD) a = *sp++ % a; 515 516 else if (i == OPEN) a = open((char *)sp[1], *sp); 517 else if (i == READ) a = read(sp[2], (char *)sp[1], *sp); 518 else if (i == CLOS) a = close(*sp); 519 else if (i == PRTF) { t = sp + pc[1]; a = printf((char *)t[-1], t[-2], t[-3], t[-4], t[-5], t[-6]); } 520 else if (i == MALC) a = (int)malloc(*sp); 521 else if (i == FREE) free((void *)*sp); 522 else if (i == MSET) a = (int)memset((char *)sp[2], sp[1], *sp); 523 else if (i == MCMP) a = memcmp((char *)sp[2], (char *)sp[1], *sp); 524 else if (i == EXIT) { printf("exit(%d) cycle = %d\n", *sp, cycle); return *sp; } 525 else { printf("unknown instruction = %d! cycle = %d\n", i, cycle); return -1; } 526 } 527 }