Commit | Line | Data |
---|---|---|
44e29279 MW |
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" |