Commit f1843fc1271a27a2d1eba971a6a3dbc77e335c03

Thomas de Grivel 2022-01-03T14:06:48

quote

diff --git a/Makefile b/Makefile
index 3002572..3f5e205 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ CFLAGS += -W -Wall -Werror -std=c89 -pedantic -I.
 ifeq ($(DEBUG),)
 CFLAGS += -O2
 else
-CFLAGS += -DDEBUG -O0
+CFLAGS += -DDEBUG -O0 -g3
 endif
 
 CLEANFILES =
diff --git a/buffer.c b/buffer.c
index 84fed94..33f1ce5 100644
--- a/buffer.c
+++ b/buffer.c
@@ -69,11 +69,10 @@ int buffer_close (s_buffer *b)
 int buffer_fp (s_buffer *b, FILE *fp, const char *file_path)
 {
   assert(b);
-  if (b->fp) {
+  if (b->fp)
     fclose(b->fp);
-    b->fp = fp;
-    b->file_path = file_path;
-  }
+  b->fp = fp;
+  b->file_path = file_path;
   return 0;
 }
 
@@ -96,6 +95,7 @@ int buffer_fill (s_buffer *b)
 {
   size_t r;
   assert(b);
+  assert(b->fp);
   if (b->wpos == b->size &&
       buffer_resize(b, b->size + BUFFER_SIZE))
     return -1;
diff --git a/kv.c b/kv.c
index 7d8189d..f836bd1 100644
--- a/kv.c
+++ b/kv.c
@@ -93,6 +93,8 @@ int quote (int argc, char **argv)
   if (!(r = kv_quote(&q, &q_size)) &&
       fwrite(q, q_size, 1, stdout) != 1)
     err(1, "stdout");
+  fflush(stdout);
+  free(q);
   return r;
 }
 
diff --git a/kv_chars.c b/kv_chars.c
index d86efb0..b06fb9c 100644
--- a/kv_chars.c
+++ b/kv_chars.c
@@ -11,9 +11,13 @@ int kv_is_quotable_char (int c)
   switch (c) {
   case '"':
   case '\\':
+  case '\n':
+  case '\r':
+  case '\t':
+  case '\v':
     return 1;
   default:
-    return kv_is_space(c);
+    return 0;
   }
   return 0;
 }
diff --git a/kv_quote.c b/kv_quote.c
index a25a091..bb06419 100644
--- a/kv_quote.c
+++ b/kv_quote.c
@@ -38,13 +38,12 @@ int kv_check_delimiter (const char *delim)
 int kv_contains_delimiter (const char *str, size_t str_size,
                            const char *delim)
 {
-  size_t dsz;
+  size_t delim_len;
   assert(str);
   assert(delim);
-  dsz = strlen(delim);
-  while (str_size >= 4) {
-    if (str[0] == '\n' && str[1] == '"' && str[2] == '"' &&
-        str[3] == '"')
+  delim_len = strlen(delim);
+  while (str_size >= delim_len) {
+    if (!strcmp(str, delim))
       return 1;
     str++;
     str_size--;
@@ -65,9 +64,8 @@ int kv_contains_reserved_char (const char *str, size_t str_size)
 
 int kv_contains_triple_double_quotes (const char *str, size_t str_size)
 {
-  while (str_size >= 4) {
-    if (str[0] == '\n' && str[1] == '"' && str[2] == '"' &&
-        str[3] == '"')
+  while (str_size >= 3) {
+    if (str[0] == '"' && str[1] == '"' && str[2] == '"')
       return 1;
     str++;
     str_size--;
@@ -75,6 +73,15 @@ int kv_contains_triple_double_quotes (const char *str, size_t str_size)
   return 0;
 }
 
+size_t kv_count_quotable_chars (const char *str, size_t str_size)
+{
+  size_t c = 0;
+  while (str_size--)
+    if (kv_is_quotable_char(*str++))
+      c++;
+  return c;
+}
+
 int kv_needs_quoting (const char *str, size_t str_size)
 {
   if (str_size == 0 ||
@@ -114,8 +121,7 @@ int kv_quote (char **str, size_t *str_size)
   q = *str;
   q_size = *str_size;
   delim = &g_delims[0];
-  r = kv_quote_delim(&q, &q_size, *delim);
-  delim++;
+  r = 1;
   while (*delim && r > 0) {
     r = kv_quote_delim(&q, &q_size, *delim);
     delim++;
@@ -128,7 +134,10 @@ int kv_quote (char **str, size_t *str_size)
   }
   if (!rope)
     return 1;
+  rope_print(rope, stderr);
   rope_sort_by_size(rope);
+  rope_print(rope, stderr);
+  fflush(stderr);
   *str = rope->str;
   *str_size = rope->size;
   rope = rope->next;
@@ -136,13 +145,33 @@ int kv_quote (char **str, size_t *str_size)
   return 0;
 }
 
-size_t kv_count_reserved_chars (const char *str, size_t str_size)
+int kv_quote_delim (char **str, size_t *str_size, const char *delim)
 {
-  size_t c = 0;
-  while (str_size--)
-    if (kv_is_reserved_char(*str++))
-      c++;
-  return c;
+  char  *s;
+  size_t delim_len;
+  size_t len;
+  assert(str);
+  assert(str_size);
+  assert(delim);
+  if (kv_check_delimiter(delim)) {
+    fprintf(stderr, "bad delimiter: %s\n", delim);
+    return 1;
+  }
+  if (kv_contains_delimiter(*str, *str_size, delim))
+    return 1;
+  delim_len = strlen(delim);
+  len = *str_size + delim_len * 2 + 3;
+  s = calloc(len + 1, 1);
+  if (!s)
+    return -1;
+  s[0] = '<'; s[1] = '<';
+  memcpy(s + 2, delim, delim_len);
+  s[2 + delim_len] = '\n';
+  memcpy(s + delim_len + 3, *str, *str_size);
+  memcpy(s + *str_size + delim_len + 3, delim, delim_len);
+  *str = s;
+  *str_size = len;
+  return 0;
 }
 
 int kv_quote_double_quotes (char **str, size_t *str_size)
@@ -153,20 +182,25 @@ int kv_quote_double_quotes (char **str, size_t *str_size)
   char  *s;
   assert(str);
   assert(str_size);
-  res = kv_count_reserved_chars(*str, *str_size);
+  res = kv_count_quotable_chars(*str, *str_size);
   s = calloc(*str_size + res + 3, 1);
   if (!s)
     return -1;
-  s[0] = '"';
+  s[o++] = '"';
   while (i < *str_size) {
-    int c = (*str)[i];
-    if (kv_is_reserved_char(c))
+    int c = (*str)[i++];
+    if (kv_is_quotable_char(c))
       s[o++] = '\\';
-    if (c == 0)
-      s[o++] = '0';
-    else
-      s[o++] = c;
+    switch (c) {
+    case 0:    s[o++] = '0'; break;
+    case '\n': s[o++] = 'n'; break;
+    case '\r': s[o++] = 'r'; break;
+    case '\t': s[o++] = 't'; break;
+    case '\v': s[o++] = 'v'; break;
+    default: s[o++] = c;
+    }
   }
+  s[o++] = '"';
   assert(o == *str_size + res + 2);
   s[o] = 0;
   *str = s;
@@ -180,14 +214,14 @@ int kv_quote_triple_double_quotes (char **str, size_t *str_size)
   char *s;
   if (kv_contains_triple_double_quotes(*str, *str_size))
     return 1;
-  s = calloc(*str_size + 9, 1);
+  s = calloc(*str_size + 8, 1);
   if (!s)
     return -1;
   s[0] = '"'; s[1] = '"'; s[2] = '"'; s[3] = '\n';
   memcpy(s + 4, *str, *str_size);
   e = s + 4 + *str_size;
-  e[0] = '\n'; e[1] = '"'; e[2] = '"'; e[3] = '"'; e[4] = 0;
-  *str = e;
-  *str_size = *str_size + 8;
+  e[0] = '"'; e[1] = '"'; e[2] = '"'; e[3] = 0;
+  *str = s;
+  *str_size = *str_size + 7;
   return 0;
 }
diff --git a/rope.c b/rope.c
index 9f519de..477d19e 100644
--- a/rope.c
+++ b/rope.c
@@ -5,6 +5,7 @@
 */
 
 #include <assert.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include "rope.h"
 
@@ -111,3 +112,28 @@ void rope_sort_by_size (s_rope *r)
     n--;
   }
 }
+
+int rope_print (s_rope *r, FILE *fp)
+{
+  int ret;
+  if (r) {
+    assert(fp);
+    ret = fwrite(r->str, r->size, 1, fp);
+    if (ret != 1)
+      return -1;
+    r = r->next;
+    while (r) {
+      ret = fwrite("\n\n", 2, 1, fp);
+      if (ret != 1)
+        return -1;
+      ret = fwrite(r->str, r->size, 1, fp);
+      if (ret != 1)
+        return -1;
+      r = r->next;
+    }
+  }
+  ret = fwrite("\n", 1, 1, fp);
+  if (ret != 1)
+    return -1;
+  return 0;
+}
diff --git a/rope.h b/rope.h
index 7c04be9..1e769f9 100644
--- a/rope.h
+++ b/rope.h
@@ -22,5 +22,6 @@ void     rope_delete_all (s_rope *r);
 void     rope_delete_all_free (s_rope *r);
 int      rope_push (s_rope **r, char *str, size_t size);
 void     rope_sort_by_size (s_rope *r);
+int      rope_print (s_rope *r, FILE *fp);
 
 #endif