d_options.sh 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. #!/bin/bash
  2. # This file is part of GNU libmicrohttpd
  3. # Copyright (C) 2024 Karlson2k (Evgeny Grin), Christian Grothoff
  4. # This library is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU Lesser General Public
  6. # License as published by the Free Software Foundation; either
  7. # version 2.1 of the License, or (at your option) any later version.
  8. # This library is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. # Lesser General Public License for more details.
  12. # You should have received a copy of the GNU Lesser General Public
  13. # License along with this library; if not, write to the Free Software
  14. # Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. # Boston, MA 02110-1301 USA
  16. export LC_ALL=C
  17. export LANG=C
  18. if command -v recsel >/dev/null 2>&1 ; then : ; else
  19. echo "Error: The command 'recsel' is missing. Please install recutils." >&2
  20. exit 1
  21. fi
  22. if command -v recset >/dev/null 2>&1 ; then : ; else
  23. echo "Error: The command 'recset' is missing. Please install recutils." >&2
  24. exit 1
  25. fi
  26. if command -v recfmt >/dev/null 2>&1 ; then : ; else
  27. echo "Error: The command 'recfmt' is missing. Please install recutils." >&2
  28. exit 1
  29. fi
  30. if (( 0 + 1 )) 2>/dev/null && test "$(( 2 + 2 ))" = "4" 2>/dev/null ; then : ; else
  31. echo "Error: Built-in shell math is required" >&2
  32. exit 1
  33. fi
  34. if declare -a ARGS 2>/dev/null ; then : ; else
  35. echo "Error: Indexed arrays support is required" >&2
  36. exit 1
  37. fi
  38. if [[ "false" ]] ; then : ; else
  39. echo "Error: Compound command support is required" >&2
  40. exit 1
  41. fi
  42. if [[ $'\n' = '
  43. ' ]] ; then : ; else
  44. echo "Error: ANSI-C quoting support is required" >&2
  45. exit 1
  46. fi
  47. if [[ "abc" =~ 'b' ]] && [[ "xyz" =~ [x-z]{3} ]] ; then : ; else
  48. echo "Error: Regular expression match support is required" >&2
  49. exit 1
  50. fi
  51. test_var="abc ABC Abc"
  52. if test "${test_var^}" = "Abc ABC Abc" && test "${test_var^^}" = "ABC ABC ABC" && test "${test_var,,}" = "abc abc abc"; then : ; else
  53. echo "Error: Shell upper- and lowercase variable conversion support required" >&2
  54. exit 1
  55. fi
  56. if test "${test_var// /_}" = "abc_ABC_Abc" ; then : ; else
  57. echo "Error: Shell variable replacement conversion support required" >&2
  58. exit 1
  59. fi
  60. unset test_var
  61. if [[ "${0}" =~ (^|/|\\)'d_options.sh'$ ]]; then
  62. options_type='daemon'
  63. elif [[ "${0}" =~ (^|/|\\)'r_options.sh'$ ]]; then
  64. options_type='response'
  65. else
  66. echo "Wrong name ('$0') of the script file" >&2
  67. exit 1
  68. fi
  69. # parameters
  70. max_width=79
  71. if [[ "$options_type" = 'daemon' ]]; then
  72. input_rec='d_options.rec'
  73. rec_name='D_Options'
  74. hdr_marker="Daemon"
  75. one_char_opt_name='D'
  76. short_opt_name="$options_type"
  77. else
  78. input_rec="r_options.rec"
  79. rec_name='R_Options'
  80. hdr_marker="Response"
  81. one_char_opt_name='R'
  82. short_opt_name="resp"
  83. fi
  84. tmp_rec_name="${rec_name}_preproc"
  85. tmp_rec_file="${input_rec%.rec}_preproc.rec"
  86. # fixed strings
  87. flat_arg_descr='the value of the parameter'
  88. err_exit() {
  89. local msg="$1"
  90. local err=$2
  91. [[ -z $msg ]] && msg="Error!"
  92. ( [[ -z $err ]] || (( err < 1 )) ) && err=2
  93. echo "$msg" >&2
  94. exit $err
  95. }
  96. # cut string an newline character
  97. cut_str_nl() {
  98. local str="$1"
  99. declare -g cut_str_nl_res=''
  100. if [[ "$str" =~ $'\n' ]]; then
  101. cut_str_nl_res="${str%%$'\n'*}"
  102. return 0
  103. fi
  104. return 1
  105. }
  106. # cut string to given length at word boundary if possible
  107. # process embedded new line characters
  108. cut_str_word () {
  109. local str="$1"
  110. local len=$2
  111. declare -g cut_str_word_res=''
  112. [[ $len -le 0 ]] && return 1
  113. if cut_str_nl "${str:0:$(( len + 1 ))}"; then
  114. cut_str_word_res="${cut_str_nl_res}"
  115. cut_str_word_res="${cut_str_word_res% }"
  116. return 0
  117. fi
  118. if [[ ${#str} -le $len ]]; then
  119. cut_str_word_res="${str}"
  120. return 0
  121. fi
  122. if [[ "${str:${len}:1}" = " " ]]; then
  123. cut_str_word_res="${str:0:${len}}"
  124. cut_str_word_res="${cut_str_word_res% }"
  125. return 0
  126. fi
  127. cut_str_word_res="${str:0:${len}}"
  128. cut_str_word_res="${cut_str_word_res% *}"
  129. cut_str_word_res="${cut_str_word_res% }"
  130. return 0
  131. }
  132. format_doxy() {
  133. local prefix1="$1" # first line prefix
  134. local desc="$2"
  135. local prefix2="$3" # prefix on all other lines
  136. local width="$4"
  137. local tmp_str
  138. declare -g format_doxy_res=''
  139. [[ -z $width ]] && width=$max_width
  140. prefix1="${prefix1%"${prefix1##*[! ]}"} " # force single trailing space
  141. [[ -z $prefix2 ]] && prefix2="$prefix1"
  142. [[ ${#prefix1} -ge $width ]] && err_exit "Too long prefix ('${prefix1}') for width $width."
  143. desc="${desc#"${desc%%[! ]*}"}"
  144. desc="${desc%"${desc##*[! ]}"}" # trim desc
  145. local width_r=$(( width - ${#prefix1} ))
  146. local tmp_str="${prefix1//?/ }" # Space-only string with the same length
  147. prefix2="
  148. ${prefix2}${tmp_str:${#prefix2}}"
  149. cut_str_word "$desc" $width_r || return 1
  150. format_doxy_res="${prefix1}${cut_str_word_res}"
  151. format_doxy_res="${format_doxy_res% }"
  152. desc="${desc:${#cut_str_word_res}}"
  153. desc="${desc#"${desc%%[! ]*}"}" # trim leading spaces
  154. desc="${desc#$'\n'}" # remove leading newline character
  155. while [[ -n "$desc" ]]; do
  156. cut_str_word "$desc" $width_r || return 1
  157. tmp_str="${prefix2}${cut_str_word_res}"
  158. format_doxy_res+="${tmp_str% }"
  159. desc="${desc:${#cut_str_word_res}}"
  160. desc="${desc#"${desc%%[! ]*}"}" # trim leading spaces
  161. desc="${desc#$'\n'}" # remove leading newline character
  162. done
  163. return 0
  164. }
  165. def_name_for_type() {
  166. case $1 in
  167. 'enum MHD_Bool') echo -n "bool_val";;
  168. 'unsigned int') echo -n "uint_val";;
  169. 'uint_fast64_t') echo -n "uint64_val";;
  170. 'uint_fast32_t') echo -n "uint32_val";;
  171. 'uint_fast16_t') echo -n "uint16_val";;
  172. 'size_t') echo -n "sizet_val";;
  173. *) local tp="${1,,}" && printf '%s' "${tp// /_}_val";;
  174. esac
  175. }
  176. capitalise_first() {
  177. local first_char="${1:0:1}"
  178. printf '%s' "${first_char^^}${1:1}"
  179. }
  180. echo "Trimming lines in '$input_rec'..."
  181. ${SED-sed} -E -e 's/ +$//' -i "$input_rec" || err_exit
  182. echo "OK"
  183. echo "Checking '$input_rec'..."
  184. recfix --check "$input_rec" || exit 3
  185. echo "OK"
  186. cat << _EOF_ > "$tmp_rec_file"
  187. %rec: ${tmp_rec_name}
  188. %key: EName
  189. %mandatory: Value
  190. %mandatory: Name
  191. %type: Value int
  192. %sort: Value
  193. %singular: EName UName SName Value
  194. _EOF_
  195. echo "Processing input file..."
  196. for N in $(recsel -t "${rec_name}" -R Value "$input_rec")
  197. do
  198. NAME=$(recsel -t "${rec_name}" -P Name -e "Value = $N" "$input_rec")
  199. if [[ -z $NAME ]]; then
  200. echo "The 'Name' field is empty for 'Value=$N'" >&2
  201. exit 2
  202. fi
  203. echo -n '.'
  204. COMMENT=$(recsel -t "${rec_name}" -P Comment -e "Value = $N" "$input_rec")
  205. if [[ -z $COMMENT ]]; then
  206. echo "The 'Comment' field is empty for '$NAME' ('Value=$N')" >&2
  207. exit 2
  208. fi
  209. TYPE=$(recsel -t "${rec_name}" -P Type -e "Value = $N" "$input_rec")
  210. EComment="" # The initial part of doxy comment for the enum value
  211. EName="" # The name of the enum value
  212. UName="" # The name of the union member
  213. UType="" # The type of the union member
  214. UTypeSp='' # The type of the union member with space at the end for non-pointers
  215. SComment="" # The doxy comment for the set macro/function
  216. SName="" # The name of the set macro/function
  217. MArguments="" # The arguments for the macro
  218. CLBody="" # The Compound Literal body (for the set macro)
  219. SFArguments="" # The arguments for the static function
  220. SFBody="" # The static function body
  221. StBody='' # The data struct body (if any)
  222. nested='maybe' # The option has nested struct parameters ('yes'/'no'/'maybe')
  223. clean_name="${NAME//_/ }"
  224. clean_name="${clean_name,,}" # Lowercase space-delimited
  225. echo -n "$N: ${clean_name// /_}"
  226. EName="${clean_name^^}"
  227. EName="MHD_${one_char_opt_name^^}_O_${EName// /_}" # Uppercase '_'-joined
  228. UName="v_${clean_name// /_}" # lowercase '_'-joined
  229. SName="${clean_name^^}"
  230. SName="MHD_${one_char_opt_name^^}_OPTION_${SName// /_}" # Uppercase '_'-joined
  231. format_doxy ' * ' "$COMMENT" || err_exit
  232. EComment="$format_doxy_res"
  233. format_doxy ' * ' "$COMMENT" || err_exit
  234. SComment="$format_doxy_res"
  235. # Read option parameters
  236. ARGS=( )
  237. DESCRS=( )
  238. MEMBERS=( )
  239. M=1
  240. while
  241. ARGM=$(recsel -t "${rec_name}" -P Argument${M} -e "Value = $N" "$input_rec")
  242. [[ -n $ARGM ]]
  243. do
  244. ARGS[$M]="$ARGM"
  245. DESCRS[$M]=$(recsel -t "${rec_name}" -P Description${M} -e "Value = $N" "$input_rec")
  246. MEMBERS[$M]=$(recsel -t "${rec_name}" -P Member${M} -e "Value = $N" "$input_rec")
  247. (( M++ ))
  248. echo -n '.'
  249. done
  250. # Basic data checks
  251. (( M - 1 == ${#ARGS[@]} )) || err_exit
  252. if [[ ${#ARGS[@]} -eq 0 ]]; then
  253. [[ -z $TYPE ]] && err_exit "No 'Argument1' is specified for '$NAME' ('Value=$N') without 'Type'" >&2
  254. nested='no'
  255. ARGS[1]=''
  256. DESCRS[1]="$flat_arg_descr"
  257. MEMBERS[1]=''
  258. elif [[ ${#ARGS[@]} -eq 1 ]]; then
  259. nested='no'
  260. else
  261. nested='yes'
  262. [[ -z $TYPE ]] && err_exit "No 'Type' is specified for non-flat (nested, with multiple parameters) '$NAME' ('Value=$N')" >&2
  263. fi
  264. # Process option parameters
  265. for (( M=1 ; M <= ${#ARGS[@]} ; M++ )) ; do
  266. arg_name='' # The name of the current argument
  267. arg_type='' # The type of the data of the current argument
  268. arg_descr='' # The description of the current argument
  269. nest_member='' # The name of the member of the nested structure
  270. [[ "${ARGS[$M]}" =~ (^' '|' '$) ]] && err_exit "'Argument${M}' value '${ARGS[$M]}' for '$NAME' ('Value=$N') is not trimmed"
  271. [[ "${DESCRS[$M]}" =~ (^' '|' '$) ]] && err_exit "'Description${M}' value '${DESCRS[$M]}' for '$NAME' ('Value=$N') is not trimmed"
  272. [[ "${MEMBERS[$M]}" =~ (^' '|' '$) ]] && err_exit "'Member${M}' value '${MEMBERS[$M]}' for '$NAME' ('Value=$N') is not trimmed"
  273. # Pre-process parameters data
  274. if [[ -n ${ARGS[$M]} ]]; then
  275. arg_name="${ARGS[$M]##* }"
  276. arg_name="${arg_name#\*}"
  277. arg_type="${ARGS[$M]%${arg_name}}"
  278. arg_type="${arg_type% }"
  279. else
  280. if [[ $nested = 'yes' ]]; then
  281. err_exit "Empty or no 'Argument${M}' ('$arg_type') for '$NAME' ('Value=$N')"
  282. else
  283. [[ -z $TYPE ]] && err_exit "No 'Argument1' is specified for '$NAME' ('Value=$N') without 'Type'" >&2
  284. arg_name="$(def_name_for_type "$TYPE")"
  285. arg_type="$TYPE"
  286. fi
  287. fi
  288. arg_descr="${DESCRS[$M]}"
  289. nest_membr="${MEMBERS[$M]}"
  290. [[ -z $arg_name ]] && err_exit # Should not happen
  291. if [[ $nested = 'yes' ]]; then
  292. # non-flat, nested
  293. [[ -z $arg_type ]] && err_exit "No argument type in 'Argument${M}' ('${ARGS[$M]}') for $NAME ('Value=$N')"
  294. [[ $TYPE = $arg_type ]] && \
  295. err_exit "The same 'Type' and type for in 'Argument${M}' ('$arg_type') used for non-flat (nested) '$NAME' ('Value=$N')"
  296. [[ -z $arg_descr ]] && \
  297. err_exit "Empty or no 'Description${M}' for argument '${ARGS[$M]}' for non-flat (nested) '$NAME' ('Value=$N')"
  298. if [[ "$arg_name" = "$nest_membr" ]]; then
  299. echo "The name for 'Argument${M}' ('${ARGS[$M]}') is the same as the 'Member${M}' ('$nest_membr') for non-flat (nested) '$NAME' ('Value=$N')" >&2
  300. nest_membr="v_${nest_membr}"
  301. echo "Auto-correcting the struct member name to '$nest_membr' to avoid wrong macro expansion" >&2
  302. fi
  303. else
  304. # flat, non-nested
  305. if [[ -z $arg_type ]]; then
  306. if [[ -z $TYPE ]]; then
  307. err_exit "Both 'Type' and type for in 'Argument${M}' ('${ARGS[$M]}') are empty for '$NAME' ('Value=$N')"
  308. else
  309. arg_type="$TYPE"
  310. fi
  311. else
  312. if [[ -z $TYPE ]]; then
  313. TYPE="$arg_type"
  314. elif [[ $TYPE != $arg_type ]]; then
  315. err_exit "Different 'Type' ('$TYPE') and type for in 'Argument${M}' ('$arg_type') used for '$NAME' ('Value=$N')"
  316. fi
  317. fi
  318. [[ -z $arg_descr ]] && arg_descr="$flat_arg_descr"
  319. [[ -n $nest_membr ]] && \
  320. err_exit "'Member${M}' is provided for non-nested (flat) '$NAME' ('Value=$N')"
  321. fi
  322. [[ "$arg_type" =~ \*$ ]] || arg_type+=' ' # Position '*' correctly
  323. [[ "$arg_name" = "${UName}" ]] && err_exit "The name ('$arg_name') of the argument 'Argument${M}' ('${ARGS[$M]}') for '$NAME' ('Value=$N') conflicts with the union member name ('${UName}'). Macro would not work."
  324. [[ "$arg_name" = "opt" ]] && err_exit "The name ('$arg_name') of the argument 'Argument${M}' ('${ARGS[$M]}') for '$NAME' ('Value=$N') conflicts with the option struct member name ('opt'). Macro would not work."
  325. [[ "$arg_name" = "val" ]] && err_exit "The name ('$arg_name') of the argument 'Argument${M}' ('${ARGS[$M]}') for '$NAME' ('Value=$N') conflicts with the option struct member name ('val'). Macro would not work."
  326. [[ "${arg_name,,}" = "${arg_name}" ]] || err_exit "The name ('$arg_name') of the argument 'Argument${M}' ('${ARGS[$M]}') for '$NAME' ('Value=$N') has capital letter(s)"
  327. [[ $nested = 'yes' ]] && [[ -z $nest_membr ]] && nest_membr="v_${arg_name}"
  328. [[ "${#arg_name}" -ge 15 ]] && echo "Warning: too long (${#arg_name} chars) parameter name '${arg_name}'." >&2
  329. [[ $M -gt 1 ]] && [[ $nested = 'no' ]] && err_exit
  330. # Use parameters data
  331. format_doxy ' * @param '"$arg_name " "$arg_descr" ' * '|| err_exit
  332. SComment+=$'\n'"$format_doxy_res"
  333. [[ $M -gt 1 ]] && MArguments+=','
  334. MArguments+="$arg_name"
  335. if [[ $nested = 'yes' ]]; then
  336. [[ $M -gt 1 ]] && SFArguments+=','
  337. SFArguments+=$'\n'" ${arg_type}$arg_name"
  338. else
  339. if (( ${#SName} + ${#arg_type} + ${#arg_name} <= $max_width )); then
  340. SFArguments+="${arg_type}$arg_name"
  341. else
  342. SFArguments+=$'\n'" ${arg_type}$arg_name"
  343. fi
  344. fi
  345. #[[ $M -gt 1 ]] && CLBody+=', \'$'\n'" "
  346. [[ $M -gt 1 ]] && CLBody+=', \##removeme##'$'\n'" " # '##removeme##' is a workaround for requtils bug
  347. CLBody+=".val.${UName}"
  348. [[ $nested = 'yes' ]] && CLBody+=".${nest_membr}"
  349. CLBody+=" = ($arg_name)"
  350. [[ $M -gt 1 ]] && SFBody+=$'\n'" "
  351. SFBody+="opt_val.val.${UName}"
  352. [[ $nested = 'yes' ]] && SFBody+=".${nest_membr}"
  353. SFBody+=" = ${arg_name};"
  354. if [[ $nested = 'yes' ]] && [[ "$TYPE" =~ ^'struct ' ]]; then
  355. StBody+=$'\n'
  356. StBody+=" /**"$'\n'
  357. format_doxy ' * ' "$(capitalise_first "$arg_descr")" || err_exit
  358. StBody+="$format_doxy_res"$'\n'" */"$'\n'
  359. StBody+=" ${arg_type}$nest_membr;"
  360. fi
  361. echo -n '.'
  362. done
  363. UType="$TYPE"
  364. if [[ $nested = 'yes' ]] && [[ "$TYPE" =~ ^'struct ' ]]; then
  365. need_struct_decl='yes'
  366. else
  367. need_struct_decl='no'
  368. fi
  369. [[ "$UType" =~ \*$ ]] && UTypeSp="$UType" || UTypeSp="$UType " # Position '*' correctly
  370. recins -t "${tmp_rec_name}" \
  371. -f Name -v "$NAME" \
  372. -f Value -v "$N" \
  373. -f hdr_marker -v "$hdr_marker" \
  374. -f EComment -v "$EComment" \
  375. -f EName -v "$EName" \
  376. -f UName -v "$UName" \
  377. -f UType -v "$UType" \
  378. -f UTypeSp -v "$UTypeSp" \
  379. -f SComment -v "$SComment" \
  380. -f SName -v "$SName" \
  381. -f MArguments -v "$MArguments" \
  382. -f CLBody -v "$CLBody" \
  383. -f SFArguments -v "$SFArguments" \
  384. -f SFBody -v "$SFBody" \
  385. -f StBody -v "$StBody" \
  386. --verbose "$tmp_rec_file" || err_exit
  387. echo '.'
  388. done
  389. echo "finished."
  390. echo "Updating header file..."
  391. header_name='microhttpd2.h'
  392. start_of_marker=" = MHD ${hdr_marker} Option "
  393. end_of_start_marker=' below are generated automatically = '
  394. end_of_end_marker=' above are generated automatically = '
  395. I=0
  396. cp "../src/include/${header_name}" "./${header_name}" || err_exit
  397. middle_of_marker='enum values'
  398. echo "${middle_of_marker}..."
  399. in_file="${header_name}"
  400. out_file="${header_name%.h}_tmp$((++I)).h"
  401. recfmt -f options_enum.template < "$tmp_rec_file" > "header_insert${I}.h" || err_exit
  402. middle_of_marker='enum values'
  403. start_marker="${start_of_marker}${middle_of_marker}${end_of_start_marker}" && end_marker="${start_of_marker}${middle_of_marker}${end_of_end_marker}" || err_exit
  404. ${SED-sed} -e '/'"$start_marker"'/{p; r header_insert'"$I"'.h
  405. }
  406. /'"$end_marker"'/p
  407. /'"$start_marker"'/,/'"$end_marker"'/d' "${in_file}" > "${out_file}" || err_exit
  408. middle_of_marker='structures'
  409. echo "${middle_of_marker}..."
  410. in_file="${out_file}"
  411. out_file="${header_name%.h}_tmp$((++I)).h"
  412. recsel -e "StBody != ''" "$tmp_rec_file" | recfmt -f options_struct.template > "header_insert${I}.h" || err_exit
  413. start_marker="${start_of_marker}${middle_of_marker}${end_of_start_marker}" && end_marker="${start_of_marker}${middle_of_marker}${end_of_end_marker}" || err_exit
  414. ${SED-sed} -e '/'"$start_marker"'/{p; r header_insert'"$I"'.h
  415. }
  416. /'"$end_marker"'/p
  417. /'"$start_marker"'/,/'"$end_marker"'/d' "${in_file}" > "${out_file}" || err_exit
  418. middle_of_marker='union members'
  419. echo "${middle_of_marker}..."
  420. in_file="${out_file}"
  421. out_file="${header_name%.h}_tmp$((++I)).h"
  422. recfmt -f options_union.template < "$tmp_rec_file" > "header_insert${I}.h" || err_exit
  423. start_marker="${start_of_marker}${middle_of_marker}${end_of_start_marker}" && end_marker="${start_of_marker}${middle_of_marker}${end_of_end_marker}" || err_exit
  424. ${SED-sed} -e '/'"$start_marker"'/{p; r header_insert'"$I"'.h
  425. }
  426. /'"$end_marker"'/p
  427. /'"$start_marker"'/,/'"$end_marker"'/d' "${in_file}" > "${out_file}" || err_exit
  428. middle_of_marker='macros'
  429. echo "${middle_of_marker}..."
  430. in_file="${out_file}"
  431. out_file="${header_name%.h}_tmp$((++I)).h"
  432. recfmt -f options_macro.template < "$tmp_rec_file" | ${SED-sed} -e 's/##removeme##//g' - > "header_insert${I}.h" || err_exit
  433. start_marker="${start_of_marker}${middle_of_marker}${end_of_start_marker}" && end_marker="${start_of_marker}${middle_of_marker}${end_of_end_marker}" || err_exit
  434. ${SED-sed} -e '/'"$start_marker"'/{p; r header_insert'"$I"'.h
  435. }
  436. /'"$end_marker"'/p
  437. /'"$start_marker"'/,/'"$end_marker"'/d' "${in_file}" > "${out_file}" || err_exit
  438. middle_of_marker='static functions'
  439. echo "${middle_of_marker}..."
  440. in_file="${out_file}"
  441. out_file="${header_name%.h}_tmp$((++I)).h"
  442. recfmt -f options_func.template < "$tmp_rec_file" > "header_insert${I}.h" || err_exit
  443. start_marker="${start_of_marker}${middle_of_marker}${end_of_start_marker}" && end_marker="${start_of_marker}${middle_of_marker}${end_of_end_marker}" || err_exit
  444. ${SED-sed} -e '/'"$start_marker"'/{p; r header_insert'"$I"'.h
  445. }
  446. /'"$end_marker"'/p
  447. /'"$start_marker"'/,/'"$end_marker"'/d' "${in_file}" > "${out_file}" || err_exit
  448. echo "finished."
  449. if diff "../src/include/${header_name}" "${out_file}" > /dev/null; then
  450. echo "The updated header '${header_name}' content is equal to the previous content, the file remains the same."
  451. else
  452. mv "${out_file}" "../src/include/${header_name}" || err_exit
  453. echo "The header '${header_name}' has been updated with the new content."
  454. fi
  455. echo "Cleanup..."
  456. rm -f "$tmp_rec_file" ${header_name%.h}_tmp?.h header_insert?.h
  457. echo "completed."