/*
* table ... :TABLE: [class=name] [format={lower,upper}]
* [ignore=pattern] [map[=map]] [name=name]
* [novariables] [options] [state]
*
* if map==1 then do $(.TABLE.MAP. $(table) [name=name]) otherwise
* define variables in table name of the form [(class|table)_]name=1[value]
* format=upper[lower] converts var names to upper[lower] case
* ignore=pattern to ignore matching .TABLE.SET. generated variables
* set TABLE.list=1 or TABLE.list.name=1 to list the table variables
* if state==1 then define state variables rather than normal variables
* if noassign then variables not defined
*/
":TABLE:" : .MAKE .OPERATOR
local I
for I $(<)
local table=$(I) class format ignore map name novariables options list state $(~$(I)) $(>)
if "$(@$(I):V)"
if name
name := name=$(name)
end
if map == "1"
: $(.TABLE.MAP. $(table) $(name))
else
if TABLE.list || "$(TABLE.list.$(table))"
list = 1
end
if class == "1"
class := $(table)_
else if class
class := $(class)_
end
if format
format := F=%($(format))s
end
format := :$(format)
if options
options := options
end
if novariables
state = -
else if state
state = ==
else
state = =
end
table := $(.TABLE.INIT. $(table) $(options) $(name))
if map
map := $(.TABLE.MAP. $(map) $(name))
end
: $(.TABLE.SET. $(table) "$(class)" $(format) "$(state)" "$(map)" "$(ignore)" "$(list)")
end
else if name
if map
map = MAP.
end
.TABLE.$(map)$(table) := $(name)
end
end
/*
* :TABLE: inner loop
*/
.TABLE.SET. :FUNCTION:
local I J M N V (row name format assign map ignore list) $(%)
local class $($(row).)
if class
name := $(class)_
end
for I $($(row))
if I == "*=*"
V := $(I:/[^=]*=//)
I := $(I:/=.*)
else
V = 1
end
if I == "-"
continue
end
N := $("$(name)$(I)":/[^a-zA-Z_0-9]/_/G:$(format))
if N != "$(ignore)"
if map && ( M = "$($(map).$(N))" )
M := $(M:/,/ /G)
end
if assign != "-"
for J $(M|N)
if J != "-"
eval
$(J) $(assign) $(V)
if list
print $(J) $(assign) $(V)
end
end
end
end
end
: $(.TABLE.SET. $(row).$(I) $(N)_ "$(format)" "$(assign)" "$(map)" "$(ignore)" "$(list)")
end
end
/*
* $(.TABLE.INIT. table [name=name] [options])
*
* name {
* [no|NO]op1[=value]
* [no|NO]op2[=value] {
* ...
* }
* }
*
* convert the table in action to name[name]=value
* if options then op names matching no* are placed in noname[name]=value
* if options then op names matching NO* are placed in NOname[name]=value
* TABLE.all=1 or TABLE.all.name=1 enables all no* entries
* table data name returned
*/
.TABLE.INIT. :FUNCTION:
local T name options table=$(%)
if ( T = "$(.TABLE.$(table))" )
return $(T)
end
if "$(@$(table):V)"
local I K P X all level=0 no=
if TABLE.all || "$(TABLE.all.$(table))"
all = 1
end
T := $(name|table)
.TABLE.$(table) := $(T)
.TABLE.options.$(level). := $(options)
.TABLE.no.$(level). :=
for I $(@$(table))
if I == "{"
let level = level + 1
.TABLE.options.$(level). := $(options)
.TABLE.no.$(level). := $(no)
if options
if P == "no*"
P := $(P:/..//)
if ! all
no = no
$(no)$(T) += $(P)
end
else if P == "NO*"
P := $(P:/..//)
no = NO
$(no)$(T) += $(P)
end
end
T := $(T).$(P:/=.*//)
P :=
else if I == "}"
if T == "*."
eval
$(P:N=options=*)
end
let level = level - 1
.TABLE.options.$(level). := $(options)
.TABLE.no.$(level). := $(no)
let level = level + 1
if ! options && no
T := $(T:/\.\([^.]*\)\.$/.$(no)\1./)
no :=
end
else if no
$(T) :=
K := 0
else
if options
if P == "-|no*"
P := $(P:/..//)
no$(T) += $(P)
if ! all && P != "-"
P :=
end
else if P == "NO*"
P := $(P:/..//)
NO$(T) += $(P)
P :=
end
end
$(T) += $(P)
K := 1
end
P := $(T)
T := $(T:/\.[^.]*$//)
if K
$(T) += $(P:/.*\.//)
end
P :=
let level = level - 1
options := $(.TABLE.options.$(level).)
no := $(.TABLE.no.$(level).)
else
if options
if P == "-|no*"
P := $(P:/..//)
no$(T) += $(P)
if ! all && P != "-"
P :=
end
else if P == "NO*"
P := $(P:/..//)
NO$(T) += $(P)
P :=
end
end
$(T) += $(P)
P := $(I)
end
end
if options
if P == "no*"
P := $(P:/..//)
no$(T) += $(P)
if ! all
P :=
end
else if P == "NO*"
P := $(P:/..//)
NO$(T) += $(P)
P :=
end
end
$(T) += $(P)
clear $(table)
end
return $(T)
/*
* $(.TABLE.MAP. map [name=name])
*
* name {
* old new[,new...]|-
* ...
* }
*
* convert the map in name's action to name[name].old=new
* map data name returned
*/
.TABLE.MAP. :FUNCTION:
local T name map=$(%)
if ( T = "$(.TABLE.MAP.$(map))" )
return $(T)
end
if "$(@$(map):V)"
local I P
T := $(name|map)
.TABLE.MAP.$(map) := $(T)
for I $(@$(map))
if P
$(T).$(P) := $(I)
P =
else
P := $(I)
end
end
clear $(map)
end
return $(T)