Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/nmake/TABLE.mk
1808 views
/*
 * 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)