diff --git a/drake/test1/main b/drake/test1/main new file mode 100755 index 0000000000000000000000000000000000000000..f184c09488f33bb06aa276cba7bcc7e9ca63bc0a Binary files /dev/null and b/drake/test1/main differ diff --git a/drake/test2/Makefile b/drake/test2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..915290724b2c3bc6af1a5483d87579d93ec409c0 --- /dev/null +++ b/drake/test2/Makefile @@ -0,0 +1,3 @@ + +all: + ls /doesntexist diff --git a/duck/duck.c b/duck/duck.c index 280eb9e4c44e6698c78d959312d884fe5604bc3a..3f52e8febb65bfc1e47fdc250608a4e312c9808c 100644 --- a/duck/duck.c +++ b/duck/duck.c @@ -82,15 +82,12 @@ int main(int argc, char **argv) } else if (strcmp(argv[i], "nod") == 0) { if (argv[i+1]) { int numnods = atoi(argv[i+1]); - shake(MOTOR_2, numnods, -90, 0, 250); + shake(MOTOR_2, numnods, 0, 90, 250); i++; } } else if (strcmp(argv[i], "facepalm") == 0) { - if (argv[i+1]) { - int numnods = atoi(argv[i+1]); - shake(MOTOR_2, numnods, -90, 0, 250); - i++; - } + duck_set_velocity(2, 30, 3000); + duck_delay(3000); } else if (strcmp(argv[i], "print") == 0) { if (argv[i+1]) { duck_write_text(argv[i+1]); diff --git a/gduckb/Makefile b/gduckb/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7862772b9554e78ccc2bc46cbdb4bfda3df98d3c --- /dev/null +++ b/gduckb/Makefile @@ -0,0 +1,2 @@ +gduckb: gduckb.c ../libduck/libduck.so + cc gduckb.c -o gduckb -L ../libduck -l duck -g diff --git a/gduckb/gdbinit b/gduckb/gdbinit new file mode 100644 index 0000000000000000000000000000000000000000..1ca4a9c7a12efa12040bd6201940058ed0061def --- /dev/null +++ b/gduckb/gdbinit @@ -0,0 +1,2 @@ +b main +r a.out diff --git a/gduckb/gduckb.c b/gduckb/gduckb.c new file mode 100644 index 0000000000000000000000000000000000000000..8efabd4a1b83b62279c1b7ffe7727fa6f31ca265 --- /dev/null +++ b/gduckb/gduckb.c @@ -0,0 +1,231 @@ +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#include <err.h> +#include <stdlib.h> +#include <poll.h> +#include <unistd.h> +#include <fcntl.h> +#include "../libduck/libduck.h" + +int this_in_gdb_out[2]; +int gdb_in_this_out[2]; + +void setup_pipes(void) +{ + if (pipe(gdb_in_this_out) || + pipe(this_in_gdb_out)) err(EXIT_FAILURE, "Pipe failed"); + /*this_in_gdb_out[0] = STDIN_FILENO; + gdb_in_this_out[1] = STDOUT_FILENO;*/ +} + +void launch_gdb(const char *prog) +{ + int res = fork(); + if (res < 0) { + err(EXIT_FAILURE, "fork failed"); + } else if (res == 0) { /* Child */ + dup2(gdb_in_this_out[0], STDIN_FILENO); + dup2(this_in_gdb_out[1], STDOUT_FILENO); + + if (execl("/bin/gdb", "/bin/gdb", "--interpreter=mi3", "-x", "gdbinit", prog, (char *)NULL)) { + err(EXIT_FAILURE, "Failed to launch gdb"); + } + } else { /* Parent */ + return; + } +} + +enum { + STATE_LINENO, STATE_WHITESPACE, STATE_CODE, STATE_NL +}; + +void process_code_line(const char *str) +{ + if (str[0] != '~' || str[1] != '"') return; + + int state = STATE_LINENO; + static char lineno_buf[20]; + int lb_ind = 0; + int lineno; + static char code_buf[200]; + int code_ind = 0; + int esc = 0; + + for (const char *c=str+2; *c; c++) { + switch (state) { + case STATE_LINENO: + if (isdigit(*c)) { + lineno_buf[lb_ind++] = *c; + } else if (c[0] == '\\' && c[1] == 't') { + lineno_buf[lb_ind] = 0; + lineno = atoi(lineno_buf); + if (lineno <= 0) return; + state = STATE_WHITESPACE; + c += 2; + } + break; + case STATE_WHITESPACE: + if (!isspace(*c)) { + state = STATE_CODE; + code_buf[code_ind++] = *c; + } + break; + case STATE_CODE: + if (esc) { + if (*c == 't') code_buf[code_ind++] = '\t'; + if (*c == '\\') code_buf[code_ind++] = '\\'; + if (*c == '"') code_buf[code_ind++] = '"'; + if (*c == '\'') code_buf[code_ind++] = '\''; + if (*c == 'n') state = STATE_NL; + esc = 0; + } else if (*c == '\\') { + esc = 1; + } else { + code_buf[code_ind++] = *c; + } + break; + case STATE_NL: + code_buf[code_ind] = 0; + duck_write_text(code_buf); + break; + } + } +} + +/* Line of code is last ~ line before prompt, matching line pattern */ + +enum { STATE_PROMPT, STATE_TILDE_LINE, STATE_OTHER_LINE }; + +void parse_line(const char *line) +{ + static int state = STATE_OTHER_LINE; + static char codelinebuf[200]; + + switch (state) { + case STATE_PROMPT: + if (line[0] == '~') { + state = STATE_TILDE_LINE; + strncpy(codelinebuf, line, 199); + } + break; + case STATE_TILDE_LINE: + if (line[0] != '~') { + state = STATE_OTHER_LINE; + process_code_line(codelinebuf); + } + break; + case STATE_OTHER_LINE: + if (strcmp(line, "(gdb)") == 0) { + state = STATE_PROMPT; + } + if (line[0] == '~') process_code_line(line); + break; + } +} + + +char buf[4096]; +int buf_ind = 0; + +char linebuf[200]; +int linebuf_ind = 0; + +void read_data(void) +{ + int n; + + if ((n=read(this_in_gdb_out[0], buf, 4065)) <= 0) { + return; + } else { + for (int i=0; i < n; i++) { + if (buf[i] == '\n') { + linebuf[linebuf_ind] = '\0'; + parse_line(linebuf); + linebuf_ind = 0; + } else { + linebuf[linebuf_ind++] = buf[i]; + } + } + } +} + +void sleep_ms(int ms) +{ + struct timespec ts = { + .tv_sec=ms/1000, .tv_nsec=(ms % 1000) * 1000000 + }; + nanosleep(&ts, NULL); +} + +void shake(int motor, int number, int min, int max, int delay) +{ + int delay1 = (delay * (-min)) / (max - min); + int delay2 = delay - delay1; + + duck_set_velocity(motor, 100, 100); + duck_delay(100); + duck_set_velocity(motor, -100, 200); + duck_delay(200); + duck_set_velocity(motor, 100, 100); + duck_delay(100); +} +int interact_gdb(void) +{ + FILE *to_gdb = fdopen(gdb_in_this_out[1], "w"); + if (!to_gdb) err(EXIT_FAILURE, "fdopen failed"); + setbuf(to_gdb, NULL); + + struct pollfd fds[] = { + { .fd = this_in_gdb_out[0], POLLIN, 0 }, + { .fd = duckfd, POLLIN, 0 }, + }; + + static char tmp[4096]; + + /*read(this_in_gdb_out[0], tmp, 4096); + fprintf(to_gdb, "b main\n"); + sleep_ms(300); + read(this_in_gdb_out[0], tmp, 4096); + fprintf(to_gdb, "r\n");*/ + sleep_ms(300); + + while (1) { + if (poll(fds, 2, -1)) { + if (fds[0].revents) { + read_data(); + fds[0].revents = 0; + } + if (fds[1].revents) { + int c = duck_getc(); + fprintf(to_gdb, c == 'a' ? "s\n" : "n\n"); + shake(MOTOR_1, 2, -20, 20, 200); + fds[1].revents = 0; + } + } + } +} + + + +int main(int argc, char **argv) +{ + duck_debug_mode = 0; + if (argc < 2) { + printf("Usage: gduckb program-name\n"); + return -1; + } + + setup_pipes(); + launch_gdb("a.out"); + open_duck(DEFAULT_DUCK_FNAME); + configure_duck(); + + if (interact_gdb()) { + err(EXIT_FAILURE, "gdb interaction failed"); + } + close_duck(); + return 0; + +} diff --git a/libduck/libduck.c b/libduck/libduck.c index d0e210f6dd936bb2ec60e724ba460b765bd612cb..f967f3fb039f1d5bdf7797ae8877c32cc4eb2f85 100644 --- a/libduck/libduck.c +++ b/libduck/libduck.c @@ -11,14 +11,14 @@ # define DUCK_BAUD B115200 #endif /* DUCK_BAUD */ -static int duckfd = 0; +int duckfd = 0; int duck_debug_mode = 0; void open_duck(const char *fname) { if (duck_debug_mode) { - printf("Opening duck\n"); + fprintf(stderr, "Opening duck\n"); } else { duckfd = open(fname, O_NOCTTY | O_RDWR); @@ -31,7 +31,7 @@ void open_duck(const char *fname) void configure_duck(void) { if (duck_debug_mode) { - printf("Configuring duck\n"); + fprintf(stderr, "Configuring duck\n"); } else { struct termios tio; if (tcgetattr(duckfd, &tio)) { @@ -51,7 +51,7 @@ static int duck_printf(const char *fmt, ...) va_list ap; va_start(ap, fmt); if (duck_debug_mode) { - return vprintf(fmt, ap); + return vfprintf(stderr, fmt, ap); } else { return vdprintf(duckfd, fmt, ap) < 0; } @@ -103,10 +103,17 @@ void read_duck_to_stdout(void) } } +int duck_getc(void) +{ + char c; + if (read(duckfd, &c, 1)) return c; + else return EOF; +} + void close_duck(void) { if (duck_debug_mode) { - printf("Closing duck\n"); + fprintf(stderr, "Closing duck\n"); } else { close(duckfd); } diff --git a/libduck/libduck.h b/libduck/libduck.h index 9ce01667bf2b107d35497b1a3b4a7de3b95fa6bf..524c3de95e56a5f2baddeeb07c1af29aa4acbdc8 100644 --- a/libduck/libduck.h +++ b/libduck/libduck.h @@ -10,6 +10,7 @@ #endif /* DEFAULT_DUCK_FNAME */ extern int duck_debug_mode; +extern int duckfd; void open_duck(const char *fname); void configure_duck(void); @@ -18,6 +19,7 @@ int duck_delay(int ms); int duck_set_velocity(int motor, int deg_per_sec, int ms); int duck_write_text(const char *str); void read_duck_to_stdout(void); +int duck_getc(void); void close_duck(void); #endif /* _LIBDUCK_H */