sed-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

proposed features for branching logic + minimal implementation


From: Liam Quinlan
Subject: proposed features for branching logic + minimal implementation
Date: Tue, 6 Oct 2020 18:47:36 -0400

I would like to propose four related additions to the sed toolbox
(represented below, arbitrarily, as '@', 'k', 'j', and 'J').  In my
opinion, these additions improve sed's usability near one of its
weaknesses (restricted branching logic), and represent a solid value
proposition in light of their minor code change requirements.
They are:


i)   A 't'-like address specifier, which tests (and resets) the
condition flag.  The address matches if the condition flag was set.
If used to control brace block entry, this effectively provides a
"forward branch" mechanism:

  ' ...; @{ ...; }; ...; '

Note that constructs are possible which include back-edges (t, T, b,
D, etc) and they can be arbitrarily nested.


ii)   A 'compliment-condition' command, which inverts the state of the
test flag.  When daisy-chaining condition state, this allows greater
logical control, particularly when the relevant sequences have
multiple entry points.

  ' ...; @!{ ...; :0; k; ...; @{ ...; }; ...; }; ...; t0; '


iii)  Two 'set-condition' commands ('j' and 'J'), essentially for
convenience, for setting the condition flag to a known state.  By
replacing indirect mechanisms, these explicit commands can improve
clarity and concision in script code:

  ' :_;t_; '  ->   ' J; '
  ' s/^//; '  ->   ' j; '


A working implementation of this feature set in "git diff" form is
offered below, for me at least test suite is passing (though I was
unable to build with -Werror).
The change set seems surprisingly minor :)



Being unfamiliar with the project and what would might be considered
appropriate, I have not included any new error-reporting, debug code,
or build tests;
I am willing to do so, but would appreciate some direction.

Cheers
-lk


CHANGES BELOW



diff --git a/sed/compile.c b/sed/compile.c
index 8321d68..082619a 100644
--- a/sed/compile.c
+++ b/sed/compile.c
@@ -962,6 +962,10 @@ compile_address (struct addr *addr, int ch)
     {
       addr->addr_type = ADDR_IS_LAST;
     }
+  else if ((ch == '@') && posixicity != POSIXLY_BASIC)
+   {
+      addr->addr_type = ADDR_IS_TEST;
+   }
   else
     return false;

@@ -1036,7 +1040,8 @@ compile_program (struct vector *vector)
        switch (ch)
          {
            case 'e': case 'F': case 'v': case 'z': case 'L':
-           case 'Q': case 'T': case 'R': case 'W':
+           case 'Q': case 'T': case 'R': case 'W': case 'j':
+           case 'J': case 'k':
              bad_command (ch);
              FALLTHROUGH;

@@ -1180,6 +1185,9 @@ compile_program (struct vector *vector)
        case 'G':
        case 'h':
         case 'H':
+        case 'j':
+        case 'J':
+        case 'k':
         case 'n':
         case 'N':
         case 'p':
diff --git a/sed/debug.c b/sed/debug.c
index 181f87d..02103f0 100644
--- a/sed/debug.c
+++ b/sed/debug.c
@@ -144,6 +144,9 @@ debug_print_addr (const struct addr *a)
     case ADDR_IS_STEP_MOD:
       printf ("~%lu", a->addr_step);
       break;
+    case ADDR_IS_TEST:
+      putchar ('@');
+      break;
     case ADDR_IS_LAST:
       putchar ('$');
       break;
@@ -339,6 +342,15 @@ debug_print_function (const struct vector
*program, const struct sed_cmd *sc)

       /* 'i' is lumped above with 'a' and 'c' */

+    case 'j':
+      break;
+
+    case 'J':
+      break;
+
+    case 'k':
+      break;
+
     case 'L':
     case 'l':
     case 'q':
diff --git a/sed/execute.c b/sed/execute.c
index f94b125..75b4960 100644
--- a/sed/execute.c
+++ b/sed/execute.c
@@ -811,6 +811,9 @@ match_an_address_p (struct addr *addr, struct input *input)
     case ADDR_IS_LAST:
       return test_eof (input);

+    case ADDR_IS_TEST:
+      return replaced && !(replaced = false);
+
     case ADDR_IS_NUM:
       /* reminder: these are only meaningful for a1 addresses */
       return (addr->addr_number == input->line_number);
@@ -1443,6 +1446,18 @@ execute_program (struct vector *vec, struct input *input)
                           true, &output_file);
               break;

+            case 'j':
+              replaced = true;
+              break;
+
+            case 'J':
+              replaced = false;
+              break;
+
+            case 'k':
+              replaced = !replaced;
+              break;
+
             case 'l':
               do_list (cur_cmd->x.int_arg == -1
                       ? lcmd_out_line_len
diff --git a/sed/sed.h b/sed/sed.h
index 1c8e83a..7ce341d 100644
--- a/sed/sed.h
+++ b/sed/sed.h
@@ -97,7 +97,8 @@ enum addr_types {
   ADDR_IS_NUM_MOD,     /* a.addr_number is valid, addr_step is modulo */
   ADDR_IS_STEP,                /* address is +N (only valid for addr2) */
   ADDR_IS_STEP_MOD,    /* address is ~N (only valid for addr2) */
-  ADDR_IS_LAST         /* address is $ */
+  ADDR_IS_LAST,                /* address is $ */
+  ADDR_IS_TEST         /* address is @ */
 };

 struct addr {


reply via email to

[Prev in Thread] Current Thread [Next in Thread]