|
23 | 23 | package main |
24 | 24 |
|
25 | 25 | import ( |
| 26 | +"bytes" |
26 | 27 | "fmt" |
27 | 28 | "io/ioutil" |
28 | 29 | "math/rand" |
29 | 30 | "os" |
| 31 | +"os/exec" |
| 32 | +"regexp" |
30 | 33 | "strconv" |
31 | 34 | "time" |
32 | 35 | ) |
@@ -89,6 +92,47 @@ func debugPrintf(fmt_ string, args ...interface{}) { |
89 | 92 | fmt.Printf(prefix,args...) |
90 | 93 | } |
91 | 94 |
|
| 95 | +// Split a line of text into tokens, but keep anything "quoted" |
| 96 | +// together.. |
| 97 | +// |
| 98 | +// So this input: |
| 99 | +// |
| 100 | +// /bin/sh -c "ls /etc" |
| 101 | +// |
| 102 | +// Would give output of the form: |
| 103 | +// /bin/sh |
| 104 | +// -c |
| 105 | +// ls /etc |
| 106 | +// |
| 107 | +funcsplitCommand(inputstring) []string { |
| 108 | + |
| 109 | +// |
| 110 | +// This does the split into an array |
| 111 | +// |
| 112 | +r:=regexp.MustCompile(`[^\s"']+|"([^"]*)"|'([^']*)`) |
| 113 | +res:=r.FindAllString(input,-1) |
| 114 | + |
| 115 | +// |
| 116 | +// However the resulting pieces might be quoted. |
| 117 | +// So we have to remove them, if present. |
| 118 | +// |
| 119 | +varresult []string |
| 120 | +for_,e:=rangeres { |
| 121 | +result=append(result,trimQuotes(e,'"')) |
| 122 | +} |
| 123 | +return (result) |
| 124 | +} |
| 125 | + |
| 126 | +// Remove balanced characters around a string. |
| 127 | +functrimQuotes(instring,cbyte)string { |
| 128 | +iflen(in)>=2 { |
| 129 | +ifin[0]==c&&in[len(in)-1]==c { |
| 130 | +returnin[1 :len(in)-1] |
| 131 | +} |
| 132 | +} |
| 133 | +returnin |
| 134 | +} |
| 135 | + |
92 | 136 | // |
93 | 137 | // Stack functions |
94 | 138 | // |
@@ -353,6 +397,57 @@ func (c *CPU) Run() { |
353 | 397 |
|
354 | 398 | fmt.Printf("%s",c.regs[reg].s) |
355 | 399 | c.ip+=1 |
| 400 | + |
| 401 | +case0x32: |
| 402 | +debugPrintf("STRING_CONCAT\n") |
| 403 | + |
| 404 | +// output register |
| 405 | +c.ip+=1 |
| 406 | +res:=c.mem[c.ip] |
| 407 | + |
| 408 | +// src1 |
| 409 | +c.ip+=1 |
| 410 | +a:=c.mem[c.ip] |
| 411 | + |
| 412 | +// src2 |
| 413 | +c.ip+=1 |
| 414 | +b:=c.mem[c.ip] |
| 415 | + |
| 416 | +c.ip+=1 |
| 417 | + |
| 418 | +c.regs[res].s=c.regs[a].s+c.regs[b].s |
| 419 | +c.regs[res].t="string" |
| 420 | + |
| 421 | +case0x33: |
| 422 | +debugPrintf("SYSTEM\n") |
| 423 | + |
| 424 | +// register |
| 425 | +c.ip+=1 |
| 426 | +r:=c.mem[c.ip] |
| 427 | +c.ip+=1 |
| 428 | + |
| 429 | +ifc.regs[r].t!="string" { |
| 430 | +fmt.Printf("BUG: Attempting to exec a non-string register\n") |
| 431 | +os.Exit(3) |
| 432 | +} |
| 433 | + |
| 434 | +// run the command |
| 435 | +toExec:=splitCommand(c.regs[r].s) |
| 436 | +cmd:=exec.Command(toExec[0],toExec[1:]...) |
| 437 | + |
| 438 | +varout bytes.Buffer |
| 439 | +varerr bytes.Buffer |
| 440 | +cmd.Stdout=&out |
| 441 | +cmd.Stderr=&err |
| 442 | +cmd.Run() |
| 443 | + |
| 444 | +// stdout |
| 445 | +fmt.Printf("%s",out.String()) |
| 446 | + |
| 447 | +// stderr - if non-empty |
| 448 | +iflen(err.String())>0 { |
| 449 | +fmt.Printf("%s",err.String()) |
| 450 | +} |
356 | 451 | case0x34: |
357 | 452 | debugPrintf("STRING_TOINT\n") |
358 | 453 |
|
@@ -454,6 +549,20 @@ func (c *CPU) Run() { |
454 | 549 | case0x50: |
455 | 550 | debugPrintf("NOP\n") |
456 | 551 | c.ip+=1 |
| 552 | +case0x51: |
| 553 | +debugPrintf("STORE\n") |
| 554 | + |
| 555 | +// register |
| 556 | +c.ip+=1 |
| 557 | +dst:=int(c.mem[c.ip]) |
| 558 | +c.ip+=1 |
| 559 | + |
| 560 | +// register |
| 561 | +src:=int(c.mem[c.ip]) |
| 562 | +c.ip+=1 |
| 563 | + |
| 564 | +c.regs[src]=c.regs[dst] |
| 565 | + |
457 | 566 | case0x60: |
458 | 567 | debugPrintf("PEEK\n") |
459 | 568 |
|
@@ -489,7 +598,6 @@ func (c *CPU) Run() { |
489 | 598 |
|
490 | 599 | debugPrintf("Writing %02X to %04X\n",val,addr) |
491 | 600 | c.mem[addr]=byte(val) |
492 | | - |
493 | 601 | case0x70: |
494 | 602 | debugPrintf("PUSH\n") |
495 | 603 |
|
|