__ini_value: starting base parts
Initial body of the __ini_value. It contains two awk-scripts: to detect the state that is important to trigger a code generation, and to change that line to the correct line. It might have problems which is not matured enoght. The most difficult points will be the comment detection, as this is a critical point as you don't know if the user want to have this touched.
This commit is contained in:
parent
22f637c15b
commit
8c7a6906de
17 changed files with 471 additions and 0 deletions
152
cdist/conf/type/__ini_value/explorer/state
Executable file
152
cdist/conf/type/__ini_value/explorer/state
Executable file
|
@ -0,0 +1,152 @@
|
|||
#!/bin/sh -e
|
||||
# __ini_value/explorer/state
|
||||
|
||||
# Check the state of the key-value pair in the ini file
|
||||
#
|
||||
# There are following states:
|
||||
# - present
|
||||
# - wrongvalue
|
||||
# - wrongformat
|
||||
# - commented
|
||||
# - absent
|
||||
# - nosuchfile
|
||||
|
||||
# Using ' \t' for matching spaces as char classes not implemented in mawk
|
||||
# see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=65617#40
|
||||
|
||||
# Parameters
|
||||
# (maybe multi-variable object id for this ..)
|
||||
#state_should="$(cat "$__object/parameter/state")"
|
||||
file="$(cat "$__object/parameter/file")"
|
||||
|
||||
# abort if no file exist
|
||||
if ! [ -f "$file" ]; then
|
||||
echo nosuchfile
|
||||
exit
|
||||
fi
|
||||
|
||||
# run awk
|
||||
awk -f - "$file" <<'AWK'
|
||||
function trim(var) {
|
||||
sub(/^[ \t]*/, "", var)
|
||||
sub(/[ \t]*$/, "", var)
|
||||
return var
|
||||
}
|
||||
function check_spaces(var) {
|
||||
return match(var, /^[ \t]*$/) == 1
|
||||
}
|
||||
function state(val) {
|
||||
print val
|
||||
exit
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
_param = (ENVIRON["__object"] "/parameter/")
|
||||
getline state_should < (_param "state")
|
||||
getline section < (_param "section")
|
||||
getline key < (_param "key")
|
||||
getline delimiter < (_param "delimiter")
|
||||
getline value < (_param "value")
|
||||
getline indentation < (_param "indentation")
|
||||
|
||||
do_normalization = (system("test -f " (_param "normalize")) == 0)
|
||||
|
||||
i=0; _comm_param = (_param "comment-sign");
|
||||
while((getline tmp < _comm_param) > 0) {
|
||||
comment_signs[i++] = tmp
|
||||
}
|
||||
|
||||
found=0
|
||||
curr_section=""
|
||||
if(section == "")
|
||||
found_section=1
|
||||
else
|
||||
found_section=0
|
||||
}
|
||||
|
||||
# catch sections
|
||||
/^[ \t]*\[.*\][ \t]*$/ {
|
||||
curr_section = trim($0)
|
||||
if(found_section)
|
||||
exit # game over, section ends
|
||||
if(section == curr_section)
|
||||
found_section=1
|
||||
next
|
||||
}
|
||||
|
||||
# only interesting if a delimiter was found
|
||||
found_section {
|
||||
line = $0
|
||||
|
||||
# index 1 cause of trimmed string
|
||||
if((idel = index(line, delimiter)) && (ikey = index(line, key))) {
|
||||
if(ikey > 1) {
|
||||
# maybe comment character or only spaces
|
||||
start_string = substr(line, 1, ikey - 1)
|
||||
|
||||
# something inside rather than a space -> comment
|
||||
if((icom = match(start_string, /[^ \t]+/)) > 0) {
|
||||
# icom = RSTART
|
||||
# only one free-standing char or directly before the key
|
||||
if(RLENGTH == 1 || icom == ikey - 1) {
|
||||
start_sign = substr(line, RSTART, 1)
|
||||
is_com=0
|
||||
for(i in comment_signs) {
|
||||
if(start_sign == comment_signs[i]) {
|
||||
is_com = 1; break;
|
||||
}
|
||||
}
|
||||
if(!is_com) next
|
||||
else {
|
||||
aftercom_length = ikey - icom - 1
|
||||
if(!check_spaces(substr(line, icom + 1, aftercom_length))) next
|
||||
start_spaces = (icom - 1) + aftercom_length
|
||||
}
|
||||
}
|
||||
else next
|
||||
}
|
||||
# must only contain spaces
|
||||
else start_spaces = ikey - 1
|
||||
}
|
||||
# start_spaces set or 0
|
||||
|
||||
idelspace_start = ikey + length(key)
|
||||
idelspace_length = idel - (idelspace_start)
|
||||
# check for delimiter is only preceded with spaces
|
||||
if(idelspace_length == 0 || check_spaces(substr(line, idelspace_start, idelspace_length))) {
|
||||
found = 1
|
||||
|
||||
# short-circuit on state absent to just delete
|
||||
if(state_should == "absent") state("present");
|
||||
|
||||
|
||||
# extract the value
|
||||
found_value = substr(line, idel + length(delimiter))
|
||||
is_value = trim(found_value)
|
||||
|
||||
# check if value is incorrect
|
||||
if(value != is_value) state("wrongvalue")
|
||||
else {
|
||||
# check if the format is important
|
||||
if(do_normalization) {
|
||||
# the format must exactly match, else it is incorrect
|
||||
if(indentation != start_spaces || idelspace_length != 0 || found_value != is_value)
|
||||
state("wrongformat")
|
||||
}
|
||||
|
||||
if(is_com)
|
||||
state("commented")
|
||||
else
|
||||
state("present")
|
||||
}
|
||||
# this will never be reached
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# in the end, check if it is absent
|
||||
END {
|
||||
if(!found)
|
||||
state("absent")
|
||||
}
|
||||
AWK
|
128
cdist/conf/type/__ini_value/files/base.awk
Normal file
128
cdist/conf/type/__ini_value/files/base.awk
Normal file
|
@ -0,0 +1,128 @@
|
|||
BEGIN {
|
||||
#bufindex = 0
|
||||
#maxbuflen = 2
|
||||
|
||||
# no section means the start to the first section
|
||||
if(section == "") {
|
||||
is_curr_section = 1
|
||||
found_section = 1
|
||||
}
|
||||
}
|
||||
|
||||
# legacy function
|
||||
function flush_buffer() {
|
||||
#while(bufindex > 0) {
|
||||
# _pop_buffer()
|
||||
#}
|
||||
if(lastlinepopulated) {
|
||||
print lastline
|
||||
lastlinepopulated = 0
|
||||
}
|
||||
}
|
||||
|
||||
# excepts the first character is the sign to check (string is trimmed)
|
||||
function is_comment(line) {
|
||||
# get character and check
|
||||
line_sign = substr(line, 1, 1)
|
||||
for(i in comment_signs)
|
||||
if(line_sign == comment_signs[i])
|
||||
return 1
|
||||
|
||||
# nothing found
|
||||
return 0
|
||||
}
|
||||
function was_comment(line, comment) {
|
||||
line = trim(line)
|
||||
if(is_comment(line)) {
|
||||
return trim(substr(line, 2)) == comment
|
||||
}
|
||||
}
|
||||
|
||||
# print everything if line found instead of processing it
|
||||
# maybe just a function to loop through getline for lightest overhead
|
||||
found {print; next}
|
||||
|
||||
# main loop (til the line was found)
|
||||
!found {
|
||||
line = trim($0)
|
||||
# short curcit on empty lines
|
||||
if(line == "") {
|
||||
# TODO code to function!
|
||||
flush_buffer()
|
||||
lastline = $0
|
||||
lastlinepopulated = 1
|
||||
next
|
||||
}
|
||||
|
||||
# write to linebuffer
|
||||
#if(bufindex > maxbuflen)
|
||||
# _pop_buffer()
|
||||
#linebuffer[++bufindex] = $0
|
||||
|
||||
# check for a ini section
|
||||
if(substr(line, 1, 1) == "[" && substr(line, length(line), 1) == "]") {
|
||||
is_section = 1
|
||||
curr_section = line
|
||||
|
||||
if(curr_section == section) {
|
||||
found_section = 1
|
||||
is_curr_section = 1
|
||||
}
|
||||
else {
|
||||
# if nothing found, print it in the valid section before the next one
|
||||
if(is_curr_section) {
|
||||
if(!found) {
|
||||
# set found as it is there now
|
||||
found=1
|
||||
|
||||
# %codeblock_insert%
|
||||
}
|
||||
is_curr_section = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
# only current session is interessting
|
||||
if(is_curr_section) {
|
||||
# check for a comment
|
||||
is_com = is_comment(line)
|
||||
if(is_com) {
|
||||
line = trim(substr(line, 2))
|
||||
}
|
||||
|
||||
# check for a delimiter and a key (must be at first position due to trimming)
|
||||
if((idel = index(line, delimiter)) && (ikey = index(line, key)) == 1) {
|
||||
# check there are only spaces between the delimiter
|
||||
if(check_spaces(substr(line, ikey + length(key), idel - (length(key) + 1)))) {
|
||||
found = 1
|
||||
|
||||
# %codeblock_found%
|
||||
|
||||
next
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# TODO
|
||||
# works cause no next statement from above *structual programming*
|
||||
#print lastline
|
||||
flush_buffer()
|
||||
lastline = $0
|
||||
lastlinepopulated = 1
|
||||
}
|
||||
|
||||
END {
|
||||
# if not found, it's not already printed
|
||||
if(!found) {
|
||||
flush_buffer()
|
||||
|
||||
# print with section if not found
|
||||
if(!found_section) {
|
||||
# TODO check via buffer if a empty line is necessary
|
||||
print section
|
||||
|
||||
# %codeblock_insert%
|
||||
}
|
||||
}
|
||||
}
|
61
cdist/conf/type/__ini_value/files/common.awk
Normal file
61
cdist/conf/type/__ini_value/files/common.awk
Normal file
|
@ -0,0 +1,61 @@
|
|||
BEGIN {
|
||||
# parameter variables
|
||||
section = get_param_string("section")
|
||||
key = get_param_string("key")
|
||||
delimiter = get_param_string("delimiter")
|
||||
value = get_param_string("value")
|
||||
comment = get_param_string("comment")
|
||||
indentation = get_param_string("indentation")
|
||||
|
||||
get_param_array("comment-sign", comment_signs)
|
||||
comment_sign = comment_signs[0]
|
||||
}
|
||||
|
||||
function trim(var) {
|
||||
sub(/^[ \t]*/, "", var)
|
||||
sub(/[ \t]*$/, "", var)
|
||||
return var
|
||||
}
|
||||
function check_spaces(part) {
|
||||
return match(part, /^[ \t]*$/) == 1
|
||||
}
|
||||
|
||||
function get_param_string(name) {
|
||||
_paramfile = (ENVIRON["__object"] "/parameter/" name)
|
||||
if((getline tmp < _paramfile) > 0) {
|
||||
close(_paramfile)
|
||||
return tmp
|
||||
}
|
||||
else return ""
|
||||
}
|
||||
function get_param_array(name, arr) {
|
||||
_paramfile = (ENVIRON["__object"] "/parameter/" name)
|
||||
i=0
|
||||
split("", arr) # portable clear, like `delete arr`
|
||||
while((getline tmp < _paramfile) > 0) {
|
||||
arr[i++] = tmp
|
||||
}
|
||||
close(_paramfile)
|
||||
}
|
||||
|
||||
# print value
|
||||
function v_print() {
|
||||
spaces = ""
|
||||
for(i = 0; i < indentation; i++)
|
||||
spaces = (spaces " ")
|
||||
printf "%s%s%s%s%s", spaces, key, delimiter, value, ORS
|
||||
}
|
||||
# print commented value
|
||||
function v_print_commented() {
|
||||
spaces = ""
|
||||
for(i = 0; i < indentation; i++)
|
||||
spaces = (spaces " ")
|
||||
printf "%s%s%s%s%s%s", spaces, comment_sign, key, delimiter, value, ORS
|
||||
}
|
||||
# print comment
|
||||
function c_print() {
|
||||
spaces = ""
|
||||
for(i = 0; i < indentation; i++)
|
||||
spaces = (spaces " ")
|
||||
printf "%s%s%s%s%s", spaces, comment_sign, " ", comment, ORS
|
||||
}
|
53
cdist/conf/type/__ini_value/files/gen-awk.sh
Executable file
53
cdist/conf/type/__ini_value/files/gen-awk.sh
Executable file
|
@ -0,0 +1,53 @@
|
|||
#!/bin/sh -e
|
||||
# __ini_value/files/gen-awk.sh
|
||||
|
||||
# Generates the awk script that will modify the line
|
||||
#
|
||||
# Arguments:
|
||||
# 1: the file to modify
|
||||
# 2: the should_state
|
||||
|
||||
strip_comments() {
|
||||
grep -v '^[[:space:]]*\($\|#\)'
|
||||
}
|
||||
|
||||
|
||||
file="$1"
|
||||
state="$2"
|
||||
|
||||
|
||||
# Generate the basic awk struct
|
||||
cat <<SHELL
|
||||
tmpfile="\$(mktemp '${file}.cdist.XXXXXXXX')"
|
||||
if [ -f '$file' ]; then
|
||||
cp -p '$file' "\$tmpfile"
|
||||
fi
|
||||
|
||||
awk -f - '$file' > "\$tmpfile" <<'AWK'
|
||||
SHELL
|
||||
|
||||
|
||||
# generate the awk script and strip unnecessary things
|
||||
{
|
||||
# basic functions which everyone needs
|
||||
cat "$__type/files/common.awk"
|
||||
|
||||
# generate the script and strip
|
||||
awk -v state="$state" '
|
||||
{
|
||||
if(match($0, /^[ \t]*# %codeblock_([^%]+)%$/, result) > 0) {
|
||||
file = (ENVIRON["__type"] "/files/parts/" state "/" result[1] ".awk")
|
||||
while((getline line < file) > 0)
|
||||
print line
|
||||
close(file)
|
||||
}
|
||||
else print
|
||||
}' "$__type/files/base.awk"
|
||||
} | strip_comments
|
||||
|
||||
|
||||
# end of here-doc
|
||||
cat <<SHELL
|
||||
AWK
|
||||
mv -f "\$tmpfile" '$file'
|
||||
SHELL
|
3
cdist/conf/type/__ini_value/files/parts/absent/found.awk
Normal file
3
cdist/conf/type/__ini_value/files/parts/absent/found.awk
Normal file
|
@ -0,0 +1,3 @@
|
|||
# flush last line if it was not the meant comment
|
||||
if(!was_comment(lastline, comment)) flush_buffer()
|
||||
else lastlinepopulated = 0
|
|
@ -0,0 +1,8 @@
|
|||
# check if last line was the comment
|
||||
was_com_there = was_comment(lastline, comment)
|
||||
|
||||
# print + comment if not there
|
||||
flush_buffer()
|
||||
if(comment && !was_com_there) c_print()
|
||||
|
||||
v_print_commented()
|
|
@ -0,0 +1,9 @@
|
|||
was_com_there = was_comment(lastline, comment)
|
||||
|
||||
# print before and comment
|
||||
flush_buffer()
|
||||
if(comment && !was_com_there) c_print()
|
||||
|
||||
# print value + seperator line at the end
|
||||
v_print_commented()
|
||||
print ""
|
|
@ -0,0 +1,8 @@
|
|||
# check if last line was the comment
|
||||
was_com_there = was_comment(lastline, comment)
|
||||
|
||||
# print + comment if not there
|
||||
flush_buffer()
|
||||
if(comment && !was_com_there) c_print()
|
||||
|
||||
v_print()
|
|
@ -0,0 +1,9 @@
|
|||
was_com_there = was_comment(lastline, comment)
|
||||
|
||||
# print before and comment
|
||||
flush_buffer()
|
||||
if(comment && !was_com_there) c_print()
|
||||
|
||||
# print value + seperator line at the end
|
||||
v_print()
|
||||
print ""
|
26
cdist/conf/type/__ini_value/gencode-remote
Executable file
26
cdist/conf/type/__ini_value/gencode-remote
Executable file
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh -e
|
||||
# __ini_value/gencode-remote
|
||||
|
||||
|
||||
state_is="$(cat "$__object/explorer/state")"
|
||||
state_should="$(cat "$__object/parameter/state")"
|
||||
|
||||
# short-circuit if nothing to do
|
||||
if [ "$state_is" = "$state_should" ]; then exit; fi
|
||||
|
||||
# file to change
|
||||
file="$(cat "$__object/parameter/file")"
|
||||
|
||||
|
||||
# validation check
|
||||
case "$state_should" in
|
||||
present|commented|absent)
|
||||
# FIXME no need for a seperate file?
|
||||
"$__type/files/gen-awk.sh" "$file" "$state_should"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "not done yet!" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
1
cdist/conf/type/__ini_value/parameter/boolean
Normal file
1
cdist/conf/type/__ini_value/parameter/boolean
Normal file
|
@ -0,0 +1 @@
|
|||
normalize
|
|
@ -0,0 +1,2 @@
|
|||
;
|
||||
#
|
|
@ -0,0 +1 @@
|
|||
0
|
1
cdist/conf/type/__ini_value/parameter/default/state
Normal file
1
cdist/conf/type/__ini_value/parameter/default/state
Normal file
|
@ -0,0 +1 @@
|
|||
present
|
6
cdist/conf/type/__ini_value/parameter/optional
Normal file
6
cdist/conf/type/__ini_value/parameter/optional
Normal file
|
@ -0,0 +1,6 @@
|
|||
section
|
||||
key
|
||||
state
|
||||
value
|
||||
indentation
|
||||
comment
|
1
cdist/conf/type/__ini_value/parameter/optional_multiple
Normal file
1
cdist/conf/type/__ini_value/parameter/optional_multiple
Normal file
|
@ -0,0 +1 @@
|
|||
comment-sign
|
2
cdist/conf/type/__ini_value/parameter/required
Normal file
2
cdist/conf/type/__ini_value/parameter/required
Normal file
|
@ -0,0 +1,2 @@
|
|||
file
|
||||
delimiter
|
Loading…
Reference in a new issue