Merge branch 't/clang'
[paraslash.git] / command_util.sh
1 #!/usr/bin/env bash
2
3 read_header()
4 {
5         local key value i
6
7         while read key value; do
8                 case "$key" in
9                 ---)
10                         break
11                         ;;
12                 BN:)
13                         base_name="$value"
14                         ;;
15                 SF:)
16                         source_files="$value"
17                         ;;
18                 SN:)
19                         section_name="$value"
20                         ;;
21                 TM:)
22                         template_members="$value"
23                 esac
24         done
25 }
26
27 read_one_command()
28 {
29         local line
30
31         name_txt=""
32         desc_txt=""
33         usage_txt=""
34         help_txt=""
35         perms_txt=""
36         template=0
37         template_name=""
38         template_prototype=""
39         mkdir -p man/man1
40         while read key value; do
41                 case "$key" in
42                 ---)
43                         break
44                         ;;
45                 N:)
46                         name_txt="$value"
47                         ;;
48                 T:)
49                         template_name="$value"
50                         template=1
51                         ;;
52                 O:)
53                         template_prototype="$value"
54                         template=1
55                         ;;
56                 P:)
57                         perms_txt="$value"
58                         ;;
59                 D:)
60                         desc_txt="$value"
61                         ;;
62                 U:)
63                         usage_txt="$value"
64                         ;;
65                 H:)
66                         help_txt="${value}"
67                         while read line; do
68                                 if test "$line" = "---"; then
69                                         break;
70                                 fi
71                                 line=${line#H:}
72                                 help_txt="$help_txt
73 ${line# }"
74                         done
75                         break
76                         ;;
77                 esac
78         done
79         if test $template -eq 0; then
80                 if test -n "$name_txt" -a -n "$desc_txt" -a -n "$usage_txt" \
81                                 -a -n "$help_txt"; then
82                         ret=1
83                         return
84                 fi
85         else
86                 if test -n "$template_name" -a -n "$template_prototype" \
87                                 -a -n "$name_txt " -a -n "$template_members" \
88                                 -a -n "$desc_txt" -a -n "$usage_txt" \
89                                 -a -n "$help_txt"; then
90                         ret=1
91                         return
92                 fi
93         fi
94         if test -z "$name_txt" -a -z "$desc_txt" -a -z "$usage_txt" \
95                         -a -z "$help_txt"; then
96                 ret=0
97                 return
98         fi
99         ret=-1
100         #return
101         echo "!ERROR!"
102         echo "N: $name_txt"
103         echo "D: $desc_txt"
104         echo "S: $usage_txt"
105         echo "P: $perms_txt"
106         echo "H: $help_txt"
107         echo "O: $template_prototype"
108 }
109
110 dump_man()
111 {
112         if test $template -eq 0; then
113                 echo ".SS \"$name_txt\""
114                 echo "$desc_txt"
115                 echo
116                 echo "\\fBUsage: \\fP$usage_txt"
117         else
118                 for member in $template_members; do
119                         local sed_cmd="sed -e s/@member@/$member/g"
120                         local t_name_txt=$(echo $name_txt | $sed_cmd)
121                         echo ".SS \"$t_name_txt\""
122                 done
123                 echo "$desc_txt" | sed -e "s/@member@/{$(echo $template_members | sed -e 's/ / | /g')}/g"
124                 echo
125                 echo "\\fBUsage: \\fP"
126                 echo
127                 echo ".nf"
128                 for member in $template_members; do
129                         local sed_cmd="sed -e s/@member@/$member/g"
130                         local t_usage_txt=$(echo $usage_txt | $sed_cmd)
131                         printf "\t$t_usage_txt\n"
132                 done
133                 echo ".fi"
134         fi
135         echo
136         echo "$help_txt" | sed -e 's/^  //'
137         echo
138         if test -n "$perms_txt"; then
139                 echo -n "\\fBpermissions:\\fP "
140                 if test "$perms_txt" = "0"; then
141                         echo "(none)"
142                 else
143                         echo "$perms_txt"
144                 fi
145         fi
146         echo
147 }
148
149
150 com_man()
151 {
152         echo "[$section_name]"
153         echo
154         while : ; do
155                 read_one_command
156                 if test $ret -lt 0; then
157                         exit 1
158                 fi
159                 if test $ret -eq 0; then
160                         break
161                 fi
162                 dump_man
163         done
164 }
165
166 make_proto()
167 {
168         local regex='\(__noreturn \)*\(static \)*int com_'
169         local source_file match="" all_commands CR='
170 '
171         if test -n "$prototype"; then
172                 result="$prototype$CR"
173                 return
174         fi
175         all_commands="$(cat $source_files | grep "$regex")"
176         result=
177         for source_file in $source_files; do
178                 match=$(grep "$regex$name_txt(" <<< "$all_commands" | head -n 1 | sed -e 's/$/;/1')
179                 if test -n "$match"; then
180                         result="$result$match$CR"
181                         break
182                 fi
183         done
184 }
185
186 make_array_member()
187 {
188         local TAB='     ' CR='
189 '
190         local tmp
191
192         result="{.name = \"$name_txt\", .handler = com_$name_txt, "
193         if test -n "$perms_txt"; then
194                 result="$result .perms = $perms_txt,"
195         fi
196         result="$result.description = \"$desc_txt\", .usage = \"$usage_txt\", \\$CR .help = "
197         tmp="$(printf "%s\n" "$help_txt" | sed -e 's/^/\"/g' -e 's/$/\\n\"/g' \
198                 -e "s/$TAB/\\\t/g" -e's/$/\\/g')"
199         result="$result$tmp$CR}, \\$CR"
200 }
201
202 make_completion()
203 {
204         local CR='
205 '
206         result="  {.name = \"$name_txt\", .completer = ${name_txt}_completer}, \\$CR"
207 }
208
209 template_loop()
210 {
211         local loop_result=
212
213         local t_name="$name_txt"
214         local t_perms="$perms_txt"
215         local t_desc="$desc_txt"
216         local t_usage="$usage_txt"
217         local t_help="$help_txt"
218         local t_source_files="$source_files"
219         local member
220         for member in $template_members; do
221                 name_txt="${t_name//@member@/$member}"
222                 perms_txt="${t_perms//@member@/$member}"
223                 desc_txt="${t_desc//@member@/$member}"
224                 usage_txt="${t_usage//@member@/$member}"
225                 help_txt="${t_help//@member@/$member}"
226                 prototype="${template_prototype//@member@/$member}"
227                 result=
228                 $1
229                 loop_result="$loop_result$result"
230         done
231         result="$loop_result"
232         # reset global variables
233         name_txt="$t_name"
234         perms_txt="$t_perms"
235         desc_txt="$t_desc"
236         usage_txt="$t_usage"
237         help_txt="$t_help"
238         source_files="$t_source_files"
239 }
240
241 com_header()
242 {
243         local array_members CR='
244 '
245
246         while : ; do
247                 read_one_command
248                 if test $ret -lt 0; then
249                         exit 1
250                 fi
251                 if test $ret -eq 0; then
252                         break
253                 fi
254                 if test $template -eq 0; then
255                         make_proto
256                         printf "%s" "$result"
257                         make_array_member
258                         array_members="$array_members$result"
259                         continue
260                 fi
261                 template_loop make_proto
262                 printf "%s" "$result"
263                 template_loop make_array_member
264                 array_members="$array_members$result"
265         done
266         array_members="$array_members{.name = NULL} \\$CR"
267         echo "#define DEFINE_$(tr 'a-z' 'A-Z' <<< "$base_name")_CMD_ARRAY $array_members"
268 }
269
270 com_completion()
271 {
272
273         echo "#define $1 \\"
274         while : ; do
275                 read_one_command
276                 if test $ret -lt 0; then
277                         exit 1
278                 fi
279                 if test $ret -eq 0; then
280                         break
281                 fi
282                 if test $template -eq 0; then
283                         make_completion
284                         printf "%s" "$result"
285                         continue
286                 fi
287                 template_loop make_completion
288                 printf "%s" "$result"
289         done
290         echo
291 }
292
293 read_header
294 arg="$1"
295 shift
296 case "$arg" in
297         "h")
298                 com_header
299                 ;;
300         "man")
301                 com_man $*
302                 ;;
303         "compl")
304                 com_completion $*
305                 ;;
306 esac