cfg80211: fix parsing when db.txt ends on a rule

If genregdb.awk assumes the file will end with an
extra empty line or a comment line. This is could
not be true so just address this.

Signed-off-by: Luis R. Rodriguez <d4fa18192c5a479e564d29c2300c2e15afd1d8d7@do-not-panic.com>
Acked-by: John W. Linville <2a53bac7a5d324865ef46ec4c38b2c0fba1456b4@tuxdriver.com>
Signed-off-by: Johannes Berg <bff32994ff0f8d048f262a8388145a71b6071bfe@intel.com>

#!/usr/bin/awk -f
#
# genregdb.awk -- generate regdb.c from db.txt
#
# Actually, it reads from stdin (presumed to be db.txt) and writes
# to stdout (presumed to be regdb.c), but close enough...
#
# Copyright 2009 John W. Linville <linville@tuxdriver.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

BEGIN {
	active = 0
	rules = 0;
	print "/*"
	print " * DO NOT EDIT -- file generated from data in db.txt"
	print " */"
	print ""
	print "#include <linux/nl80211.h>"
	print "#include <net/cfg80211.h>"
	print "#include \"regdb.h\""
	print ""
	regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n"
}

function parse_country_head() {
	country=$2
	sub(/:/, "", country)
	printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
	printf "\t.alpha2 = \"%s\",\n", country
	if ($NF ~ /DFS-ETSI/)
		printf "\t.dfs_region = NL80211_DFS_ETSI,\n"
	else if ($NF ~ /DFS-FCC/)
		printf "\t.dfs_region = NL80211_DFS_FCC,\n"
	else if ($NF ~ /DFS-JP/)
		printf "\t.dfs_region = NL80211_DFS_JP,\n"
	printf "\t.reg_rules = {\n"
	active = 1
	regdb = regdb "\t&regdom_" country ",\n"
}

function parse_reg_rule()
{
	start = $1
	sub(/\(/, "", start)
	end = $3
	bw = $5
	sub(/\),/, "", bw)
	gain = $6
	sub(/\(/, "", gain)
	sub(/,/, "", gain)
	power = $7
	sub(/\)/, "", power)
	sub(/,/, "", power)
	# power might be in mW...
	units = $8
	sub(/\)/, "", units)
	sub(/,/, "", units)
	if (units == "mW") {
		if (power == 100) {
			power = 20
		} else if (power == 200) {
			power = 23
		} else if (power == 500) {
			power = 27
		} else if (power == 1000) {
			power = 30
		} else {
			print "Unknown power value in database!"
		}
	}
	flagstr = ""
	for (i=8; i<=NF; i++)
		flagstr = flagstr $i
	split(flagstr, flagarray, ",")
	flags = ""
	for (arg in flagarray) {
		if (flagarray[arg] == "NO-OFDM") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_OFDM | "
		} else if (flagarray[arg] == "NO-CCK") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_CCK | "
		} else if (flagarray[arg] == "NO-INDOOR") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_INDOOR | "
		} else if (flagarray[arg] == "NO-OUTDOOR") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_OUTDOOR | "
		} else if (flagarray[arg] == "DFS") {
			flags = flags "\n\t\t\tNL80211_RRF_DFS | "
		} else if (flagarray[arg] == "PTP-ONLY") {
			flags = flags "\n\t\t\tNL80211_RRF_PTP_ONLY | "
		} else if (flagarray[arg] == "PTMP-ONLY") {
			flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | "
		} else if (flagarray[arg] == "PASSIVE-SCAN") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
		} else if (flagarray[arg] == "NO-IBSS") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
		} else if (flagarray[arg] == "NO-IR") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
		}

	}
	flags = flags "0"
	printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
	rules++
}

function print_tail_country()
{
	active = 0
	printf "\t},\n"
	printf "\t.n_reg_rules = %d\n", rules
	printf "};\n\n"
	rules = 0;
}

/^[ \t]*#/ {
	# Ignore
}

!active && /^[ \t]*$/ {
	# Ignore
}

!active && /country/ {
	parse_country_head()
}

active && /^[ \t]*\(/ {
	parse_reg_rule()
}

active && /^[ \t]*$/ {
	print_tail_country()
}

END {
	if (active)
		print_tail_country()
	print regdb "};"
	print ""
	print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);"
}

#!/usr/bin/awk -f
#
# genregdb.awk -- generate regdb.c from db.txt
#
# Actually, it reads from stdin (presumed to be db.txt) and writes
# to stdout (presumed to be regdb.c), but close enough...
#
# Copyright 2009 John W. Linville <linville@tuxdriver.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

BEGIN {
	active = 0
	rules = 0;
	print "/*"
	print " * DO NOT EDIT -- file generated from data in db.txt"
	print " */"
	print ""
	print "#include <linux/nl80211.h>"
	print "#include <net/cfg80211.h>"
	print "#include \"regdb.h\""
	print ""
	regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n"
}

function parse_country_head() {
	country=$2
	sub(/:/, "", country)
	printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
	printf "\t.alpha2 = \"%s\",\n", country
	if ($NF ~ /DFS-ETSI/)
		printf "\t.dfs_region = NL80211_DFS_ETSI,\n"
	else if ($NF ~ /DFS-FCC/)
		printf "\t.dfs_region = NL80211_DFS_FCC,\n"
	else if ($NF ~ /DFS-JP/)
		printf "\t.dfs_region = NL80211_DFS_JP,\n"
	printf "\t.reg_rules = {\n"
	active = 1
	regdb = regdb "\t&regdom_" country ",\n"
}

function parse_reg_rule()
{
	start = $1
	sub(/\(/, "", start)
	end = $3
	bw = $5
	sub(/\),/, "", bw)
	gain = $6
	sub(/\(/, "", gain)
	sub(/,/, "", gain)
	power = $7
	sub(/\)/, "", power)
	sub(/,/, "", power)
	# power might be in mW...
	units = $8
	sub(/\)/, "", units)
	sub(/,/, "", units)
	if (units == "mW") {
		if (power == 100) {
			power = 20
		} else if (power == 200) {
			power = 23
		} else if (power == 500) {
			power = 27
		} else if (power == 1000) {
			power = 30
		} else {
			print "Unknown power value in database!"
		}
	}
	flagstr = ""
	for (i=8; i<=NF; i++)
		flagstr = flagstr $i
	split(flagstr, flagarray, ",")
	flags = ""
	for (arg in flagarray) {
		if (flagarray[arg] == "NO-OFDM") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_OFDM | "
		} else if (flagarray[arg] == "NO-CCK") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_CCK | "
		} else if (flagarray[arg] == "NO-INDOOR") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_INDOOR | "
		} else if (flagarray[arg] == "NO-OUTDOOR") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_OUTDOOR | "
		} else if (flagarray[arg] == "DFS") {
			flags = flags "\n\t\t\tNL80211_RRF_DFS | "
		} else if (flagarray[arg] == "PTP-ONLY") {
			flags = flags "\n\t\t\tNL80211_RRF_PTP_ONLY | "
		} else if (flagarray[arg] == "PTMP-ONLY") {
			flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | "
		} else if (flagarray[arg] == "PASSIVE-SCAN") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
		} else if (flagarray[arg] == "NO-IBSS") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
		} else if (flagarray[arg] == "NO-IR") {
			flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
		}

	}
	flags = flags "0"
	printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
	rules++
}

function print_tail_country()
{
	active = 0
	printf "\t},\n"
	printf "\t.n_reg_rules = %d\n", rules
	printf "};\n\n"
	rules = 0;
}

/^[ \t]*#/ {
	# Ignore
}

!active && /^[ \t]*$/ {
	# Ignore
}

!active && /country/ {
	parse_country_head()
}

active && /^[ \t]*\(/ {
	parse_reg_rule()
}

active && /^[ \t]*$/ {
	print_tail_country()
}

END {
	print regdb "};"
	print ""
	print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);"
}


invisible h1 now appears

invisible h1 now appears

BEGIN {
    heading = 0
}

hunt && /class="section_anchor">/ {
    hier[heading] = $0
    sub(/<\/a>/, "", hier[heading])
    sub(/<\/a>/, "", hier[heading])
    print "
"
    if (heading > 1) {
	print "
" hier[heading] "
"
    }
    for (i=1; i < heading; ++i) {
	print "<h" i " style='color: #C0C0C0;'>" hier[i] "</h" i ">"
    }
    print "<h" heading ">" hier[heading]
    hunt = 0
    next
}

/
/ {
    #print "
"
    heading = 1
    hunt = 1
    #print
    next
}

/<\/h[1-9]>/ {
    heading = 0
    print
    next
}

/
/ && heading == 0 {
    print "
"
    #print "
"
    #print "
" hier[1] "
"
    heading = 2
    hunt = 1
    #print
    next
}

/
/ && heading == 0 {
    print "
"
    #print "
"
    #print "
" hier[1] "
"
    #print "
" hier[2] "
"
    heading = 3
    hunt = 1
    #print
    next
}

/
/ && heading == 3 {
    heading = 4
    hunt = 1
    #print
    next
}

BEGIN {
    heading = 0
}

hunt && /class="section_anchor">/ {
    hier[heading] = $0
    sub(/<\/a>/, "", hier[heading])
    sub(/<\/a>/, "", hier[heading])
    print hier[heading]
    hunt = 0
    next
}

/
/ {
    print "
"
    heading = 1
    hunt = 1
    print
    next
}

/<\/h[1-9]>/ {
    heading = 0
    print
    next
}

/
/ && heading == 0 {
    print "
"
    print "
"
    print "
" hier[1] "
"
    heading = 2
    hunt = 1
    print
    next
}

/
/ && heading == 0 {
    print "
"
    print "
"
    print "
" hier[1] "
"
    print "
" hier[2] "
"
    heading = 3
    hunt = 1
    print
    next
}

/
/ && heading == 3 {
    heading = 4
    hunt = 1
    print
    next
}


[as-x86] Remove debug information from gen.awk

BEGIN		{
		FS = "\t"
		printf "#include \"../../../inc/scc.h\"\n"\
		       "#include \"../../as.h\"\n"\
		       "#include \"../x86/proc.h\"\n"\
		       "#include \"ins.h\"\n\n"
		nop = 0; nvar = 0
}
		{sub(/#.*/,"")}

$6 !~ bits	{next}

/^$/		{next}

		{
		if (opstart[$1] == 0) {
			opstart[$1] = nvar
			opnames[nop++] = $1
		}
		opcount[$1]++
		opargs[nvar] = $2
		opsize[nvar] = $3
		opbytes[nvar] = ($4 == "none") ? "" : $4
		opformat[nvar++] = $5
		formats[$5] = 1
}
END		{
		for (i in formats)
			printf "Format %s;\n", i

		printf "int nr_ins = %d;\n\n", nop
		print "struct ins instab[] = {"
		for (i = 0; i < nop; i++) {
			n = opnames[i]
			start = opstart[n]
			end = start + opcount[n]
			printf "\t{.str = \"%s\", .begin = %d, .end = %d},\n",
			       n, start, end | "sort"
		}
		close("sort")
		printf "};\n\n"

		print "struct op optab[] = {"
		for (i = 0; i < nvar; i++) {
			printf "\t{\n" \
			       "\t\t.size = %d,\n"\
			       "\t\t.format = %s,\n",
			       opsize[i], opformat[i]

			if (opbytes[i] != "")
				printf "\t\t.bytes = (char []) {%s},\n",
				        opbytes[i]

			a = str2args(opargs[i])
			if (a != "")
				printf "\t\t.args = (char []) {%s}\n", a

			print "\t},"
		}
		print "};"
}

function str2args(s, args, i, out)
{
	if (split(s, args, /,/) == 0 || args[1] == "none")
		return ""
	for (i in args) {
		a = args[i]
		if (match(a, /^imm8/)) {
			out = "AIMM8"
		} else if (match(a, /^imm16/)) {
			out = "AIMM16"
		} else if (match(a, /^imm32/)) {
			out = "AIMM32"
		} else if (match(a, /^imm64/)) {
			out = "AIMM64"
		} else {
			print "wrong arg", a
			exit 1
		}
		a = substr(a, RLENGTH+1)
		if (a ~ /^\+$/) {
			return out "|AREP"
		} else if (a != "") {
			print "wrong arg", a
			exit 1
		}
		out = out ","
	}
	out = out "0"

	return out
}

BEGIN		{
		print "bits=",bits > "/dev/stderr"
		FS = "\t"
		printf "#include \"../../../inc/scc.h\"\n"\
		       "#include \"../../as.h\"\n"\
		       "#include \"../x86/proc.h\"\n"\
		       "#include \"ins.h\"\n\n"
		nop = 0; nvar = 0
}
		{sub(/#.*/,"")}

$6 !~ bits	{next}

/^$/		{next}

		{
		if (opstart[$1] == 0) {
			opstart[$1] = nvar
			opnames[nop++] = $1
		}
		opcount[$1]++
		opargs[nvar] = $2
		opsize[nvar] = $3
		opbytes[nvar] = ($4 == "none") ? "" : $4
		opformat[nvar++] = $5
		formats[$5] = 1
}
END		{
		for (i in formats)
			printf "Format %s;\n", i

		printf "int nr_ins = %d;\n\n", nop
		print "struct ins instab[] = {"
		for (i = 0; i < nop; i++) {
			n = opnames[i]
			start = opstart[n]
			end = start + opcount[n]
			printf "\t{.str = \"%s\", .begin = %d, .end = %d},\n",
			       n, start, end | "sort"
		}
		close("sort")
		printf "};\n\n"

		print "struct op optab[] = {"
		for (i = 0; i < nvar; i++) {
			printf "\t{\n" \
			       "\t\t.size = %d,\n"\
			       "\t\t.format = %s,\n",
			       opsize[i], opformat[i]

			if (opbytes[i] != "")
				printf "\t\t.bytes = (char []) {%s},\n",
				        opbytes[i]

			a = str2args(opargs[i])
			if (a != "")
				printf "\t\t.args = (char []) {%s}\n", a

			print "\t},"
		}
		print "};"
}

function str2args(s, args, i, out)
{
	if (split(s, args, /,/) == 0 || args[1] == "none")
		return ""
	for (i in args) {
		a = args[i]
		if (match(a, /^imm8/)) {
			out = "AIMM8"
		} else if (match(a, /^imm16/)) {
			out = "AIMM16"
		} else if (match(a, /^imm32/)) {
			out = "AIMM32"
		} else if (match(a, /^imm64/)) {
			out = "AIMM64"
		} else {
			print "wrong arg", a
			exit 1
		}
		a = substr(a, RLENGTH+1)
		if (a ~ /^\+$/) {
			return out "|AREP"
		} else if (a != "") {
			print "wrong arg", a
			exit 1
		}
		out = out ","
	}
	out = out "0"

	return out
}


unix-yy.test: fix portability issue

unix-yy.test: fix portability issue

* tests/unix-yy-connect.awk (r_close_listen): Quote square brackets
that are not part of a bracket expression.

BEGIN {
  lines = 6
  fail = 0
  addrlen = length(addr) + 3

  r_i = "[1-9][0-9]*"
  r_socket = "^socket\\(PF_(LOCAL|UNIX|FILE), SOCK_STREAM, 0\\) += 1<UNIX:\\[(" r_i ")\\]>$"
  r_close_listen = "^close\\(0<UNIX:\\[" r_i ",\"" addr "\"\\]>\\) += 0$"
}

NR == 1 {
  if (match($0, r_socket, a)) {
    inode = a[2]
    r_connect = "^connect\\(1<UNIX:\\[" inode "\\]>, \\{sa_family=AF_(LOCAL|UNIX|FILE), sun_path=\"" addr "\"\\}, " addrlen "\\) += 0$"
    next
  }
}

NR == 2 {if (match($0, r_close_listen)) next}

NR == 3 {
  if (r_connect != "" && match($0, r_connect)) {
    r_close_connected = "^close\\(1<UNIX:\\[(" r_i ")->" r_i "\\]>\\) += 0$"
    next
  }
}

NR == 4 && /^--- SIGUSR1 / {next}

NR == 5 {
  if (inode != "" && r_close_connected != "" && match($0, r_close_connected, a) && a[1] == inode) {
    next
  }
}

NR == lines && $0 == "+++ exited with 0 +++" {next}

{
  print "Line " NR " does not match: " $0
  fail=1
}

END {
  if (NR != lines) {
    print "Expected " lines " lines, found " NR " line(s)."
    print ""
    exit 1
  }
  if (fail) {
    print ""
    exit 1
  }
}

BEGIN {
  lines = 6
  fail = 0
  addrlen = length(addr) + 3

  r_i = "[1-9][0-9]*"
  r_socket = "^socket\\(PF_(LOCAL|UNIX|FILE), SOCK_STREAM, 0\\) += 1<UNIX:\\[(" r_i ")\\]>$"
  r_close_listen = "^close\\(0<UNIX:[" r_i ",\"" addr "\"]>\\) += 0$"
}

NR == 1 {
  if (match($0, r_socket, a)) {
    inode = a[2]
    r_connect = "^connect\\(1<UNIX:\\[" inode "\\]>, \\{sa_family=AF_(LOCAL|UNIX|FILE), sun_path=\"" addr "\"\\}, " addrlen "\\) += 0$"
    next
  }
}

NR == 2 {if (match($0, r_close_listen)) next}

NR == 3 {
  if (r_connect != "" && match($0, r_connect)) {
    r_close_connected = "^close\\(1<UNIX:\\[(" r_i ")->" r_i "\\]>\\) += 0$"
    next
  }
}

NR == 4 && /^--- SIGUSR1 / {next}

NR == 5 {
  if (inode != "" && r_close_connected != "" && match($0, r_close_connected, a) && a[1] == inode) {
    next
  }
}

NR == lines && $0 == "+++ exited with 0 +++" {next}

{
  print "Line " NR " does not match: " $0
  fail=1
}

END {
  if (NR != lines) {
    print "Expected " lines " lines, found " NR " line(s)."
    print ""
    exit 1
  }
  if (fail) {
    print ""
    exit 1
  }
}


Robustify mpers.awk against input containing index loops

Make mpers.awk check for potential index loops.  Such loops should not
normally happen, but mpers.awk will not go into infinite recursion if
they do.

* mpers.awk (enter, leave): New functions.
(what_is): Use them.

function compare_indices(i1, v1, i2, v2) {
	c1 = strtonum(sprintf("%s", i1))
	c2 = strtonum(sprintf("%s", i2))
	if (c1 < c2)
		return -1
	return (c1 != c2)
}
function array_get(array_idx, array_member, array_return)
{
	array_return = array[array_idx][array_member]
	if ("" == array_return) {
		printf("%s: index [%s] without %s\n",
		       FILENAME, array_idx, array_member) > "/dev/stderr"
		exit 1
	}
	return array_return
}
function enter(array_idx)
{
	if (called[array_idx]) {
		printf("%s: index loop detected:", FILENAME) > "/dev/stderr"
		for (item in called)
			printf(" %s", item) > "/dev/stderr"
		print "" > "/dev/stderr"
		exit 1
	}
	called[array_idx] = 1
}
function leave(array_idx, to_return)
{
	delete called[array_idx]
	return to_return
}
function what_is(what_idx, type_idx, special, item, \
		 location, prev_location, prev_returned_size)
{
	enter(what_idx)
	special = array_get(what_idx, "special")
	switch (special) {
	case "base_type":
		switch (array_get(what_idx, "encoding")) {
		case 5: # signed
			printf("%s ", "int" \
			8 * array_get(what_idx, "byte_size") "_t")
			break
		case 7: # unsigned
			printf("%s ", "uint" \
			8 * array_get(what_idx, "byte_size") "_t")
			break
		default: # float, signed/unsigned char
			printf("%s ", array_get(what_idx, "name"))
			break
		}
		returned_size = array_get(what_idx, "byte_size")
		break
	case "enumeration_type":
		type_idx = array_get(what_idx, "type")
		returned_size = array_get(what_idx, "byte_size")
		printf("%s ", "uint" 8 * returned_size "_t")
		break
	case "pointer_type":
		printf("%s", "mpers_ptr_t ")
		returned_size = array_get(what_idx, "byte_size")
		break
	case "array_type":
		type_idx = array_get(what_idx, "type")
		what_is(type_idx)
		to_return = array[what_idx]["upper_bound"]
		returned_size = to_return * returned_size
		if ("" == to_return)
			to_return = "00"
		return leave(what_idx, to_return)
		break
	case "structure_type":
		print "struct {"
		prev_location = 0
		location = 0
		returned_size = 0
		prev_returned_size = 0
		for (item in array) {
			if ("parent" in array[item] && \
				array_get(item, "parent") == what_idx) {
				location = array_get(item, "location")
				loc_diff = location - prev_location - \
					prev_returned_size
				if (loc_diff != 0) {
					printf("%s", \
						"unsigned char mpers_filler_" \
						item "[" loc_diff "];\n")
				}
				prev_location = location
				returned = what_is(item)
				prev_returned_size = returned_size
				printf("%s", array[item]["name"])
				if (returned) {
					printf("[%s]", returned)
				}
				print ";"
			}
		}
		returned_size = array_get(what_idx, "byte_size")
		loc_diff = returned_size - prev_location - prev_returned_size
		if (loc_diff != 0) {
			printf("%s", "unsigned char mpers_end_filler_" \
				item "[" loc_diff "];\n")
		}
		printf("%s", "} ATTRIBUTE_PACKED ")
		break
	case "union_type":
		print "union {"
		for (item in array) {
			if ("parent" in array[item] && \
				array_get(item, "parent") == what_idx) {
				returned = what_is(item)
				printf("%s", array_get(item, "name"))
				if (returned) {
					printf("[%s]", returned)
				}
				print ";"
			}
		}
		printf("%s", "} ")
		returned_size = array_get(what_idx, "byte_size")
		break
	case "typedef":
		type_idx = array_get(what_idx, "type")
		return leave(what_idx, what_is(type_idx))
		break
	case "member":
		type_idx = array_get(what_idx, "type")
		return leave(what_idx, what_is(type_idx))
		break
	default:
		type_idx = array_get(what_idx, "type")
		what_is(type_idx)
		break
	}
	return leave(what_idx, 0)
}
BEGIN {
	print "#include <inttypes.h>"
}
/^<[[:xdigit:]]+>/ {
	match($0, /([[:alnum:]]+)><([[:alnum:]]+)/, matches)
	level = matches[1]
	idx = "0x" matches[2]
	array[idx]["idx"] = idx
	parent[level] = idx
	if (level > 1) {
		array[idx]["parent"] = parent[level-1]
	}
}
/^DW_AT_data_member_location/ {
	match($0, /[[:digit:]]+/, temparray)
	array[idx]["location"] = temparray[0]
}
/^DW_AT_name/ {
	match($0, /:[[:space:]]+([[:alpha:]_][[:alnum:]_[:space:]]*)/, \
		temparray)
	array[idx]["name"] = temparray[1]
}
/^DW_AT_byte_size/ {
	match($0, /[[:digit:]]+/, temparray)
	array[idx]["byte_size"] = temparray[0]
}
/^DW_AT_encoding/ {
	match($0, /[[:digit:]]+/, temparray)
	array[idx]["encoding"] = temparray[0]
}
/^DW_AT_type/ {
	match($0, /:[[:space:]]+<(0x[[:xdigit:]]*)>$/, temparray)
	array[idx]["type"] = temparray[1]
}
/^DW_AT_upper_bound/ {
	match($0, /[[:digit:]]+/, temparray)
	array[parent[level-1]]["upper_bound"] = temparray[0] + 1
}
/^Abbrev Number:[^(]+\(DW_TAG_/ {
	if (match($0, /typedef|union_type|structure_type|pointer_type\
|enumeration_type|array_type|base_type|member/, temparray)) {
		array[idx]["special"] = temparray[0]
	}
}
END {
	PROCINFO["sorted_in"] = "compare_indices"
	for (item in array) {
		if (array[item]["special"] == "pointer_type") {
			print "typedef uint" \
				8 * array_get(item, "byte_size") "_t mpers_ptr_t;"
			break
		}
	}
	for (item in array) {
		if (array[item]["name"] == VAR_NAME) {
			type = array_get(item, "type")
			print "typedef"
			what_is(type)
			name = array_get(type, "name")
			print ARCH_FLAG "_" name ";"
			print "#define MPERS_" \
				ARCH_FLAG "_" name " " \
				ARCH_FLAG "_" name
			break
		}
	}
}

function compare_indices(i1, v1, i2, v2) {
	c1 = strtonum(sprintf("%s", i1))
	c2 = strtonum(sprintf("%s", i2))
	if (c1 < c2)
		return -1
	return (c1 != c2)
}
function array_get(array_idx, array_member, array_return)
{
	array_return = array[array_idx][array_member]
	if ("" == array_return) {
		printf("%s: index [%s] without %s\n",
		       FILENAME, array_idx, array_member) > "/dev/stderr"
		exit 1
	}
	return array_return
}
function what_is(what_idx, type_idx, special, item, \
		 location, prev_location, prev_returned_size)
{
	special = array_get(what_idx, "special")
	switch (special) {
	case "base_type":
		switch (array_get(what_idx, "encoding")) {
		case 5: # signed
			printf("%s ", "int" \
			8 * array_get(what_idx, "byte_size") "_t")
			break
		case 7: # unsigned
			printf("%s ", "uint" \
			8 * array_get(what_idx, "byte_size") "_t")
			break
		default: # float, signed/unsigned char
			printf("%s ", array_get(what_idx, "name"))
			break
		}
		returned_size = array_get(what_idx, "byte_size")
		break
	case "enumeration_type":
		type_idx = array_get(what_idx, "type")
		returned_size = array_get(what_idx, "byte_size")
		printf("%s ", "uint" 8 * returned_size "_t")
		break
	case "pointer_type":
		printf("%s", "mpers_ptr_t ")
		returned_size = array_get(what_idx, "byte_size")
		break
	case "array_type":
		type_idx = array_get(what_idx, "type")
		what_is(type_idx)
		to_return = array[what_idx]["upper_bound"]
		returned_size = to_return * returned_size
		if ("" == to_return)
			to_return = "00"
		return to_return
		break
	case "structure_type":
		print "struct {"
		prev_location = 0
		location = 0
		returned_size = 0
		prev_returned_size = 0
		for (item in array) {
			if ("parent" in array[item] && \
				array_get(item, "parent") == what_idx) {
				location = array_get(item, "location")
				loc_diff = location - prev_location - \
					prev_returned_size
				if (loc_diff != 0) {
					printf("%s", \
						"unsigned char mpers_filler_" \
						item "[" loc_diff "];\n")
				}
				prev_location = location
				returned = what_is(item)
				prev_returned_size = returned_size
				printf("%s", array[item]["name"])
				if (returned) {
					printf("[%s]", returned)
				}
				print ";"
			}
		}
		returned_size = array_get(what_idx, "byte_size")
		loc_diff = returned_size - prev_location - prev_returned_size
		if (loc_diff != 0) {
			printf("%s", "unsigned char mpers_end_filler_" \
				item "[" loc_diff "];\n")
		}
		printf("%s", "} ATTRIBUTE_PACKED ")
		break
	case "union_type":
		print "union {"
		for (item in array) {
			if ("parent" in array[item] && \
				array_get(item, "parent") == what_idx) {
				returned = what_is(item)
				printf("%s", array_get(item, "name"))
				if (returned) {
					printf("[%s]", returned)
				}
				print ";"
			}
		}
		printf("%s", "} ")
		returned_size = array_get(what_idx, "byte_size")
		break
	case "typedef":
		type_idx = array_get(what_idx, "type")
		return what_is(type_idx)
		break
	case "member":
		type_idx = array_get(what_idx, "type")
		return what_is(type_idx)
		break
	default:
		type_idx = array_get(what_idx, "type")
		what_is(type_idx)
		break
	}
	return 0
}
BEGIN {
	print "#include <inttypes.h>"
}
/^<[[:xdigit:]]+>/ {
	match($0, /([[:alnum:]]+)><([[:alnum:]]+)/, matches)
	level = matches[1]
	idx = "0x" matches[2]
	array[idx]["idx"] = idx
	parent[level] = idx
	if (level > 1) {
		array[idx]["parent"] = parent[level-1]
	}
}
/^DW_AT_data_member_location/ {
	match($0, /[[:digit:]]+/, temparray)
	array[idx]["location"] = temparray[0]
}
/^DW_AT_name/ {
	match($0, /:[[:space:]]+([[:alpha:]_][[:alnum:]_[:space:]]*)/, \
		temparray)
	array[idx]["name"] = temparray[1]
}
/^DW_AT_byte_size/ {
	match($0, /[[:digit:]]+/, temparray)
	array[idx]["byte_size"] = temparray[0]
}
/^DW_AT_encoding/ {
	match($0, /[[:digit:]]+/, temparray)
	array[idx]["encoding"] = temparray[0]
}
/^DW_AT_type/ {
	match($0, /:[[:space:]]+<(0x[[:xdigit:]]*)>$/, temparray)
	array[idx]["type"] = temparray[1]
}
/^DW_AT_upper_bound/ {
	match($0, /[[:digit:]]+/, temparray)
	array[parent[level-1]]["upper_bound"] = temparray[0] + 1
}
/^Abbrev Number:[^(]+\(DW_TAG_/ {
	if (match($0, /typedef|union_type|structure_type|pointer_type\
|enumeration_type|array_type|base_type|member/, temparray)) {
		array[idx]["special"] = temparray[0]
	}
}
END {
	PROCINFO["sorted_in"] = "compare_indices"
	for (item in array) {
		if (array[item]["special"] == "pointer_type") {
			print "typedef uint" \
				8 * array_get(item, "byte_size") "_t mpers_ptr_t;"
			break
		}
	}
	for (item in array) {
		if (array[item]["name"] == VAR_NAME) {
			type = array_get(item, "type")
			print "typedef"
			what_is(type)
			name = array_get(type, "name")
			print ARCH_FLAG "_" name ";"
			print "#define MPERS_" \
				ARCH_FLAG "_" name " " \
				ARCH_FLAG "_" name
			break
		}
	}
}


Improved "Rearranged" message

Improved "Rearranged" message

# Print processed "Program" lines from a WebScraper csv file saved in tsv format

# Field numbers
#    1 web-scraper-order  2 web-scraper-start-url  3 URL        4 Program_Title   5 Sn_Years
#    6 Seasons            7  Mv_Year               8  Duration  9  Rating        10  Description

BEGIN {
    FS="\t"
    print "Sortkey\tTitle\tSeasons\tEpisodes\tDuration\tYear(s)\tRating\tDescription"
}

{
    for ( i = 1; i <= NF; i++ ) {
        if ($i == "null")
            $i = ""
    }
}

/\/us\/movie\/|\/us\/show\// {
    URL = $3
    showTitle = $4
    $7  == "" ? Year = $5 : Year = $7
    NumSeasons = $6
    Duration = $8
    Rating = $9
    Description = $10

    sub (/ Seasons?/,"",NumSeasons)
    sub( / min/,"",Duration)

    # Convert duration from minutes to HMS
    secs = 0
    mins = Duration % 60
    hrs = int(Duration / 60)
    HMS = sprintf ("%02d:%02d:%02d", hrs, mins, secs)
    if (HMS == "00:00:00")
        HMS = ""

    # Titles starting with "The" should not sort based on "The"
    if (match (showTitle, /^The /)) {
        print "==> Rearranged: " showTitle >> ERROR_FILE
        showTitle = substr(showTitle, 5) ", The"
    }

    # Indicate different types of programs
    URL ~ /^\/us\/movie\// ? showtype = "M" : showtype = "S"

    # Extract sortkey from URL
    nflds = split (URL,fld,"_")
    if (URL ~ /_[[:digit:]]*$/) {
        sortkey = sprintf ("%s%05d", showtype, fld[nflds])
        savedLine = sprintf \
            ("%s (1) %s\t=HYPERLINK(\"https://www.britbox.com%s\";\"%s\"\)\t%s\t\t%s\t%s\t%s\t%s",\
             showTitle, sortkey, URL, showTitle, NumSeasons, HMS, Year, Rating, Description)

        # Make sure line doesn't start with a single quote so it sorts correctly in Open Office
        sub (/^'/,"",savedLine)

        print savedLine
    }
}

# Print processed "Program" lines from a WebScraper csv file saved in tsv format

# Field numbers
#    1 web-scraper-order  2 web-scraper-start-url  3 URL        4 Program_Title   5 Sn_Years
#    6 Seasons            7  Mv_Year               8  Duration  9  Rating        10  Description

BEGIN {
    FS="\t"
    print "Sortkey\tTitle\tSeasons\tEpisodes\tDuration\tYear(s)\tRating\tDescription"
}

{
    for ( i = 1; i <= NF; i++ ) {
        if ($i == "null")
            $i = ""
    }
}

/\/us\/movie\/|\/us\/show\// {
    URL = $3
    showTitle = $4
    $7  == "" ? Year = $5 : Year = $7
    NumSeasons = $6
    Duration = $8
    Rating = $9
    Description = $10

    sub (/ Seasons?/,"",NumSeasons)
    sub( / min/,"",Duration)

    # Convert duration from minutes to HMS
    secs = 0
    mins = Duration % 60
    hrs = int(Duration / 60)
    HMS = sprintf ("%02d:%02d:%02d", hrs, mins, secs)
    if (HMS == "00:00:00")
        HMS = ""

    # Titles starting with "The" should not sort based on "The"
    if (match (showTitle, /^The /)) {
        print "==> Rearranging " showTitle >> ERROR_FILE
        showTitle = substr(showTitle, 5) ", The"
    }

    # Indicate different types of programs
    URL ~ /^\/us\/movie\// ? showtype = "M" : showtype = "S"

    # Extract sortkey from URL
    nflds = split (URL,fld,"_")
    if (URL ~ /_[[:digit:]]*$/) {
        sortkey = sprintf ("%s%05d", showtype, fld[nflds])
        savedLine = sprintf \
            ("%s (1) %s\t=HYPERLINK(\"https://www.britbox.com%s\";\"%s\"\)\t%s\t\t%s\t%s\t%s\t%s",\
             showTitle, sortkey, URL, showTitle, NumSeasons, HMS, Year, Rating, Description)

        # Make sure line doesn't start with a single quote so it sorts correctly in Open Office
        sub (/^'/,"",savedLine)

        print savedLine
    }
}


Don't use path as variable name in colortbl.awk

Instead of using `argv[1]` to name the variable, we now always call it
`color_lib` in awk/colortbl.awk. The reason for this, is in some build
configurations, like the Visual Studio and CMake build, the full path to
the color_lib file is used. This resulted in the variable conaining
slashes, etc. Since the rest of the code already assumes this variable is
called `color_lib`, there is no problem with hard coding it in
colortbl.awk

#
# /*************************************************************************
# * Copyright (c) 2011 AT&T Intellectual Property
# * All rights reserved. This program and the accompanying materials
# * are made available under the terms of the Eclipse Public License v1.0
# * which accompanies this distribution, and is available at
# * http://www.eclipse.org/legal/epl-v10.html
# *
# * Contributors: See CVS logs. Details at http://www.graphviz.org/
# *************************************************************************/

function rgb_to_hsv(r,g,b) {
	r = r / 255.0; g = g / 255.0; b = b / 255.0;
	max = r; if (max < g) max = g; if (max < b) max = b;
	min = r; if (min > g) min = g; if (min > b) min = b;
	v = max;
	if (max != 0) s = (max - min) / max;
	else s = 0;
	if (s == 0) h = 0;
	else {
		delta = max - min;
		rc = (max - r)/delta;
		gc = (max - g)/delta;
		bc = (max - b)/delta;
		if (r == max) h = bc - gc;
		else {
			if (g == max) h = 2.0 + (rc - bc);
			else h = 4.0 + (gc - rc);
		}
		h = h * 60.0;
		if (h < 0.0) h = h + 360.0;
	}
	h = h / 360.0 * 255.0;
	s = s * 255.0;
	v = v * 255.0;
}

BEGIN	{ gsub("\\.","_",s); printf("static hsvrgbacolor_t color_lib[] = {\n",s); }
/^$/	{ next; }
/^#/	{ next; }
		{
			rgb_to_hsv($2,$3,$4);
			printf("{\"%s\",%d,%d,%d,%d,%d,%d,%d},\n",$1,h,s,v,$2,$3,$4,$5);
		}
END		{ printf("};\n"); }

#
# /*************************************************************************
# * Copyright (c) 2011 AT&T Intellectual Property
# * All rights reserved. This program and the accompanying materials
# * are made available under the terms of the Eclipse Public License v1.0
# * which accompanies this distribution, and is available at
# * http://www.eclipse.org/legal/epl-v10.html
# *
# * Contributors: See CVS logs. Details at http://www.graphviz.org/
# *************************************************************************/

function rgb_to_hsv(r,g,b) {
	r = r / 255.0; g = g / 255.0; b = b / 255.0;
	max = r; if (max < g) max = g; if (max < b) max = b;
	min = r; if (min > g) min = g; if (min > b) min = b;
	v = max;
	if (max != 0) s = (max - min) / max;
	else s = 0;
	if (s == 0) h = 0;
	else {
		delta = max - min;
		rc = (max - r)/delta;
		gc = (max - g)/delta;
		bc = (max - b)/delta;
		if (r == max) h = bc - gc;
		else {
			if (g == max) h = 2.0 + (rc - bc);
			else h = 4.0 + (gc - rc);
		}
		h = h * 60.0;
		if (h < 0.0) h = h + 360.0;
	}
	h = h / 360.0 * 255.0;
	s = s * 255.0;
	v = v * 255.0;
}

BEGIN	{ s = ARGV[1]; gsub("\\.","_",s); printf("static hsvrgbacolor_t %s[] = {\n",s); }
/^$/	{ next; }
/^#/	{ next; }
		{
			rgb_to_hsv($2,$3,$4);
			printf("{\"%s\",%d,%d,%d,%d,%d,%d,%d},\n",$1,h,s,v,$2,$3,$4,$5);
		}
END		{ printf("};\n"); }