command_util: Generate properly documented command header files.
[paraslash.git] / command_util.sh
1 #!/usr/bin/env bash
2
3
4 read_header()
5 {
6 local key value i
7
8 while read key value; do
9 case "$key" in
10 ---)
11 break
12 ;;
13 HC:)
14 header_comment="$value"
15 ;;
16 CC:)
17 c_file_comment="$value"
18 ;;
19 OF:)
20 output_file="$value"
21 array_name=${value%command_list}cmds
22 ;;
23 SF:)
24 source_files="$value"
25 ;;
26 AT:)
27 array_type="$value"
28 ;;
29 SI:)
30 for i in $value; do
31 system_includes="$system_includes
32 #include <$i.h>"
33 done
34 ;;
35 IN:)
36 for i in $value; do
37 includes="$includes
38 #include \"$i.h\""
39 done
40 includes="$includes
41 #include \"$output_file.h\""
42 ;;
43 SN:)
44 section_name="$value"
45 ;;
46 TM:)
47 template_members="$value"
48 esac
49 done
50 if test -z "$header_comment" -o -z "$c_file_comment" \
51 -o -z "$output_file"; then
52 echo "header error" 1&>2
53 exit 1
54 fi
55 }
56
57 read_one_command()
58 {
59 local line
60
61 name_txt=""
62 desc_txt=""
63 usage_txt=""
64 help_txt=""
65 perms_txt=""
66 line_handler=0
67 template=0
68 template_name=""
69 template_prototype=""
70 mkdir -p man/man1
71 while read key value; do
72 case "$key" in
73 ---)
74 break
75 ;;
76 N:)
77 name_txt="$value"
78 ;;
79 T:)
80 template_name="$value"
81 template=1
82 ;;
83 O:)
84 template_prototype="$value"
85 template=1
86 ;;
87 P:)
88 perms_txt="$value"
89 ;;
90 D:)
91 desc_txt="$value"
92 ;;
93 L:)
94 line_handler=1
95 ;;
96 U:)
97 usage_txt="$value"
98 ;;
99 H:)
100 help_txt="${value}"
101 while read line; do
102 if test "$line" = "---"; then
103 break;
104 fi
105 line=${line#H:}
106 help_txt="$help_txt
107 ${line# }"
108 done
109 break
110 ;;
111 esac
112 done
113 if test $template -eq 0; then
114 if test -n "$name_txt" -a -n "$desc_txt" -a -n "$usage_txt" \
115 -a -n "$help_txt"; then
116 ret=1
117 return
118 fi
119 else
120 if test -n "$template_name" -a -n "$template_prototype" \
121 -a -n "$name_txt " -a -n "$template_members" \
122 -a -n "$desc_txt" -a -n "$usage_txt" \
123 -a -n "$help_txt"; then
124 ret=1
125 return
126 fi
127 fi
128 if test -z "$name_txt" -a -z "$desc_txt" -a -z "$usage_txt" \
129 -a -z "$help_txt"; then
130 ret=0
131 return
132 fi
133 ret=-1
134 #return
135 echo "!ERROR!"
136 echo "N: $name_txt"
137 echo "D: $desc_txt"
138 echo "S: $usage_txt"
139 echo "P: $perms_txt"
140 echo "H: $help_txt"
141 echo "O: $template_prototype"
142 }
143
144 dump_man()
145 {
146 if test $template -eq 0; then
147 echo ".SS \"$name_txt\""
148 echo "$desc_txt"
149 echo
150 echo "\\fBUsage: \\fP$usage_txt"
151 else
152 for member in $template_members; do
153 local sed_cmd="sed -e s/@member@/$member/g"
154 local t_name_txt=$(echo $name_txt | $sed_cmd)
155 echo ".SS \"$t_name_txt\""
156 done
157 echo "$desc_txt" | sed -e "s/@member@/{$(echo $template_members | sed -e 's/ / | /g')}/g"
158 echo
159 echo "\\fBUsage: \\fP"
160 echo
161 echo ".nf"
162 for member in $template_members; do
163 local sed_cmd="sed -e s/@member@/$member/g"
164 local t_usage_txt=$(echo $usage_txt | $sed_cmd)
165 printf "\t$t_usage_txt\n"
166 done
167 echo ".fi"
168 fi
169 echo
170 echo "$help_txt" | sed -e 's/^ //'
171 echo
172 if test -n "$perms_txt"; then
173 echo -n "\\fBpermissions:\\fP "
174 if test "$perms_txt" = "0"; then
175 echo "(none)"
176 else
177 echo "$perms_txt"
178 fi
179 fi
180 echo
181 }
182
183
184 com_man()
185 {
186 echo "[$section_name]"
187 echo
188 while : ; do
189 read_one_command
190 if test $ret -lt 0; then
191 exit 1
192 fi
193 if test $ret -eq 0; then
194 break
195 fi
196 dump_man
197 done
198 }
199
200 dump_proto()
201 {
202 local source_file match=""
203
204 echo '/**'
205 echo " * $desc_txt"
206 echo ' *'
207 if [[ "$system_includes" =~ openssl/rc4.h ]]; then
208 echo ' * \param rc4c The rc4 crypt context.'
209 else
210 echo ' * \param fd The file descriptor to send output to.'
211 fi
212 if test $line_handler -eq 0; then
213 echo ' * \param argc The number of arguments.'
214 echo ' * \param argv The argument vector.'
215 else
216 echo ' * \param cmdline The full command line.'
217 fi
218 echo ' * '
219 echo " * Usage: $usage_txt"
220 echo ' * '
221 echo "$help_txt" | sed -e 's/^/ * /g'
222 echo ' */'
223 if test -n "$prototype"; then
224 echo "$prototype"
225 echo
226 return
227 fi
228 for source_file in $source_files; do
229 match=$(grep "^\(__noreturn \)*int com_$name_txt(" $source_file | head -n 1 | sed -e 's/$/;/1')
230 if test -n "$match"; then
231 echo "$match"
232 break
233 fi
234 done
235 echo
236 }
237
238 dump_array_member()
239 {
240 echo '{'
241 echo ".name = \"$name_txt\","
242 if test $line_handler -eq 0; then
243 echo ".handler = com_$name_txt,"
244 else
245 echo ".handler = NULL,"
246 echo ".line_handler = com_$name_txt,"
247 fi
248 if test -n "$perms_txt"; then
249 echo ".perms = $perms_txt,"
250 fi
251 echo ".description = \"$desc_txt\","
252 echo ".usage = \"$usage_txt\","
253 echo ".help = "
254 printf "%s\n" "$help_txt" | sed -e 's/^/\"/g' -e 's/$/\\n\"/g'
255 echo '},'
256 }
257
258
259 template_loop()
260 {
261 local t_name="$name_txt"
262 local t_perms="$perms_txt"
263 local t_desc="$desc_txt"
264 local t_usage="$usage_txt"
265 local t_help="$help_txt"
266 local t_source_files="$source_files"
267 local member
268 for member in $template_members; do
269 local sed_cmd="sed -e s/@member@/$member/g"
270 #echo "sed_cmd: $sed_cmd"
271 name_txt=$(echo $t_name | $sed_cmd)
272 #name_txt="$tname"
273 perms_txt=$(echo $t_perms | $sed_cmd)
274 desc_txt=$(echo $t_desc | $sed_cmd)
275 usage_txt=$(echo $t_usage | $sed_cmd)
276 help_txt=$(printf "%s\n" "$t_help" | $sed_cmd)
277 prototype=$(echo "$template_prototype" | $sed_cmd)
278 $1
279 done
280
281 }
282
283 com_c_file()
284 {
285 echo "/** \file $output_file.c $c_file_comment */"
286 echo "$system_includes"
287 echo "$includes"
288 echo "struct $array_type $array_name[] = {"
289 while : ; do
290 read_one_command
291 if test $ret -lt 0; then
292 exit 1
293 fi
294 if test $ret -eq 0; then
295 break
296 fi
297 if test $template -eq 0; then
298 dump_array_member
299 continue
300 fi
301 template_loop dump_array_member
302 done
303 echo '{.name = NULL}};'
304 }
305
306 com_header()
307 {
308 echo "/** \file $output_file.h $header_comment */"
309 echo
310 echo "extern struct $array_type $array_name[];"
311 while : ; do
312 read_one_command
313 if test $ret -lt 0; then
314 exit 1
315 fi
316 if test $ret -eq 0; then
317 break
318 fi
319 if test $template -eq 0; then
320 dump_proto
321 continue
322 fi
323 template_loop dump_proto
324 done
325 }
326
327 read_header
328 arg="$1"
329 shift
330 case "$arg" in
331 "c")
332 com_c_file
333 ;;
334 "h")
335 com_header
336 ;;
337 "man")
338 com_man $*
339 ;;
340 esac