debugging, but closer to working
This commit is contained in:
parent
8360ee899b
commit
931f3652e8
|
@ -32,9 +32,9 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
WITH REGARD TO THIS SOFTWARE.
|
WITH REGARD TO THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CONSOLE_DEBUG 0
|
#define CONSOLE_DEBUG 1
|
||||||
|
|
||||||
static UxnSubprocess children[CONSOLE_MAX_CHILDREN];
|
UxnSubprocess children[CONSOLE_MAX_CHILDREN];
|
||||||
static char *fork_args[4] = {"/bin/sh", "-c", "", NULL};
|
static char *fork_args[4] = {"/bin/sh", "-c", "", NULL};
|
||||||
static int to_child_fd[2], from_child_fd[2];
|
static int to_child_fd[2], from_child_fd[2];
|
||||||
static char buf[16];
|
static char buf[16];
|
||||||
|
@ -94,8 +94,8 @@ start_fork_pty(UxnSubprocess *child, int mode)
|
||||||
} else { /*parent*/
|
} else { /*parent*/
|
||||||
do {
|
do {
|
||||||
child->pid = pid;
|
child->pid = pid;
|
||||||
child->running = 1;
|
|
||||||
child->mode = mode;
|
child->mode = mode;
|
||||||
|
child->running = 1;
|
||||||
child->pty = fd;
|
child->pty = fd;
|
||||||
child->fd_in = fd;
|
child->fd_in = fd;
|
||||||
child->fd_out = fd;
|
child->fd_out = fd;
|
||||||
|
@ -106,6 +106,7 @@ start_fork_pty(UxnSubprocess *child, int mode)
|
||||||
static void
|
static void
|
||||||
start_fork_pipe(UxnSubprocess *child, int mode)
|
start_fork_pipe(UxnSubprocess *child, int mode)
|
||||||
{
|
{
|
||||||
|
//printf("start_fork_pipe(..., %d)\n", mode);
|
||||||
if(child_reads(mode)) {
|
if(child_reads(mode)) {
|
||||||
/* parent writes to child's stdin */
|
/* parent writes to child's stdin */
|
||||||
if(pipe(to_child_fd) == -1) {
|
if(pipe(to_child_fd) == -1) {
|
||||||
|
@ -143,15 +144,23 @@ start_fork_pipe(UxnSubprocess *child, int mode)
|
||||||
child->pid = pid;
|
child->pid = pid;
|
||||||
child->mode = mode;
|
child->mode = mode;
|
||||||
child->running = 1;
|
child->running = 1;
|
||||||
|
child->pty = -1;
|
||||||
child->fd_in = child_reads(mode) ? to_child_fd[1] : -1;
|
child->fd_in = child_reads(mode) ? to_child_fd[1] : -1;
|
||||||
child->fd_out = child_writes(mode) ? from_child_fd[0] : -1;
|
child->fd_out = child_writes(mode) ? from_child_fd[0] : -1;
|
||||||
child->pty = -1;
|
|
||||||
} while (child->pid != pid);
|
} while (child->pid != pid);
|
||||||
|
//printf("child %d: pid=%d mode=%d running=%d in=%d out=%d\n", child->id, child->pid, child->mode, child->running, child->fd_in, child->fd_out);
|
||||||
if(CONSOLE_DEBUG)
|
if(CONSOLE_DEBUG)
|
||||||
fprintf(stderr, "child has pid %d\n", child->pid);
|
fprintf(stderr, "child has pid %d\n", child->pid);
|
||||||
if(child_reads(mode)) close(to_child_fd[0]);
|
if(child_reads(mode)) close(to_child_fd[0]);
|
||||||
if(child_writes(mode)) close(from_child_fd[1]);
|
if(child_writes(mode)) close(from_child_fd[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* /\* TODO *\/ */
|
||||||
|
/* for(int n = 0; n < CONSOLE_MAX_CHILDREN; n++) { */
|
||||||
|
/* UxnSubprocess *child = &children[n]; */
|
||||||
|
/* printf("child: %d/%d (%d, %d)\n", n, child->id, child->fd_out, child->pid); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -197,8 +206,8 @@ static void
|
||||||
host_response(Uxn *u, char *s)
|
host_response(Uxn *u, char *s)
|
||||||
{
|
{
|
||||||
for(int i = 0;; i++)
|
for(int i = 0;; i++)
|
||||||
console_input(u, s[i], CONSOLE_HOST);
|
console_input(u, 0x5, s[i], CONSOLE_HOST);
|
||||||
console_input(u, '\0', CONSOLE_HOST_END);
|
console_input(u, 0x5, '\0', CONSOLE_HOST_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -280,21 +289,22 @@ console_monitor(Uxn *u)
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
for(int n = 0; n < CONSOLE_MAX_CHILDREN; n++) {
|
for(int n = 0; n < CONSOLE_MAX_CHILDREN; n++) {
|
||||||
UxnSubprocess *child = &children[n];
|
UxnSubprocess *child = &children[n];
|
||||||
|
/* printf("child: %d/%d (%d, %d)\n", n, child->id, child->fd_out, child->pid); */
|
||||||
if(child->running < 0) {
|
if(child->running < 0) {
|
||||||
/* printf("child ready for clean up: %d\n", n); */
|
/* printf("child ready for clean up: %d\n", n); */
|
||||||
/* fflush(stdout); */
|
/* fflush(stdout); */
|
||||||
Uint8 status = child->running + 256;
|
Uint8 status = child->running + 256;
|
||||||
child->running = 0;
|
child->running = 0;
|
||||||
console_input(u, status, CONSOLE_CHILD_EXIT | n);
|
console_input(u, 0x4, status, CONSOLE_CHILD_EXIT | n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
console_input(Uxn *u, char c, int type)
|
console_input(Uxn *u, int port, char c, int type)
|
||||||
{
|
{
|
||||||
Uint8 *d = &u->dev[0x10];
|
Uint8 *d = &u->dev[0x10];
|
||||||
d[0x2] = c;
|
d[port] = c;
|
||||||
d[0x7] = type;
|
d[0x7] = type;
|
||||||
return uxn_eval(u, PEEK2(d));
|
return uxn_eval(u, PEEK2(d));
|
||||||
}
|
}
|
||||||
|
@ -304,8 +314,8 @@ console_listen(Uxn *u, int i, int argc, char **argv)
|
||||||
{
|
{
|
||||||
for(; i < argc; i++) {
|
for(; i < argc; i++) {
|
||||||
char *p = argv[i];
|
char *p = argv[i];
|
||||||
while(*p) console_input(u, *p++, CONSOLE_ARG);
|
while(*p) console_input(u, 0x2, *p++, CONSOLE_ARG);
|
||||||
console_input(u, '\n', i == argc - 1 ? CONSOLE_ARG_END : CONSOLE_ARG_SPACER);
|
console_input(u, 0x2, '\n', i == argc - 1 ? CONSOLE_ARG_END : CONSOLE_ARG_SPACER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ typedef struct UxnSubprocess {
|
||||||
void init_console(void);
|
void init_console(void);
|
||||||
UxnSubprocess *get_child(int n);
|
UxnSubprocess *get_child(int n);
|
||||||
void console_monitor(Uxn *u);
|
void console_monitor(Uxn *u);
|
||||||
int console_input(Uxn *u, char c, int type);
|
int console_input(Uxn *u, int port, char c, int type);
|
||||||
void console_listen(Uxn *u, int i, int argc, char **argv);
|
void console_listen(Uxn *u, int i, int argc, char **argv);
|
||||||
Uint8 console_dei(Uxn *u, Uint8 addr);
|
Uint8 console_dei(Uxn *u, Uint8 addr);
|
||||||
void console_deo(Uxn *u, Uint8 *d, Uint8 port);
|
void console_deo(Uxn *u, Uint8 *d, Uint8 port);
|
||||||
|
|
10
src/uxn11.c
10
src/uxn11.c
|
@ -150,16 +150,16 @@ toggle_scale(Uxn *u)
|
||||||
|
|
||||||
/* returns true if the fd ended (has been closed), false otherwise */
|
/* returns true if the fd ended (has been closed), false otherwise */
|
||||||
static int
|
static int
|
||||||
handle_input(Uxn *u, struct pollfd pollfd, char *coninp, int argdata, int argend)
|
handle_input(Uxn *u, struct pollfd pollfd, int port, char *coninp, int argdata, int argend)
|
||||||
{
|
{
|
||||||
if((pollfd.revents & POLLIN) != 0) {
|
if((pollfd.revents & POLLIN) != 0) {
|
||||||
int n = read(pollfd.fd, coninp, CONINBUFSIZE - 1);
|
int n = read(pollfd.fd, coninp, CONINBUFSIZE - 1);
|
||||||
coninp[n] = 0;
|
coninp[n] = 0;
|
||||||
if(n == 0)
|
if(n == 0)
|
||||||
console_input(u, 0, argend);
|
console_input(u, port, 0, argend);
|
||||||
else
|
else
|
||||||
for(int i = 0; i < n; i++)
|
for(int i = 0; i < n; i++)
|
||||||
console_input(u, coninp[i], argdata);
|
console_input(u, port, coninp[i], argdata);
|
||||||
return n == 0;
|
return n == 0;
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -289,11 +289,11 @@ emu_run(Uxn *u, char *rom)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read input from stdin */
|
/* read input from stdin */
|
||||||
handle_input(u, fds[2], coninp, CONSOLE_STDIN, CONSOLE_STDIN_END);
|
handle_input(u, fds[2], 0x2, coninp, CONSOLE_STDIN, CONSOLE_STDIN_END);
|
||||||
|
|
||||||
/* read input from child processes */
|
/* read input from child processes */
|
||||||
for(i = 0; i < 4; i++)
|
for(i = 0; i < 4; i++)
|
||||||
handle_input(u, fds[i + 3], coninp, CONSOLE_CHILD_DATA | i, CONSOLE_CHILD_END | i);
|
handle_input(u, fds[i + 3], 0x4, coninp, CONSOLE_CHILD_DATA | i, CONSOLE_CHILD_END | i);
|
||||||
|
|
||||||
/* check to see if any children exited */
|
/* check to see if any children exited */
|
||||||
console_monitor(u);
|
console_monitor(u);
|
||||||
|
|
24
src/uxncli.c
24
src/uxncli.c
|
@ -46,15 +46,15 @@ emu_deo(Uxn *u, Uint8 addr, Uint8 value)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_input(Uxn *u, int fd, int argdata, int argend)
|
handle_input(Uxn *u, int fd, int port, int argdata, int argend)
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
int n = read(fd, &buf, 32);
|
int n = read(fd, &buf, 32);
|
||||||
if(n == 0)
|
if(n == 0)
|
||||||
console_input(u, 0x00, argend);
|
console_input(u, port, 0x00, argend);
|
||||||
else
|
else
|
||||||
for(int i = 0; i < n; i++)
|
for(int i = 0; i < n; i++)
|
||||||
console_input(u, buf[i], argdata);
|
console_input(u, port, buf[i], argdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -65,9 +65,15 @@ init_rfds(fd_set *rfds)
|
||||||
FD_SET(0, rfds);
|
FD_SET(0, rfds);
|
||||||
nfds = 1;
|
nfds = 1;
|
||||||
for(i = 0; i < 4; i++) {
|
for(i = 0; i < 4; i++) {
|
||||||
int fd = get_child(i)->fd_out;
|
UxnSubprocess *child = get_child(i);
|
||||||
|
int fd = child->fd_out;
|
||||||
|
if (fd >= 0) {
|
||||||
|
/* printf("ok: %d/%d (%d, %d)\n", i, child->id, fd, child->pid); */
|
||||||
FD_SET(fd, rfds);
|
FD_SET(fd, rfds);
|
||||||
if (fd >= nfds) nfds = fd + 1;
|
if (fd >= nfds) nfds = fd + 1;
|
||||||
|
/* } else { */
|
||||||
|
/* printf("nope: %d/%d (%d, %d)\n", i, child->id, fd, child->pid); */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nfds;
|
return nfds;
|
||||||
}
|
}
|
||||||
|
@ -78,19 +84,20 @@ emu_run(Uxn *u)
|
||||||
int i;
|
int i;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
init_console();
|
|
||||||
while(!u->dev[0x0f]) {
|
while(!u->dev[0x0f]) {
|
||||||
int nfds = init_rfds(&rfds);
|
int nfds = init_rfds(&rfds);
|
||||||
tv.tv_sec = 0;
|
/* tv.tv_sec = 0; */
|
||||||
|
tv.tv_sec = 1;
|
||||||
tv.tv_usec = 1000;
|
tv.tv_usec = 1000;
|
||||||
int retval = select(nfds, &rfds, NULL, NULL, &tv);
|
int retval = select(nfds, &rfds, NULL, NULL, &tv);
|
||||||
if(retval > 0) {
|
if(retval > 0) {
|
||||||
|
/* printf("got something!\n"); */
|
||||||
if (FD_ISSET(0, &rfds))
|
if (FD_ISSET(0, &rfds))
|
||||||
handle_input(u, 0, CONSOLE_STDIN, CONSOLE_STDIN_END);
|
handle_input(u, 0, 0x2, CONSOLE_STDIN, CONSOLE_STDIN_END);
|
||||||
for(i = 0; i < 4; i++) {
|
for(i = 0; i < 4; i++) {
|
||||||
int fd = get_child(i)->fd_out;
|
int fd = get_child(i)->fd_out;
|
||||||
if (fd > 2 && FD_ISSET(fd, &rfds))
|
if (fd > 2 && FD_ISSET(fd, &rfds))
|
||||||
handle_input(u, fd, CONSOLE_CHILD_DATA | i, CONSOLE_CHILD_END | i);
|
handle_input(u, fd, 0x4, CONSOLE_CHILD_DATA | i, CONSOLE_CHILD_END | i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console_monitor(u);
|
console_monitor(u);
|
||||||
|
@ -118,6 +125,7 @@ main(int argc, char **argv)
|
||||||
return system_error("Init", "Failed to initialize uxn.");
|
return system_error("Init", "Failed to initialize uxn.");
|
||||||
/* Game Loop */
|
/* Game Loop */
|
||||||
u.dev[0x17] = argc - i;
|
u.dev[0x17] = argc - i;
|
||||||
|
init_console();
|
||||||
if(uxn_eval(&u, PAGE_PROGRAM)) {
|
if(uxn_eval(&u, PAGE_PROGRAM)) {
|
||||||
console_listen(&u, i, argc, argv);
|
console_listen(&u, i, argc, argv);
|
||||||
emu_run(&u);
|
emu_run(&u);
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
|10 @Console [
|
||||||
|
&vector $2 &stdin $1 &pad1 $1 &proc-get $1 &host-get $1 &pad2 $1 &type $1
|
||||||
|
&stdout $1 &stderr $1 &proc-put $1 &pad3 $1 ¶m $2 &opts $1 &host-put $1
|
||||||
|
]
|
||||||
|
|
||||||
|
|0000
|
||||||
|
@word-buf $100
|
||||||
|
@word-pos $2
|
||||||
|
@spelled-ok $1 ( ; was the last word spelled ok? )
|
||||||
|
@resume $2 ( ; if set should have effect ` -- BRK` )
|
||||||
|
|
||||||
|
|0100 ( -> BRK )
|
||||||
|
;on-console-init .Console/vector DEO2 ( ; set up console vector callback )
|
||||||
|
init-ispell ( ; set up ispell child process )
|
||||||
|
word-reset BRK
|
||||||
|
|
||||||
|
@init-ispell ( -- )
|
||||||
|
LIT "! print
|
||||||
|
#31 .Console/opts DEO ( ; child 1: write to stdin, read from stdout )
|
||||||
|
;ispell-cmd .Console/param DEO2 ( ; set up `ispell -a` to run )
|
||||||
|
#01 .Console/host-put DEO JMP2r ( ; run the command now and return )
|
||||||
|
|
||||||
|
@on-console-init ( -- BRK )
|
||||||
|
( LIT "? print )
|
||||||
|
.Console/type DEI #21 EQU ?{ LIT "u print BRK } ( ; 0x21 signals input from child 1 )
|
||||||
|
( LIT ". print )
|
||||||
|
( .Console/proc-get DEI emit/byte )
|
||||||
|
.Console/proc-get DEI #0a EQU ?{ BRK } ( ; skip ispell's one line banner )
|
||||||
|
LIT "> print
|
||||||
|
;on-console-read .Console/vector DEO2 ( ; finished banner, checker is ready )
|
||||||
|
BRK
|
||||||
|
|
||||||
|
@word-reset ( -> )
|
||||||
|
;word-buf ;word-pos STA2 ( ; reset word-pos pointer )
|
||||||
|
#00 ;word-buf STA JMP2r ( ; write zero into word buffer )
|
||||||
|
|
||||||
|
@on-console-read
|
||||||
|
LIT ", print
|
||||||
|
( .Console/type emit/byte )
|
||||||
|
.Console/type DEI #21 EQU ?on-ispell-input
|
||||||
|
.Console/type DEI #01 EQU ?on-stdin
|
||||||
|
BRK
|
||||||
|
|
||||||
|
@on-stdin
|
||||||
|
.Console/stdin DEI DUP #0a NEQ ?word-append
|
||||||
|
POP ;word-buf ;finish !check-spelling
|
||||||
|
|
||||||
|
@on-ispell-input ( -> BRK )
|
||||||
|
LIT "i print
|
||||||
|
.Console/proc-get DEI emit/byte
|
||||||
|
.Console/proc-get DEI LIT "* EQU ( ; line starting with "*" means ok )
|
||||||
|
.spelled-ok STZ ( ; store spelling result )
|
||||||
|
LIT "- print LIT "0 .spelled-ok LDZ ADD print
|
||||||
|
#00 ,on-ispell-drain/done STR ( ; drain two lines )
|
||||||
|
;on-ispell-drain .Console/vector DEO2 ( ; ignore rest of line )
|
||||||
|
BRK
|
||||||
|
|
||||||
|
@word-append ( c^ -> BRK )
|
||||||
|
LIT "% print
|
||||||
|
DUP print
|
||||||
|
;word-pos LDA2 STA ( ; pos<-c )
|
||||||
|
;word-pos LDA2 INC2 ;word-pos STA2 ( ; pos<-pos+1 )
|
||||||
|
#00 ;word-pos LDA2 STA BRK ( ; pos<-00 )
|
||||||
|
|
||||||
|
@finish ( -> BRK )
|
||||||
|
LIT "f print
|
||||||
|
LIT "0 .spelled-ok LDZ ADD println
|
||||||
|
LIT "> print
|
||||||
|
word-reset BRK
|
||||||
|
|
||||||
|
@ispell-cmd "ispell 20 "-a 00 ( ; "ispell -a" )
|
||||||
|
|
||||||
|
@on-ispell-drain ( -- BRK )
|
||||||
|
LIT "d print
|
||||||
|
.Console/type DEI #21 EQU ?{ BRK } ( ; 0x21 signals input from child 1 )
|
||||||
|
.Console/proc-get DEI #0a EQU ?{ BRK } ( ; skip ispell's outupt )
|
||||||
|
LIT [ &done $1 ] ?{ ( ; is this the second newline? )
|
||||||
|
#01 ,on-ispell-drain/done STR BRK ( ; no, but next one will be. )
|
||||||
|
}
|
||||||
|
;on-console-read .Console/vector DEO2 ( ; drain finished, checker is ready )
|
||||||
|
;resume LDA2 JMP2 ( ; resume whatever we wanted to do after checking )
|
||||||
|
|
||||||
|
@check-spelling ( word* continue* -- BRK )
|
||||||
|
LIT "$ print
|
||||||
|
;resume STA2 ( ; write continuation to resume )
|
||||||
|
#01 .Console/opts DEO ( ; act on child 1 )
|
||||||
|
LIT "< print
|
||||||
|
&loop LIT ": print LDAk ( #00 NEQ ) ?{
|
||||||
|
POP2
|
||||||
|
"> print
|
||||||
|
#0a .Console/proc-put DEO BRK
|
||||||
|
} ( ; when we read \0 we are done )
|
||||||
|
LDAk print
|
||||||
|
LDAk .Console/proc-put DEO INC2 !&loop ( ; send byte to child 1 and loop )
|
||||||
|
|
||||||
|
@print
|
||||||
|
.Console/stdout DEO JMP2r
|
||||||
|
|
||||||
|
@println
|
||||||
|
.Console/stdout DEO #0a .Console/stdout DEO JMP2r
|
||||||
|
|
||||||
|
@emit
|
||||||
|
&long SWP2 ,&short JSR
|
||||||
|
&short SWP ,&byte JSR
|
||||||
|
&byte DUP #04 SFT ,&char JSR
|
||||||
|
&char #0f AND DUP #09 GTH #27 MUL ADD #30 ADD #18 DEO
|
||||||
|
JMP2r
|
Loading…
Reference in New Issue