123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #!/bin/bash
  2. ini() {
  3. #
  4. # do ini operation
  5. #
  6. local op=$1
  7. local arg=$2
  8. local fn
  9. local limit=_ini_cat
  10. case $op in
  11. lskeys) fn=_ini_lskeys ;;
  12. sec) fn=_ini_grepsec ;;
  13. values) fn=_ini_greppath ;;
  14. 1value) fn=_ini_greppath; limit="tail -1" ;;
  15. *) die "incorrect use of \`ini()\`"
  16. esac
  17. _ini_cached | $fn $arg | $limit
  18. }
  19. _ini_cached() {
  20. #
  21. # Load ini file to our cache (RAM disk) and cat it
  22. #
  23. # User should set MKIT_INI_CACHE to a ram-based file
  24. # if mktemp cannot be relied upon.
  25. #
  26. if test -z "$_MKIT_INI_CACHED";
  27. then
  28. MKIT_INI_CACHE=${MKIT_INI_CACHE:-$(mktemp)}
  29. _MKIT_INI_CACHED=$MKIT_INI_CACHE
  30. test -r $MKIT_INI || die "cannot read MKIT_INI: $MKIT_INI"
  31. cp $MKIT_INI $_MKIT_INI_CACHED
  32. fi
  33. cat $_MKIT_INI_CACHED
  34. }
  35. _ini_cat() {
  36. #
  37. # A no-op for text stream
  38. #
  39. while read line;
  40. do
  41. printf -- "%s\n" "$line"
  42. done
  43. }
  44. _ini_expand() {
  45. #
  46. # Expand reference value (prefix only)
  47. #
  48. local line suffix ref value
  49. while read line; # [foo:bar]/path
  50. do
  51. suffix="${line#\[*\]}" # /path
  52. ref="${line%$suffix}" # [foo:bar]
  53. ref="${ref%\]}" # [foo:bar
  54. ref="${ref#\[}" # foo:bar
  55. value="$(ini 1value "$ref")" # foo_bar_value
  56. printf -- "%s\n" "$value$suffix" # foo_bar_value/path
  57. done
  58. }
  59. _ini_grepkey() {
  60. #
  61. # Read key from a section
  62. #
  63. local wnt=$1
  64. grep '.' \
  65. | grep -v '\s*#' \
  66. | sed -e 's/ *= */=/; s/ +$//; s/^//;' \
  67. | grep -e "^$wnt=" \
  68. | cut -d= -f2- \
  69. | _ini_maybe_expand
  70. }
  71. _ini_greppath() {
  72. #
  73. # Read key from the right section
  74. #
  75. # E.g. `files:share:my/lib.sh` should read
  76. #
  77. # [files:share]
  78. # my/lib.sh = proj/my/lib.sh
  79. #
  80. local wnt=$1
  81. local wntkey=${wnt##*:}
  82. local wntsec=${wnt%:$wntkey}
  83. if test "$wntsec" = 'ENV';
  84. then
  85. local override="${!wntkey}"
  86. if test -n "$override";
  87. then
  88. echo "$override"
  89. return
  90. fi
  91. fi
  92. _ini_grepsec $wntsec | _ini_grepkey $wntkey
  93. }
  94. _ini_grepsec() {
  95. #
  96. # Read one INI section
  97. #
  98. local wnt=$1
  99. local ok=false
  100. grep '.' \
  101. | grep -v '\s*#' \
  102. | while read line;
  103. do
  104. case "$line" in
  105. \[$wnt\]) ok=true; continue ;;
  106. \[*\]) ok=false; continue ;;
  107. esac
  108. $ok || continue
  109. printf -- "%s\n" "$line"
  110. done \
  111. | sed -e 's/ *= */=/; s/ +$//; s/^//;'
  112. }
  113. _ini_lskeys() {
  114. #
  115. # List keys from a section
  116. #
  117. local sct=$1
  118. _ini_grepsec $sct | cut -d= -f1 | sort | uniq
  119. }
  120. _ini_maybe_expand() {
  121. #
  122. # Decide whether or not to expand
  123. #
  124. if test $MKIT_INI_EXPAND -gt 0;
  125. then
  126. MKIT_INI_EXPAND=$(( $MKIT_INI_EXPAND - 1 )) _ini_expand
  127. else
  128. _ini_cat
  129. fi
  130. }