#!/bin/awk -f
BEGIN {
FS="\t"
SUBSEP="."
state = 0
# 0 read normal variables
# 1 seen start of field list, read titles
# 2 reading list values
# ident_re = /[a-zA-Z_][a-zA-Z0-9_]*/
ident_re = "[a-zA-Z_][a-zA-Z0-9_]*"
}
$0 == "]" && state == 2 {
# end of field list
state = 0
next
}
state == 2 {
V[varname,++V[varname,"rows"]] = $0
next
}
state == 1 {
if((varname, "fields") in V) {
if(V[varname,"fields"] != $0) {
print "data.awk: differing field definition for '"varname"'" >"/dev/stderr"
print "previous: '"V[varname,"fields"]"'" >"/dev/stderr"
print "current: '"$0"'" >"/dev/stderr"
exit 1
}
}
V[varname,"fields"] = $0
state = 2
next
}
/^del[ \t].*[a-zA-Z_][a-zA-Z0-9_.]$/ {
del_pattern = substr($0, 5)
for(varname in V) {
if (match(varname, del_pattern)) {
delete V[varname]
}
}
}
/^[a-zA-Z_][a-zA-Z0-9_.]*=\[$/ {
# start of field list
state = 1
m = match($0, ident_re)
varname = substr($0, m, RLENGTH)
next
}
/^[a-zA-Z_][a-zA-Z0-9_.]*=/ {
m = match($0, ident_re)
varname = substr($0, m, RLENGTH)
V[varname] = substr($0, m+1+RLENGTH)
if(DEBUG) printf "got scalar: %s = %s (%d)\n", varname, V[varname], m >"/dev/stderr"
next
}
/^\t/ {
V[varname] = V[varname] "\n" substr($0, 1)
next
}
/^#/ { next }
/^$/ { next }
{
# TODO posix compliance
print "data.awk: unparseable line: '"$0"'" >"/dev/stderr"
exit 1
}
function data_not_found_error(varname, type) {
if(ENVIRON["DATA_AWK_EMPTY_GET"]) {
if(DEBUG) {
print type" not found: " varname >"/dev/stderr"
}
} else {
print "error: undefined "type" '"varname"'" >"/dev/stderr"
exit 1
}
}
function loop_start(varname, prefix, depth) {
if(!((varname, "fields") in V)) {
data_not_found_error(varname, "table")
}
depth = ++loop_stack["depth"]
loop_stack[depth,"row"] = 0
loop_stack[depth,"var"] = varname
loop_stack[depth,"pre"] = prefix
return depth
}
function loop_iter(depth) {
loop_stack[depth,"row"]++
return (loop_stack[depth,"var"], loop_stack[depth,"row"]) in V
}
function loop_end() {
delete loop_stack[loop_stack["depth"], "row"]
delete loop_stack[loop_stack["depth"], "var"]
delete loop_stack[loop_stack["depth"], "pre"]
loop_stack["depth"]--
}
function find(varname, i, n, names, values, loopvar, looprow, prefix) {
for(i=loop_stack["depth"]; i>0; i--) {
prefix = loop_stack[i, "pre"]
if(prefix)
if(substr(varname, 1, length(prefix)) != prefix)
continue
loopvar = loop_stack[i, "var"]
looprow = loop_stack[i, "row"]
if(varname == prefix"_index") {
found = looprow
return 1
}
if(varname == prefix"_index0") {
found = looprow - 1
return 1
}
if(varname == prefix"_revindex") {
found = V[loopvar, "rows"] - looprow + 1
return 1
}
if(varname == prefix"_revindex0") {
found = V[loopvar, "rows"] - looprow
return 1
}
if(varname == prefix"_first") {
found = looprow == 1
return 1
}
if(varname == prefix"_last") {
found = looprow == V[loopvar, "rows"]
return 1
}
if(varname == prefix"_length") {
found = V[loopvar, "rows"]
return 1
}
split(V[loopvar, "fields"], names)
for(n in names) {
if(varname == (prefix names[n])) {
split(V[loopvar, looprow], values)
found = values[n]
return 1
}
}
}
if(!(varname in V)) {
return 0
}
found = V[varname]
return 1
}
function get(varname) {
if(!find(varname)) {
data_not_found_error(varname, "scalar")
found = ""
}
if(DEBUG) {
print "get →" varname "← = →"found"←" >"/dev/stderr"
}
return found
}
function or_(a, b) {
return a ? a : b
}
END {
if(DEBUG) {
print "--- loaded keys ---" >"/dev/stderr"
for(key in V) {
printf("%s\t→%s←\n", key, V[key]) >"/dev/stderr"
printf(">> %d →%s←\n", find(key), found) >"/dev/stderr"
}
print "-------------------" >"/dev/stderr"
}
}