Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/avrdude/term.c')
-rw-r--r--src/avrdude/term.c957
1 files changed, 957 insertions, 0 deletions
diff --git a/src/avrdude/term.c b/src/avrdude/term.c
new file mode 100644
index 000000000..012f6f1a5
--- /dev/null
+++ b/src/avrdude/term.c
@@ -0,0 +1,957 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* $Id$ */
+
+#include "ac_cfg.h"
+
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#if defined(HAVE_LIBREADLINE)
+#if !defined(WIN32NATIVE)
+# include <readline/readline.h>
+# include <readline/history.h>
+#endif
+#endif
+
+#include "avrdude.h"
+#include "term.h"
+
+struct command {
+ char * name;
+ int (*func)(PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
+ char * desc;
+};
+
+
+static int cmd_dump (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_write (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_erase (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_sig (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_part (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_help (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_quit (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_send (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_parms (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_vtarg (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_varef (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_fosc (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_sck (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_spi (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_pgm (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+static int cmd_verbose (PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char *argv[]);
+
+struct command cmd[] = {
+ { "dump", cmd_dump, "dump memory : %s <memtype> <addr> <N-Bytes>" },
+ { "read", cmd_dump, "alias for dump" },
+ { "write", cmd_write, "write memory : %s <memtype> <addr> <b1> <b2> ... <bN>" },
+ { "erase", cmd_erase, "perform a chip erase" },
+ { "sig", cmd_sig, "display device signature bytes" },
+ { "part", cmd_part, "display the current part information" },
+ { "send", cmd_send, "send a raw command : %s <b1> <b2> <b3> <b4>" },
+ { "parms", cmd_parms, "display adjustable parameters (STK500 only)" },
+ { "vtarg", cmd_vtarg, "set <V[target]> (STK500 only)" },
+ { "varef", cmd_varef, "set <V[aref]> (STK500 only)" },
+ { "fosc", cmd_fosc, "set <oscillator frequency> (STK500 only)" },
+ { "sck", cmd_sck, "set <SCK period> (STK500 only)" },
+ { "spi", cmd_spi, "enter direct SPI mode" },
+ { "pgm", cmd_pgm, "return to programming mode" },
+ { "verbose", cmd_verbose, "change verbosity" },
+ { "help", cmd_help, "help" },
+ { "?", cmd_help, "help" },
+ { "quit", cmd_quit, "quit" }
+};
+
+#define NCMDS (sizeof(cmd)/sizeof(struct command))
+
+
+
+static int spi_mode = 0;
+
+static int nexttok(char * buf, char ** tok, char ** next)
+{
+ char * q, * n;
+
+ q = buf;
+ while (isspace((int)*q))
+ q++;
+
+ /* isolate first token */
+ n = q+1;
+ while (*n && !isspace((int)*n))
+ n++;
+
+ if (*n) {
+ *n = 0;
+ n++;
+ }
+
+ /* find start of next token */
+ while (isspace((int)*n))
+ n++;
+
+ *tok = q;
+ *next = n;
+
+ return 0;
+}
+
+
+static int hexdump_line(char * buffer, unsigned char * p, int n, int pad)
+{
+ char * hexdata = "0123456789abcdef";
+ char * b;
+ int i, j;
+
+ b = buffer;
+
+ j = 0;
+ for (i=0; i<n; i++) {
+ if (i && ((i % 8) == 0))
+ b[j++] = ' ';
+ b[j++] = hexdata[(p[i] & 0xf0) >> 4];
+ b[j++] = hexdata[(p[i] & 0x0f)];
+ if (i < 15)
+ b[j++] = ' ';
+ }
+
+ for (i=j; i<pad; i++)
+ b[i] = ' ';
+
+ b[i] = 0;
+
+ for (i=0; i<pad; i++) {
+ if (!((b[i] == '0') || (b[i] == ' ')))
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static int chardump_line(char * buffer, unsigned char * p, int n, int pad)
+{
+ int i;
+ char b [ 128 ];
+
+ for (i=0; i<n; i++) {
+ memcpy(b, p, n);
+ buffer[i] = '.';
+ if (isalpha((int)(b[i])) || isdigit((int)(b[i])) || ispunct((int)(b[i])))
+ buffer[i] = b[i];
+ else if (isspace((int)(b[i])))
+ buffer[i] = ' ';
+ }
+
+ for (i=n; i<pad; i++)
+ buffer[i] = ' ';
+
+ buffer[i] = 0;
+
+ return 0;
+}
+
+
+static int hexdump_buf(FILE * f, int startaddr, unsigned char * buf, int len)
+{
+ int addr;
+ int n;
+ unsigned char * p;
+ char dst1[80];
+ char dst2[80];
+
+ addr = startaddr;
+ p = (unsigned char *)buf;
+ while (len) {
+ n = 16;
+ if (n > len)
+ n = len;
+ hexdump_line(dst1, p, n, 48);
+ chardump_line(dst2, p, n, 16);
+ fprintf(stdout, "%04x %s |%s|\n", addr, dst1, dst2);
+ len -= n;
+ addr += n;
+ p += n;
+ }
+
+ return 0;
+}
+
+
+static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ static char prevmem[128] = {0};
+ char * e;
+ unsigned char * buf;
+ int maxsize;
+ unsigned long i;
+ static unsigned long addr=0;
+ static int len=64;
+ AVRMEM * mem;
+ char * memtype = NULL;
+ int rc;
+
+ if (!((argc == 2) || (argc == 4))) {
+ avrdude_message(MSG_INFO, "Usage: dump <memtype> [<addr> <len>]\n");
+ return -1;
+ }
+
+ memtype = argv[1];
+
+ if (strncmp(prevmem, memtype, strlen(memtype)) != 0) {
+ addr = 0;
+ len = 64;
+ strncpy(prevmem, memtype, sizeof(prevmem)-1);
+ prevmem[sizeof(prevmem)-1] = 0;
+ }
+
+ mem = avr_locate_mem(p, memtype);
+ if (mem == NULL) {
+ avrdude_message(MSG_INFO, "\"%s\" memory type not defined for part \"%s\"\n",
+ memtype, p->desc);
+ return -1;
+ }
+
+ if (argc == 4) {
+ addr = strtoul(argv[2], &e, 0);
+ if (*e || (e == argv[2])) {
+ avrdude_message(MSG_INFO, "%s (dump): can't parse address \"%s\"\n",
+ progname, argv[2]);
+ return -1;
+ }
+
+ len = strtol(argv[3], &e, 0);
+ if (*e || (e == argv[3])) {
+ avrdude_message(MSG_INFO, "%s (dump): can't parse length \"%s\"\n",
+ progname, argv[3]);
+ return -1;
+ }
+ }
+
+ maxsize = mem->size;
+
+ if (addr >= maxsize) {
+ if (argc == 2) {
+ /* wrap around */
+ addr = 0;
+ }
+ else {
+ avrdude_message(MSG_INFO, "%s (dump): address 0x%05lx is out of range for %s memory\n",
+ progname, addr, mem->desc);
+ return -1;
+ }
+ }
+
+ /* trim len if nessary to not read past the end of memory */
+ if ((addr + len) > maxsize)
+ len = maxsize - addr;
+
+ buf = malloc(len);
+ if (buf == NULL) {
+ avrdude_message(MSG_INFO, "%s (dump): out of memory\n", progname);
+ return -1;
+ }
+
+ for (i=0; i<len; i++) {
+ rc = pgm->read_byte(pgm, p, mem, addr+i, &buf[i]);
+ if (rc != 0) {
+ avrdude_message(MSG_INFO, "error reading %s address 0x%05lx of part %s\n",
+ mem->desc, addr+i, p->desc);
+ if (rc == -1)
+ avrdude_message(MSG_INFO, "read operation not supported on memory type \"%s\"\n",
+ mem->desc);
+ return -1;
+ }
+ }
+
+ hexdump_buf(stdout, addr, buf, len);
+
+ fprintf(stdout, "\n");
+
+ free(buf);
+
+ addr = addr + len;
+
+ return 0;
+}
+
+
+static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ char * e;
+ int len, maxsize;
+ char * memtype;
+ unsigned long addr, i;
+ unsigned char * buf;
+ unsigned char b;
+ int rc;
+ int werror;
+ AVRMEM * mem;
+
+ if (argc < 4) {
+ avrdude_message(MSG_INFO, "Usage: write <memtype> <addr> <byte1> "
+ "<byte2> ... byteN>\n");
+ return -1;
+ }
+
+ memtype = argv[1];
+
+ mem = avr_locate_mem(p, memtype);
+ if (mem == NULL) {
+ avrdude_message(MSG_INFO, "\"%s\" memory type not defined for part \"%s\"\n",
+ memtype, p->desc);
+ return -1;
+ }
+
+ maxsize = mem->size;
+
+ addr = strtoul(argv[2], &e, 0);
+ if (*e || (e == argv[2])) {
+ avrdude_message(MSG_INFO, "%s (write): can't parse address \"%s\"\n",
+ progname, argv[2]);
+ return -1;
+ }
+
+ if (addr > maxsize) {
+ avrdude_message(MSG_INFO, "%s (write): address 0x%05lx is out of range for %s memory\n",
+ progname, addr, memtype);
+ return -1;
+ }
+
+ /* number of bytes to write at the specified address */
+ len = argc - 3;
+
+ if ((addr + len) > maxsize) {
+ avrdude_message(MSG_INFO, "%s (write): selected address and # bytes exceed "
+ "range for %s memory\n",
+ progname, memtype);
+ return -1;
+ }
+
+ buf = malloc(len);
+ if (buf == NULL) {
+ avrdude_message(MSG_INFO, "%s (write): out of memory\n", progname);
+ return -1;
+ }
+
+ for (i=3; i<argc; i++) {
+ buf[i-3] = strtoul(argv[i], &e, 0);
+ if (*e || (e == argv[i])) {
+ avrdude_message(MSG_INFO, "%s (write): can't parse byte \"%s\"\n",
+ progname, argv[i]);
+ free(buf);
+ return -1;
+ }
+ }
+
+ pgm->err_led(pgm, OFF);
+ for (werror=0, i=0; i<len; i++) {
+
+ rc = avr_write_byte(pgm, p, mem, addr+i, buf[i]);
+ if (rc) {
+ avrdude_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n",
+ progname, buf[i], addr+i, rc);
+ if (rc == -1)
+ avrdude_message(MSG_INFO, "write operation not supported on memory type \"%s\"\n",
+ mem->desc);
+ werror = 1;
+ }
+
+ rc = pgm->read_byte(pgm, p, mem, addr+i, &b);
+ if (b != buf[i]) {
+ avrdude_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n",
+ progname, buf[i], addr+i, b);
+ werror = 1;
+ }
+
+ if (werror) {
+ pgm->err_led(pgm, ON);
+ }
+ }
+
+ free(buf);
+
+ fprintf(stdout, "\n");
+
+ return 0;
+}
+
+
+static int cmd_send(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ unsigned char cmd[4], res[4];
+ char * e;
+ int i;
+ int len;
+
+ if (pgm->cmd == NULL) {
+ avrdude_message(MSG_INFO, "The %s programmer does not support direct ISP commands.\n",
+ pgm->type);
+ return -1;
+ }
+
+ if (spi_mode && (pgm->spi == NULL)) {
+ avrdude_message(MSG_INFO, "The %s programmer does not support direct SPI transfers.\n",
+ pgm->type);
+ return -1;
+ }
+
+
+ if ((argc > 5) || ((argc < 5) && (!spi_mode))) {
+ avrdude_message(MSG_INFO, spi_mode?
+ "Usage: send <byte1> [<byte2> [<byte3> [<byte4>]]]\n":
+ "Usage: send <byte1> <byte2> <byte3> <byte4>\n");
+ return -1;
+ }
+
+ /* number of bytes to write at the specified address */
+ len = argc - 1;
+
+ /* load command bytes */
+ for (i=1; i<argc; i++) {
+ cmd[i-1] = strtoul(argv[i], &e, 0);
+ if (*e || (e == argv[i])) {
+ avrdude_message(MSG_INFO, "%s (send): can't parse byte \"%s\"\n",
+ progname, argv[i]);
+ return -1;
+ }
+ }
+
+ pgm->err_led(pgm, OFF);
+
+ if (spi_mode)
+ pgm->spi(pgm, cmd, res, argc-1);
+ else
+ pgm->cmd(pgm, cmd, res);
+
+ /*
+ * display results
+ */
+ avrdude_message(MSG_INFO, "results:");
+ for (i=0; i<len; i++)
+ avrdude_message(MSG_INFO, " %02x", res[i]);
+ avrdude_message(MSG_INFO, "\n");
+
+ fprintf(stdout, "\n");
+
+ return 0;
+}
+
+
+static int cmd_erase(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ avrdude_message(MSG_INFO, "%s: erasing chip\n", progname);
+ pgm->chip_erase(pgm, p);
+ return 0;
+}
+
+
+static int cmd_part(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ fprintf(stdout, "\n");
+ avr_display(stdout, p, "", 0);
+ fprintf(stdout, "\n");
+
+ return 0;
+}
+
+
+static int cmd_sig(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ int i;
+ int rc;
+ AVRMEM * m;
+
+ rc = avr_signature(pgm, p);
+ if (rc != 0) {
+ avrdude_message(MSG_INFO, "error reading signature data, rc=%d\n",
+ rc);
+ }
+
+ m = avr_locate_mem(p, "signature");
+ if (m == NULL) {
+ avrdude_message(MSG_INFO, "signature data not defined for device \"%s\"\n",
+ p->desc);
+ }
+ else {
+ fprintf(stdout, "Device signature = 0x");
+ for (i=0; i<m->size; i++)
+ fprintf(stdout, "%02x", m->buf[i]);
+ fprintf(stdout, "\n\n");
+ }
+
+ return 0;
+}
+
+
+static int cmd_quit(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ return 1;
+}
+
+
+static int cmd_parms(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ if (pgm->print_parms == NULL) {
+ avrdude_message(MSG_INFO, "%s (parms): the %s programmer does not support "
+ "adjustable parameters\n",
+ progname, pgm->type);
+ return -1;
+ }
+ pgm->print_parms(pgm);
+
+ return 0;
+}
+
+
+static int cmd_vtarg(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ int rc;
+ double v;
+ char *endp;
+
+ if (argc != 2) {
+ avrdude_message(MSG_INFO, "Usage: vtarg <value>\n");
+ return -1;
+ }
+ v = strtod(argv[1], &endp);
+ if (endp == argv[1]) {
+ avrdude_message(MSG_INFO, "%s (vtarg): can't parse voltage \"%s\"\n",
+ progname, argv[1]);
+ return -1;
+ }
+ if (pgm->set_vtarget == NULL) {
+ avrdude_message(MSG_INFO, "%s (vtarg): the %s programmer cannot set V[target]\n",
+ progname, pgm->type);
+ return -2;
+ }
+ if ((rc = pgm->set_vtarget(pgm, v)) != 0) {
+ avrdude_message(MSG_INFO, "%s (vtarg): failed to set V[target] (rc = %d)\n",
+ progname, rc);
+ return -3;
+ }
+ return 0;
+}
+
+
+static int cmd_fosc(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ int rc;
+ double v;
+ char *endp;
+
+ if (argc != 2) {
+ avrdude_message(MSG_INFO, "Usage: fosc <value>[M|k] | off\n");
+ return -1;
+ }
+ v = strtod(argv[1], &endp);
+ if (endp == argv[1]) {
+ if (strcmp(argv[1], "off") == 0)
+ v = 0.0;
+ else {
+ avrdude_message(MSG_INFO, "%s (fosc): can't parse frequency \"%s\"\n",
+ progname, argv[1]);
+ return -1;
+ }
+ }
+ if (*endp == 'm' || *endp == 'M')
+ v *= 1e6;
+ else if (*endp == 'k' || *endp == 'K')
+ v *= 1e3;
+ if (pgm->set_fosc == NULL) {
+ avrdude_message(MSG_INFO, "%s (fosc): the %s programmer cannot set oscillator frequency\n",
+ progname, pgm->type);
+ return -2;
+ }
+ if ((rc = pgm->set_fosc(pgm, v)) != 0) {
+ avrdude_message(MSG_INFO, "%s (fosc): failed to set oscillator_frequency (rc = %d)\n",
+ progname, rc);
+ return -3;
+ }
+ return 0;
+}
+
+
+static int cmd_sck(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ int rc;
+ double v;
+ char *endp;
+
+ if (argc != 2) {
+ avrdude_message(MSG_INFO, "Usage: sck <value>\n");
+ return -1;
+ }
+ v = strtod(argv[1], &endp);
+ if (endp == argv[1]) {
+ avrdude_message(MSG_INFO, "%s (sck): can't parse period \"%s\"\n",
+ progname, argv[1]);
+ return -1;
+ }
+ v *= 1e-6; /* Convert from microseconds to seconds. */
+ if (pgm->set_sck_period == NULL) {
+ avrdude_message(MSG_INFO, "%s (sck): the %s programmer cannot set SCK period\n",
+ progname, pgm->type);
+ return -2;
+ }
+ if ((rc = pgm->set_sck_period(pgm, v)) != 0) {
+ avrdude_message(MSG_INFO, "%s (sck): failed to set SCK period (rc = %d)\n",
+ progname, rc);
+ return -3;
+ }
+ return 0;
+}
+
+
+static int cmd_varef(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ int rc;
+ unsigned int chan;
+ double v;
+ char *endp;
+
+ if (argc != 2 && argc != 3) {
+ avrdude_message(MSG_INFO, "Usage: varef [channel] <value>\n");
+ return -1;
+ }
+ if (argc == 2) {
+ chan = 0;
+ v = strtod(argv[1], &endp);
+ if (endp == argv[1]) {
+ avrdude_message(MSG_INFO, "%s (varef): can't parse voltage \"%s\"\n",
+ progname, argv[1]);
+ return -1;
+ }
+ } else {
+ chan = strtoul(argv[1], &endp, 10);
+ if (endp == argv[1]) {
+ avrdude_message(MSG_INFO, "%s (varef): can't parse channel \"%s\"\n",
+ progname, argv[1]);
+ return -1;
+ }
+ v = strtod(argv[2], &endp);
+ if (endp == argv[2]) {
+ avrdude_message(MSG_INFO, "%s (varef): can't parse voltage \"%s\"\n",
+ progname, argv[2]);
+ return -1;
+ }
+ }
+ if (pgm->set_varef == NULL) {
+ avrdude_message(MSG_INFO, "%s (varef): the %s programmer cannot set V[aref]\n",
+ progname, pgm->type);
+ return -2;
+ }
+ if ((rc = pgm->set_varef(pgm, chan, v)) != 0) {
+ avrdude_message(MSG_INFO, "%s (varef): failed to set V[aref] (rc = %d)\n",
+ progname, rc);
+ return -3;
+ }
+ return 0;
+}
+
+
+static int cmd_help(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ int i;
+
+ fprintf(stdout, "Valid commands:\n\n");
+ for (i=0; i<NCMDS; i++) {
+ fprintf(stdout, " %-6s : ", cmd[i].name);
+ fprintf(stdout, cmd[i].desc, cmd[i].name);
+ fprintf(stdout, "\n");
+ }
+ fprintf(stdout,
+ "\nUse the 'part' command to display valid memory types for use with the\n"
+ "'dump' and 'write' commands.\n\n");
+
+ return 0;
+}
+
+static int cmd_spi(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ pgm->setpin(pgm, PIN_AVR_RESET, 1);
+ spi_mode = 1;
+ return 0;
+}
+
+static int cmd_pgm(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ pgm->setpin(pgm, PIN_AVR_RESET, 0);
+ spi_mode = 0;
+ pgm->initialize(pgm, p);
+ return 0;
+}
+
+static int cmd_verbose(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ int nverb;
+ char *endp;
+
+ if (argc != 1 && argc != 2) {
+ avrdude_message(MSG_INFO, "Usage: verbose [<value>]\n");
+ return -1;
+ }
+ if (argc == 1) {
+ avrdude_message(MSG_INFO, "Verbosity level: %d\n", verbose);
+ return 0;
+ }
+ nverb = strtol(argv[1], &endp, 0);
+ if (endp == argv[2]) {
+ avrdude_message(MSG_INFO, "%s: can't parse verbosity level \"%s\"\n",
+ progname, argv[2]);
+ return -1;
+ }
+ if (nverb < 0) {
+ avrdude_message(MSG_INFO, "%s: verbosity level must be positive: %d\n",
+ progname, nverb);
+ return -1;
+ }
+ verbose = nverb;
+ avrdude_message(MSG_INFO, "New verbosity level: %d\n", verbose);
+
+ return 0;
+}
+
+static int tokenize(char * s, char *** argv)
+{
+ int i, n, l, nargs, offset;
+ int len, slen;
+ char * buf;
+ int bufsize;
+ char ** bufv;
+ char * q, * r;
+ char * nbuf;
+ char ** av;
+
+ slen = strlen(s);
+
+ /*
+ * initialize allow for 20 arguments, use realloc to grow this if
+ * necessary
+ */
+ nargs = 20;
+ bufsize = slen + 20;
+ buf = malloc(bufsize);
+ bufv = (char **) malloc(nargs*sizeof(char *));
+ for (i=0; i<nargs; i++) {
+ bufv[i] = NULL;
+ }
+ buf[0] = 0;
+
+ n = 0;
+ l = 0;
+ nbuf = buf;
+ r = s;
+ while (*r) {
+ nexttok(r, &q, &r);
+ strcpy(nbuf, q);
+ bufv[n] = nbuf;
+ len = strlen(q);
+ l += len + 1;
+ nbuf += len + 1;
+ nbuf[0] = 0;
+ n++;
+ if ((n % 20) == 0) {
+ /* realloc space for another 20 args */
+ bufsize += 20;
+ nargs += 20;
+ buf = realloc(buf, bufsize);
+ bufv = realloc(bufv, nargs*sizeof(char *));
+ nbuf = &buf[l];
+ for (i=n; i<nargs; i++)
+ bufv[i] = NULL;
+ }
+ }
+
+ /*
+ * We have parsed all the args, n == argc, bufv contains an array of
+ * pointers to each arg, and buf points to one memory block that
+ * contains all the args, back to back, seperated by a nul
+ * terminator. Consilidate bufv and buf into one big memory block
+ * so that the code that calls us, will have an easy job of freeing
+ * this memory.
+ */
+ av = (char **) malloc(slen + n + (n+1)*sizeof(char *));
+ q = (char *)&av[n+1];
+ memcpy(q, buf, l);
+ for (i=0; i<n; i++) {
+ offset = bufv[i] - buf;
+ av[i] = q + offset;
+ }
+ av[i] = NULL;
+
+ free(buf);
+ free(bufv);
+
+ *argv = av;
+
+ return n;
+}
+
+
+static int do_cmd(PROGRAMMER * pgm, struct avrpart * p,
+ int argc, char * argv[])
+{
+ int i;
+ int hold;
+ int len;
+
+ len = strlen(argv[0]);
+ hold = -1;
+ for (i=0; i<NCMDS; i++) {
+ if (strcasecmp(argv[0], cmd[i].name) == 0) {
+ return cmd[i].func(pgm, p, argc, argv);
+ }
+ else if (strncasecmp(argv[0], cmd[i].name, len)==0) {
+ if (hold != -1) {
+ avrdude_message(MSG_INFO, "%s: command \"%s\" is ambiguous\n",
+ progname, argv[0]);
+ return -1;
+ }
+ hold = i;
+ }
+ }
+
+ if (hold != -1)
+ return cmd[hold].func(pgm, p, argc, argv);
+
+ avrdude_message(MSG_INFO, "%s: invalid command \"%s\"\n",
+ progname, argv[0]);
+
+ return -1;
+}
+
+
+char * terminal_get_input(const char *prompt)
+{
+#if defined(HAVE_LIBREADLINE) && !defined(WIN32NATIVE)
+ char *input;
+ input = readline(prompt);
+ if ((input != NULL) && (strlen(input) >= 1))
+ add_history(input);
+
+ return input;
+#else
+ char input[256];
+ printf("%s", prompt);
+ if (fgets(input, sizeof(input), stdin))
+ {
+ /* FIXME: readline strips the '\n', should this too? */
+ return strdup(input);
+ }
+ else
+ return NULL;
+#endif
+}
+
+
+int terminal_mode(PROGRAMMER * pgm, struct avrpart * p)
+{
+ char * cmdbuf;
+ int i;
+ char * q;
+ int rc;
+ int argc;
+ char ** argv;
+
+ rc = 0;
+ while ((cmdbuf = terminal_get_input("avrdude> ")) != NULL) {
+ /*
+ * find the start of the command, skipping any white space
+ */
+ q = cmdbuf;
+ while (*q && isspace((int)*q))
+ q++;
+
+ /* skip blank lines and comments */
+ if (!*q || (*q == '#'))
+ continue;
+
+ /* tokenize command line */
+ argc = tokenize(q, &argv);
+
+ fprintf(stdout, ">>> ");
+ for (i=0; i<argc; i++)
+ fprintf(stdout, "%s ", argv[i]);
+ fprintf(stdout, "\n");
+
+ /* run the command */
+ rc = do_cmd(pgm, p, argc, argv);
+ free(argv);
+ if (rc > 0) {
+ rc = 0;
+ break;
+ }
+ free(cmdbuf);
+ }
+
+ return rc;
+}
+
+