Blob Blame History Raw
From 0cce971fabef13af3a9592ef93a505378f73338a Mon Sep 17 00:00:00 2001
From: Dominic Cleal <dcleal@redhat.com>
Date: Wed, 29 Jan 2014 22:57:02 +0000
Subject: [PATCH 5/5] Shellvars: handle case statements with same-line ;;
 tokens

Fixes RHBZ#1033799

(cherry picked from commit a1b9831d14f22f81cf7dc840160c08cc14234ee9)

Conflicts:
	NEWS
	lenses/shellvars.aug
---
 lenses/shellvars.aug            | 65 +++++++++++++++++++++++++----------------
 lenses/sysconfig.aug            |  6 ++--
 lenses/tests/test_shellvars.aug | 11 +++++++
 3 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/lenses/shellvars.aug b/lenses/shellvars.aug
index 4111ee6..eff933a 100644
--- a/lenses/shellvars.aug
+++ b/lenses/shellvars.aug
@@ -59,40 +59,37 @@ module Shellvars =
             | bquot | dbquot | dollar_assign | empty_array)
 
   let export = [ key "export" . Util.del_ws_spc ]
-  let kv = [ Util.indent . export? . key key_re
-           . eq . (simple_value | array) . comment_or_eol ]
+  let kv = Util.indent . export? . key key_re
+           . eq . (simple_value | array)
 
   let var_action (name:string) =
-    Util.indent . del name name . Util.del_ws_spc .
-      [ label ("@" . name) . counter "var_action"
-        . Build.opt_list [ seq "var_action" . store (key_re | matching_re) ] Util.del_ws_spc
-        . comment_or_eol ]
+    Util.indent . del name name . Util.del_ws_spc
+    . label ("@" . name) . counter "var_action"
+    . Build.opt_list [ seq "var_action" . store (key_re | matching_re) ] Util.del_ws_spc
 
   let unset = var_action "unset"
   let bare_export = var_action "export"
 
   let source =
-    [ Util.indent
-      . del /\.|source/ "." . label ".source"
-      . Util.del_ws_spc . store /[^;=# \t\n]+/ . comment_or_eol ]
+    Util.indent
+    . del /\.|source/ "." . label ".source"
+    . Util.del_ws_spc . store /[^;=# \t\n]+/
 
   let shell_builtin_cmds = "ulimit" | "shift" | "exit"
 
   let builtin =
-    [ Util.indent . label "@builtin"
-      . store shell_builtin_cmds
-      . (Util.del_ws_spc
-      . [ label "args" . sto_to_semicol ])?
-      . comment_or_eol ]
+    Util.indent . label "@builtin"
+    . store shell_builtin_cmds
+    . (Util.del_ws_spc
+    . [ label "args" . sto_to_semicol ])?
 
   let keyword (kw:string) = Util.indent . Util.del_str kw
   let keyword_label (kw:string) (lbl:string) = keyword kw . label lbl
 
   let return =
-    [ Util.indent . label "@return"
-      . Util.del_str "return"
-      . ( Util.del_ws_spc . store Rx.integer )?
-      . comment_or_eol ]
+    Util.indent . label "@return"
+    . Util.del_str "return"
+    . ( Util.del_ws_spc . store Rx.integer )?
 
 
 (************************************************************************
@@ -128,11 +125,11 @@ module Shellvars =
   let loop_select (entry:lens) =
     generic_cond "select" "@select" "do" entry+ "done"
 
-  let case (entry:lens) =
+  let case (entry:lens) (entry_noeol:lens) =
     let case_entry = [ label "@case_entry"
                        . Util.indent . store /[^ \t\n\)]+/
                        . Util.del_str ")" . eol
-                       . entry*
+                       . ( entry+ | entry_noeol )?
                        . Util.indent . Util.del_str ";;" . eol ] in
       [ keyword_label "case" "@case" . Sep.space
         . store (char+ | ("\"" . char+ . "\""))
@@ -149,20 +146,38 @@ module Shellvars =
       . entry+
       . Util.indent . Util.del_str "}" . eol ]
 
+  let entry_eol =
+    let entry_eol_item (item:lens) =
+      [ item . comment_or_eol ] in
+      entry_eol_item source
+        | entry_eol_item kv
+        | entry_eol_item unset
+        | entry_eol_item bare_export
+        | entry_eol_item builtin
+        | entry_eol_item return
+
+  let entry_noeol =
+    let entry_item (item:lens) = [ item ] in
+      entry_item source
+        | entry_item kv
+        | entry_item unset
+        | entry_item bare_export
+        | entry_item builtin
+        | entry_item return
+
   let rec rec_entry =
-    let entry = comment | source | kv
-              | unset | bare_export | builtin | return | rec_entry in
+    let entry = comment | entry_eol | rec_entry in
         cond_if entry
       | loop_for entry
       | loop_select entry
       | loop_while entry
       | loop_until entry
-      | case entry
+      | case entry entry_noeol
       | function entry
 
-  let lns_norec = empty* . (comment | source | kv | unset | bare_export | builtin | return) *
+  let lns_norec = empty* . (comment | entry_eol) *
 
-  let lns = empty* . (comment | source | kv | unset | bare_export | builtin | return | rec_entry) *
+  let lns = empty* . (comment | entry_eol | rec_entry) *
 
   let sc_incl (n:string) = (incl ("/etc/sysconfig/" . n))
   let sc_excl (n:string) = (excl ("/etc/sysconfig/" . n))
diff --git a/lenses/sysconfig.aug b/lenses/sysconfig.aug
index ee83af1..8c505b3 100644
--- a/lenses/sysconfig.aug
+++ b/lenses/sysconfig.aug
@@ -55,10 +55,10 @@ module Sysconfig =
 
   let var_action = Shellvars.var_action
 
-  let unset = var_action "unset"
-  let bare_export = var_action "export"
+  let unset = [ var_action "unset" . comment_or_eol ]
+  let bare_export = [ var_action "export" . comment_or_eol ]
 
-  let source = Shellvars.source
+  let source = [ Shellvars.source . comment_or_eol ]
 
   let lns = empty* . (comment | source | assign | unset | bare_export)*
 
diff --git a/lenses/tests/test_shellvars.aug b/lenses/tests/test_shellvars.aug
index 79a5a4e..18fd361 100644
--- a/lenses/tests/test_shellvars.aug
+++ b/lenses/tests/test_shellvars.aug
@@ -446,6 +446,17 @@ esac\n" =
       { "1" = "TestVar1" }
       { "2" = "TestVar2" } }
 
+  (* Support ;; on same line as a case statement entry, RHBZ#1033799 *)
+  test lns get "case $ARG in
+        0) TestVar=\"test0\" ;;
+        1) TestVar=\"test1\" ;;
+esac\n" =
+    { "@case" = "$ARG"
+      { "@case_entry" = "0"
+        { "TestVar" = "\"test0\"" } }
+      { "@case_entry" = "1"
+        { "TestVar" = "\"test1\"" } } }
+
 (* Local Variables: *)
 (* mode: caml       *)
 (* End:             *)
-- 
1.8.5.3