changeset 1545:b6ff5dc17763 draft

Implement a few sed commands. Not done, and not tested yet.
author Rob Landley <rob@landley.net>
date Sat, 08 Nov 2014 01:51:59 -0600
parents e3aeb7435efe
children aa74fb336bf4
files toys/pending/sed.c
diffstat 1 files changed, 106 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/toys/pending/sed.c	Thu Nov 06 16:26:59 2014 -0600
+++ b/toys/pending/sed.c	Sat Nov 08 01:51:59 2014 -0600
@@ -180,8 +180,9 @@
   // processed pattern list
   struct double_list *pattern;
 
-  char *nextline;
-  long nextlen, count;
+  char *nextline, *remember;
+  void *restart;
+  long nextlen, rememberlen, count;
   int fdout, noeol;
 )
 
@@ -236,15 +237,31 @@
 
 }
 
+// Extend allocation to include new string.
+
+static char *extend_string(char **old, char *new, int oldlen, int newlen)
+{
+  int newline = newlen < 0;
+  char *s;
+
+  if (newline) newlen = -newlen;
+  s = *old = xrealloc(*old, oldlen+newlen+newline+1);
+  if (newline) s[oldlen++] = '\n';
+  memcpy(s+oldlen, new, newlen);
+  s[oldlen+newlen] = 0;
+
+  return s+oldlen+newlen;
+}
+
 // Apply pattern to line from input file
 static void walk_pattern(char **pline, long plen)
 {
-  char *line = TT.nextline;
+  char *line = TT.nextline, *append = 0;
   long len = TT.nextlen;
   struct step *logrus;
-  int eol = 0;
+  int eol = 0, tea = 0;
 
-  // Grab next line for deferred processing (EOF detection, we get a NULL
+  // Grab next line for deferred processing (EOF detection: we get a NULL
   // pline at EOF to flush last line). Note that only end of _last_ input
   // file matches $ (unless we're doing -i).
   if (pline) {
@@ -257,8 +274,10 @@
   if (line[len-1] == '\n') line[--len] = eol++;
   TT.count++;
 
-  for (logrus = (void *)TT.pattern; logrus; logrus = logrus->next) {
-    char c = logrus->c;
+  logrus = TT.restart ? TT.restart : (void *)TT.pattern;
+  TT.restart = 0;
+  while (logrus) {
+    char *str, c = logrus->c;
 
     // Have we got a matching range for this rule?
     if (*logrus->lmatch || *logrus->rmatch) {
@@ -305,20 +324,93 @@
       if (miss) logrus->hit = 0;
     }
 
-    // Process like the wind, bullseye!
+    // Process command
+
+    if (c == 'a') {
+      long alen = append ? strlen(append) : 0;
+
+      str = logrus->arg1+(char *)logrus;
+      extend_string(&append, str, alen, -strlen(str));
+    } else if (c == 'b') {
+      str = logrus->arg1+(char *)logrus;
 
-    // if (strchr("dDgGhHlnNpPqx=", c)) {
-
+      if (!*str) break;
+      for (logrus = (void *)TT.pattern; logrus; logrus = logrus->next)
+        if (logrus->c == ':' && !strcmp(logrus->arg1+(char *)logrus, str))
+          break;
+      if (!logrus) error_exit("no :%s", str);
+    } else if (c == 'd') goto done;
+    else if (c == 'D') {
+      // Delete up to \n or end of buffer
+      for (str = line; !*str || *str == '\n'; str++);
+      len -= str - line;
+      memmove(line, str, len);
+      line[len] = 0;
 
-//    if (strchr("abcirstTwy:", c)
-    if (c == 'p') {
+      // restart script
+      logrus = (void *)TT.pattern;
+      continue;
+    } else if (c == 'g') {
+      free(line);
+      line = xstrdup(TT.remember);
+      len = TT.rememberlen;
+    } else if (c == 'G') {
+      line = xrealloc(line, len+TT.rememberlen+2);
+      line[len++] = '\n';
+      memcpy(line+len, TT.remember, TT.rememberlen);
+      line[len += TT.rememberlen] = 0;
+    } else if (c == 'h') {
+      free(TT.remember);
+      TT.remember = xstrdup(line);
+      TT.rememberlen = len;
+    } else if (c == 'H') {
+      TT.remember = xrealloc(TT.remember, TT.rememberlen+len+2);
+      TT.remember[TT.rememberlen++] = '\n';
+      memcpy(TT.remember+TT.rememberlen, line, len);
+      TT.remember[TT.rememberlen += len] = 0;
+    } else if (c == 'l') {
+      error_exit("todo: l");
+    } else if (c == 'n') {
+      TT.restart = logrus->next;
+
+      break;
+    } else if (c == 'N') {
+      if (pline) {
+        TT.restart = logrus->next;
+        extend_string(&line, TT.nextline, plen, -TT.nextlen);
+        free(TT.nextline);
+        TT.nextline = line;
+      }
+
+      goto append; 
+    } else if (c == 'p') {
       if (emit(line, len, eol)) break;
-    } else error_exit("what?");
+    } else if (c == 'q') break;
+    else if (c == 'x') {
+      long swap = TT.rememberlen;
+
+      str = TT.remember;
+      TT.remember = line;
+      line = str;
+      TT.rememberlen = len;
+      len = swap;
+    } else if (c == '=') xprintf("%ld\n", TT.count);
+    // labcirstTwy
+    else if (c != ':') error_exit("todo: %c", c);
+
+    logrus = logrus->next;
   }
 
   if (!(toys.optflags & FLAG_n)) emit(line, len, eol);
 
+done:
   free(line);
+
+append:
+  if (append) {
+    emit(append, strlen(append), 1);
+    free(append);
+  }
 }
 
 // Genericish function, can probably get moved to lib.c
@@ -424,19 +516,6 @@
   return rc;
 }
 
-// Extend allocation to include new string. We use offsets instead of
-// pointers so realloc() moving stuff doesn't break things. Do it
-// here instead of toybuf so there's no maximum size.
-
-static char *extend_string(char **old, char *new, int oldlen, int newlen)
-{
-  *old = xrealloc(*old, oldlen+newlen+1);
-  memcpy(*old+oldlen, new, newlen);
-  (*old)[oldlen+newlen] = 0;
-
-  return (*old)+oldlen+newlen;
-}
-
 // Translate primal pattern into walkable form.
 static void jewel_of_judgement(char **pline, long len)
 {
@@ -636,6 +715,7 @@
   if (TT.nextlen) error_exit("no }");  
 
   TT.fdout = 1;
+  TT.remember = xstrdup("");
 
   // Inflict pattern upon input files
   loopfiles_rw(args, O_RDONLY, 0, 0, do_sed);