From f0f9059ade2fe39267b19738846034651aac16ae Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Fri, 1 Apr 2022 16:52:59 +0200
Subject: [PATCH 1/5] Tweak nexttok for better string handling Now a string
 that starts and ends with a quote (") is combined into a single (argc)
 argument rather than being split where spaces used to be

---
 src/term.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/term.c b/src/term.c
index 5961f8df..a09880fc 100644
--- a/src/term.c
+++ b/src/term.c
@@ -126,12 +126,19 @@ static int nexttok(char * buf, char ** tok, char ** next)
     q++;
 
   /* isolate first token */
-  n = q+1;
-  while (*n && !isspace((int)*n))
+  n = q;
+  uint8_t quotes = 0;
+  while (*n && (!isspace((int)*n) || quotes)) {
+    if (*n == '\"')
+      quotes++;
+    else if (isspace((int)*n) && *(n-1) == '\"')
+      break;
     n++;
+  }
 
   if (*n) {
     *n = 0;
+    avrdude_message(MSG_INFO, "q: %s\n", q);
     n++;
   }
 

From 8f100f5df38a7542632acd40d51916415ed838d9 Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Fri, 1 Apr 2022 20:35:18 +0200
Subject: [PATCH 2/5] Initial support for string write

---
 src/term.c | 50 ++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 14 deletions(-)

diff --git a/src/term.c b/src/term.c
index a09880fc..604116e1 100644
--- a/src/term.c
+++ b/src/term.c
@@ -404,17 +404,26 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
     uint8_t size;
     bool is_float;
     bool is_signed;
+    char * str_ptr;
     // Data union
     union {
       float f;
       int64_t ll;
       uint8_t a[8];
     };
-  } data = {.bytes_grown = 0, .size = 0, .is_float = false, .ll = 0, .is_signed = false};
+  } data = {
+    .bytes_grown = 0,
+    .size        = 0,
+    .is_float    = false,
+    .is_signed   = false,
+    .str_ptr     = NULL,
+    .ll = 0
+  };
 
   for (i = start_offset; i < len + start_offset; i++) {
     data.is_float = false;
     data.size = 0;
+    data.str_ptr = NULL;
 
     // Handle the next argument
     if (i < argc - start_offset + 3) {
@@ -453,10 +462,17 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
           if (argv[i][0] == '\'' && argv[i][2] == '\'') {
             data.ll = argv[i][1];
           } else {
+            // Try string that starts and ends with quote
+            if (argv[i][0] == '\"' && argv[i][strlen(argv[i]) - 1] == '\"') {
+              data.str_ptr = calloc(strlen(argv[i])+0x10, sizeof(char));
+              strncpy(data.str_ptr, argv[i] + 1, strlen(argv[i]) - 2);
+              avrdude_message(MSG_INFO, "argv: %s, malloc: %s\n", argv[i], data.str_ptr);
+            } else {
             avrdude_message(MSG_INFO, "\n%s (write): can't parse data \"%s\"\n",
-                  progname, argv[i]);
+                            progname, argv[i]);
             free(buf);
             return -1;
+            }
           }
         }
       }
@@ -491,18 +507,24 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
           data.size = 1;
       }
     }
-    buf[i - start_offset + data.bytes_grown]     = data.a[0];
-    if (llabs(data.ll) > 0x000000FF || data.size >= 2 || data.is_float)
-      buf[i - start_offset + ++data.bytes_grown] = data.a[1];
-    if (llabs(data.ll) > 0x0000FFFF || data.size >= 4 || data.is_float) {
-      buf[i - start_offset + ++data.bytes_grown] = data.a[2];
-      buf[i - start_offset + ++data.bytes_grown] = data.a[3];
-    }
-    if (llabs(data.ll) > 0xFFFFFFFF || data.size == 8) {
-      buf[i - start_offset + ++data.bytes_grown] = data.a[4];
-      buf[i - start_offset + ++data.bytes_grown] = data.a[5];
-      buf[i - start_offset + ++data.bytes_grown] = data.a[6];
-      buf[i - start_offset + ++data.bytes_grown] = data.a[7];
+    if(data.str_ptr != NULL) {
+      for(int16_t j = 0; j < strlen(data.str_ptr); j++)
+        buf[i - start_offset + data.bytes_grown++] = (uint8_t)data.str_ptr[j];
+      free(data.str_ptr);
+    } else {
+      buf[i - start_offset + data.bytes_grown]     = data.a[0];
+      if (llabs(data.ll) > 0x000000FF || data.size >= 2 || data.is_float)
+        buf[i - start_offset + ++data.bytes_grown] = data.a[1];
+      if (llabs(data.ll) > 0x0000FFFF || data.size >= 4 || data.is_float) {
+        buf[i - start_offset + ++data.bytes_grown] = data.a[2];
+        buf[i - start_offset + ++data.bytes_grown] = data.a[3];
+      }
+      if (llabs(data.ll) > 0xFFFFFFFF || data.size == 8) {
+        buf[i - start_offset + ++data.bytes_grown] = data.a[4];
+        buf[i - start_offset + ++data.bytes_grown] = data.a[5];
+        buf[i - start_offset + ++data.bytes_grown] = data.a[6];
+        buf[i - start_offset + ++data.bytes_grown] = data.a[7];
+      }
     }
   }
 

From 795dd915756bfb57924c58b4725f0fd1592baadb Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Fri, 1 Apr 2022 22:23:55 +0200
Subject: [PATCH 3/5] Code cleanup + formatting

---
 src/term.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/term.c b/src/term.c
index 604116e1..e9fc6de8 100644
--- a/src/term.c
+++ b/src/term.c
@@ -138,7 +138,6 @@ static int nexttok(char * buf, char ** tok, char ** next)
 
   if (*n) {
     *n = 0;
-    avrdude_message(MSG_INFO, "q: %s\n", q);
     n++;
   }
 
@@ -462,13 +461,17 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
           if (argv[i][0] == '\'' && argv[i][2] == '\'') {
             data.ll = argv[i][1];
           } else {
-            // Try string that starts and ends with quote
+            // Try string that starts and ends with quotes
             if (argv[i][0] == '\"' && argv[i][strlen(argv[i]) - 1] == '\"') {
-              data.str_ptr = calloc(strlen(argv[i])+0x10, sizeof(char));
+              data.str_ptr = calloc(strlen(argv[i]), sizeof(char));
+              if (data.str_ptr == NULL) {
+                avrdude_message(MSG_INFO, "%s (write str): out of memory\n", progname);
+                return -1;
+              }
+              // Strip start and end quotes
               strncpy(data.str_ptr, argv[i] + 1, strlen(argv[i]) - 2);
-              avrdude_message(MSG_INFO, "argv: %s, malloc: %s\n", argv[i], data.str_ptr);
             } else {
-            avrdude_message(MSG_INFO, "\n%s (write): can't parse data \"%s\"\n",
+            avrdude_message(MSG_INFO, "\n%s (write): can't parse data '%s'\n",
                             progname, argv[i]);
             free(buf);
             return -1;
@@ -507,7 +510,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
           data.size = 1;
       }
     }
-    if(data.str_ptr != NULL) {
+    if(data.str_ptr) {
       for(int16_t j = 0; j < strlen(data.str_ptr); j++)
         buf[i - start_offset + data.bytes_grown++] = (uint8_t)data.str_ptr[j];
       free(data.str_ptr);

From 17b67da03e153a344b03bf90315a1b8ee9b7c803 Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Mon, 4 Apr 2022 09:38:02 +0200
Subject: [PATCH 4/5] Make sure memory can be filled with a string ... and not
 just the last character

---
 src/term.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/term.c b/src/term.c
index e9fc6de8..04301304 100644
--- a/src/term.c
+++ b/src/term.c
@@ -422,10 +422,15 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
   for (i = start_offset; i < len + start_offset; i++) {
     data.is_float = false;
     data.size = 0;
-    data.str_ptr = NULL;
 
     // Handle the next argument
     if (i < argc - start_offset + 3) {
+      // Free string pointer if already allocated
+      if(data.str_ptr) {
+        free(data.str_ptr);
+        data.str_ptr = NULL;
+      }
+
       // Get suffix if present
       char suffix  = argv[i][strlen(argv[i]) - 1];
       char lsuffix = argv[i][strlen(argv[i]) - 2];
@@ -474,6 +479,8 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
             avrdude_message(MSG_INFO, "\n%s (write): can't parse data '%s'\n",
                             progname, argv[i]);
             free(buf);
+            if(data.str_ptr != NULL)
+              free(data.str_ptr);
             return -1;
             }
           }
@@ -513,7 +520,6 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
     if(data.str_ptr) {
       for(int16_t j = 0; j < strlen(data.str_ptr); j++)
         buf[i - start_offset + data.bytes_grown++] = (uint8_t)data.str_ptr[j];
-      free(data.str_ptr);
     } else {
       buf[i - start_offset + data.bytes_grown]     = data.a[0];
       if (llabs(data.ll) > 0x000000FF || data.size >= 2 || data.is_float)
@@ -543,6 +549,9 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
     return -1;
   }
 
+  if(data.str_ptr)
+    free(data.str_ptr);
+
   avrdude_message(MSG_NOTICE, "\nInfo: Writing %d bytes starting from address 0x%02x",
                   len + data.bytes_grown, addr);
   if (write_mode == WRITE_MODE_FILL)

From 08bd5fa938a9fe2b672f503b1c9641fffbefc316 Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Tue, 5 Apr 2022 19:37:45 +0200
Subject: [PATCH 5/5] Add string write to terminal example

---
 src/doc/avrdude.texi | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi
index fe3f9314..ad4a6598 100644
--- a/src/doc/avrdude.texi
+++ b/src/doc/avrdude.texi
@@ -1553,14 +1553,16 @@ avrdude: AVR device initialized and ready to accept instructions
 Reading | ################################################## | 100% 0.01s
 
 avrdude: Device signature = 0x1e970c (probably avr128db48)
-avrdude> write eeprom 0 1234567890 'A' 'V' 'R' 2.718282
->>> write eeprom 0 1234567890 'A' 'V' 'R' 2.718282 
+avrdude> write eeprom 0 1234567890 'A' 'V' 'R' 2.718282 "Hello World!"
+>>> write eeprom 0 1234567890 'A' 'V' 'R' 2.718282 "Hello World!"
 Warning: no size suffix specified for "1234567890". Writing 4 byte(s)
+Info: Writing 24 bytes starting from address 0x00
 
 avrdude> dump eeprom 0 32
 >>> dump eeprom 0 32 
-0000  d2 02 96 49 41 56 52 55  f8 2d 40 ff ff ff ff ff  |...IAVRU.-@.....|
-0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
+
+0000  d2 02 96 49 41 56 52 55  f8 2d 40 48 65 6c 6c 6f  |...IAVRU.-@Hello|
+0010  20 57 6f 72 6c 64 21 00  ff ff ff ff ff ff ff ff  | World!.........|
 
 avrdude> q
 @end cartouche