convert edge lables from quoted strings to 'html-like' to highlight losses

#! /usr/bin/gawk -f

# label_dot_edge.awk
# Augment ontological terms with their label
# example usage:
# ${DIPPER}/scripts/label_dot_edge.awk
#	${DIPPER}/translationtable/GLOBAL_TERMS.yaml  in.dot > out.dot
#
# Arguments: two files
# Loads the first file as a map from  to curie to label :
 # (expects: "label": "curie:term",)
# Reads the second Graphviz digraph dot format file:
# looks for <term> as edge-text
# and appends "! <label> (Iff curie:term is found in the translation table)
# note: This "<term> ! <label>" structure is a convention used by Ontologists.

BEGIN{FS="\""; OFS="\t"}
# load label->curie:term  as curie:term -> label
FNR == NR && /^"/{label[$4]=$2}

# output graphviz lines that do not get labels
FNR != NR && ! /.* -> .* [label=<.*>];/ {print}

# output lines w/labels if they are available
FNR != NR && /.* -> .* [label=<.*>];/ {
	line="";
	split($0, row, / /)
	split(row[4], term, /<>/)
	split(term[2], lclid, ":")

	if (term[2] in label && lclid[2] != label[term[2]])
		row[4] = term[1] "<" term[2] " ! " label[term[2]] ">" term[3]
	line = row[1]
	for(i=2;i<=length(row);i++)
		line = line " " row[i]
	print  line
}

#! /usr/bin/gawk -f

# label_dot_edge.awk
# Augment ontological terms with their label
# example usage:
# ${DIPPER}/scripts/label_dot_edge.awk
#	${DIPPER}/translationtable/GLOBAL_TERMS.yaml  in.dot > out.dot
#
# Arguments: two files
# Loads the first file as a map from  to curie to label :
 # (expects: "label": "curie",)
# Reads the second Graphviz digraph dot format file:
# looks for <term> as edge-text
# and appends "! <label> (Iff <term> is found in map)
# note: This "<term> ! <label>" structure is a convention used by Ontologists.

BEGIN{FS="\""; OFS="\t"}
# load labels
FNR == NR && /^"/{label[$4]=$2}

# output lines that do not get labels
FNR != NR && !/.* -> .*label=.*/ {print}

# output lines w/labels if they are available

FNR != NR && /.* -> .*label=.*/ {
	line="";
	split($0, row, / /)

	split(row[4], term, /"/)
	split(term[2], lclid, ":")

	if (term[2] in label && lclid[2] != label[term[2]]){
		term[2] = term[2] " ! " label[term[2]];
		row[4] = term[1];
		for(i=2;i<=length(term);i++)
			row[4] = row[4] "\"" term[i]
	}
	line = row[1]
	for(i=2;i<=length(row);i++)
		line = line " " row[i]
	print  line
}


Add support for dollar single quotes

Add support for dollar single quotes

This unbreaks tests/bsda_obj.sh, which silently was not performed
correctly.


Theme: update default theme

Theme: update default theme

####################################################################
# Theme.awk                                                        #
####################################################################

function prettify(name, string,    i, temp) {
    temp = string
    if ("sgr-" name in Option)
        if (isarray(Option["sgr-" name]))
            for (i in Option["sgr-" name])
                temp = ansi(Option["sgr-" name][i], temp)
        else
            temp = ansi(Option["sgr-" name], temp)
    return temp
}

function setTheme(    file, line, script) {
    if (Option["theme"] && Option["theme"] != "default") {
        file = Option["theme"]
        if (!fileExists(file))
            file = ENVIRON["HOME"] "/.translate-shell/" Option["theme"]
    }

    if (file && fileExists(file)) {
        # Read from theme file
        script = NULLSTR
        while (getline line < file)
            script = script "\n" line
        loadOptions(script)
    } else {
        # Default theme
        Option["sgr-translation"] = "bold"
        Option["sgr-translation-phonetics"] = "bold"
        Option["sgr-prompt-message-original"] = "underline"
        Option["sgr-languages-sl"] = "underline"
        Option["sgr-languages-tl"] = "bold"
        Option["fmt-languages"] = "[ %s -> %t ]"
        Option["sgr-original-dictionary-detailed-explanation"] = "bold"
        Option["sgr-original-dictionary-detailed-synonyms-item"] = "bold"
        Option["sgr-original-dictionary-synonyms-synonyms-item"] = "bold"
        Option["sgr-original-dictionary-examples-original"][1] = "bold"
        Option["sgr-original-dictionary-examples-original"][2] = "underline"
        Option["sgr-original-dictionary-see-also-phrases-item"] = "bold"
        Option["sgr-dictionary-word"] = "bold"
        Option["sgr-alternatives-original"] = "underline"
        Option["sgr-alternatives-translations-item"] = "bold"
    }
}

####################################################################
# Theme.awk                                                        #
####################################################################

function prettify(name, string,    i, temp) {
    temp = string
    if ("sgr-" name in Option)
        if (isarray(Option["sgr-" name]))
            for (i in Option["sgr-" name])
                temp = ansi(Option["sgr-" name][i], temp)
        else
            temp = ansi(Option["sgr-" name], temp)
    return temp
}

function setTheme(    file, line, script) {
    if (Option["theme"] && Option["theme"] != "default") {
        file = Option["theme"]
        if (!fileExists(file))
            file = ENVIRON["HOME"] "/.translate-shell/" Option["theme"]
    }

    if (file && fileExists(file)) {
        # Read from theme file
        script = NULLSTR
        while (getline line < file)
            script = script "\n" line
        loadOptions(script)
    } else {
        # Default theme
        Option["sgr-original"][1] = "bold"
        Option["sgr-original"][2] = "negative"
        Option["sgr-translation"] = "bold"
        Option["sgr-prompt-message-original"] = "underline"
        Option["sgr-original-dictionary-detailed-explanation"] = "bold"
        Option["sgr-original-dictionary-examples-original"][1] = "bold"
        Option["sgr-original-dictionary-examples-original"][2] = "negative"
        Option["sgr-original-dictionary-see-also-item"] = "underline"
        Option["sgr-dictionary-word"] = "bold"
        Option["sgr-alternatives-original"] = "underline"
        Option["sgr-alternatives-translation"] = "bold"
    }
}


Provide the same unmarked symbold on the fr.apple layout as found on the adb map; provides all the missing symbold (such as ~ | and \) one can not really use unix without. With (again) some help from Jean-Marc Harang.

#! /usr/bin/awk -f
#	$OpenBSD: makemap.awk,v 1.5 2005/05/19 17:49:54 miod Exp $
#
# Copyright (c) 2005, Miodrag Vallat
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
#
# This script attempts to convert, with minimal hacks and losses, the
# regular PS/2 keyboard (pckbd) layout tables into USB keyboard (ukbd)
# layout tables.
#

BEGIN {
	rcsid = "$OpenBSD: makemap.awk,v 1.5 2005/05/19 17:49:54 miod Exp $"
	ifdepth = 0
	ignore = 0
	declk = 0
	haskeys = 0
	kbfr = 0

	# PS/2 id -> UKBD conversion table, or "sanity lossage 102"
	# (101 is for GSC keyboards!)
	for (i = 0; i < 256; i++)
		conv[i] = -1

	conv[1] = 41
	conv[2] = 30
	conv[3] = 31
	conv[4] = 32
	conv[5] = 33
	conv[6] = 34
	conv[7] = 35
	conv[8] = 36
	conv[9] = 37
	conv[10] = 38
	conv[11] = 39
	conv[12] = 45
	conv[13] = 46
	conv[14] = 42
	conv[15] = 43
	conv[16] = 20
	conv[17] = 26
	conv[18] = 8
	conv[19] = 21
	conv[20] = 23
	conv[21] = 28
	conv[22] = 24
	conv[23] = 12
	conv[24] = 18
	conv[25] = 19
	conv[26] = 47
	conv[27] = 48
	conv[28] = 40
	conv[29] = 224
	conv[30] = 4
	conv[31] = 22
	conv[32] = 7
	conv[33] = 9
	conv[34] = 10
	conv[35] = 11
	conv[36] = 13
	conv[37] = 14
	conv[38] = 15
	conv[39] = 51
	conv[40] = 52
	conv[41] = 53
	conv[42] = 225
	conv[43] = 50
	conv[44] = 29
	conv[45] = 27
	conv[46] = 6
	conv[47] = 25
	conv[48] = 5
	conv[49] = 17
	conv[50] = 16
	conv[51] = 54
	conv[52] = 55
	conv[53] = 56
	conv[54] = 229
	conv[55] = 85
	conv[56] = 226
	conv[57] = 44
	conv[58] = 57
	conv[59] = 58
	conv[60] = 59
	conv[61] = 60
	conv[62] = 61
	conv[63] = 62
	conv[64] = 63
	conv[65] = 64
	conv[66] = 65
	conv[67] = 66
	conv[68] = 67
	conv[69] = 83
	conv[70] = 71
	conv[71] = 95
	conv[72] = 96
	conv[73] = 97
	conv[74] = 86
	conv[75] = 92
	conv[76] = 93
	conv[77] = 94
	conv[78] = 87
	conv[79] = 89
	conv[80] = 90M
	conv[81] = 91
	conv[82] = 98
	conv[83] = 99
	conv[86] = 100
	conv[87] = 68
	conv[88] = 69
	conv[112] = 135
	conv[115] = 136
	conv[121] = 137
	conv[123] = 138
	conv[125] = 139
	conv[127] = 72
	conv[156] = 88
	conv[157] = 228
	conv[170] = 70
	conv[181] = 84
	conv[184] = 230
	# 198 is #if 0 in the PS/2 map...
	conv[199] = 74
	conv[200] = 82
	conv[201] = 75
	conv[203] = 80
	conv[205] = 79
	conv[207] = 77
	conv[208] = 81
	conv[209] = 78
	conv[210] = 73
	conv[211] = 99
	conv[219] = 227
	conv[220] = 231
	conv[221] = 101
}
NR == 1 {
	VERSION = $0
	gsub("\\$", "", VERSION)
	gsub("\\$", "", rcsid)

	printf("/*\t\$OpenBSD\$\t*/\n\n")
	printf("/*\n")
	printf(" * THIS FILE IS AUTOMAGICALLY GENERATED.  DO NOT EDIT.\n")
	printf(" *\n")
	printf(" * generated by:\n")
	printf(" *\t%s\n", rcsid)
	printf(" * generated from:\n")
	printf(" */\n")
	print VERSION

	next
}

#
# A very limited #if ... #endif parser. We only want to correctly detect
# ``#if 0'' constructs, so as not to process their contents. This is necessary
# since our output is out-of-order from our input.
#
# Note that this does NOT handle ``#ifdef notyet'' correctly - please only use
# ``#if 0'' constructs in the input.
#

/^#if/ {
	ignores[ifdepth] = ignore
	if ($2 == "0")
		ignore = 1
	else
		ignore = 0
	ifdepth++
	if (ignore)
		next
}
/^#endif/ {
	oldignore = ignore
	ifdepth--
	ignore = ignores[ifdepth]
	ignores[ifdepth] = 0
	if (oldignore)
		next
}

$1 == "#include" {
	if (ignore)
		next
	if ($2 == "<dev/pckbc/wskbdmap_mfii.h>")
		print "#include <dev/usb/usb_port.h>"
	else
		printf("#include %s\n", $2)

	next
}
$1 == "#define" || $1 == "#undef" {
	if (ignore)
		next
	print $0
	next
}

# Don't bother converting the DEC LK layout.
/declk\[/ {
	declk = 1
	next
}
/declk/ {
	next
}

/pckbd/ {
	gsub("pckbd", "ukbd", $0)
	mapname = $4
}

/KC/ {
	if (ignore)
		next

	if (declk)
		next

	haskeys = 1

	sidx = substr($1, 4, length($1) - 5)
	orig = int(sidx)
	id = conv[orig]

	# 183 is another Print Screen...
	if (orig == 183)
		next

	if (id == -1) {
		printf("/* initially KC(%d),", orig)
		for (f = 2; f <= NF; f++) {
			if ($f != "/*" && $f != "*/")
				printf("\t%s", $f)
		}
		printf("\t*/\n")
	} else {
		lines[id] = sprintf("    KC(%d),\t", id)
		#
		# This makes sure that the non-comment part of the output
		# ends up with a trailing comma. This is necessary since
		# the last line of an input block might not have a trailing
		# comma, but might not be the last line of an output block
		# due to sorting.
		#
		comma = 0
		for (f = 2; f <= NF; f++) {
			l = length($f)
			if ($f == "/*")
				comma++
			if (comma == 0 && substr($f, l) != ",") {
				lines[id] = sprintf("%s%s,", lines[id], $f)
				l++
			} else {
				lines[id] = sprintf("%s%s", lines[id], $f)
			}
			if (comma == 0 && f != NF) {
				if (l < 2 * 8)
					lines[id] = lines[id] "\t"
				if (l < 8)
					lines[id] = lines[id] "\t"
			}
			if ($f == "*/")
				comma--
		}
	}

	next
}
/};/ {
	if (ignore)
		next

	if (declk) {
		declk = 0
		next
	}

	if (haskeys) {
		# Duplicate 42 (backspace) as 76
		# XXX maybe not correct anymore?
		lines[76] = lines[42]
		sub("42", "76", lines[76])

		for (i = 0; i < 256; i++)
			if (lines[i]) {
				print lines[i]
				lines[i] = ""
			}

		haskeys = 0

		#
		# Apple black USB keyboards use a slightly different
		# layout. We define them here.
		#
		if (mapname == "ukbd_keydesc_fr[]") {
			print $0
			print "\nstatic const keysym_t ukbd_keydesc_fr_apple[] = {"
			print "    KC(5),\tKS_b,\t\tKS_B,\t\tKS_ssharp,"
			print "    KC(8),\tKS_e,\t\tKS_E,\t\tKS_ecircumflex,\tKS_Ecircumflex,"
			print "    KC(11),\tKS_h,\t\tKS_H,\t\tKS_Igrave,\tKS_Icircumflex,"
			print "    KC(12),\tKS_i,\t\tKS_I,\t\tKS_icircumflex,\tKS_idiaeresis,"
			print "    KC(13),\tKS_j,\t\tKS_J,\t\tKS_Idiaeresis,\tKS_Iacute,"
			print "    KC(14),\tKS_k,\t\tKS_K,\t\tKS_Egrave,\tKS_Ediaeresis,"
			print "    KC(15),\tKS_l,\t\tKS_L,\t\tKS_voidSymbol,\tKS_bar,"
			print "    KC(16),\tKS_comma,\tKS_question,\tKS_voidSymbol,\tKS_questiondown,"
			print "    KC(17),\tKS_n,\t\tKS_N,\t\tKS_asciitilde,"
			print "    KC(20),\tKS_a,\t\tKS_A,\t\tKS_ae,\t\tKS_AE,"
			print "    KC(21),\tKS_r,\t\tKS_R,\t\tKS_registered,\tKS_comma,"
			print "    KC(22),\tKS_s,\t\tKS_S,\t\tKS_Ograve,"
			print "    KC(26),\tKS_z,\t\tKS_Z,\t\tKS_Acircumflex,\tKS_Aring,"
			print "    KC(28),\tKS_y,\t\tKS_Y,\t\tKS_Uacute,"
			print "    KC(31),\tKS_eacute,\tKS_2,\t\tKS_ediaeresis,"
			print "    KC(32),\tKS_quotedbl,\tKS_3,"
			print "    KC(33),\tKS_apostrophe,\tKS_4,"
			print "    KC(34),\tKS_parenleft,\tKS_5,\t\tKS_braceleft,\tKS_bracketleft,"
			print "    KC(35),\tKS_section,\tKS_6,"
			print "    KC(36),\tKS_egrave,\tKS_7,\t\tKS_guillemotleft,"
			print "\t\t\t\t\t\tKS_guillemotright,"
			print "    KC(37),\tKS_exclam,\tKS_8,"
			print "    KC(38),\tKS_ccedilla,\tKS_9,\t\tKS_Ccedilla,\tKS_Aacute,"
			print "    KC(37),\tKS_exclam,\tKS_8,\t\tKS_exclamdown,\tKS_Ucircumflex,"
			print "    KC(39),\tKS_agrave,\tKS_0,\t\tKS_oslash,\tKS_Ooblique,"
			print "    KC(45),\tKS_parenright,\tKS_degree,\tKS_braceright,\tKS_bracketright,"
			print "    KC(46),\tKS_minus,\tKS_underscore,"
			print "    KC(47),\tKS_dead_circumflex, KS_dead_diaeresis,"
			print "\t\t\t\t\t\tKS_ocircumflex,\tKS_Ocircumflex,"
			print "    KC(48),\tKS_dollar,\tKS_asterisk,\tKS_cent,\tKS_yen,"
			print "    KC(50),\tKS_grave,\tKS_sterling,\tKS_at,\t\tKS_numbersign,"
			print "    KC(51),\tKS_m,\t\tKS_M,\t\tKS_mu,\t\tKS_Oacute,"
			print "    KC(52),\tKS_ugrave,\tKS_percent,\tKS_Ugrave,"
			print "    KC(53),\tKS_at,\t\tKS_numbersign,"
			print "    KC(55),\tKS_colon,\tKS_slash,\tKS_voidSymbol,\tKS_backslash,"
			print "    KC(56),\tKS_equal,\tKS_plus,"
			print "    KC(103),\tKS_KP_Equal,"
			print "    KC(231),\tKS_Mode_switch,\tKS_Multi_key,"
		} else
		if (mapname == "ukbd_keydesc_pt[]") {
			print $0
			print "\nstatic const keysym_t ukbd_keydesc_pt_apple[] = {"
			print "/*  pos\t\tnormal\t\tshifted */"
			print "    KC(46),\tKS_plus,\tKS_asterisk,"
			print "    KC(47),\tKS_masculine,\tKS_ordfeminine,"
			print "    KC(50),\tKS_backslash,\tKS_bar,"
			print "    KC(52),\tKS_dead_tilde,\tKS_dead_circumflex"
		}
	}
}
/KB_FR/ {
	print $0
	if (kbfr++ == 0) {
		print "\tKBD_MAP(KB_FR | KB_APPLE,\tKB_FR,\tukbd_keydesc_fr_apple),"
	} else {
		print "\tKBD_MAP(KB_FR | KB_APPLE | KB_SWAPCTRLCAPS,\tKB_FR | KB_APPLE,"
		print "\t\tukbd_keydesc_swapctrlcaps),"
	}
	next
}
/KB_PT/ {
	print $0
	print "\tKBD_MAP(KB_PT | KB_APPLE,\tKB_PT,\tukbd_keydesc_pt_apple),"
	next
}
{
	if (ignore)
		next
	if (declk)
		next
	print $0
}

#! /usr/bin/awk -f
#	$OpenBSD: makemap.awk,v 1.4 2005/05/19 10:40:48 miod Exp $
#
# Copyright (c) 2005, Miodrag Vallat
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
#
# This script attempts to convert, with minimal hacks and losses, the
# regular PS/2 keyboard (pckbd) layout tables into USB keyboard (ukbd)
# layout tables.
#

BEGIN {
	rcsid = "$OpenBSD: makemap.awk,v 1.4 2005/05/19 10:40:48 miod Exp $"
	ifdepth = 0
	ignore = 0
	declk = 0
	haskeys = 0
	kbfr = 0

	# PS/2 id -> UKBD conversion table, or "sanity lossage 102"
	# (101 is for GSC keyboards!)
	for (i = 0; i < 256; i++)
		conv[i] = -1

	conv[1] = 41
	conv[2] = 30
	conv[3] = 31
	conv[4] = 32
	conv[5] = 33
	conv[6] = 34
	conv[7] = 35
	conv[8] = 36
	conv[9] = 37
	conv[10] = 38
	conv[11] = 39
	conv[12] = 45
	conv[13] = 46
	conv[14] = 42
	conv[15] = 43
	conv[16] = 20
	conv[17] = 26
	conv[18] = 8
	conv[19] = 21
	conv[20] = 23
	conv[21] = 28
	conv[22] = 24
	conv[23] = 12
	conv[24] = 18
	conv[25] = 19
	conv[26] = 47
	conv[27] = 48
	conv[28] = 40
	conv[29] = 224
	conv[30] = 4
	conv[31] = 22
	conv[32] = 7
	conv[33] = 9
	conv[34] = 10
	conv[35] = 11
	conv[36] = 13
	conv[37] = 14
	conv[38] = 15
	conv[39] = 51
	conv[40] = 52
	conv[41] = 53
	conv[42] = 225
	conv[43] = 50
	conv[44] = 29
	conv[45] = 27
	conv[46] = 6
	conv[47] = 25
	conv[48] = 5
	conv[49] = 17
	conv[50] = 16
	conv[51] = 54
	conv[52] = 55
	conv[53] = 56
	conv[54] = 229
	conv[55] = 85
	conv[56] = 226
	conv[57] = 44
	conv[58] = 57
	conv[59] = 58
	conv[60] = 59
	conv[61] = 60
	conv[62] = 61
	conv[63] = 62
	conv[64] = 63
	conv[65] = 64
	conv[66] = 65
	conv[67] = 66
	conv[68] = 67
	conv[69] = 83
	conv[70] = 71
	conv[71] = 95
	conv[72] = 96
	conv[73] = 97
	conv[74] = 86
	conv[75] = 92
	conv[76] = 93
	conv[77] = 94
	conv[78] = 87
	conv[79] = 89
	conv[80] = 90M
	conv[81] = 91
	conv[82] = 98
	conv[83] = 99
	conv[86] = 100
	conv[87] = 68
	conv[88] = 69
	conv[112] = 135
	conv[115] = 136
	conv[121] = 137
	conv[123] = 138
	conv[125] = 139
	conv[127] = 72
	conv[156] = 88
	conv[157] = 228
	conv[170] = 70
	conv[181] = 84
	conv[184] = 230
	# 198 is #if 0 in the PS/2 map...
	conv[199] = 74
	conv[200] = 82
	conv[201] = 75
	conv[203] = 80
	conv[205] = 79
	conv[207] = 77
	conv[208] = 81
	conv[209] = 78
	conv[210] = 73
	conv[211] = 99
	conv[219] = 227
	conv[220] = 231
	conv[221] = 101
}
NR == 1 {
	VERSION = $0
	gsub("\\$", "", VERSION)
	gsub("\\$", "", rcsid)

	printf("/*\t\$OpenBSD\$\t*/\n\n")
	printf("/*\n")
	printf(" * THIS FILE IS AUTOMAGICALLY GENERATED.  DO NOT EDIT.\n")
	printf(" *\n")
	printf(" * generated by:\n")
	printf(" *\t%s\n", rcsid)
	printf(" * generated from:\n")
	printf(" */\n")
	print VERSION

	next
}

#
# A very limited #if ... #endif parser. We only want to correctly detect
# ``#if 0'' constructs, so as not to process their contents. This is necessary
# since our output is out-of-order from our input.
#
# Note that this does NOT handle ``#ifdef notyet'' correctly - please only use
# ``#if 0'' constructs in the input.
#

/^#if/ {
	ignores[ifdepth] = ignore
	if ($2 == "0")
		ignore = 1
	else
		ignore = 0
	ifdepth++
	if (ignore)
		next
}
/^#endif/ {
	oldignore = ignore
	ifdepth--
	ignore = ignores[ifdepth]
	ignores[ifdepth] = 0
	if (oldignore)
		next
}

$1 == "#include" {
	if (ignore)
		next
	if ($2 == "<dev/pckbc/wskbdmap_mfii.h>")
		print "#include <dev/usb/usb_port.h>"
	else
		printf("#include %s\n", $2)

	next
}
$1 == "#define" || $1 == "#undef" {
	if (ignore)
		next
	print $0
	next
}

# Don't bother converting the DEC LK layout.
/declk\[/ {
	declk = 1
	next
}
/declk/ {
	next
}

/pckbd/ {
	gsub("pckbd", "ukbd", $0)
	mapname = $4
}

/KC/ {
	if (ignore)
		next

	if (declk)
		next

	haskeys = 1

	sidx = substr($1, 4, length($1) - 5)
	orig = int(sidx)
	id = conv[orig]

	# 183 is another Print Screen...
	if (orig == 183)
		next

	if (id == -1) {
		printf("/* initially KC(%d),", orig)
		for (f = 2; f <= NF; f++) {
			if ($f != "/*" && $f != "*/")
				printf("\t%s", $f)
		}
		printf("\t*/\n")
	} else {
		lines[id] = sprintf("    KC(%d),\t", id)
		#
		# This makes sure that the non-comment part of the output
		# ends up with a trailing comma. This is necessary since
		# the last line of an input block might not have a trailing
		# comma, but might not be the last line of an output block
		# due to sorting.
		#
		comma = 0
		for (f = 2; f <= NF; f++) {
			l = length($f)
			if ($f == "/*")
				comma++
			if (comma == 0 && substr($f, l) != ",") {
				lines[id] = sprintf("%s%s,", lines[id], $f)
				l++
			} else {
				lines[id] = sprintf("%s%s", lines[id], $f)
			}
			if (comma == 0 && f != NF) {
				if (l < 2 * 8)
					lines[id] = lines[id] "\t"
				if (l < 8)
					lines[id] = lines[id] "\t"
			}
			if ($f == "*/")
				comma--
		}
	}

	next
}
/};/ {
	if (ignore)
		next

	if (declk) {
		declk = 0
		next
	}

	if (haskeys) {
		# Duplicate 42 (backspace) as 76
		# XXX maybe not correct anymore?
		lines[76] = lines[42]
		sub("42", "76", lines[76])

		for (i = 0; i < 256; i++)
			if (lines[i]) {
				print lines[i]
				lines[i] = ""
			}

		haskeys = 0

		#
		# Apple black USB keyboards use a slightly different
		# layout. We define them here.
		#
		if (mapname == "ukbd_keydesc_fr[]") {
			print $0
			print "\nstatic const keysym_t ukbd_keydesc_fr_apple[] = {"
			print "    KC(35),\tKS_section,\tKS_6,"
			print "    KC(37),\tKS_exclam,\tKS_8,"
			print "    KC(46),\tKS_minus,\tKS_underscore,"
			print "    KC(48),\tKS_dollar,\tKS_asterisk,"
			print "    KC(50),\tKS_backslash,\tKS_sterling,"
			print "    KC(53),\tKS_at,\tKS_numbersign,"
			print "    KC(56),\tKS_equal,\tKS_plus,"
			print "    KC(103),\tKS_KP_Equal,"
		} else
		if (mapname == "ukbd_keydesc_pt[]") {
			print $0
			print "\nstatic const keysym_t ukbd_keydesc_pt_apple[] = {"
			print "/*  pos\t\tnormal\t\tshifted */"
			print "    KC(46),\tKS_plus,\tKS_asterisk,"
			print "    KC(47),\tKS_masculine,\tKS_ordfeminine,"
			print "    KC(50),\tKS_backslash,\tKS_bar,"
			print "    KC(52),\tKS_dead_tilde,\tKS_dead_circumflex"
		}
	}
}
/KB_FR/ {
	print $0
	if (kbfr++ == 0) {
		print "\tKBD_MAP(KB_FR | KB_APPLE,\tKB_FR,\tukbd_keydesc_fr_apple),"
	} else {
		print "\tKBD_MAP(KB_FR | KB_APPLE | KB_SWAPCTRLCAPS,\tKB_FR | KB_APPLE,"
		print "\t\tukbd_keydesc_swapctrlcaps),"
	}
	next
}
/KB_PT/ {
	print $0
	print "\tKBD_MAP(KB_PT | KB_APPLE,\tKB_PT,\tukbd_keydesc_pt_apple),"
	next
}
{
	if (ignore)
		next
	if (declk)
		next
	print $0
}


Add AWK script to compute a range

Add AWK script to compute a range


Test 2015.

Test 2015.

#!/usr/bin/awk -f
#tdbout -t publisher,plugin,publisher:info[tester],status,year *.tdb

BEGIN {
  FS="\t"
  pn = 0
}

{
  # add a loop to add line only if either [status is _not_ manifest] OR [journal year (or journal end year) is lt or eq to the current year we are testing]
  current_year = 2015
  end_year = 0
  incontract = 0
  #test_year = ""
  #test_year = 2005
  if (length($5) > 3) {
    end_year = substr($5,length($5)-3,4)
  }
  #printf "%s\n", $0
  #if (($4 != "manifest") || ((end_year >= test_year) && (end_year <= current_year))) {
  if (($4 != "manifest") || (end_year <= current_year)) {
    incontract = 1
  }

  if (incontract == 1) {
    nn = split($2,na,/\./)
    lp2 = na[nn]
    if (!(($1,lp2) in b)) {
      p[pn] = $1
      n[pn] = lp2
  #    n[pn] = $2
      r[pn] = $3
      if (r[pn] == "") {
          r[pn] = "8"
      }
      pn++
    }
    b[$1,lp2]++
    c[$1,lp2,$4]++
    x[$4]++
    tt++
  }
}

END {
  s[0] = "expected"
  s[1] = "exists"
  s[2] = "manifest"
  s[3] = "wanted"
  s[4] = "testing"
  s[5] = "notReady"
  s[6] = "ready"
  s[7] = "released"
  s[8] = "down"
  s[9] = "superseded"
  s[10] = "doNotProcess"
  s[11] = "doesNotExist"
  sn = 12

  sc[0] = "expe"
  sc[1] = "exis"
  sc[2] = "mani"
  sc[3] = "want"
  sc[4] = "test"
  sc[5] = "notR"
  sc[6] = "read"
  sc[7] = "rele"
  sc[8] = "down"
  sc[9] = "supe"
  sc[10] = "doNP"
  sc[11] = "dNoE"
  scn = 12

  #print out header
  printf "Publisher\tPlugin\tT\tTotal"
  for (j = 0 ; j < scn ; j++) {
    if (x[s[j]] > 0) {
    printf "\t%s", sc[j]
    }
  }
  printf "\n"

  #print out publisher, plugin, tester, total aus
  for (i = 0 ; i < pn ; i++) {
    printf "%s\t%s\t%s\t%d", p[i], n[i], r[i], b[p[i],n[i]]
    for (j = 0 ; j < sn ; j++) {
      if (x[s[j]] > 0){
      if (c[p[i],n[i],s[j]] == 0) {
      printf "\t.."
    } else {
        printf "\t%d", c[p[i],n[i],s[j]]
      }
    }
    }
    printf "\n"
  }
    #print out bottom line sums
    printf "Publisher\tPlugin\tT\t%d", tt
    for (j = 0 ; j < sn ; j++) {
      if (x[s[j]] > 0) {
        printf "\t%d", x[s[j]]
      }
    }

  printf "\n"
}

#!/usr/bin/awk -f
#tdbout -t publisher,plugin,publisher:info[tester],status,year *.tdb

BEGIN {
  FS="\t"
  pn = 0
}

{
  # add a loop to add line only if either [status is _not_ manifest] OR [journal year (or journal end year) is lt or eq to the current year we are testing]
  current_year = 2014
  end_year = 0
  incontract = 0
  #test_year = ""
  #test_year = 2005
  if (length($5) > 3) {
    end_year = substr($5,length($5)-3,4)
  }
  #printf "%s\n", $0
  #if (($4 != "manifest") || ((end_year >= test_year) && (end_year <= current_year))) {
  if (($4 != "manifest") || (end_year <= current_year)) {
    incontract = 1
  }

  if (incontract == 1) {
    nn = split($2,na,/\./)
    lp2 = na[nn]
    if (!(($1,lp2) in b)) {
      p[pn] = $1
      n[pn] = lp2
  #    n[pn] = $2
      r[pn] = $3
      if (r[pn] == "") {
          r[pn] = "8"
      }
      pn++
    }
    b[$1,lp2]++
    c[$1,lp2,$4]++
    x[$4]++
    tt++
  }
}

END {
  s[0] = "expected"
  s[1] = "exists"
  s[2] = "manifest"
  s[3] = "wanted"
  s[4] = "testing"
  s[5] = "notReady"
  s[6] = "ready"
  s[7] = "released"
  s[8] = "down"
  s[9] = "superseded"
  s[10] = "doNotProcess"
  s[11] = "doesNotExist"
  sn = 12

  sc[0] = "expe"
  sc[1] = "exis"
  sc[2] = "mani"
  sc[3] = "want"
  sc[4] = "test"
  sc[5] = "notR"
  sc[6] = "read"
  sc[7] = "rele"
  sc[8] = "down"
  sc[9] = "supe"
  sc[10] = "doNP"
  sc[11] = "dNoE"
  scn = 12

  #print out header
  printf "Publisher\tPlugin\tT\tTotal"
  for (j = 0 ; j < scn ; j++) {
    if (x[s[j]] > 0) {
    printf "\t%s", sc[j]
    }
  }
  printf "\n"

  #print out publisher, plugin, tester, total aus
  for (i = 0 ; i < pn ; i++) {
    printf "%s\t%s\t%s\t%d", p[i], n[i], r[i], b[p[i],n[i]]
    for (j = 0 ; j < sn ; j++) {
      if (x[s[j]] > 0){
      if (c[p[i],n[i],s[j]] == 0) {
      printf "\t.."
    } else {
        printf "\t%d", c[p[i],n[i],s[j]]
      }
    }
    }
    printf "\n"
  }
    #print out bottom line sums
    printf "Publisher\tPlugin\tT\t%d", tt
    for (j = 0 ; j < sn ; j++) {
      if (x[s[j]] > 0) {
        printf "\t%d", x[s[j]]
      }
    }

  printf "\n"
}


Ignore AUs with year lt contract date

Ignore AUs with year lt contract date

git-svn-id: 293778eaa97c8c94097d610b1bd5133a8f478f36@17397 4f837ed2-42f5-46e7-a7a5-fa17313484d4

#!/usr/bin/awk -f
# input: publisher\tcontract_year\tyear\tstatus
# add a loop to add line only if first 4 char or last 4 char of year are gt or eq to contract

BEGIN {
  FS="\t"
  pn = 0
}

{
  if (substr($3,0,4) >= $2) {
  if (!(($1,$2,$3) in b)) {
    p[pn] = $1
    t[pn] = $2
    d[pn] = $3
    pn++
  }
  b[$1,$2,$3]++
  c[$1,$2,$3,$4]++
  x[$4]++
  tt++
}
}

END {
  s[0] = "expected"
  s[1] = "exists"
  s[2] = "manifest"
  s[3] = "wanted"
  s[4] = "crawling"
  s[5] = "testing"
  s[6] = "notReady"
  s[7] = "released"
  s[8] = "down"
  s[9] = "superseded"
  sn = 10

  printf "Publisher\tContract\tYear\tTotal"
  for (j = 0 ; j < sn ; j++) {
    printf "\t%s", s[j]
  }
  printf "\n"

  for (i = 0 ; i < pn ; i++) {
    printf "%s\t%s\t%s\t%d", p[i], t[i], d[i], b[p[i],t[i],d[i]]
    for (j = 0 ; j < sn ; j++) {
      printf "\t%d", c[p[i],t[i],d[i],s[j]]
    }
    printf "\n"
  }
    printf "Publisher\tContract\tYear\t%d", tt
    for (j = 0 ; j < sn ; j++) {
    	printf "\t%d", x[s[j]]
    }

}

#!/usr/bin/awk -f
# input: publisher\tcontract_year\tyear\tstatus

BEGIN {
  FS="\t"
  pn = 0
}

{
  if (!(($1,$2,$3) in b)) {
    p[pn] = $1
    t[pn] = $2
    d[pn] = $3
    pn++
  }
  b[$1,$2,$3]++
  c[$1,$2,$3,$4]++
  x[$4]++
  tt++
}

END {
  s[0] = "expected"
  s[1] = "exists"
  s[2] = "manifest"
  s[3] = "wanted"
  s[4] = "crawling"
  s[5] = "testing"
  s[6] = "notReady"
  s[7] = "released"
  s[8] = "down"
  s[9] = "superseded"
  sn = 10

  printf "Publisher\tContract\tYear\tTotal"
  for (j = 0 ; j < sn ; j++) {
    printf "\t%s", s[j]
  }
  printf "\n"

  for (i = 0 ; i < pn ; i++) {
    printf "%s\t%s\t%s\t%d", p[i], t[i], d[i], b[p[i],t[i],d[i]]
    for (j = 0 ; j < sn ; j++) {
      printf "\t%d", c[p[i],t[i],d[i],s[j]]
    }
    printf "\n"
  }
    printf "Publisher\tContract\tYear\t%d", tt
    for (j = 0 ; j < sn ; j++) {
    	printf "\t%d", x[s[j]]
    }

}


Special Montalbano page 2 processing

Special Montalbano page 2 processing

# Generate a separate file with a line for each episode containing
# seriesNumber, episodeURL, seriesTitle, seasonNumber, episodeNumber,
# episodeTitle, episodeDuration, & episodeDescription with the same columns
# as the primary spreadsheet so they can be combined into one.
# Add to the number of episodes but with no terminating newline
#
# INVOCATION:
#       curl -s https://watch.mhzchoice.com/a-french-village/season:1 \
#           | awk -v EPISODE_INFO_FILE=$EPISODE_INFO_FILE -v SERIES_NUMBER=$lastRow \
#           -v NUM_EPISODES_FILE=$NUM_EPISODES_FILE -v ERROR_FILE=$ERROR_FILE \
#           -f getMHzFrom-episodePages.awk
#
# INPUT:
#        <title>A French Village - MHz Choice</title>
#  ---
#        <meta name="apple-itunes-app" content="app-id=1096194231, \
#        app-argument=https://watch.mhzchoice.com/detective-montalbano?page=2">
#  ---
#

#          18 Episodes
#

#  ---
#
47:58

#  ---
#        The Landing (June 12, 1940)\
#
#  ---
#
Episode 1

#

#
A doctor oversees the birth of a child. Directed by Phillipe Triboit, 2009.

#
#
This episode will be made available on August 8.

#

# OUTPUT:
#       $EPISODE_INFO_FILE & the number of episodes
#

# Extract whether this is a page 2
/<meta name="apple-itunes-app" content=".*?page=2">/ {
    page2 = "yes"
}

# Extract only the number of episodes, print them with no terminating newline
# but if this is page 2 skip to avoid double counting
/
> NUM_EPISODES_FILE
        next
    }
}

# Extract the series title
/<title>/ {
    sub (/.*<title>/,"")
    sub (/ - MHz Choice<.*/,"")
    gsub (/'/,"'")
    gsub (/"/,"\"\"")
    gsub (/&/,"\\&")
    if (match ($0, /^The /)) {
        $0 = substr($0, 5) ", The"
    }
    seriesTitle = $0
    next
}

# Extract the duration
/<div class="duration-container/ {
    split ($0,fld,"[<>]")
    episodeDuration = fld[3]
    gsub (/ /,"",episodeDuration)
    # Spreadsheets decipher 2 part durations as time-of-day so make sure they're 3 parts
    if (split (episodeDuration, tm, ":") == 2)
        episodeDuration = "00:" episodeDuration
    next
}

# Extract the episode URL, the episode type, the episode title, and the seasonNumber
/<strong title="/ {
    gsub (/'/,"'")
    split ($0,fld,"\"")
    episodeURL = fld[2]
    if (episodeURL ~ /-c-.[[:digit:]]{3,4}$/)
        episodeNumberFromURL = substr (episodeURL, length(episodeURL)-1, 2) + 0
    shortURL = episodeURL
    sub (/.*watch/,"watch",shortURL)
    # Default episodeType to "E"
    episodeType = "E"
    # If episode is a Trailer or Finale (i.e. First look), set episodeType to "T"
    if (episodeURL ~ /-trailer-|-finale-/)
        episodeType = "T"
    # If episode is a BONUS:, set episodeType to "X"
    if (episodeURL ~ /-c-x[[:digit:]]{3,4}$|montme-c-01001/)
        episodeType = "X"
    episodeTitle = fld[4]
    gsub (/"/,"\"\"",episodeTitle)
    gsub (/&/,"\\&",episodeTitle)
    sub (/.*season:/,"")
    sub (/\/.*/,"")
    seasonNumber = $0
    next
}

# Extract the episode number, and correct if necessary
# Detective Montalbano requires special processing for page 2 episodeNumber
/<h4 class="/ {
    sub (/.*Episode /,"")
    sub (/<\/span>.*/,"")
    episodeNumber = $0 + 0
    if (seriesTitle == "Detective Montalbano" && page2 == "yes") {
        oldEpisodeNumber = episodeNumber
        episodeNumber += 24
        printf ("==> Corrected E%02d to %s%02d: %s\n", oldEpisodeNumber, episodeType, \
                episodeNumber, shortURL) >> ERROR_FILE
    }
    next
}

# WARNING - other scripts depend on the number and order of the fields below
# Extract the episode description and print the composed info
/<div class="transparent padding-top-medium"/,/<\/div>/ {
    if ($0 ~ /
 Corrected %s00 to %s%02d: %s\n", episodeType, episodeType,
                        episodeNumberFromURL, shortURL) >> ERROR_FILE
                episodeNumber = episodeNumberFromURL
            } else {
                printf ("==> Episode number is 00: %s\n", shortURL) >> ERROR_FILE
            }
        }
        printf ("%d\t=HYPERLINK(\"%s\";\"%s, S%02d%s%02d, %s\"\)\t\t\t%s\t\t\t\t\t", \
                SERIES_NUMBER, episodeURL, seriesTitle, seasonNumber, episodeType, episodeNumber, \
                episodeTitle, episodeDuration) >> EPISODE_INFO_FILE
        # Need to account for multiple lines of description
        descriptionLinesFound = 0
        episodeDescription = ""
        # make sure there is no carryforward
        episodeNumber = ""
        episodeNumberFromURL = ""
    }
    if ($0 ~ /
/) {
        split ($0,fld,"[<>]")
        paragraph = fld[3]
        gsub (/"/,"\"",paragraph)
        gsub (/&/,"\\&",paragraph)
        # Could be in multiple paragraphs
        descriptionLinesFound += 1
        episodeDescription = episodeDescription (descriptionLinesFound == 1 ? "" : " ") paragraph
    }
    if ($0 ~ /<\/div>/) {
        if (episodeDescription == "")
            print "==> No description: " shortURL >> ERROR_FILE
        print episodeDescription >> EPISODE_INFO_FILE
    }
}

# Generate a separate file with a line for each episode containing
# seriesNumber, episodeURL, seriesTitle, seasonNumber, episodeNumber,
# episodeTitle, episodeDuration, & episodeDescription with the same columns
# as the primary spreadsheet so they can be combined into one.
# Add to the number of episodes but with no terminating newline
#
# INVOCATION:
#       curl -s https://watch.mhzchoice.com/a-french-village/season:1 \
#           | awk -v EPISODE_INFO_FILE=$EPISODE_INFO_FILE -v SERIES_NUMBER=$lastRow \
#           -v NUM_EPISODES_FILE=$NUM_EPISODES_FILE -v ERROR_FILE=$ERROR_FILE \
#           -f getMHzFrom-episodePages.awk
#
# INPUT:
#        <title>A French Village - MHz Choice</title>
#  ---
#        <meta name="apple-itunes-app" content="app-id=1096194231, \
#        app-argument=https://watch.mhzchoice.com/detective-montalbano?page=2">
#  ---
#

#          18 Episodes
#

#  ---
#
47:58

#  ---
#        The Landing (June 12, 1940)\
#
#  ---
#
Episode 1

#

#
A doctor oversees the birth of a child. Directed by Phillipe Triboit, 2009.

#
#
This episode will be made available on August 8.

#

# OUTPUT:
#       $EPISODE_INFO_FILE & the number of episodes
#

# Extract whether this is a page 2
/<meta name="apple-itunes-app" content=".*?page=2">/ {
    page2 = "yes"
}

# Extract only the number of episodes, print them with no terminating newline
# but if this is page 2 skip to avoid double counting
/
> NUM_EPISODES_FILE
        next
    }
}

# Extract the series title
/<title>/ {
    sub (/.*<title>/,"")
    sub (/ - MHz Choice<.*/,"")
    gsub (/'/,"'")
    gsub (/"/,"\"\"")
    gsub (/&/,"\\&")
    if (match ($0, /^The /)) {
        $0 = substr($0, 5) ", The"
    }
    seriesTitle = $0
    next
}

# Extract the duration
/<div class="duration-container/ {
    split ($0,fld,"[<>]")
    episodeDuration = fld[3]
    gsub (/ /,"",episodeDuration)
    # Spreadsheets decipher 2 part durations as time-of-day so make sure they're 3 parts
    if (split (episodeDuration, tm, ":") == 2)
        episodeDuration = "00:" episodeDuration
    next
}

# Extract the episode URL, the episode type, the episode title, and the seasonNumber
/<strong title="/ {
    gsub (/'/,"'")
    split ($0,fld,"\"")
    episodeURL = fld[2]
    if (episodeURL ~ /-c-.[[:digit:]]{3,4}$/)
        episodeNumberFromURL = substr (episodeURL, length(episodeURL)-1, 2) + 0
    shortURL = episodeURL
    sub (/.*watch/,"watch",shortURL)
    # Default episodeType to "E"
    episodeType = "E"
    # If episode is a Trailer or Finale (i.e. First look), set episodeType to "T"
    if (episodeURL ~ /-trailer-|-finale-/)
        episodeType = "T"
    # If episode is a BONUS:, set episodeType to "X"
    if (episodeURL ~ /-c-x[[:digit:]]{3,4}$/)
        episodeType = "X"
    episodeTitle = fld[4]
    gsub (/"/,"\"\"",episodeTitle)
    gsub (/&/,"\\&",episodeTitle)
    sub (/.*season:/,"")
    sub (/\/.*/,"")
    seasonNumber = $0
    next
}

# Extract the episode number, and correct if necessary
/<h4 class="/ {
    sub (/.*Episode /,"")
    sub (/<\/span>.*/,"")
    episodeNumber = $0 + 0
    if ((episodeURL ~ /-c-.[[:digit:]]{3,4}$/) && episodeNumber != episodeNumberFromURL) {
        printf ("==> Corrected %s%02d to %s%02d: %s\n", episodeType, episodeNumber, episodeType, \
                episodeNumberFromURL, shortURL) >> ERROR_FILE
        episodeNumber = episodeNumberFromURL
    }
    next
}

# WARNING - other scripts depend on the number and order of the fields below
# Extract the episode description and print the composed info
/<div class="transparent padding-top-medium"/,/<\/div>/ {
    if ($0 ~ /
 Corrected %s00 to %s%02d: %s\n", episodeType, episodeType,
                        episodeNumberFromURL, shortURL) >> ERROR_FILE
                episodeNumber = episodeNumberFromURL
            } else {
                printf ("==> Episode number is 00: %s\n", shortURL) >> ERROR_FILE
            }
        }
        printf ("%d\t=HYPERLINK(\"%s\";\"%s, S%02d%s%02d, %s\"\)\t\t\t%s\t\t\t\t\t", \
                SERIES_NUMBER, episodeURL, seriesTitle, seasonNumber, episodeType, episodeNumber, \
                episodeTitle, episodeDuration) >> EPISODE_INFO_FILE
        # Need to account for multiple lines of description
        descriptionLinesFound = 0
        episodeDescription = ""
        # make sure there is no carryforward
        episodeNumber = ""
        episodeNumberFromURL = ""
    }
    if ($0 ~ /
/) {
        split ($0,fld,"[<>]")
        paragraph = fld[3]
        gsub (/"/,"\"",paragraph)
        gsub (/&/,"\\&",paragraph)
        # Could be in multiple paragraphs
        descriptionLinesFound += 1
        episodeDescription = episodeDescription (descriptionLinesFound == 1 ? "" : " ") paragraph
    }
    if ($0 ~ /<\/div>/) {
        if (episodeDescription == "")
            print "==> No description: " shortURL >> ERROR_FILE
        print episodeDescription >> EPISODE_INFO_FILE
    }
}


color_funcs.awk	-- aded rgb2hsv and hsv2rgb converters

function init_crange(crange, colorInfo,   nf, ary, nf2, ary2, R, G, B, rgb, hsv) {
	nf = split(crange, ary, ":")
	if(nf != 2){
		printf("ERROR: bad color range: %s, must be r,g,b:r,g,b r,g,b in [0,1]\n", crange) > "/dev/stderr"
		return 1
	}

	# get start color
	nf2 = split(ary[1], ary2, ",")
	if(nf2 != 3){
		printf("ERROR: bad start color: %s, must be r,g,b r,g,b in [0,1]\n", ary[1]) > "/dev/stderr"
		return 1
	}
	R = ary2[1]
	if(R < 0 || R > 1){
		printf("ERROR: bad start R value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[1]) > "/dev/stderr"
		return 1
	}
	G = ary2[2]
	if(G < 0 || G > 1){
		printf("ERROR: bad start G value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[2]) > "/dev/stderr"
		return 1
	}
	B = ary2[3]
	if(B < 0 || B > 1){
		printf("ERROR: bad start B value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[3]) > "/dev/stderr"
		return 1
	}
	rgb["R"] = R
	rgb["G"] = G
	rgb["B"] = B
	rgb2hsv(rgb, hsv)

#	colorInfo["R_start"] = R
#	colorInfo["G_start"] = G
#	colorInfo["B_start"] = B

	colorInfo["H_start"] = hsv["H"]
	colorInfo["S_start"] = hsv["S"]
	colorInfo["V_start"] = hsv["V"]

	# get end color
	nf2 = split(ary[2], ary2, ",")
	if(nf2 != 3){
		printf("ERROR: bad end color: %s, must be r,g,b r,g,b in [0,1]\n", ary[2]) > "/dev/stderr"
		return 1
	}
	R = ary2[1]
	if(R < 0 || R > 1){
		printf("ERROR: bad end R value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[1]) > "/dev/stderr"
		return 1
	}
	G = ary2[2]
	if(G < 0 || G > 1){
		printf("ERROR: bad end G value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[2]) > "/dev/stderr"
		return 1
	}
	B = ary2[3]
	if(B < 0 || B > 1){
		printf("ERROR: bad end B value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[3]) > "/dev/stderr"
		return 1
	}
	rgb["R"] = R
	rgb["G"] = G
	rgb["B"] = B
	rgb2hsv(rgb, hsv)

#	colorInfo["R_end"] = R
#	colorInfo["G_end"] = G
#	colorInfo["B_end"] = B

	colorInfo["H_end"] = hsv["H"]
	colorInfo["S_end"] = hsv["S"]
	colorInfo["V_end"] = hsv["V"]

	return 0
}
function set_4bit_color(frac, colorInfo,    r_max_cval, hsv, rgb, R, G, B) {

	# RGB gradient is really not all that nice, hsv is better
#	r_max_cval = 1.0/15
#	R = int((frac * colorInfo["R_end"] + (1.0 - frac) * colorInfo["R_start"]) / r_max_cval)
#	G = int((frac * colorInfo["G_end"] + (1.0 - frac) * colorInfo["G_start"]) / r_max_cval)
#	B = int((frac * colorInfo["B_end"] + (1.0 - frac) * colorInfo["B_start"]) / r_max_cval)

	hsv["H"] = frac * colorInfo["H_end"] + (1.0 - frac) * colorInfo["H_start"]
	hsv["S"] = frac * colorInfo["S_end"] + (1.0 - frac) * colorInfo["S_start"]
	hsv["V"] = frac * colorInfo["V_end"] + (1.0 - frac) * colorInfo["V_start"]
	hsv2rgb(hsv, rgb)

	r_max_cval = 1.0/15
	R = rgb["R"] / r_max_cval
	G = rgb["G"] / r_max_cval
	B = rgb["B"] / r_max_cval

	return sprintf("%x%x%x", R, G, B)
}
function rgb2hsv(rgb, hsv,   min, max, delta) {

	min = rgb["R"] < rgb["G"] ? rgb["R"] : rgb["G"]
	min = min      < rgb["B"] ? min      : rgb["B"]

	max = rgb["R"] > rgb["G"] ? rgb["R"] : rgb["G"]
	max = max      > rgb["B"] ? max      : rgb["B"]

	hsv["V"] = max

	delta = max - min
	if(delta < 0.00001){
		hsv["S"] = 0
		hsv["H"] = 0
		return
	}

	if(max > 0)
		hsv["S"] = (delta/max)
	else{
		hsv["S"] = 0
		hsv["H"] = 0	# V is 0, s H doesn't matter, so use 0
		return
	}
	if(rgb["R"] >= max)
		hsv["H"] = (rgb["G"] - rgb["B"])/delta		# between magenta & yellow
	else if(rgb["G"] >= max)
		hsv["H"] = 2.0 + (rgb["B"] - rgb["R"])/delta	# between yellow & cyan
	else
		hsv["H"] = 4.0 + (rgb["R"] - rgb["G"])/delta	# between cyan & magenta
	hsv["H"] *= 60
	if(hsv["H"] < 0)
		hsv["H"] += 360
	return
}
function hsv2rgb(hsv, rgb,    hh, p, q, t, ff, i) {

	if(hsv["S"] <= 0){
		rgb["R"] = hsv["V"]
		rgb["G"] = hsv["V"]
		rgb["B"] = hsv["V"]
		return
	}
	hh = hsv["H"]
	if(hh >= 360)
		hh = 0
	hh /= 60
	i = int(hh)
	ff = hh - i
	p = hsv["V"] * (1.0 - hsv["S"])
	q = hsv["V"] * (1.0 - (hsv["S"] * ff))
	t = hsv["V"] * (1.0 - (hsv["S"] * (1 - ff)))

	if(i == 0){
		rgb["R"] = hsv["V"]
		rgb["G"] = t
		rgb["B"] = p
	}else if(i == 1){
		rgb["R"] = q
		rgb["G"] = hsv["V"]
		rgb["B"] = p
	}else if(i == 2){
		rgb["R"] = p
		rgb["G"] = hsv["V"]
		rgb["B"] = t
	}else if(i == 3){
		rgb["R"] = p
		rgb["G"] = q
		rgb["B"] = hsv["V"]
	}else if(i == 4){
		rgb["R"] = t
		rgb["G"] = p
		rgb["B"] = hsv["V"]
	}else{	# must be 5
		rgb["R"] = hsv["V"]
		rgb["G"] = p
		rgb["B"] = q
	}
	return
}

function init_crange(crange, colorInfo,   nf, ary, nf2, ary2, R, G, B) {
	nf = split(crange, ary, ":")
	if(nf != 2){
		printf("ERROR: bad color range: %s, must be r,g,b:r,g,b r,g,b in [0,1]\n", crange) > "/dev/stderr"
		return 1
	}

	# get start color
	nf2 = split(ary[1], ary2, ",")
	if(nf2 != 3){
		printf("ERROR: bad start color: %s, must be r,g,b r,g,b in [0,1]\n", ary[1]) > "/dev/stderr"
		return 1
	}
	R = ary2[1]
	if(R < 0 || R > 1){
		printf("ERROR: bad start R value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[1]) > "/dev/stderr"
		return 1
	}
	G = ary2[2]
	if(G < 0 || G > 1){
		printf("ERROR: bad start G value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[2]) > "/dev/stderr"
		return 1
	}
	B = ary2[3]
	if(B < 0 || B > 1){
		printf("ERROR: bad start B value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[3]) > "/dev/stderr"
		return 1
	}
	colorInfo["R_start"] = R
	colorInfo["G_start"] = G
	colorInfo["B_start"] = B

	# get end color
	nf2 = split(ary[2], ary2, ",")
	if(nf2 != 3){
		printf("ERROR: bad end color: %s, must be r,g,b r,g,b in [0,1]\n", ary[2]) > "/dev/stderr"
		return 1
	}
	R = ary2[1]
	if(R < 0 || R > 1){
		printf("ERROR: bad end R value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[1]) > "/dev/stderr"
		return 1
	}
	G = ary2[2]
	if(G < 0 || G > 1){
		printf("ERROR: bad end G value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[2]) > "/dev/stderr"
		return 1
	}
	B = ary2[3]
	if(B < 0 || B > 1){
		printf("ERROR: bad end B value: %s, must be r,g,b r,g,b in [0,1]\n", ary2[3]) > "/dev/stderr"
		return 1
	}
	colorInfo["R_end"] = R
	colorInfo["G_end"] = G
	colorInfo["B_end"] = B

	return 0
}
function set_4bit_color(frac, colorInfo,    r_max_cval, R, G, B) {

	r_max_cval = 1.0/15
	R = int((frac * colorInfo["R_end"] + (1.0 - frac) * colorInfo["R_start"]) / r_max_cval)
	G = int((frac * colorInfo["G_end"] + (1.0 - frac) * colorInfo["G_start"]) / r_max_cval)
	B = int((frac * colorInfo["B_end"] + (1.0 - frac) * colorInfo["B_start"]) / r_max_cval)

	return sprintf("%x%x%x", R, G, B)
}


Edit awk directory

Edit awk directory

#!/usr/bin/awk -f

BEGIN {
  # It is not possible to define output file names here because
  # FILENAME is not define in the BEGIN section
  n = "";
  printf "Generating data files ...";
  network_max_bandwidth_in_byte = 10000000;
  network_max_packet_per_second = 1000000;
  last3 = 0;
  last4 = 0;
  last5 = 0;
  last6 = 0;
}
{
  if ($1 ~ /Average/)
    { # Skip the Average values
      n = "";
      next;
    }

  if ($2 ~ /all/)
    { # This is the cpu info
      print $3 > FILENAME".cpu.user.dat";
#	  print $4 > FILENAME".cpu.nice.dat";
      print $5 > FILENAME".cpu.system.dat";
#     print $6 > FILENAME".cpu.iowait.dat";
      print $7 > FILENAME".cpu.idle.dat";
      print 100-$7 > FILENAME".cpu.busy.dat";
    }
  if ($2 ~ /eth0/)
    { # This is the eth0 network info
      if ($3 > network_max_packet_per_second)
	print last3 > FILENAME".net.rxpck.dat"; # Total number of packets received per second.
      else
	{
	  last3 = $3;
	  print $3 > FILENAME".net.rxpck.dat"; # Total number of packets received per second.
	}
      if ($4 > network_max_packet_per_second)
	print last4 > FILENAME".net.txpck.dat"; # Total number of packets transmitted per second.
      else
	{
	  last4 = $4;
	  print $4 > FILENAME".net.txpck.dat"; # Total number of packets transmitted per second.
	}
      if ($5 > network_max_bandwidth_in_byte)
	print last5 > FILENAME".net.rxbyt.dat"; # Total number of bytes received per second.
      else
	{
	  last5 = $5;
	  print $5 > FILENAME".net.rxbyt.dat"; # Total number of bytes received per second.
	}
      if ($6 > network_max_bandwidth_in_byte)
	print last6 > FILENAME".net.txbyt.dat"; # Total number of bytes transmitted per second.
      else
	{
	  last6 = $6;
	  print $6 > FILENAME".net.txbyt.dat"; # Total number of bytes transmitted per second.
	}
#     print $7 > FILENAME".net.rxcmp.dat"; # Number of compressed packets received per second (for cslip etc.).
#     print $8 > FILENAME".net.txcmp.dat"; # Number of compressed packets transmitted per second.
#     print $9 > FILENAME".net.rxmcst.dat"; # Number of multicast packets received per second.
    }

  # Detect which is the next info to be parsed
  if ($2 ~ /proc|cswch|tps|kbmemfree|totsck/)
    {
      n = $2;
    }

  # Only get lines with numbers (real data !)
  if ($2 ~ /[0-9]/)
    {
      if (n == "proc/s")
	{ # This is the proc/s info
	  print $2 > FILENAME".proc.dat";
#	  n = "";
	}
      if (n == "cswch/s")
	{ # This is the context switches per second info
	  print $2 > FILENAME".ctxsw.dat";
#	  n = "";
	}
      if (n == "tps")
	{ # This is the disk info
	  print $2 > FILENAME".disk.tps.dat"; # total transfers per second
	  print $3 > FILENAME".disk.rtps.dat"; # read requests per second
	  print $4 > FILENAME".disk.wtps.dat"; # write requests per second
	  print $5 > FILENAME".disk.brdps.dat"; # block reads per second
	  print $6 > FILENAME".disk.bwrps.dat"; # block writes per second
#	  n = "";
	}
      if (n == "kbmemfree")
	{ # This is the mem info
	  print $2 > FILENAME".mem.kbmemfree.dat"; # Amount of free memory available in kilobytes.
	  print $3 > FILENAME".mem.kbmemused.dat"; # Amount of used memory in kilobytes. This does not take into account memory used by the kernel itself.
	  print $4 > FILENAME".mem.memused.dat"; # Percentage of used memory.
#         It appears the kbmemshrd has been removed from the sysstat output - ntolia
#	  print $X > FILENAME".mem.kbmemshrd.dat"; # Amount of memory shared by the system in kilobytes.  Always zero with 2.4 kernels.
#	  print $5 > FILENAME".mem.kbbuffers.dat"; # Amount of memory used as buffers by the kernel in kilobytes.
	  print $6 > FILENAME".mem.kbcached.dat"; # Amount of memory used to cache data by the kernel in kilobytes.
#	  print $7 > FILENAME".mem.kbswpfree.dat"; # Amount of free swap space in kilobytes.
#	  print $8 > FILENAME".mem.kbswpused.dat"; # Amount of used swap space in kilobytes.
	  print $9 > FILENAME".mem.swpused.dat"; # Percentage of used swap space.
#	  n = "";
 	}
      if (n == "totsck")
	{ # This is the socket info
	  print $2 > FILENAME".sock.totsck.dat"; # Total number of used sockets.
	  print $3 > FILENAME".sock.tcpsck.dat"; # Number of TCP sockets currently in use.
#	  print $4 > FILENAME".sock.udpsck.dat"; # Number of UDP sockets currently in use.
#	  print $5 > FILENAME".sock.rawsck.dat"; # Number of RAW sockets currently in use.
#	  print $6 > FILENAME".sock.ip-frag.dat"; # Number of IP fragments currently in use.
#	  n = "";
 	}
    }
}
END {
  print " '" FILENAME "' done.";
}

#!/bin/awk -f

BEGIN {
  # It is not possible to define output file names here because
  # FILENAME is not define in the BEGIN section
  n = "";
  printf "Generating data files ...";
  network_max_bandwidth_in_byte = 10000000;
  network_max_packet_per_second = 1000000;
  last3 = 0;
  last4 = 0;
  last5 = 0;
  last6 = 0;
}
{
  if ($1 ~ /Average/)
    { # Skip the Average values
      n = "";
      next;
    }

  if ($2 ~ /all/)
    { # This is the cpu info
      print $3 > FILENAME".cpu.user.dat";
#	  print $4 > FILENAME".cpu.nice.dat";
      print $5 > FILENAME".cpu.system.dat";
#     print $6 > FILENAME".cpu.iowait.dat";
      print $7 > FILENAME".cpu.idle.dat";
      print 100-$7 > FILENAME".cpu.busy.dat";
    }
  if ($2 ~ /eth0/)
    { # This is the eth0 network info
      if ($3 > network_max_packet_per_second)
	print last3 > FILENAME".net.rxpck.dat"; # Total number of packets received per second.
      else
	{
	  last3 = $3;
	  print $3 > FILENAME".net.rxpck.dat"; # Total number of packets received per second.
	}
      if ($4 > network_max_packet_per_second)
	print last4 > FILENAME".net.txpck.dat"; # Total number of packets transmitted per second.
      else
	{
	  last4 = $4;
	  print $4 > FILENAME".net.txpck.dat"; # Total number of packets transmitted per second.
	}
      if ($5 > network_max_bandwidth_in_byte)
	print last5 > FILENAME".net.rxbyt.dat"; # Total number of bytes received per second.
      else
	{
	  last5 = $5;
	  print $5 > FILENAME".net.rxbyt.dat"; # Total number of bytes received per second.
	}
      if ($6 > network_max_bandwidth_in_byte)
	print last6 > FILENAME".net.txbyt.dat"; # Total number of bytes transmitted per second.
      else
	{
	  last6 = $6;
	  print $6 > FILENAME".net.txbyt.dat"; # Total number of bytes transmitted per second.
	}
#     print $7 > FILENAME".net.rxcmp.dat"; # Number of compressed packets received per second (for cslip etc.).
#     print $8 > FILENAME".net.txcmp.dat"; # Number of compressed packets transmitted per second.
#     print $9 > FILENAME".net.rxmcst.dat"; # Number of multicast packets received per second.
    }

  # Detect which is the next info to be parsed
  if ($2 ~ /proc|cswch|tps|kbmemfree|totsck/)
    {
      n = $2;
    }

  # Only get lines with numbers (real data !)
  if ($2 ~ /[0-9]/)
    {
      if (n == "proc/s")
	{ # This is the proc/s info
	  print $2 > FILENAME".proc.dat";
#	  n = "";
	}
      if (n == "cswch/s")
	{ # This is the context switches per second info
	  print $2 > FILENAME".ctxsw.dat";
#	  n = "";
	}
      if (n == "tps")
	{ # This is the disk info
	  print $2 > FILENAME".disk.tps.dat"; # total transfers per second
	  print $3 > FILENAME".disk.rtps.dat"; # read requests per second
	  print $4 > FILENAME".disk.wtps.dat"; # write requests per second
	  print $5 > FILENAME".disk.brdps.dat"; # block reads per second
	  print $6 > FILENAME".disk.bwrps.dat"; # block writes per second
#	  n = "";
	}
      if (n == "kbmemfree")
	{ # This is the mem info
	  print $2 > FILENAME".mem.kbmemfree.dat"; # Amount of free memory available in kilobytes.
	  print $3 > FILENAME".mem.kbmemused.dat"; # Amount of used memory in kilobytes. This does not take into account memory used by the kernel itself.
	  print $4 > FILENAME".mem.memused.dat"; # Percentage of used memory.
#         It appears the kbmemshrd has been removed from the sysstat output - ntolia
#	  print $X > FILENAME".mem.kbmemshrd.dat"; # Amount of memory shared by the system in kilobytes.  Always zero with 2.4 kernels.
#	  print $5 > FILENAME".mem.kbbuffers.dat"; # Amount of memory used as buffers by the kernel in kilobytes.
	  print $6 > FILENAME".mem.kbcached.dat"; # Amount of memory used to cache data by the kernel in kilobytes.
#	  print $7 > FILENAME".mem.kbswpfree.dat"; # Amount of free swap space in kilobytes.
#	  print $8 > FILENAME".mem.kbswpused.dat"; # Amount of used swap space in kilobytes.
	  print $9 > FILENAME".mem.swpused.dat"; # Percentage of used swap space.
#	  n = "";
 	}
      if (n == "totsck")
	{ # This is the socket info
	  print $2 > FILENAME".sock.totsck.dat"; # Total number of used sockets.
	  print $3 > FILENAME".sock.tcpsck.dat"; # Number of TCP sockets currently in use.
#	  print $4 > FILENAME".sock.udpsck.dat"; # Number of UDP sockets currently in use.
#	  print $5 > FILENAME".sock.rawsck.dat"; # Number of RAW sockets currently in use.
#	  print $6 > FILENAME".sock.ip-frag.dat"; # Number of IP fragments currently in use.
#	  n = "";
 	}
    }
}
END {
  print " '" FILENAME "' done.";
}


Update example

Update example

#!/usr/bin/env awk -f
#
# Samples a column of values.
#
# Usage: sample prob seed
#
# Input:
#   - a column of values
#
# Arguments:
#   - prob: success probability
#   - seed: pseudorandom number generator seed
#
# Output:
#   - sample values
#
# Example:
#   $ seq 1 100 | sample 0.1 $RANDOM

BEGIN {
	if (ARGC == 1) {
		prob = 0.5
	} else if (ARGC == 2) {
		prob = ARGV[1]
		ARGV[1] = ""
	} else {
		prob = ARGV[1]
		srand(ARGV[2])
		ARGV[1] = ""
		ARGV[2] = ""
	}
	# No filenames so force stdin:
	ARGV[ARGC++] = "-"
}
rand() <= prob {
	print $0
}

#!/usr/bin/env awk -f
#
# Samples a column of values.
#
# Usage: sample prob seed
#
# Input:
#   - a column of values
#
# Arguments:
#   - prob: success probability
#   - seed: pseudorandom number generator seed
#
# Output:
#   - sample values
#
# Example:
#   $ sample 0.1 $RANDOM

BEGIN {
	if (ARGC == 1) {
		prob = 0.5
	} else if (ARGC == 2) {
		prob = ARGV[1]
		ARGV[1] = ""
	} else {
		prob = ARGV[1]
		srand(ARGV[2])
		ARGV[1] = ""
		ARGV[2] = ""
	}
	# No filenames so force stdin:
	ARGV[ARGC++] = "-"
}
rand() <= prob {
	print $0
}


Accept 4.6.x-google

Accept 4.6.x-google

Change-Id: I4eadea9498dcb5f55bd5cc025d2866b39b486cc3

#*************************************************************************
#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# Copyright 2000, 2010 Oracle and/or its affiliates.
#
# OpenOffice.org - a multi-platform office productivity suite
#
# This file is part of OpenOffice.org.
#
# OpenOffice.org is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# only, as published by the Free Software Foundation.
#
# OpenOffice.org is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License version 3 for more details
# (a copy is included in the LICENSE file that accompanied this code).
#
# You should have received a copy of the GNU Lesser General Public License
# version 3 along with OpenOffice.org.  If not, see
# <http://www.openoffice.org/license.html>
# for a copy of the LGPLv3 License.
#
#*************************************************************************
BEGIN {
    CCversion = 0
    compiler_matched = 0
}
# Sun c++ compiler
/Sun WorkShop/ || /Forte Developer/ || /Sun/{
    compiler_matched = 1
    # version number right after "C++"
    x = match( $0, /C\+\+ .*/ )
    btwn = substr( $0, RSTART, RLENGTH)
    # extract version, whitespaces get striped later
    x = match( btwn, / .*\..*[ $\t]/)
    CCversion = substr( btwn, RSTART, RLENGTH)
}
# Microsoft c++ compiler
/Microsoft/ && /..\...\...../ {
    compiler_matched = 1
    # match on the format of the ms versions ( dd.dd.dddd )
    x = match( $0, /..\...\...../ )
    CCversion = substr( $0, RSTART, RLENGTH)
}
# Java
/java version/ || /openjdk version/ {
    compiler_matched = 1
    # match on the format of the java versions ( d[d].d[d].d[d] )
    x = match( $0, /[0-9]*\.[0-9]*\.[0-9]*/ )
    CCversion = substr( $0, RSTART, RLENGTH)
}
/^[0-9]*[.][0-9]*\r*$/ {
    if ( compiler_matched == 0 ) {
# need to blow to x.xx.xx for comparing
    	CCversion = $0 ".0"
    }
}
/^[0-9]*[.][0-9]*[.][0-9]*\r*$/ {
    if ( compiler_matched == 0 ) {
        CCversion = $0
    }
}
/^[0-9]*[.][0-9]*[.][0-9]*-[0-9a-z]*$/ {
    if ( compiler_matched == 0 ) {
        CCversion = substr($0, 0, index($0, "-") - 1)
    }
}
# NDK r8b has "4.6.x-google"
/^[0-9]*[.][0-9]*[.][a-z]*-[0-9a-z]*$/ {
    if ( compiler_matched == 0 ) {
	# Include the second period in the match so that
	# we will get a micro version of zero
	x = match(  $0, /^[0-9]*[.][0-9]*[.]/ )
        CCversion = substr($0, RSTART, RLENGTH)
    }
}
END {
    if ( num == "true" ) {
        tokencount = split (CCversion,vertoken,".")
        for ( i = 1 ; i <= tokencount ; i++ ) {
            printf ("%04d",vertoken[i] )
        }
    } else
        print CCversion
}

#*************************************************************************
#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# Copyright 2000, 2010 Oracle and/or its affiliates.
#
# OpenOffice.org - a multi-platform office productivity suite
#
# This file is part of OpenOffice.org.
#
# OpenOffice.org is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# only, as published by the Free Software Foundation.
#
# OpenOffice.org is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License version 3 for more details
# (a copy is included in the LICENSE file that accompanied this code).
#
# You should have received a copy of the GNU Lesser General Public License
# version 3 along with OpenOffice.org.  If not, see
# <http://www.openoffice.org/license.html>
# for a copy of the LGPLv3 License.
#
#*************************************************************************
BEGIN {
    CCversion = 0
    compiler_matched = 0
}
# Sun c++ compiler
/Sun WorkShop/ || /Forte Developer/ || /Sun/{
    compiler_matched = 1
    # version number right after "C++"
    x = match( $0, /C\+\+ .*/ )
    btwn = substr( $0, RSTART, RLENGTH)
    # extract version, whitespaces get striped later
    x = match( btwn, / .*\..*[ $\t]/)
    CCversion = substr( btwn, RSTART, RLENGTH)
}
# Microsoft c++ compiler
/Microsoft/ && /..\...\...../ {
    compiler_matched = 1
    # match on the format of the ms versions ( dd.dd.dddd )
    x = match( $0, /..\...\...../ )
    CCversion = substr( $0, RSTART, RLENGTH)
}
# Java
/java version/ || /openjdk version/ {
    compiler_matched = 1
    # match on the format of the java versions ( d[d].d[d].d[d] )
    x = match( $0, /[0-9]*\.[0-9]*\.[0-9]*/ )
    CCversion = substr( $0, RSTART, RLENGTH)
}
/^[0-9]*[.][0-9]*\r*$/ {
    if ( compiler_matched == 0 ) {
# need to blow to x.xx.xx for comparing
    	CCversion = $0 ".0"
    }
}
/^[0-9]*[.][0-9]*[.][0-9]*\r*$/ {
    if ( compiler_matched == 0 ) {
        CCversion = $0
    }
}
/^[0-9]*[.][0-9]*[.][0-9]*-[0-9a-z]*$/ {
    if ( compiler_matched == 0 ) {
        CCversion = substr($0, 0, index($0, "-") - 1)
    }
}
END {
    if ( num == "true" ) {
        tokencount = split (CCversion,vertoken,".")
        for ( i = 1 ; i <= tokencount ; i++ ) {
            printf ("%04d",vertoken[i] )
        }
    } else
        print CCversion
}


In c1, use season number in episodeTitle

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

# INVOCATION:
#       awk -v EPISODE_INFO_FILE=$EPISODE_INFO_FILE -v ERROR_FILE=$ERROR_FILE \
#           -f getBBoxEpisodesFrom-webscraper.awk $EPISODES_SORTED_FILE >$EPISODES_SPREADSHEET_FILE

# Field numbers
#    1 web-scraper-start-url  2 SsnURL     3 SsnURL-href    4 URL        5 Program_Title
#    6 Episode_Title          7 Year       8 Duration       9 Rating    10 Description

BEGIN {
    FS="\t"
    OFS="\t"
    print "Sortkey\tTitle\tSeasons\tEpisodes\tDuration\tYear(s)\tRating\tDescription"
    # For debugging variations in seasons and episodes format
    str = "date +%y%m%d.%H%M%S"
    str | getline longdate
    close str
    for ( i = 1; i <= 4; i++ ) {
        outfile = "BBox-scrapes/c" i "-" longdate ".csv"
        print "Type\t#\tSortkey\tURL\tshowTitle\tepisodeTitle\tYear(s)" > outfile
    }
}

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

/\/us\/movie\/|\/us\/episode\// {
    baseURL = $1
    URL = $4
    showTitle = $5
    episodeTitle = $6
    Years = $7
    Duration = $8
    Rating = $9
    Description = $10
    showtype = "S"

    if (match (episodeTitle, /^Season [[:digit:]]+|^Series [[:digit:]]+/))
        episodeSeason = substr(episodeTitle,8,RLENGTH-7)
    else
        episodeSeason = ""

    # Extract sortkey from URL
    nflds = split (URL,fld,"_")
    if (URL ~ /_S[[:digit:]]*_E[[:digit:]]*_[[:digit:]]*$/) {
        # /us/episode/35_Days_S3_E8_23851
        # Season 3, Episode 8
        seasonNumber = substr(fld[nflds-2], 2)
        episodeNumber = substr(fld[nflds-1], 2)
        # Give precedence to season number in episodeTitle over season number in URL
        if (episodeSeason != "" && seasonNumber+0 != episodeSeason+0) {
            revisedSeasons1 += 1
            shortURL = URL
            sub (/^\/us\/episode\//,"",shortURL)
            printf ("==> Fixed c1 season: %02d-%02d\t%s\t%s\n", \
                    seasonNumber, episodeSeason, shortURL, episodeTitle) >> ERROR_FILE
            seasonNumber = episodeSeason
        }
        sortkey = sprintf ("%s%02dE%03d", showtype, seasonNumber, episodeNumber)
        c1Num += 1
        outfile = "BBox-scrapes/c1-" longdate ".csv"
        printf ("c1\t%d\t%s\t%s\t%s\t%s\t%s\n",c1Num,sortkey,URL,showTitle,episodeTitle,Years) >> outfile
    } else if (URL ~ /_E[[:digit:]]*_[[:digit:]]*$/) {
        # /us/episode/35_Hours_E1_26129
        # 35 Hours, Episode 1
        revisedSeasons2 += 1
        seasonNumber = "99"
        episodeNumber = substr(fld[nflds-1], 2)
        sortkey = sprintf ("%s%02dE%03d", showtype, seasonNumber, episodeNumber)
        c2Num += 1
        outfile = "BBox-scrapes/c2-" longdate ".csv"
        printf ("c2\t%d\t%s\t%s\t%s\t%s\t%s\n",c2Num,sortkey,URL,showTitle,episodeTitle,Years) >> outfile
    } else if (URL ~ /Episode_[[:digit:]]*_[[:digit:]]*$/) {
        # /us/episode/Episode_5_26089
        # Season 4, Episode 5
        revisedSeasons3 += 1
        seasonNumber = "98"
        episodeNumber = substr(fld[nflds-1], 1)
        sortkey = sprintf ("%s%02dE%03d", showtype, seasonNumber, episodeNumber)
        c3Num += 1
        outfile = "BBox-scrapes/c3-" longdate ".csv"
        printf ("c3\t%d\t%s\t%s\t%s\t%s\t%s\n",c3Num,sortkey,URL,showTitle,episodeTitle,Years) >> outfile
    } else {
        revisedSeasons4 += 1
        URL ~ /^\/us\/movie\// ? showtype = "M" : showtype = "E"
        # /us/episode/Orkneys_Stone_Age_Temple_7144
        # A History of Ancient Britain Special, Orkney's Stone Age Temple
        sortkey = sprintf ("%s%05d", showtype, fld[nflds])
        c4Num += 1
        outfile = "BBox-scrapes/c4-" longdate ".csv"
        printf ("c4\t%d\t%s\t%s\t%s\t%s\t%s\n",c4Num,sortkey,URL,showTitle,episodeTitle,Years) >> outfile
    }

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

    # Special processing for some shows is needed in all getBBox*From-webscraper.awk scripts.
    # "Changed" message and counting revisedTitles are only in getBBoxProgramsFrom-webscraper.awk
    # so they are not repeated for each episode and each season.
    if (baseURL ~ /Maigret_15974$/) {
        showTitle = "Maigret (2016)"
    }
    if (baseURL ~ /Maigret_\(1992\)_15928$/) {
        showTitle = "Maigret (1992)"
    }
    if (baseURL ~ /Porridge_9509$/) {
        showTitle = "Porridge (1974-1977)"
    }
    if (baseURL ~ /Porridge_14747$/) {
        showTitle = "Porridge (2016-2017)"
    }

    # Get rid of redundant "Series #" or "Series #" from episodeTitle
    if (match (episodeTitle, /^Season [[:digit:]]*, |^Series [[:digit:]]*, /))
        episodeTitle = substr(episodeTitle,RLENGTH+1)

    # Get rid of initial/trailing quotes in showTitle
    # "BBC Three's ""Murdered By..."" Collection Trailer"
    if (showTitle ~ /^".*"$/) {
        revisedTitles += 1
        printf ("==> Fixed quoted title: www.britbox.com%s\n", URL) >> ERROR_FILE
        # printf ("    %s\n", showTitle) >> ERROR_FILE
        sub (/^"/,"",showTitle)
        sub (/"$/,"",showTitle)
        # printf ("    %s\n", showTitle) >> ERROR_FILE
    }

    # Non-existent fields in movies or episodes
    if (URL ~ /^\/us\/movie\//) {
        depth = "1"
        numSeasons = 1
        numEpisodes = 1
        fullTitle = showTitle
    } else {
        depth = "2"
        numSeasons = ""
        numEpisodes = ""
        fullTitle = showTitle ", " sortkey ", " episodeTitle
    }

    # Fix two consecutive double quotes in showTitle, but leave in fullTitle
    gsub ("\"\"","\"",showTitle)

    # Fix HEX quotes in Description
    gsub ("\xc2\x91","\"",Description)
    gsub ("\xc2\x92","\"",Description)

    # Create spreadsheet row in common format
    savedLine = sprintf \
        ("%s (%s) %s %s\t=HYPERLINK(\"https://www.britbox.com%s\";\"%s\"\)\t%s\t%s\t%s\t%s\t%s\t%s",\
         showTitle, depth, Years, sortkey, URL, fullTitle, numSeasons, numEpisodes, \
         HMS, Years, Rating, Description)

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

    print savedLine
    next
}

/\/us\/show\// {
    # Shouldn't get here
    badEpisodes += 1
    URL = $4
    nflds = split (URL,URLflds,"/")
    printf ("==> Upstream error in %s\n", FILENAME)  >> ERROR_FILE
    print "==> Found /us/show/ in episodes: " URLflds[nflds]  >> ERROR_FILE
}

END {
    printf ("In getBBoxEpisodesFrom-webscraper.awk\n") > "/dev/stderr"
    if (revisedTitles > 0 ) {
        revisedTitles == 1 ? field = "title" : field = "titles"
        printf ("    %2d %s revised in %s\n", revisedTitles, field, FILENAME) > "/dev/stderr"
    }
    if (revisedSeasons1 > 0 ) {
        revisedSeasons1 == 1 ? field = "season" : field = "seasons"
        printf ("    %3d c1 %s revised in %s\n", revisedSeasons1, field, FILENAME) > "/dev/stderr"
    }
    if (revisedSeasons2 > 0 ) {
        revisedSeasons2 == 1 ? field = "season" : field = "seasons"
        printf ("    %3d c2 %s revised in %s\n", revisedSeasons2, field, FILENAME) > "/dev/stderr"
    }
    if (revisedSeasons3 > 0 ) {
        revisedSeasons3 == 1 ? field = "season" : field = "seasons"
        printf ("    %3d c3 %s revised in %s\n", revisedSeasons3, field, FILENAME) > "/dev/stderr"
    }
    if (revisedSeasons4 > 0 ) {
        revisedSeasons4 == 1 ? field = "season" : field = "seasons"
        printf ("    %3d c4 %s revised in %s\n", revisedSeasons4, field, FILENAME) > "/dev/stderr"
    }
    if (badEpisodes > 0 ) {
        badEpisodes == 1 ? field = "URL" : field = "URLs"
        printf ("    %2d extra /show/ %s in %s\n", badEpisodes, field, FILENAME) > "/dev/stderr"
    }
}

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

# INVOCATION:
#       awk -v EPISODE_INFO_FILE=$EPISODE_INFO_FILE -v ERROR_FILE=$ERROR_FILE \
#           -f getBBoxEpisodesFrom-webscraper.awk $EPISODES_SORTED_FILE >$EPISODES_SPREADSHEET_FILE

# Field numbers
#    1 web-scraper-start-url  2 SsnURL     3 SsnURL-href    4 URL        5 Program_Title
#    6 Episode_Title          7 Year       8 Duration       9 Rating    10 Description

BEGIN {
    FS="\t"
    OFS="\t"
    print "Sortkey\tTitle\tSeasons\tEpisodes\tDuration\tYear(s)\tRating\tDescription"
    # For debugging variations in seasons and episodes format
    str = "date +%y%m%d.%H%M%S"
    str | getline longdate
    close str
    for ( i = 1; i <= 4; i++ ) {
        outfile = "BBox-scrapes/c" i "-" longdate ".csv"
        print "Type\t#\tSortkey\tURL\tshowTitle\tepisodeTitle\tYear(s)" > outfile
    }
}

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

/\/us\/movie\/|\/us\/episode\// {
    baseURL = $1
    URL = $4
    showTitle = $5
    episodeTitle = $6
    Years = $7
    Duration = $8
    Rating = $9
    Description = $10
    showtype = "S"

    # Extract sortkey from URL
    nflds = split (URL,fld,"_")
    if (URL ~ /_S[[:digit:]]*_E[[:digit:]]*_[[:digit:]]*$/) {
        # /us/episode/35_Days_S3_E8_23851
        # Season 3, Episode 8
        seasonNumber = substr(fld[nflds-2], 2)
        episodeNumber = substr(fld[nflds-1], 2)
        sortkey = sprintf ("%s%02dE%03d", showtype, seasonNumber, episodeNumber)
        c1Num += 1
        outfile = "BBox-scrapes/c1-" longdate ".csv"
        printf ("c1\t%d\t%s\t%s\t%s\t%s\t%s\n",c1Num,sortkey,URL,showTitle,episodeTitle,Years) >> outfile
    } else if (URL ~ /_E[[:digit:]]*_[[:digit:]]*$/) {
        # /us/episode/35_Hours_E1_26129
        # 35 Hours, Episode 1
        seasonNumber = "99"
        episodeNumber = substr(fld[nflds-1], 2)
        sortkey = sprintf ("%s%02dE%03d", showtype, seasonNumber, episodeNumber)
        c2Num += 2
        outfile = "BBox-scrapes/c2-" longdate ".csv"
        printf ("c2\t%d\t%s\t%s\t%s\t%s\t%s\n",c2Num,sortkey,URL,showTitle,episodeTitle,Years) >> outfile
    } else if (URL ~ /Episode_[[:digit:]]*_[[:digit:]]*$/) {
        # /us/episode/Episode_5_26089
        # Season 4, Episode 5
        seasonNumber = "98"
        episodeNumber = substr(fld[nflds-1], 1)
        sortkey = sprintf ("%s%02dE%03d", showtype, seasonNumber, episodeNumber)
        c3Num += 3
        outfile = "BBox-scrapes/c3-" longdate ".csv"
        printf ("c3\t%d\t%s\t%s\t%s\t%s\t%s\n",c3Num,sortkey,URL,showTitle,episodeTitle,Years) >> outfile
    } else {
        URL ~ /^\/us\/movie\// ? showtype = "M" : showtype = "E"
        # /us/episode/Orkneys_Stone_Age_Temple_7144
        # A History of Ancient Britain Special, Orkney's Stone Age Temple
        sortkey = sprintf ("%s%05d", showtype, fld[nflds])
        c4Num += 4
        outfile = "BBox-scrapes/c4-" longdate ".csv"
        printf ("c4\t%d\t%s\t%s\t%s\t%s\t%s\n",c4Num,sortkey,URL,showTitle,episodeTitle,Years) >> outfile
    }

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

    # Special processing for some shows is needed in all getBBox*From-webscraper.awk scripts.
    # "Changed" message and counting revisedTitles are only in getBBoxProgramsFrom-webscraper.awk
    # so they are not repeated for each episode and each season.
    if (baseURL ~ /Maigret_15974$/) {
        showTitle = "Maigret (2016)"
    }
    if (baseURL ~ /Maigret_\(1992\)_15928$/) {
        showTitle = "Maigret (1992)"
    }
    if (baseURL ~ /Porridge_9509$/) {
        showTitle = "Porridge (1974-1977)"
    }
    if (baseURL ~ /Porridge_14747$/) {
        showTitle = "Porridge (2016-2017)"
    }

    # Get rid of redundant "Series #" or "Series #" from episodeTitle
    if (match (episodeTitle, /^Season [[:digit:]]*, |^Series [[:digit:]]*, /))
        episodeTitle = substr(episodeTitle,RLENGTH+1)

    # Get rid of initial/trailing quotes in showTitle
    # "BBC Three's ""Murdered By..."" Collection Trailer"
    if (showTitle ~ /^".*"$/) {
        revisedTitles += 1
        printf ("==> Fixed quoted title: www.britbox.com%s\n", URL) >> ERROR_FILE
        # printf ("    %s\n", showTitle) >> ERROR_FILE
        sub (/^"/,"",showTitle)
        sub (/"$/,"",showTitle)
        # printf ("    %s\n", showTitle) >> ERROR_FILE
    }

    # Non-existent fields in movies or episodes
    if (URL ~ /^\/us\/movie\//) {
        depth = "1"
        numSeasons = 1
        numEpisodes = 1
        fullTitle = showTitle
    } else {
        depth = "2"
        numSeasons = ""
        numEpisodes = ""
        fullTitle = showTitle ", " sortkey ", " episodeTitle
    }

    # Fix two consecutive double quotes in showTitle, but leave in fullTitle
    gsub ("\"\"","\"",showTitle)

    # Fix HEX quotes in Description
    gsub ("\xc2\x91","\"",Description)
    gsub ("\xc2\x92","\"",Description)

    # Create spreadsheet row in common format
    savedLine = sprintf \
        ("%s (%s) %s %s\t=HYPERLINK(\"https://www.britbox.com%s\";\"%s\"\)\t%s\t%s\t%s\t%s\t%s\t%s",\
         showTitle, depth, Years, sortkey, URL, fullTitle, numSeasons, numEpisodes, \
         HMS, Years, Rating, Description)

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

    print savedLine
    next
}

/\/us\/show\// {
    # Shouldn't get here
    badEpisodes += 1
    URL = $4
    nflds = split (URL,URLflds,"/")
    printf ("==> Upstream error in %s\n", FILENAME)  >> ERROR_FILE
    print "==> Found /us/show/ in episodes: " URLflds[nflds]  >> ERROR_FILE
}

END {
    printf ("In getBBoxEpisodesFrom-webscraper.awk\n") > "/dev/stderr"
    if (revisedTitles > 0 ) {
        revisedTitles == 1 ? field = "title" : field = "titles"
        printf ("    %2d %s revised in %s\n", revisedTitles, field, FILENAME) > "/dev/stderr"
    }
    if (badEpisodes > 0 ) {
        badEpisodes == 1 ? field = "URL" : field = "URLs"
        printf ("    %2d extra /show/ %s in %s\n", badEpisodes, field, FILENAME) > "/dev/stderr"
    }
}


Switch minutes to HMS

Switch minutes to HMS

BEGIN {
    FS="[<>]"
}

# Eliminate unneeded constant fields
/^<item>/ {
    sub (/^<item>/,"")
    sub (/<\/item>$/,"")
    gsub (/<value>/,"")
    gsub (/<\/value>/,"")
}

/\/us\// {
    URL = $3
    showTitle = $7

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

# <URL>/us/episode/Vera_S3_E1_13502</URL><Title>Vera</Title><Subtitle>Season 3, Castles in The Air</Subtitle>\
# <Duration>88 min</Duration><Year>2013</Year><Rating>TV-MA</Rating>
/\/us\/episode\// {
    episodeTitle = $11
    episodeDuration = $15
    episodeYear = $19
    episodeRating = $23
    episodeDescription = $27

    nflds = split (URL,fld,"_")
    seasonNumber = fld[nflds - 2]
    sub (/S/,"",seasonNumber)
    episodeNumber = fld[nflds - 1]
    sub (/E/,"",episodeNumber)

    secs = 0
    mins = episodeDuration % 60
    hrs = int(episodeDuration / 60)
    episode_HMS = sprintf ("%02d:%02d:%02d", hrs, mins, secs)

    # Get rid of perfunctory "Season <n>, " from episode title
    episodePrefix = "Season " seasonNumber ", "
    sub (episodePrefix, "", episodeTitle)

    if (episodeNumber != "") {
        printf \
            ("%s S%02dE%02d\t=HYPERLINK(\"https://www.britbox.com%s\";\"%s, S%02dE%02d, %s\"\)\t\t%s\t%s\t%s\t%s\n", \
             showTitle, seasonNumber, episodeNumber, URL, showTitle, seasonNumber, episodeNumber, \
             episodeTitle, episode_HMS, episodeYear, episodeRating, episodeDescription)
    }
}

# <URL>/us/season/Vera_S8_15720</URL><Title>Vera</Title><SeasonNumber>8</SeasonNumber>\
# <Year>2018</Year><NumEpisodes>4</NumEpisodes>
/\/us\/season\// {
    seasonNumber = $11
    seasonYear = $15
    seasonEpisodes = $19

    if (seasonNumber != "") {
        printf \
            ("%s S%02d\t=HYPERLINK(\"https://www.britbox.com%s\";\"%s, Season %d\"\)\t%s\t\t%s\t%s\t%s\n", \
             showTitle, seasonNumber, URL, showTitle, seasonNumber, \
             seasonEpisodes, seasonYear, seasonRating, seasonDescription)
    }
}

BEGIN {
    FS="[<>]"
}

# Eliminate unneeded constant fields
/^<item>/ {
    sub (/^<item>/,"")
    sub (/<\/item>$/,"")
    gsub (/<value>/,"")
    gsub (/<\/value>/,"")
}

/\/us\// {
    URL = $3
    showTitle = $7

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

# <URL>/us/episode/Vera_S3_E1_13502</URL><Title>Vera</Title><Subtitle>Season 3, Castles in The Air</Subtitle>\
# <Duration>88 min</Duration><Year>2013</Year><Rating>TV-MA</Rating>
/\/us\/episode\// {
    episodeTitle = $11
    episodeDuration = $15
    episodeYear = $19
    episodeRating = $23
    episodeDescription = $27

    nfields = split (URL,fld,"_")
    seasonNumber = fld[nfields - 2]
    sub (/S/,"",seasonNumber)
    episodeNumber = fld[nfields - 1]
    sub (/E/,"",episodeNumber)

    # Get rid of perfunctory "Season <n>, " from episode title
    episodePrefix = "Season " seasonNumber ", "
    sub (episodePrefix, "", episodeTitle)

    if (episodeNumber != "") {
        printf \
            ("%s S%02dE%02d\t=HYPERLINK(\"https://www.britbox.com%s\";\"%s, S%02dE%02d, %s\"\)\t\t%s\t%s\t%s\t%s\n", \
             showTitle, seasonNumber, episodeNumber, URL, showTitle, seasonNumber, episodeNumber, \
             episodeTitle, episodeDuration, episodeYear, episodeRating, episodeDescription)
    }
}

# <URL>/us/season/Vera_S8_15720</URL><Title>Vera</Title><SeasonNumber>8</SeasonNumber>\
# <Year>2018</Year><NumEpisodes>4</NumEpisodes>
/\/us\/season\// {
    seasonNumber = $11
    seasonYear = $15
    seasonEpisodes = $19

    if (seasonNumber != "") {
        printf \
            ("%s S%02d\t=HYPERLINK(\"https://www.britbox.com%s\";\"%s, Season %d\"\)\t%s\t\t%s\t%s\t%s\n", \
             showTitle, seasonNumber, URL, showTitle, seasonNumber, \
             seasonEpisodes, seasonYear, seasonRating, seasonDescription)
    }
}