#!/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" } }