chiark / gitweb /
server/: Post-merge fixup.
[tripe] / maint-utils / keysubst
1 #! /bin/sh
2
3 ## This sed(1) script takes key/value pairs in tripe-admin(5) format as
4 ## input; it writes sh(1) variable assignments as output.  The idea is that
5 ## you can say
6 ##
7 ##      eval $(tripectl algs | sed "$keysubst")
8 ##
9 ## and have shell variables set from the output of the command.  The shell
10 ## variable names are worked out from the key names, with sequences of
11 ## nonalphanumerics replaced by single underscores.  Quoting is handled
12 ## correctly, both on input and output.
13 ##
14 ## Theory of operation: firstly, ! and @ characters in the input are replaced
15 ## by !e and !a respectively; this is a reversible transformation, which we
16 ## undo at the end.  We now know that the input does not contain @.  We use a
17 ## string of the form [lr][nqQ]@ as a cursor to move across the input from
18 ## left to right.  The letters on the left of the @ are state markers: l
19 ## means left of =, r means right; n means not in quotes; q means single-
20 ## quoted; Q means double-quoted.
21 ##
22 ## This is a particularly awful hack.  I'm so sorry.
23 keysubst='
24         ## Initial transformation.
25         s/!/!e/g'$p'
26         s/@/!a/g'$p'
27
28         ## Initial state: left-hand side, not quoted
29         s/^/ln@/'$p'
30
31 :loop
32         ## Reached the end: exit.
33         /@$/ b end
34
35         ## Enter or leave quoted state as necessary.
36         s/\(.\)n@'\''/\1q@/'$p'
37         s/\(.\)n@"/\1Q@/'$p'
38         s/\(.\)q@'\''/\1n@/'$p'
39         s/\(.\)Q@"/\1n@/'$p'
40         t loop
41
42         ## Leave backslashed things alone.
43         /\(..\)@\\/ {
44           s//\1@/
45           b lit
46         }
47
48         ## Unquotes spaces delimit key/value pairs.
49         s/\(rn\)@[      ]\+/'\'' ln@/'$p'
50
51         ## An = sign separates left and right sides.
52         s/l\(.\)@=/='\''r\1@/'$p'
53
54         ## Single quotes on the right-hand side need special care.
55         t loop
56         s/r\(.\)@'\'/\''\\'\'\''r\1@/'$p'
57
58         ## Sequences of alphanumerics are always easy.
59         s/\(..\)@\([[:alnum:]]\+\)/\2\1@/'$p'
60
61 :lit
62         ## Convert bad left-hand-side characters to underscores.
63         t loop
64         s/l\(.\)@\(!.\|[^=![:alnum:]]\)\+/_l\1@/'$p'
65
66         ## Convert sequences of nonproblematic right-hand-side characters.
67         t loop
68         s/\(r.\)@\([^   '\''"`]\+\)/\2\1@/'$p'
69
70         ## And anything else is probably OK.
71         s/\(..\)@\(.\)/\2\1@/'$p'
72         b loop
73
74 :end
75         ## Unquote the end appropriately.
76         s/r.@/'\''/'$p'
77         s/..@//'$p'
78
79         ## And undo the initial transformation.
80         s/!a/@/g'$p'
81         s/!e/!/g'$p'
82 '
83
84 sed "$keysubst"