include locales inheriting patterns

include locales inheriting patterns

Change-Id: I06f4578f6d681064a8e41e4bef45a7034b7b5a64

#!/usr/bin/gawk -f
# -*- Mode: awk; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
#
# Copyright 2012 LibreOffice contributors.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# Usage: gawk -f list-dateacceptancepattern.awk *.xml [--html]
#
# Outputs three lists of locales, one with DateAcceptancePattern elements
# defined, one with inherited LC_FORMAT elements and thus date patterns, and
# one where no DateAcceptancePattern are defined.
#
# If --html is given as the last parameter, format output suitable for
# inclusion in HTML.

BEGIN {
    html = 0
    if (ARGV[ARGC-1] == "--html") {
        html = 1
        --ARGC
    }
    file = ""
    nopatterns = 0
    inheritedcount = 0
    if (html)
        print "
"
    else
        print ""
    print "Locales with explicit DateAcceptancePattern elements:"
    if (html)
        print "
"
}

file != FILENAME {
    if (file)
        endFile()
    file = FILENAME
    patterns = 0
    inherited = ""
}

/<DateAcceptancePattern>/ {
    split( $0, a, /<|>/ )
    pattern[patterns++] = a[3]
}

# pattern inherited as well
/<LC_FORMAT[^>]* ref="[^>"]+"[^>]*>/ {
    split( $0, a, /.* ref="|"/ )
    inherited = a[2]
}

END {
    if (file)
        endFile()
    if (html)
    {
        print "
"
        print "\n
"
    }
    else
        print "\n"

    print "Locales inheriting patterns:"
    if (html)
    {
        print "
"
        for (i=0; i<inheritedcount; ++i)
        {
            if (LocaleHasPatterns[InheritedList[i][1]])
                print InheritedList[i][0] " = " InheritedList[i][1] "    "
        }
        print "\n
"
    }
    else
    {
        for (i=0; i<inheritedcount; ++i)
        {
            if (LocaleHasPatterns[InheritedList[i][1]])
                print InheritedList[i][0] " = " InheritedList[i][1]
        }
        print "\n"
    }

    print "Locales without explicit DateAcceptancePattern elements:"
    if (html)
        print "
"
    print "(one implicit full date pattern is always generated)"
    if (html)
        print "
"
    if (html)
    {
        for (i=0; i<nopatterns; ++i)
        {
            print NoPatternList[i] "    "
        }
    }
    else
    {
        for (i=0; i<nopatterns; ++i)
        {
            print NoPatternList[i]
        }
    }
}

function endFile() {
    locale =  getLocale( file)
    LocaleHasPatterns[locale] = patterns
    if (patterns)
    {
        if (html)
        {
            print "
 " locale ":"
            print "
"
            for ( i=0; i<patterns; ++i )
            {
                print "
 " pattern[i]
            }
            print "
"
        }
        else
        {
            print locale ":"
            for ( i=0; i<patterns; ++i )
            {
                print "    " pattern[i]
            }
        }
    }
    else if (inherited)
    {
        InheritedList[inheritedcount][0] = locale
        InheritedList[inheritedcount][1] = inherited
        ++inheritedcount
    }
    else
        NoPatternList[nopatterns++] = locale
}

function getLocale( file, tmp ) {
    tmp = file
    gsub( /.*\//, "", tmp )
    gsub( /\.xml/, "", tmp )
    return tmp
}

# vim:set shiftwidth=4 softtabstop=4 expandtab:

#!/usr/bin/gawk -f
# -*- Mode: awk; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
#
# Copyright 2012 LibreOffice contributors.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# Usage: gawk -f list-dateacceptancepattern.awk *.xml [--html]
# Outputs two lists of locales, one with DateAcceptancePattern elements
# defined, and one where none are defined.
# If --html is given as the last parameter, format output suitable for
# inclusion in HTML.

BEGIN {
    html = 0
    if (ARGV[ARGC-1] == "--html") {
        html = 1
        --ARGC
    }
    file = ""
    nopatterns = 0
    if (html)
        print "
"
    else
        print ""
    print "Locales with explicit DateAcceptancePattern elements:"
    if (html)
        print "
"
}

file != FILENAME {
    if (file)
        endFile()
    file = FILENAME
    patterns = 0
    noFormatCode = 1
}

/<DateAcceptancePattern>/ {
    split( $0, a, /<|>/ )
    pattern[patterns++] = a[3]
}

# No FormatCode element means inherited LC_FORMAT ref=...
# hence pattern inherited as well.
/<FormatCode>/ {
    noFormatCode = 0
}

END {
    if (file)
        endFile()
    if (html)
    {
        print "
"
        print "\n
"
    }
    else
        print "\n"
    print "Locales without explicit DateAcceptancePattern elements:"
    if (html)
        print "
"
    print "(one implicit full date pattern is always generated)"
    if (html)
        print "
"
    if (html)
    {
        for (i=0; i<nopatterns; ++i)
        {
            print NoPatternList[i] "    "
        }
    }
    else
    {
        for (i=0; i<nopatterns; ++i)
        {
            print NoPatternList[i]
        }
    }
}

function endFile() {
    if (patterns)
    {
        if (html)
        {
            print "
 " getLocale( file) ":"
            print "
"
            for ( i=0; i<patterns; ++i )
            {
                print "
 " pattern[i]
            }
            print "
"
        }
        else
        {
            print getLocale( file) ":"
            for ( i=0; i<patterns; ++i )
            {
                print "    " pattern[i]
            }
        }
    }
    else if (!noFormatCode)
        NoPatternList[nopatterns++] = getLocale( file)
}

function getLocale( file, tmp ) {
    tmp = file
    gsub( /.*\//, "", tmp )
    gsub( /\.xml/, "", tmp )
    return tmp
}

# vim:set shiftwidth=4 softtabstop=4 expandtab:


Convert transcript to all lower case

Convert transcript to all lower case

git-svn-id: a8b04003a33e1d3e001b9d20391fa392a9f62d91@1411 94700074-3cef-4d97-a70e-9c8c206c02f5

# An awk script that takes the hub4/eval99 data and
# generates a set of S4 batch files and raw audio
# to allow a supervised mode of testing
#
# Requires 'sox' the sound exchange program to extract the data
# Change 'directory' as appropriate for your system.
#
# Usage:
#       gawk -f unbundleHub4 *.stm
#
#

BEGIN {
    directory = "/lab/speech/sphinx4/data/hub4/eval99/supervised/";
    system("rm -rf " directory );
    system("mkdir -p " directory);
    audioCount = 0;
}

#
# Display info about stm file (for debugging purposes)
#
function displaySummary() {
    print "========================";
    print "Sphere   : "  sphereName;
    print "Audio    : " audioName;
    print "Speaker  : "  speaker;
    print "start    : "  startTime;
    print "end      : "  endTime;
    print "duration : " duration;
    print "class    : " speechClass;
    print "sox cmd  : " soxCommand;
    print "xcrpt    : " transcript;
}

#
# Output the batch file, generate the audio file
#
function outputCommands() {
    printf("%s %s\n", audioName, transcript) >> batchName;
    printf("%s %s\n", audioName, transcript) >> allBatch;
    system(soxCommand);
}

#
# Determines if the current utterance is worth keeping
#
function isGoodUtterance() {
    return speechClass != "";
}

#
# The main processing loop, extract the pertinent info
# and excute the commands
#
$1 != ";;"  {
    audioCount++;
    source = $1;
    sphereName = $1 ".sph";
    speaker = $3;
    startTime = $4;
    endTime = $5
    duration = endTime - startTime;
    info = $6;

    split(info, infoArray, ",");
    speechClass = infoArray[2];
    transcript = "";
    for (i = 7; i <= NF; i++) {
        # markup is in parans, so drop that.
        if (index($i, "(")  == 0) {
            transcript = transcript " " $i;
        }
    }
    transcript = tolower(transcript);

    audioName = directory source "." audioCount "." speechClass ".raw";
    batchName = directory speechClass "_hub4.batch"
    allBatch = directory "all_hub4.batch"

    soxCommand =  "sox " sphereName " -r 16000 -s -w " audioName  \
        " trim " startTime " " duration

    if (isGoodUtterance()) {
        displaySummary();
        outputCommands();
    }
}

# An awk script that takes the hub4/eval99 data and
# generates a set of S4 batch files and raw audio
# to allow a supervised mode of testing
#
# Requires 'sox' the sound exchange program to extract the data
# Change 'directory' as appropriate for your system.
#
# Usage:
#       gawk -f unbundleHub4 *.stm
#
#

BEGIN {
    directory = "/lab/speech/sphinx4/data/hub4/eval99/supervised/";
    system("rm -rf " directory );
    system("mkdir -p " directory);
    audioCount = 0;
}

#
# Display info about stm file (for debugging purposes)
#
function displaySummary() {
    print "========================";
    print "Sphere   : "  sphereName;
    print "Audio    : " audioName;
    print "Speaker  : "  speaker;
    print "start    : "  startTime;
    print "end      : "  endTime;
    print "duration : " duration;
    print "class    : " speechClass;
    print "sox cmd  : " soxCommand;
    print "xcrpt    : " transcript;
}

#
# Output the batch file, generate the audio file
#
function outputCommands() {
    printf("%s %s\n", audioName, transcript) >> batchName;
    printf("%s %s\n", audioName, transcript) >> allBatch;
    system(soxCommand);
}

#
# Determines if the current utterance is worth keeping
#
function isGoodUtterance() {
    return speechClass != "";
}

#
# The main processing loop, extract the pertinent info
# and excute the commands
#
$1 != ";;"  {
    audioCount++;
    source = $1;
    sphereName = $1 ".sph";
    speaker = $3;
    startTime = $4;
    endTime = $5
    duration = endTime - startTime;
    info = $6;

    split(info, infoArray, ",");
    speechClass = infoArray[2];
    transcript = "";
    for (i = 7; i <= NF; i++) {
        # markup is in parans, so drop that.
        if (index($i, "(")  == 0) {
            transcript = transcript " " $i;
        }
    }

    audioName = directory source "." audioCount "." speechClass ".raw";
    batchName = directory speechClass "_hub4.batch"
    allBatch = directory "all_hub4.batch"

    soxCommand =  "sox " sphereName " -r 16000 -s -w " audioName  \
        " trim " startTime " " duration

    if (isGoodUtterance()) {
        displaySummary();
        outputCommands();
    }
}


remove the influence of LC_ALL environment locale

Fixes #3539

BEGIN {
    print "// Code generated by all_keywords.awk."
    print ""
    print "package parser"
    print ""
    print "var keywords = map[string]int{"

    # This variable will be associated with a pipe for intermediate output.
    sort = "env LC_ALL=C sort"
}

/^.*_keyword:/ {
  keyword = 1
  next
}

/^$/ {
  keyword = 0
}

{
  if (keyword && $NF != "") {
    printf("\"%s\": %s,\n", $NF, $NF) | sort
  }
}

END {
    # Flush the intermediate output by closing the pipe.
    close(sort)
    print "}"
}

BEGIN {
    print "// Code generated by all_keywords.awk."
    print ""
    print "package parser"
    print ""
    print "var keywords = map[string]int{"

    # This variable will be associated with a pipe for intermediate output.
    sort = "sort"
}

/^.*_keyword:/ {
  keyword = 1
  next
}

/^$/ {
  keyword = 0
}

{
  if (keyword && $NF != "") {
    printf("\"%s\": %s,\n", $NF, $NF) | sort
  }
}

END {
    # Flush the intermediate output by closing the pipe.
    close(sort)
    print "}"
}


Got rid of the funny for loop

Got rid of the funny for loop

BEGIN {
	# Constants
	# This does not work:
	#     RE_GET_NAME = /\(JNICALL \*[^)]+\)/
	RE_GET_NAME = "\\(JNICALL \\*[^)]+\\)"

	# Variables
	state = 0
	pending = ""
	declarations[0] = ""
	decl_index = 0

	# Beginning Stub
	print "#ifndef _GO_JNI_JNIENV_H_"
	print "#define _GO_JNI_JNIENV_H_"
	print ""
	print "#include <jni.h>"
	print ""
}

function save(declaration) {
	declarations[decl_index++] = declaration
}

function get_name(declaration) {
	match(declaration, RE_GET_NAME)
	return substr(declaration, RSTART + 10, RLENGTH - 11)
}

END {
	# Notice: "index" is a built-in function.
	# Notice: AWK arrays are associative, so j is needed.
	name = ""
	family = ""
	declaration = ""
	j = length(declarations)
	for (i = 0; i < j; ++i) {
		declaration = declarations[i]
		next_declaration = declarations[i+1]
		name = get_name(declaration)
		next_name = get_name(next_declaration)
		if (next_name == name "V") {
			print "// jni.h:"
			print "//     " declaration
			family = name
		} else if (name == family "V") {
			print "//     " declaration
		} else if (name == family "A") {
			print "//     " declaration
			sub(RE_GET_NAME, "_GoJni" name, declaration)
			gsub(/ *\* */, "* ", declaration)
			print declaration
			print ""
			family = ""
		} else {
			print "// jni.h:"
			print "//     " declaration
			sub(RE_GET_NAME, "_GoJni" name, declaration)
			gsub(/ *\* */, "* ", declaration)
			print declaration
			print ""
		}
	}

	# Ending Stub
	print "#endif // #ifndef _GO_JNI_JNIENV_H_"
}

/^struct JNINativeInterface_ {$/, /^};$/ {
	sub(/^[\t ]+/, "", $0)
	if (state == 0) {
		if ($0 !~ /JNICALL/) {
			next
		}
		if ($0 ~ /;$/) {
			save($0)
		} else {
			pending = $0
			state = 1
		}
	} else {
		pending = pending $0
		if ($0 ~ /,$/) {
			pending = pending " "
		} else if ($0 ~ /;$/) {
			save(pending)
			state = 0
		}
	}
}

BEGIN {
	# Constants
	# This does not work:
	#     RE_GET_NAME = /\(JNICALL \*[^)]+\)/
	RE_GET_NAME = "\\(JNICALL \\*[^)]+\\)"

	# Variables
	state = 0
	pending = ""
	declarations[0] = ""
	decl_index = 0

	# Beginning Stub
	print "#ifndef _GO_JNI_JNIENV_H_"
	print "#define _GO_JNI_JNIENV_H_"
	print ""
	print "#include <jni.h>"
	print ""
}

function save(declaration) {
	declarations[decl_index++] = declaration
}

function get_name(declaration) {
	match(declaration, RE_GET_NAME)
	return substr(declaration, RSTART + 10, RLENGTH - 11)
}

END {
	# Notice: "index" is a built-in function.
	# Notice: AWK arrays are associative, so j is needed.
	name = ""
	family = ""
	declaration = ""
	j = 0
	for (i in declarations) {
		declaration = declarations[j]
		next_declaration = declarations[j+1]
		name = get_name(declaration)
		next_name = get_name(next_declaration)
		if (next_name == name "V") {
			print "// jni.h:"
			print "//     " declaration
			family = name
		} else if (name == family "V") {
			print "//     " declaration
		} else if (name == family "A") {
			print "//     " declaration
			sub(RE_GET_NAME, "_GoJni" name, declaration)
			gsub(/ *\* */, "* ", declaration)
			print declaration
			print ""
			family = ""
		} else {
			print "// jni.h:"
			print "//     " declaration
			sub(RE_GET_NAME, "_GoJni" name, declaration)
			gsub(/ *\* */, "* ", declaration)
			print declaration
			print ""
		}
		j++
	}

	# Ending Stub
	print "#endif // #ifndef _GO_JNI_JNIENV_H_"
}

/^struct JNINativeInterface_ {$/, /^};$/ {
	sub(/^[\t ]+/, "", $0)
	if (state == 0) {
		if ($0 !~ /JNICALL/) {
			next
		}
		if ($0 ~ /;$/) {
			save($0)
		} else {
			pending = $0
			state = 1
		}
	} else {
		pending = pending $0
		if ($0 ~ /,$/) {
			pending = pending " "
		} else if ($0 ~ /;$/) {
			save(pending)
			state = 0
		}
	}
}


Skip invalid lines, probably should emit a warning

{env=""; if (NF<3) next; for (i=4; i<=NF; i++) {env=$i" "env}; print env "handlers/"$1 " " $2 " " $3;}


Include the dynamically generated constants in the brlapi_keys group. (dm)

git-svn-id: 30a5f035a20f1bc647618dbad7eea2a951b61b7c@2833 91a5dbb7-01b9-0310-9b5f-b28072856b6e

###############################################################################
# BRLTTY - A background process providing access to the console screen (when in
#          text mode) for a blind person using a refreshable braille display.
#
# Copyright (C) 1995-2006 by The BRLTTY Developers.
#
# BRLTTY comes with ABSOLUTELY NO WARRANTY.
#
# This is free software, placed under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation.  Please see the file COPYING for details.
#
# Web Page: http://mielke.cc/brltty/
#
# This software is maintained by Dave Mielke <dave@mielke.cc>.
###############################################################################

BEGIN {
  writeHeaderPrologue("BRLAPI_INCLUDED_CONSTANTS", "brlapi.h")
  beginDoxygenFile()
  print "/** \\ingroup brlapi_keys"
  print " * @{ */"
  print ""
}

END {
  print "/** @} */"
  print ""
  writeHeaderEpilogue()
}

function brlCommand(name, symbol, value, help) {
  writeMacroDefinition("BRLAPI_KEY_CMD_" name, "(BRLAPI_KEY_CMD(0) + " value ")", help)
}

function brlBlock(name, symbol, value, help) {
  if (name == "PASSCHAR") return
  if (name == "PASSKEY") return

  if (value ~ /^0[xX][0-9a-fA-F]+00$/) {
    writeMacroDefinition("BRLAPI_KEY_CMD_" name, "BRLAPI_KEY_CMD(" substr(value, 1, length(value)-2) ")", help)
  }
}

function brlKey(name, symbol, value, help) {
}

function brlFlag(name, symbol, value, help) {
  if (value ~ /^0[xX][0-9a-fA-F]+0000$/) {
    value = substr(value, 1, length(value)-4)
    if (name ~ /^CHAR_/) {
      name = substr(name, 6)
    } else {
      value = value "00"
    }
    value = "BRLAPI_KEY_FLG(" value ")"
  } else if (value ~ /^\(/) {
    gsub("BRL_FLG_", "BRLAPI_KEY_FLG_", value)
  } else {
    return
  }
  writeMacroDefinition("BRLAPI_KEY_FLG_" name, value, help)
}

function brlDot(number, symbol, value, help) {
  writeMacroDefinition("BRLAPI_DOT" number, value, help)
}

###############################################################################
# BRLTTY - A background process providing access to the console screen (when in
#          text mode) for a blind person using a refreshable braille display.
#
# Copyright (C) 1995-2006 by The BRLTTY Developers.
#
# BRLTTY comes with ABSOLUTELY NO WARRANTY.
#
# This is free software, placed under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation.  Please see the file COPYING for details.
#
# Web Page: http://mielke.cc/brltty/
#
# This software is maintained by Dave Mielke <dave@mielke.cc>.
###############################################################################

BEGIN {
  writeHeaderPrologue("BRLAPI_INCLUDED_CONSTANTS", "brlapi.h")
  beginDoxygenFile("BrlAPI Commans")
  beginDoxygenGroup("brlapi_commands", "Defines for BrlAPI Commands")
}

END {
  endDoxygenGroup()
  writeHeaderEpilogue()
}

function brlCommand(name, symbol, value, help) {
  writeMacroDefinition("BRLAPI_KEY_CMD_" name, "(BRLAPI_KEY_CMD(0) + " value ")", help)
}

function brlBlock(name, symbol, value, help) {
  if (name == "PASSCHAR") return
  if (name == "PASSKEY") return

  if (value ~ /^0[xX][0-9a-fA-F]+00$/) {
    writeMacroDefinition("BRLAPI_KEY_CMD_" name, "BRLAPI_KEY_CMD(" substr(value, 1, length(value)-2) ")", help)
  }
}

function brlKey(name, symbol, value, help) {
}

function brlFlag(name, symbol, value, help) {
  if (value ~ /^0[xX][0-9a-fA-F]+0000$/) {
    value = substr(value, 1, length(value)-4)
    if (name ~ /^CHAR_/) {
      name = substr(name, 6)
    } else {
      value = value "00"
    }
    value = "BRLAPI_KEY_FLG(" value ")"
  } else if (value ~ /^\(/) {
    gsub("BRL_FLG_", "BRLAPI_KEY_FLG_", value)
  } else {
    return
  }
  writeMacroDefinition("BRLAPI_KEY_FLG_" name, value, help)
}

function brlDot(number, symbol, value, help) {
  writeMacroDefinition("BRLAPI_DOT" number, value, help)
}


Use URN in rdf-n3.awk

Use URN in rdf-n3.awk

#!/usr/bin/awk -f
BEGIN {
    FS = "\t";

    LABEL         = "<http://www.w3.org/2000/01/rdf-schema#label>";
    TYPE          = "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>";

    CONCEPT       = "<http://www.w3.org/2004/02/skos/core#Concept>";
    LEXICALSENSE  = "<http://lemon-model.net/lemon#LexicalSense>";
    WORD          = "<http://lemon-model.net/lemon#Word>";
    FORM          = "<http://lemon-model.net/lemon#Form>";

    WRITTENREP    = "<http://lemon-model.net/lemon#writtenRep>";
    CANONICALFORM = "<http://lemon-model.net/lemon#canonicalForm>";
    BROADER       = "<http://lemon-model.net/lemon#broader>";
    NARROWER      = "<http://lemon-model.net/lemon#narrower>";
    SENSE         = "<http://lemon-model.net/lemon#sense>";
    ISSENSEOF     = "<http://lemon-model.net/lemon#isSenseOf>";
    REFERENCE     = "<http://lemon-model.net/lemon#reference>";
    ISREFERENCEOF = "<http://lemon-model.net/lemon#isReferenceOf>";
}
{
    nsenses = split($3, senses, ", ");
    nisas   = split($5, isas,   ", ");

    if (nsenses == 0 || nisas == 0) next;

    print "<urn:linked:c" $1 ">", TYPE,  CONCEPT,           ".";
    print "<urn:linked:c" $1 ">", LABEL, "\"synset" $1 "\"", ".";

    for (sense_id in senses) {
        sense = senses[sense_id];

        sub(":.*$", "", sense);

        if (!(sense in sindex)) {
            sindex[sense] = scount++;

            word = sense;
            gsub("_", " ",  word);
            sub("#.*$", "", word);

            if (!(word in windex)) {
                windex[word] = wcount++;

                print "<urn:linked:w" windex[word] ">", TYPE,          WORD,                             ".";
                print "<urn:linked:w" windex[word] ">", LABEL,         "\"" word "\"",                   ".";
                print "<urn:linked:f" windex[word] ">", TYPE,          FORM,                             ".";
                print "<urn:linked:f" windex[word] ">", LABEL,         "\"" word "\"",                   ".";
                print "<urn:linked:f" windex[word] ">", WRITTENREP,    "\"" word "\"",                   ".";
                print "<urn:linked:w" windex[word] ">", CANONICALFORM, "<urn:linked:f" windex[word] ">", ".";
            }

            print "<urn:linked:s" sindex[sense] ">", TYPE,          LEXICALSENSE,       ".";
            print "<urn:linked:s" sindex[sense] ">", LABEL,         "\"" sense "\"",    ".";
            print "<urn:linked:s" sindex[sense] ">", ISSENSEOF,     "<urn:linked:w" windex[word] ">",  ".";
            print "<urn:linked:w" windex[word] ">",  SENSE,         "<urn:linked:s" sindex[sense] ">", ".";
            print "<urn:linked:s" sindex[sense] ">", REFERENCE,     "<urn:linked:c" $1 ">",            ".";
            print "<urn:linked:c" $1 ">",            ISREFERENCEOF, "<urn:linked:s" sindex[sense] ">", ".";
        }

        for (isa_id in isas) {
            isa = isas[isa_id];

            sub(":.*$", "", isa);

            if (!(isa in sindex)) {
                sindex[isa] = scount++;

                word = isa;
                gsub("_", " ",  word);
                sub("#.*$", "", word);

                if (!(word in windex)) {
                    windex[word] = wcount++;

                    print "<urn:linked:w" windex[word] ">", TYPE,          WORD,              ".";
                    print "<urn:linked:w" windex[word] ">", LABEL,         "\"" word "\"",    ".";
                    print "<urn:linked:f" windex[word] ">", TYPE,          FORM,              ".";
                    print "<urn:linked:f" windex[word] ">", LABEL,         "\"" word "\"",    ".";
                    print "<urn:linked:f" windex[word] ">", WRITTENREP,    "\"" word "\"",    ".";
                    print "<urn:linked:w" windex[word] ">", CANONICALFORM, "<urn:linked:f" windex[word] ">", ".";
                }

                print "<urn:linked:s" sindex[isa] ">",  TYPE,      LEXICALSENSE,      ".";
                print "<urn:linked:s" sindex[isa] ">",  LABEL,     "\"" isa "\"",     ".";
                print "<urn:linked:s" sindex[isa] ">",  ISSENSEOF, "<urn:linked:w" windex[word] ">", ".";
                print "<urn:linked:w" windex[word] ">", SENSE,     "<urn:linked:s" sindex[isa] ">",  ".";
            }

            print "<urn:linked:s" sindex[sense] ">", BROADER,  "<urn:linked:s" sindex[isa] ">",   ".";
            print "<urn:linked:s" sindex[isa] ">",   NARROWER, "<urn:linked:s" sindex[sense] ">", ".";
        }
    }
}

#!/usr/bin/awk -f
BEGIN {
    FS = "\t";

    LABEL         = "<http://www.w3.org/2000/01/rdf-schema#label>";
    TYPE          = "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>";

    CONCEPT       = "<http://www.w3.org/2004/02/skos/core#Concept>";
    LEXICALSENSE  = "<http://lemon-model.net/lemon#LexicalSense>";
    WORD          = "<http://lemon-model.net/lemon#Word>";
    FORM          = "<http://lemon-model.net/lemon#Form>";

    WRITTENREP    = "<http://lemon-model.net/lemon#writtenRep>";
    CANONICALFORM = "<http://lemon-model.net/lemon#canonicalForm>";
    BROADER       = "<http://lemon-model.net/lemon#broader>";
    NARROWER      = "<http://lemon-model.net/lemon#narrower>";
    SENSE         = "<http://lemon-model.net/lemon#sense>";
    ISSENSEOF     = "<http://lemon-model.net/lemon#isSenseOf>";
    REFERENCE     = "<http://lemon-model.net/lemon#reference>";
    ISREFERENCEOF = "<http://lemon-model.net/lemon#isReferenceOf>";
}
{
    nsenses = split($3, senses, ", ");
    nisas   = split($5, isas,   ", ");

    if (nsenses == 0 || nisas == 0) next;

    print ":c" $1, TYPE, CONCEPT, ".";

    for (sense_id in senses) {
        sense = senses[sense_id];

        sub(":.*$", "", sense);

        if (!(sense in sindex)) {
            sindex[sense] = scount++;

            word = sense;
            gsub("_", " ",  word);
            sub("#.*$", "", word);

            if (!(word in windex)) {
                windex[word] = wcount++;

                print ":w" windex[word], TYPE,          WORD,              ".";
                print ":w" windex[word], LABEL,         "\"" word "\"",    ".";
                print ":f" windex[word], TYPE,          FORM,              ".";
                print ":f" windex[word], LABEL,         "\"" word "\"",    ".";
                print ":f" windex[word], WRITTENREP,    "\"" word "\"",    ".";
                print ":w" windex[word], CANONICALFORM, ":f" windex[word], ".";
            }

            print ":s" sindex[sense], TYPE,          LEXICALSENSE,       ".";
            print ":s" sindex[sense], LABEL,         "\"" sense "\"",    ".";
            print ":s" sindex[sense], ISSENSEOF,     ":w" windex[word],  ".";
            print ":w" windex[word],  SENSE,         ":s" sindex[sense], ".";
            print ":s" sindex[sense], REFERENCE,     ":c" $1,            ".";
            print ":c" $1,            ISREFERENCEOF, ":s" sindex[sense], ".";
        }

        for (isa_id in isas) {
            isa = isas[isa_id];

            sub(":.*$", "", isa);

            if (!(isa in sindex)) {
                sindex[isa] = scount++;

                word = isa;
                gsub("_", " ",  word);
                sub("#.*$", "", word);

                if (!(word in windex)) {
                    windex[word] = wcount++;

                    print ":w" windex[word], TYPE,          WORD,              ".";
                    print ":w" windex[word], LABEL,         "\"" word "\"",    ".";
                    print ":f" windex[word], TYPE,          FORM,              ".";
                    print ":f" windex[word], LABEL,         "\"" word "\"",    ".";
                    print ":f" windex[word], WRITTENREP,    "\"" word "\"",    ".";
                    print ":w" windex[word], CANONICALFORM, ":f" windex[word], ".";
                }

                print ":s" sindex[isa],  TYPE,      LEXICALSENSE,      ".";
                print ":s" sindex[isa],  LABEL,     "\"" isa "\"",     ".";
                print ":s" sindex[isa],  ISSENSEOF, ":w" windex[word], ".";
                print ":w" windex[word], SENSE,     ":s" sindex[isa],  ".";
            }

            print ":s" sindex[sense], BROADER,  ":s" sindex[isa],   ".";
            print ":s" sindex[isa],   NARROWER, ":s" sindex[sense], ".";
        }
    }
}


feat: Add plaintext option

feat: Add plaintext option

#!/usr/bin/awk -f
BEGIN {
	REPO_URL = getRepoURL()
	# Prefixes that determine whether a commit will be printed
	CHANGELOG_REGEX = "^(changelog|fix|docs|chore|feat|feature|refactor|update): "
	FS="|"
	# %D: tags
	# %s: commit message
	# %H: long hash
	# %h: short hash
	while ("git log --pretty='%D|%s|%H|%h'" | getline) {
		IS_GIT_TAG = length($1) && match($1, /tag:/)
		if (IS_GIT_TAG) {
			printTag($1)
		} else {
			printCommit($2, $3, $4)
		}

	}
}
function printTag(input) {
	# Cut out text up to tag
	sub(/.*tag: /, "", input)
	# Cut out text after tag
	sub(/,.*/, "", input)
	if (TYPE == "plain")
		printf("\n%s\n", input)
	else
		printf("\n## %s\n", input)
}
function printCommit(input, longHash, shortHash) {
	if ( match(input, CHANGELOG_REGEX) ) {
		sub(CHANGELOG_REGEX, "", input)
		if (TYPE == "plain")
			printf("\t- %s\n", input, makeCommitLink(REPO_URL, shortHash, longHash) )
		else
			printf("- %s (%s)\n", input, makeCommitLink(REPO_URL, shortHash, longHash) )
	}
}
function makeCommitLink(repoUrl, shortHash, longHash) {
	return ("[" shortHash "](" repoUrl "/commit/" longHash ")")
}
# Get Git repo URL
function getRepoURL() {
	"git config --get remote.upstream.url || git config --get remote.origin.url || git config --get remote.dev.url" | getline REPO_URL
	sub(/:/, "/", REPO_URL)
	sub(/git@/, "https://", REPO_URL)
	sub(/\.git/, "", REPO_URL)
	return REPO_URL
}

#!/usr/bin/awk -f
BEGIN {
	REPO_URL = getRepoURL()
	# Prefixes that determine whether a commit will be printed
	CHANGELOG_REGEX = "^(changelog|fix|docs|chore|feat|feature|refactor|update): "
	FS="|"
	# %D: tags
	# %s: commit message
	# %H: long hash
	# %h: short hash
	while ("git log --pretty='%D|%s|%H|%h'" | getline) {
		IS_GIT_TAG = length($1) && match($1, /tag:/)
		if (IS_GIT_TAG) {
			printTag($1)
		} else {
			printCommit($2, $3, $4)
		}

	}
}
function printTag(input) {
	# Cut out text up to tag
	sub(/.*tag: /, "", input)
	# Cut out text after tag
	sub(/,.*/, "", input)
	printf("\n## %s\n", input)
}
function printCommit(input, longHash, shortHash) {
	if ( match(input, CHANGELOG_REGEX) ) {
		sub(CHANGELOG_REGEX, "", input)
		printf("- %s (%s)\n", input, makeCommitLink(REPO_URL, shortHash, longHash) )
	}
}
function makeCommitLink(repoUrl, shortHash, longHash) {
	return ("[" shortHash "](" repoUrl "/commit/" longHash ")")
}
# Get Git repo URL
function getRepoURL() {
	"git config --get remote.upstream.url || git config --get remote.origin.url || git config --get remote.dev.url" | getline REPO_URL
	sub(/:/, "/", REPO_URL)
	sub(/git@/, "https://", REPO_URL)
	sub(/\.git/, "", REPO_URL)
	return REPO_URL
}


Include "First Look" episodes

Include "First Look" episodes

But don't add them to episode count or total duration

# Generate SHORT_SPREADSHEET by processing LONG_SPREADSHEET to calculate and include durations
#
# Generate a grand total duration by adding up the duration of episodes
# Generate totals for each show by adding up the duration of its episodes
# Update the number of episodes and the show's duration for any that are missing
# NOTE: Depends on file being sorted in reverse order

# INVOCATION:
#    sort -fu --key=4 --field-separator=\" $UNSORTED | tail -r | awk -v ERRORS=$ERRORS \
#        -v DURATION="$DURATION" -v LONG_SPREADSHEET=$LONG_SPREADSHEET -f calculateMHzShowDurations.awk |
#        tail -r >$SHORT_SPREADSHEET

# Field numbers returned by getMHzCatalogFromSitemap.awk
#    1 Title    2 Seasons    3 Episodes    4 Duration    5 Genre    6 Country    7 Language
#    8  Rating    9 Description

BEGIN {
    FS = "\t"
    OFS = "\t"
}

# No processing on header and other lines unrelated to shows
$1 !~ /=HYPERLINK/ {
    print
    print >> LONG_SPREADSHEET
    next
}

# No processing on seasons lines, but count them
$3 != "" {
    totalSeasons += 1
}

# Accumulate total time on any line that has a valid duration, it must be an episode
$4 != "" {
    # Are we a "First Look" episode? Print it, but don't count it as a real episode
    if ($1 ~ /, PR \| /) {
        # Don't use its duration
        $4 = ""
        print >> LONG_SPREADSHEET
        # Skip everything else
        next
    }
    # We have a normal episode
    episodesCounted += 1
    # print "==> episodesCounted = " episodesCounted > "/dev/stderr"
    print >> LONG_SPREADSHEET
    # Check all durations for strict HH:MM:SS format
    if ($4 !~ /^[[:digit:]]{1,2}:[[:digit:]]{2}:[[:digit:]]{2}$/) {
        print "==> Bad duration " $4 " in " $0 >> ERRORS
        next
    }
    # We have a valid duration, add to total
    split ($4, tm, ":")
    totalTime[3] += tm[3]
    totalTime[2] += tm[2] + int(totalTime[3] / 60)
    totalTime[1] += tm[1] + int(totalTime[2] / 60)
    totalTime[3] %= 60; totalTime[2] %= 60
    totalEpisodes += 1
    # Accumulate episode times to use when a show line is found
    secs += tm[3]
    mins += tm[2] + int(secs / 60)
    hrs += tm[1] + int(mins / 60)
    secs %= 60; mins %= 60
    next
}

# If a line has seasons, it must be a show - Add it to the short spreadsheet
# If it has no episodes or duration, update them from the running total
$2 != "" {
    if ($3 == "") {
        $3 = episodesCounted
        $4 = sprintf ("%02d:%02d:%02d", hrs, mins, secs)
        # Print line with episodesCounted and duration to short spreadsheet
        print
        # Don't print show duration to LONG_SPREADSHEET so durations column can be summed
        $4 = ""
        print >> LONG_SPREADSHEET
        totalShows += 1
        # Make sure there is no carryover
        secs = 0; mins = 0; hrs = 0;
        episodesCounted = 0
        next
    }
}

END {
    printf ("%02d:%02d:%02d\n", totalTime[1], totalTime[2], totalTime[3]) >> DURATION

    printf ("In calculateMHzShowDurations.awk\n") > "/dev/stderr"

    totalShows == 1 ? pluralShows = "show" : pluralShows = "shows"
    totalSeasons == 1 ? pluralSeasons = "season" : pluralSeasons = "seasons"
    totalEpisodes == 1 ? pluralEpisodes = "episode" : pluralEpisodes = "episodes"
    #
    printf ("    Processed %d %s, %d %s, %d %s\n", totalShows, pluralShows, totalSeasons, pluralSeasons,
            totalEpisodes, pluralEpisodes) > "/dev/stderr"
}

# Generate SHORT_SPREADSHEET by processing LONG_SPREADSHEET to calculate and include durations
#
# Generate a grand total duration by adding up the duration of episodes
# Generate totals for each show by adding up the duration of its episodes
# Update the number of episodes and the show's duration for any that are missing
# NOTE: Depends on file being sorted in reverse order

# INVOCATION:
#    sort -fu --key=4 --field-separator=\" $UNSORTED | tail -r | awk -v ERRORS=$ERRORS \
#        -v DURATION="$DURATION" -v LONG_SPREADSHEET=$LONG_SPREADSHEET -f calculateMHzShowDurations.awk |
#        tail -r >$SHORT_SPREADSHEET

# Field numbers returned by getMHzCatalogFromSitemap.awk
#    1 Title    2 Seasons    3 Episodes    4 Duration    5 Genre    6 Country    7 Language
#    8  Rating    9 Description

BEGIN {
    FS = "\t"
    OFS = "\t"
}

# No processing on header and other lines unrelated to shows
$1 !~ /=HYPERLINK/ {
    print
    print >> LONG_SPREADSHEET
    next
}

# No processing on seasons lines, but count them
$3 != "" {
    totalSeasons += 1
}

# Accumulate total time on any line that has a valid duration, it must be an episode
$4 != "" {
    print >> LONG_SPREADSHEET
    # Check all durations for strict HH:MM:SS format
    if ($4 !~ /^[[:digit:]]{1,2}:[[:digit:]]{2}:[[:digit:]]{2}$/) {
        # print "==> Bad duration " $4 " in " $0 >> ERRORS
        print "==> Bad duration " $4 " in " $0 >> ERRORS
        next
    } else {
        split ($4, tm, ":")
        totalTime[3] += tm[3]
        totalTime[2] += tm[2] + int(totalTime[3] / 60)
        totalTime[1] += tm[1] + int(totalTime[2] / 60)
        totalTime[3] %= 60; totalTime[2] %= 60
        totalEpisodes += 1
        # Accumulate episode times to use when a show line is found
        secs += tm[3]
        mins += tm[2] + int(secs / 60)
        hrs += tm[1] + int(mins / 60)
        secs %= 60; mins %= 60
        episodesCounted += 1
        # print "==> episodesCounted = " episodesCounted > "/dev/stderr"
        next
    }
}

# If a line has seasons, it must be a show - Add it to the short spreadsheet
# If it has no episodes or duration, update them from the running total
$2 != "" {
    if ($3 == "") {
        $3 = episodesCounted
        $4 = sprintf ("%02d:%02d:%02d", hrs, mins, secs)
        # Print line with episodesCounted and duration to short spreadsheet
        print
        # Don't print show duration to LONG_SPREADSHEET so durations icolumn can be summed
        $4 = ""
        print >> LONG_SPREADSHEET
        totalShows += 1
        # Make sure there is no carryover
        secs = 0; mins = 0; hrs = 0;
        episodesCounted = 0
        next
    }
}

END {
    printf ("%02d:%02d:%02d\n", totalTime[1], totalTime[2], totalTime[3]) >> DURATION

    printf ("In calculateMHzShowDurations.awk\n") > "/dev/stderr"

    totalShows == 1 ? pluralShows = "show" : pluralShows = "shows"
    totalSeasons == 1 ? pluralSeasons = "season" : pluralSeasons = "seasons"
    totalEpisodes == 1 ? pluralEpisodes = "episode" : pluralEpisodes = "episodes"
    #
    printf ("    Processed %d %s, %d %s, %d %s\n", totalShows, pluralShows, totalSeasons, pluralSeasons,
            totalEpisodes, pluralEpisodes) > "/dev/stderr"
}


Reassign testers.

Reassign testers.

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

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

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

{
  # add a loop to add line only if either status is _not_ manifest or ending year is gt or eq to contract year
  current_year = 2012
  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))) {
    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] == "") {
        if ((substr(p[pn],1,2) <= "American R")) {
          r[pn] = "5"
        } else if ((substr(p[pn],1,2) >= "American S") && (substr(p[pn],1,2) <= "Bz")) {
          r[pn] = "4"
        } else if ((substr(p[pn],1,2) >= "CA") && (substr(p[pn],1,2) <= "Pz")) {
          r[pn] = "5"
        } else if (substr(p[pn],1,1) >= "Q") {
          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] = "crawling"
  s[5] = "testing"
  s[6] = "notReady"
  s[7] = "released"
  s[8] = "down"
  s[9] = "superseded"
  s[10] = "zapped"
  sn = 11

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

  #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
# cat *.tdb | tdbout -t publisher,plugin,publisher:info[tester],status,year

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

{
  # add a loop to add line only if either status is _not_ manifest or ending year is gt or eq to contract year
  current_year = 2012
  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))) {
    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] == "") {
        if ((substr(p[pn],1,2) <= "American H")) {
          r[pn] = "5"
        } else if ((substr(p[pn],1,2) >= "American I") && (substr(p[pn],1,2) <= "Bz")) {
          r[pn] = "4"
        } else if ((substr(p[pn],1,2) >= "CA") && (substr(p[pn],1,2) <= "Nz")) {
          r[pn] = "5"
        } else if (substr(p[pn],1,1) >= "O") {
          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] = "crawling"
  s[5] = "testing"
  s[6] = "notReady"
  s[7] = "released"
  s[8] = "down"
  s[9] = "superseded"
  s[10] = "zapped"
  sn = 11

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

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


s/pckbd_keydesc_precisionbook/gsckbd_keydesc_precisionbook/g

#! /usr/bin/awk -f
#	$OpenBSD: makemap.awk,v 1.4 2005/05/06 18:04:37 mickey Exp $
#
# Copyright (c) 2003, Miodrag Vallat.
# All rights reserved.
#
# 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 GSC keyboard (gsckbd)
# layout tables, as almost all scancodes are completely different in the
# GSC world.
#

BEGIN {
	mapnum = 0
	declk = 0

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

	conv[1] = 118
	conv[2] = 22
	conv[3] = 30
	conv[4] = 38
	conv[5] = 37
	conv[6] = 46
	conv[7] = 54
	conv[8] = 61
	conv[9] = 62
	conv[10] = 70
	conv[11] = 69
	conv[12] = 78
	conv[13] = 85
	conv[14] = 102
	conv[15] = 13
	conv[16] = 21
	conv[17] = 29
	conv[18] = 36
	conv[19] = 45
	conv[20] = 44
	conv[21] = 53
	conv[22] = 60
	conv[23] = 67
	conv[24] = 68
	conv[25] = 77
	conv[26] = 84
	conv[27] = 91
	conv[28] = 90
	conv[29] = 20
	conv[30] = 28
	conv[31] = 27
	conv[32] = 35
	conv[33] = 43
	conv[34] = 52
	conv[35] = 51
	conv[36] = 59
	conv[37] = 66
	conv[38] = 75
	conv[39] = 76
	conv[40] = 82
	conv[41] = 14
	conv[42] = 18
	conv[43] = 93
	conv[44] = 26
	conv[45] = 34
	conv[46] = 33
	conv[47] = 42
	conv[48] = 50
	conv[49] = 49
	conv[50] = 58
	conv[51] = 65
	conv[52] = 73
	conv[53] = 74
	conv[54] = 89
	conv[55] = 124
	conv[56] = 17
	conv[57] = 41
	conv[58] = 88
	conv[59] = 5
	conv[60] = 6
	conv[61] = 4
	conv[62] = 12
	conv[63] = 3
	conv[64] = 11
	conv[65] = 131
	conv[66] = 10
	conv[67] = 1
	conv[68] = 9
	conv[69] = 119
	conv[70] = 126
	conv[71] = 108
	conv[72] = 117
	conv[73] = 125
	conv[74] = 123
	conv[75] = 107
	conv[76] = 115
	conv[77] = 116
	conv[78] = 121
	conv[79] = 105
	conv[80] = 114
	conv[81] = 122
	conv[82] = 112
	conv[83] = 113
	conv[86] = 97
	conv[87] = 120
	conv[88] = 7
	# 112 used by jp
	# 115 used by jp and br
	# 121 used by jp
	# 123 used by jp
	# 125 used by jp
	conv[127] = 127
	conv[156] = 218
	conv[157] = 148
	# Print Screen produces E0 12 E0 7C when pressed, then E0 7C E0 12
	# when released.  Ignore the E0 12 code and match only on E0 7C
	conv[170] = 252
	conv[181] = 202
	conv[184] = 145
	conv[198] = 254
	conv[199] = 236
	conv[200] = 245
	conv[201] = 253
	conv[203] = 235
	conv[205] = 244
	conv[207] = 233
	conv[208] = 242
	conv[209] = 250
	conv[210] = 240
	conv[211] = 113
}
NR == 1 {
	VERSION = $0
	gsub("\\$", "", VERSION)

	printf("/*\t\$OpenBSD\$\t*/\n\n")
	printf("/*\n")
	printf(" * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.\n")
	printf(" *\n")
	printf(" * generated from:\n")
	printf(" */\n")
	print VERSION

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

	next
}
$1 == "#define" || $1 == "#undef" {
	print $0
	next
}
# Don't bother converting the DEC LK layout.
/declk\[/ {
	declk = 1
	next
}
/declk/ {
	next
}
/pckbd/ {
	gsub("pckbd", "gsckbd", $0)
	print $0
	next
}
/KC/ {
	if (declk)
		next

	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 {
		printf("    KC(%d),", id)
		for (f = 2; f <= NF; f++) {
			printf("\t%s", $f)
		}
		printf("\n")
	}

	next
}
/};/ {
	if (declk) {
		declk = 0
		next
	}
	if (mapnum == 0) {
		# Add 241 to the US map...
		print "    KC(241),\tKS_Delete"
		print $0
		print "\nstatic const keysym_t gsckbd_keydesc_precisionbook[] = {"
		print "/*  pos      command\t\tnormal		shifted */"
		print "    KC(7),   KS_Cmd_Screen0,\tKS_f1,"
		print "    KC(15),  KS_Cmd_Screen1,\tKS_f2,"
		print "    KC(23),  KS_Cmd_Screen2,\tKS_f3,"
		print "    KC(31),  KS_Cmd_Screen3,\tKS_f4,"
		print "    KC(39),  KS_Cmd_Screen4,\tKS_f5,"
		print "    KC(47),  KS_Cmd_Screen5,\tKS_f6,"
		print "    KC(55),  KS_Cmd_Screen6,\tKS_f7,"
		print "    KC(63),  KS_Cmd_Screen7,\tKS_f8,"
		print "    KC(71),  KS_Cmd_Screen8,\tKS_f9,"
		print "    KC(79),  KS_Cmd_Screen9,\tKS_f10,"
		print "    KC(86),  KS_Cmd_Screen10,\tKS_f11,"
		print "    KC(94),  KS_Cmd_Screen11,\tKS_f12,"
		print "    KC(8),   KS_Cmd_Debugger,\tKS_Escape,"
		print "    KC(87),\t\t\tKS_Print_Screen,"
		print "    KC(92),\t\t\tKS_backslash,\tKS_bar,"
		print "    KC(96),\t\t\tKS_KP_Down,\tKS_KP_2,"
		print "    KC(95),\t\t\tKS_Hold_Screen,"
		print "    KC(97),\t\t\tKS_KP_Left,\tKS_KP_4,"
		print "    KC(98),\t\t\tKS_Pause, /* Break */"
		print "    KC(99),\t\t\tKS_KP_Up,\tKS_KP_8,"
		print "    KC(100),\t\t\tKS_KP_Delete,\tKS_KP_Decimal,"
		print "    KC(101),\t\t\tKS_KP_End,\tKS_KP_1,"
		print "    KC(103),\t\t\tKS_KP_Insert,\tKS_KP_0,"
		print "    KC(106),\t\t\tKS_KP_Right,\tKS_KP_6,"
		print "    KC(109),\t\t\tKS_KP_Next,\tKS_KP_3,"
		print "    KC(110),\t\t\tKS_KP_Home,\tKS_KP_7,"
		print "    KC(111),\t\t\tKS_KP_Prior,\tKS_KP_9,"
		print "    KC(20),\t\t\tKS_Caps_Lock,"
		print "    KC(17),  KS_Cmd1,\t\tKS_Control_L,"
		print "    KC(88),  KS_Cmd1,\t\tKS_Control_R,"
		print "    KC(25),  KS_Cmd2,\t\tKS_Alt_L,"
		print "    KC(57),  KS_Cmd2,\t\tKS_Alt_R,\tKS_Multi_key,"
		print "    KC(139),\t\t\tKS_Meta_L,"
		print "    KC(140),\t\t\tKS_Meta_R,"
	}
	mapnum++
}
/{0, 0, 0, 0}/ {
	printf("\tKBD_MAP(KB_US | KB_MACHDEP,\tKB_US,\tgsckbd_keydesc_precisionbook),\n");
}
{
	if (declk)
		next
	print $0
}

#! /usr/bin/awk -f
#	$OpenBSD: makemap.awk,v 1.3 2005/05/04 20:07:07 miod Exp $
#
# Copyright (c) 2003, Miodrag Vallat.
# All rights reserved.
#
# 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 GSC keyboard (gsckbd)
# layout tables, as almost all scancodes are completely different in the
# GSC world.
#

BEGIN {
	mapnum = 0
	declk = 0

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

	conv[1] = 118
	conv[2] = 22
	conv[3] = 30
	conv[4] = 38
	conv[5] = 37
	conv[6] = 46
	conv[7] = 54
	conv[8] = 61
	conv[9] = 62
	conv[10] = 70
	conv[11] = 69
	conv[12] = 78
	conv[13] = 85
	conv[14] = 102
	conv[15] = 13
	conv[16] = 21
	conv[17] = 29
	conv[18] = 36
	conv[19] = 45
	conv[20] = 44
	conv[21] = 53
	conv[22] = 60
	conv[23] = 67
	conv[24] = 68
	conv[25] = 77
	conv[26] = 84
	conv[27] = 91
	conv[28] = 90
	conv[29] = 20
	conv[30] = 28
	conv[31] = 27
	conv[32] = 35
	conv[33] = 43
	conv[34] = 52
	conv[35] = 51
	conv[36] = 59
	conv[37] = 66
	conv[38] = 75
	conv[39] = 76
	conv[40] = 82
	conv[41] = 14
	conv[42] = 18
	conv[43] = 93
	conv[44] = 26
	conv[45] = 34
	conv[46] = 33
	conv[47] = 42
	conv[48] = 50
	conv[49] = 49
	conv[50] = 58
	conv[51] = 65
	conv[52] = 73
	conv[53] = 74
	conv[54] = 89
	conv[55] = 124
	conv[56] = 17
	conv[57] = 41
	conv[58] = 88
	conv[59] = 5
	conv[60] = 6
	conv[61] = 4
	conv[62] = 12
	conv[63] = 3
	conv[64] = 11
	conv[65] = 131
	conv[66] = 10
	conv[67] = 1
	conv[68] = 9
	conv[69] = 119
	conv[70] = 126
	conv[71] = 108
	conv[72] = 117
	conv[73] = 125
	conv[74] = 123
	conv[75] = 107
	conv[76] = 115
	conv[77] = 116
	conv[78] = 121
	conv[79] = 105
	conv[80] = 114
	conv[81] = 122
	conv[82] = 112
	conv[83] = 113
	conv[86] = 97
	conv[87] = 120
	conv[88] = 7
	# 112 used by jp
	# 115 used by jp and br
	# 121 used by jp
	# 123 used by jp
	# 125 used by jp
	conv[127] = 127
	conv[156] = 218
	conv[157] = 148
	# Print Screen produces E0 12 E0 7C when pressed, then E0 7C E0 12
	# when released.  Ignore the E0 12 code and match only on E0 7C
	conv[170] = 252
	conv[181] = 202
	conv[184] = 145
	conv[198] = 254
	conv[199] = 236
	conv[200] = 245
	conv[201] = 253
	conv[203] = 235
	conv[205] = 244
	conv[207] = 233
	conv[208] = 242
	conv[209] = 250
	conv[210] = 240
	conv[211] = 113
}
NR == 1 {
	VERSION = $0
	gsub("\\$", "", VERSION)

	printf("/*\t\$OpenBSD\$\t*/\n\n")
	printf("/*\n")
	printf(" * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.\n")
	printf(" *\n")
	printf(" * generated from:\n")
	printf(" */\n")
	print VERSION

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

	next
}
$1 == "#define" || $1 == "#undef" {
	print $0
	next
}
# Don't bother converting the DEC LK layout.
/declk\[/ {
	declk = 1
	next
}
/declk/ {
	next
}
/pckbd/ {
	gsub("pckbd", "gsckbd", $0)
	print $0
	next
}
/KC/ {
	if (declk)
		next

	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 {
		printf("    KC(%d),", id)
		for (f = 2; f <= NF; f++) {
			printf("\t%s", $f)
		}
		printf("\n")
	}

	next
}
/};/ {
	if (declk) {
		declk = 0
		next
	}
	if (mapnum == 0) {
		# Add 241 to the US map...
		print "    KC(241),\tKS_Delete"
		print $0
		print "\nstatic const keysym_t pckbd_keydesc_precisionbook[] = {"
		print "/*  pos      command\t\tnormal		shifted */"
		print "    KC(7),   KS_Cmd_Screen0,\tKS_f1,"
		print "    KC(15),  KS_Cmd_Screen1,\tKS_f2,"
		print "    KC(23),  KS_Cmd_Screen2,\tKS_f3,"
		print "    KC(31),  KS_Cmd_Screen3,\tKS_f4,"
		print "    KC(39),  KS_Cmd_Screen4,\tKS_f5,"
		print "    KC(47),  KS_Cmd_Screen5,\tKS_f6,"
		print "    KC(55),  KS_Cmd_Screen6,\tKS_f7,"
		print "    KC(63),  KS_Cmd_Screen7,\tKS_f8,"
		print "    KC(71),  KS_Cmd_Screen8,\tKS_f9,"
		print "    KC(79),  KS_Cmd_Screen9,\tKS_f10,"
		print "    KC(86),  KS_Cmd_Screen10,\tKS_f11,"
		print "    KC(94),  KS_Cmd_Screen11,\tKS_f12,"
		print "    KC(8),   KS_Cmd_Debugger,\tKS_Escape,"
		print "    KC(87),\t\t\tKS_Print_Screen,"
		print "    KC(92),\t\t\tKS_backslash,\tKS_bar,"
		print "    KC(96),\t\t\tKS_KP_Down,\tKS_KP_2,"
		print "    KC(95),\t\t\tKS_Hold_Screen,"
		print "    KC(97),\t\t\tKS_KP_Left,\tKS_KP_4,"
		print "    KC(98),\t\t\tKS_Pause, /* Break */"
		print "    KC(99),\t\t\tKS_KP_Up,\tKS_KP_8,"
		print "    KC(100),\t\t\tKS_KP_Delete,\tKS_KP_Decimal,"
		print "    KC(101),\t\t\tKS_KP_End,\tKS_KP_1,"
		print "    KC(103),\t\t\tKS_KP_Insert,\tKS_KP_0,"
		print "    KC(106),\t\t\tKS_KP_Right,\tKS_KP_6,"
		print "    KC(109),\t\t\tKS_KP_Next,\tKS_KP_3,"
		print "    KC(110),\t\t\tKS_KP_Home,\tKS_KP_7,"
		print "    KC(111),\t\t\tKS_KP_Prior,\tKS_KP_9,"
		print "    KC(20),\t\t\tKS_Caps_Lock,"
		print "    KC(17),  KS_Cmd1,\t\tKS_Control_L,"
		print "    KC(88),  KS_Cmd1,\t\tKS_Control_R,"
		print "    KC(25),  KS_Cmd2,\t\tKS_Alt_L,"
		print "    KC(57),  KS_Cmd2,\t\tKS_Alt_R,\tKS_Multi_key,"
		print "    KC(139),\t\t\tKS_Meta_L,"
		print "    KC(140),\t\t\tKS_Meta_R,"
	}
	mapnum++
}
/{0, 0, 0, 0}/ {
	printf("\tKBD_MAP(KB_US | KB_MACHDEP,\tKB_US,\tpckbd_keydesc_precisionbook),\n");
}
{
	if (declk)
		next
	print $0
}


msg_parser.awk: including extra headers in the generated parser table.

darcs-hash:20061207172708-65a35-a9577448d54623753513bc66ff31012de9f35ba4.gz

#! /usr/bin/env awk
#
# This script recreates C files containing header-specific boilerplate stuff
# using the given list of headers (usually obtained from the master structure).
#
# It can also create a parser table.
#
# --------------------------------------------------------------------
#
# This file is part of the Sofia-SIP package
#
# Copyright (C) 2005 Nokia Corporation.
#
# Contact: Pekka Pessi <pekka.pessi@nokia.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; either version 2.1 of
# the License, or (at your option) any later version.
#
# This library 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 for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
#
# --------------------------------------------------------------------
#
# Contributor(s): Pekka.Pessi@nokia.com.
#
# Created: Fri Apr  6 12:59:59 2001 ppessi
#

BEGIN {
  "date '+%a %b %e %H:%M:%S %Y'" | getline date;

  ascii =			       \
     "                               " \
    " !\"#$%&'()*+,-./0123456789:;<=>?" \
    "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" \
    "`abcdefghijklmnopqrstuvwxyz{|}~";
  lower_case = "abcdefghijklmnopqrstuvwxyz";

  N=0;
  # Initialize these as arrays
  split("", symbols);
  split("", names);
  split("", comments);
  split("", hashes);
  split("", NAMES);
  split("", Comments);
  split("", COMMENTS);

  # indexed by the C name of the header
  split("", Since);		# Non-NUL if extra
  split("", Extra);		# Offset in extra headers

  template="";
  template1="";
  template2="";
  template3="";
  prefix="";
  tprefix="";
  extra=0;
  failed=0;
  success=0;

  extra_struct = "msg_pub_extra";

  ERRNO="error";
}

function name_hash (name)
{
  hash = 0;

  len = split(name, chars, "");

  for (i = 1; i <= len; i++) {
    c = tolower(chars[i]);
    hash = (38501 * (hash + index(ascii, c))) % 65536;
  }

  if (0) {
    # Test that hash algorithm above agrees with the C version
    pipe = ("../msg/msg_name_hash " name);
    pipe | getline;
    close(pipe);
    if (hash != $0) {
      print name ": " hash " != " $0 > "/dev/stderr";
    }
  }

  return hash "";
}

#
# Replace magic patterns in template p with header-specific values
#
function protos (name, comment, hash, since)
{
  NAME=toupper(name);
  sub(/.*[\/][*][*][<][ 	]*/, "", comment);
  sub(/[ 	]*[*][\/].*/, "", comment);
  sub(/[ 	]+/, " ", comment);

  short = match(comment, /[(][a-z][)]/);
  if (short) {
    short = substr(comment, short + 1, 1);
    sub(/ *[(][a-z][)]/, "", comment);
    shorts[index(lower_case, short)] = name;
  }

  do_hash = hash == 0;

  if (do_hash) {
    split(comment, parts, " ");
    name2 = tolower(parts[1]);
    gsub(/-/, "_", name2);
    if (name2 != name && name2 != tprefix "_" name) {
      print name " mismatch with " comment " (" real ")" > "/dev/stderr";
    }

    hash = name_hash(parts[1]);

    hashed[name] = hash;

    if (comment !~ /header/) {
      comment = comment " header";
    }
  }

  Comment = comment;
  if (!do_hash) {
    comment = tolower(comment);
  }
  COMMENT = toupper(comment);

  # Store the various forms into an array for the footer processing
  N++;
  hashes[N] = hash;
  names[N] = name;
  NAMES[N] = NAME;
  comments[N] = comment;
  Comments[N] = comment;
  COMMENTS[N] = COMMENT;

  symbols[name] = comment;
  if (since) {
    Since[name] = since;
    Extra[name] = extra++;
  }

  if (PR) {
    replace(template, hash, name, NAME, comment, Comment, COMMENT, since);
    replace(template1, hash, name, NAME, comment, Comment, COMMENT, since);
    replace(template2, hash, name, NAME, comment, Comment, COMMENT, since);
    replace(template3, hash, name, NAME, comment, Comment, COMMENT, since);
  }
}

function replace (p, hash, name, NAME, comment, Comment, COMMENT, since)
{
  #
  # Replace various forms of header name in template, print it out
  #
  if (p) {
    gsub(/#hash#/, hash, p);
    gsub(/#xxxxxx#/, name, p);
    gsub(/#XXXXXX#/, NAME, p);
    gsub(/#xxxxxxx_xxxxxxx#/, comment, p);
    gsub(/#Xxxxxxx_Xxxxxxx#/, Comment, p);
    gsub(/#XXXXXXX_XXXXXXX#/, COMMENT, p);

    if (since) {
      gsub(/#version#/, since, p);
    }
    else {
      # Remove line with #version#
      gsub(/\n[^\n]*#version#[^\n]*\n/, "\n", p);
    }

    print p > PR;
  }
}

#
# Repeat each line in the footer containing the magic replacement
# pattern with a instance of all headers
#
function process_footer (text)
{
  if (!match(tolower(text), /#(xxxxxx(x_xxxxxxx)?|hash)#/)) {
    n = length(text);
    while (substr(text, n) == "\n") {
      n = n - 1;
      text = substr(text, 1, n);
    }
    if (n > 0)
      print text > PR;
    return;
  }

  n = split(text, lines, RS);

  for (i = 1; i <= n; i++) {
    l = lines[i];
    if (match(tolower(l), /#(xxxxxx(x_xxxxxxx)?|hash)#/)) {
      for (j = 1; j <= N; j++) {
	l = lines[i];
	gsub(/#hash#/, hashes[j], l);
	gsub(/#xxxxxxx_xxxxxxx#/, comments[j], l);
	gsub(/#Xxxxxxx_Xxxxxxx#/, Comments[j], l);
	gsub(/#XXXXXXX_XXXXXXX#/, COMMENTS[j], l);
	gsub(/#xxxxxx#/, names[j], l);
	gsub(/#XXXXXX#/, NAMES[j], l);
	print l > PR;
      }
    } else {
      print l > PR;
    }
  }
}

#
# Read flags used with headers
#
function read_header_flags (flagfile,    line, tokens, name, value)
{
  while ((getline line < flagfile) > 0) {
    sub(/^[ \t]+/, "", line);
    sub(/[ \t]+$/, "", line);
    if (line ~ /^#/ || line ~ /^$/)
      continue;

    split(line, tokens,  /[ \t]*=[ \t]*/);
    name = tolower(tokens[1]);
    gsub(/-/, "_", name);
    gsub(/,/, " ", name);
    # print "FLAG: " name " = " tokens[2]

    if (header_flags[name]) {
      print flagfile ": already defined " tokens[1];
    }
    else if (!symbols[name]) {
      print flagfile ": unknown header \"" tokens[1] "\"";
    }
    else {
      header_flags[name] = tokens[2];
    }
  }
  close(flagfile);
}

#
# Read in templates
#
function templates ()
{
  if (!auto) {
    auto = FILENAME;

    if (!prefix) { prefix = module; }
    if (!tprefix) { tprefix = prefix; }

    sub(/.*\//, "", auto);
    auto = "This file is automatically generated from <" auto "> by msg_parser.awk.";

    if (PR) {
      if (TEMPLATE == "") { TEMPLATE = PR ".in"; }
      RS0=RS; RS="\f\n";
      if ((getline theader < TEMPLATE) < 0) {
	print ( TEMPLATE ": " ERRNO );
	failed=1;
        exit(1);
      }
      getline header < TEMPLATE;
      getline template < TEMPLATE;
      getline footer < TEMPLATE;

      if (TEMPLATE1) {
	if ((getline dummy < TEMPLATE1) < 0) {
	  print(TEMPLATE1 ": " ERRNO);
	  failed=1;
          exit(1);
        }
	getline dummy < TEMPLATE1;
	getline template1 < TEMPLATE1;
	getline dummy < TEMPLATE1;
      }

      if (TEMPLATE2) {
	if ((getline dummy < TEMPLATE2) < 0) {
	  print( TEMPLATE2 ": " ERRNO );
	  failed=1;
	  exit(1);
	}
	getline dummy < TEMPLATE2;
	getline template2 < TEMPLATE2;
	getline dummy < TEMPLATE2;
      }

      if (TEMPLATE3) {
	if ((getline dummy < TEMPLATE3) < 0) {
	  print( TEMPLATE3 ": " ERRNO );
	  failed=1;
	  exit(1);
	}
	getline dummy < TEMPLATE3;
	getline template3 < TEMPLATE3;
	getline dummy < TEMPLATE3;
      }

      sub(/.*[\/]/, "", TEMPLATE);
      gsub(/#AUTO#/, auto, header);
      gsub(/#DATE#/, "@date Generated: " date, header);
      if (PACKAGE_NAME) gsub(/#PACKAGE_NAME#/, PACKAGE_NAME, header);
      if (PACKAGE_VERSION) gsub(/#PACKAGE_VERSION#/, PACKAGE_VERSION, header);
      print header > PR;

      RS=RS0;
    }

    if (!NO_FIRST) {
      protos("request", "/**< Request line */", -1);
      protos("status", "/**< Status line */", -2);
    }
  }
}

/^#### EXTRA HEADER LIST STARTS HERE ####$/ { HLIST=1; templates(); }
HLIST && /^[a-z]/ { protos($1, $0, 0, $2); headers[total++] = $1; }
/^#### EXTRA HEADER LIST ENDS HERE ####$/ { HLIST=0;  }

/^ *\/\* === Headers start here \*\// { in_header_list=1;  templates(); }
/^ *\/\* === Headers end here \*\// { in_header_list=0; }

PT && /^ *\/\* === Hash headers end here \*\// { in_header_list=0;}

in_header_list && /^  (sip|rtsp|http|msg|mp)_[a-z_0-9]+_t/ {
  n=$0
  sub(/;.*$/, "", n);
  sub(/^ *(sip|rtsp|http|msg|mp)_[a-z0-9_]*_t[ 	]*/, "", n);
  sub(/^[*](sip|rtsp|http|msg|mp)_/, "", n);

  if ($0 !~ /[\/][*][*][<]/) {
    getline;
  }
  if ($0 !~ /[\/][*][*][<]/) {
    printf "msg_protos.awk: header %s is malformed\n", n;
    failed=1;
    exit 1;
  }

  if (!NO_MIDDLE)
    protos(n, $0, 0);

  headers[total++] = n;
}

END {
  if (failed) { exit };

  if (!NO_LAST) {
    protos("unknown", "/**< Unknown headers */", -3);
    protos("error", "/**< Erroneous headers */", -4);
    protos("separator", "/**< Separator line between headers and payload */", -5);
    protos("payload", "/**< Message payload */", -6);
    if (multipart)
      protos("multipart", "/**< Multipart payload */", -7);
  }

  if (PR) {
    process_footer(footer);
  }
  else if (PT) {
    if (FLAGFILE)
      read_header_flags(FLAGFILE);

    if (TEMPLATE == "") { TEMPLATE = PT ".in"; }
    RS0=RS; RS="\n";
    getline theader < TEMPLATE;
    getline header < TEMPLATE;
    getline template < TEMPLATE;
    getline footer < TEMPLATE;
    RS=RS0;

    sub(/.*[\/]/, "", TEMPLATE);
    gsub(/#AUTO#/, auto, header);
    gsub(/#DATE#/, "@date Generated: " date, header);
    print header > PT;

    if (MC_SHORT_SIZE) {
      printf("static msg_href_t const " \
	     "%s_short_forms[MC_SHORT_SIZE] = \n{\n",
	     module) > PT;

      for (i = 1; i <= MC_SHORT_SIZE; i = i + 1) {
	c = (i == MC_SHORT_SIZE) ? "" : ",";
	if (i in shorts) {
	  n = shorts[i];
        flags = header_flags[n]; if (flags) flags = ",\n      " flags;

	  printf("  { /* %s */ %s_%s_class, offsetof(%s_t, %s_%s)%s }%s\n",
		 substr(lower_case, i, 1),
		 tprefix, n, module, prefix, n, flags, c)	\
	    > PT;
	}
	else {
	  printf("  { NULL }%s\n", c) \
	    > PT;
	}
      }
      printf("};\n\n") > PT;
    }

    # printf("extern msg_hclass_t msg_multipart_class[];\n\n") > PT;

    if (extra > 0) {
      printf("struct %s {\n", extra_struct) > PT;
      printf("  %s_t base;\n", module) > PT;
      printf("  msg_header_t *extra[%u];\n", extra) > PT;
      printf("};\n\n") > PT;
    }

    printf("msg_mclass_t const %s_mclass[1] = \n{{\n", module) > PT;
    printf("# if defined (%s_HCLASS)\n", toupper(module)) > PT;
    printf("  %s_HCLASS,\n", toupper(module)) > PT;
    printf("#else\n") > PT;
    printf("  {{ 0 }},\n") > PT;
    printf("#endif\n") > PT;
    printf("  %s_VERSION_CURRENT,\n", toupper(module)) > PT;
    printf("  %s_PROTOCOL_TAG,\n", toupper(module)) > PT;
    printf("#if defined (%s_PARSER_FLAGS)\n", toupper(module)) > PT;
    printf("  %s_PARSER_FLAGS,\n", toupper(module)) > PT;
    printf("#else\n") > PT;
    printf("  0,\n") > PT;
    printf("#endif\n") > PT;
    printf("  sizeof(%s_t),\n", module) > PT;
    printf("  %s_extract_body,\n", module) > PT;

    len = split("request status separator payload unknown error", unnamed, " ");

    for (i = 1; i <= len; i++) {
      printf("  {{ %s_%s_class, offsetof(%s_t, %s_%s) }},\n",
	     tprefix, unnamed[i], module, prefix, unnamed[i]) > PT;
    }
    if (multipart) {
      printf("  {{ %s_class, offsetof(%s_t, %s_multipart) }},\n",
	     multipart, module, prefix) > PT;
    } else {
      printf("  {{ NULL, 0 }},\n") > PT;
    }
    if (MC_SHORT_SIZE) {
      printf("  %s_short_forms, \n", module) > PT;
    }
    else {
      printf("  NULL, \n") > PT;
    }
    printf("  %d, %d, \n", MC_HASH_SIZE, total) > PT;
    printf("  {\n") > PT;

    for (i = 0; i < total; i++) {
      n = headers[i];
      h = hashed[n];

      if (h < 0)
	continue;

      j = h % MC_HASH_SIZE; if (j == -0) j = 0;

      for (; j in header_hash;) {
	if (++j == MC_HASH_SIZE) {
	  j = 0;
	}
      }

      header_hash[j] = n;
    }

    for (i = 0; i < MC_HASH_SIZE; i++) {
      c = (i + 1 == MC_HASH_SIZE) ? "" : ",";
      if (i in header_hash) {
	n = header_hash[i];
        flags = header_flags[n]; if (flags) flags = ",\n      " flags;

	if (Since[n]) {
	  printf("    { %s_%s_class, offsetof(struct %s, extra[%u])%s }%s\n",
		 tprefix, n, extra_struct, Extra[n], flags, c) > PT;
	}
	else {
	  printf("    { %s_%s_class, offsetof(%s_t, %s_%s)%s }%s\n",
		 tprefix, n, module, prefix, n, flags, c) > PT;
	}
      }
      else {
	printf("    { NULL, 0 }%s\n", c) > PT;
      }
    }
    printf("  }\n}};\n\n") > PT;
  }

  exit success;
}

#! /usr/bin/env awk
#
# This script recreates C files containing header-specific boilerplate stuff
# using the given list of headers (usually obtained from the master structure).
#
# It can also create a parser table.
#
# --------------------------------------------------------------------
#
# This file is part of the Sofia-SIP package
#
# Copyright (C) 2005 Nokia Corporation.
#
# Contact: Pekka Pessi <pekka.pessi@nokia.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; either version 2.1 of
# the License, or (at your option) any later version.
#
# This library 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 for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
#
# --------------------------------------------------------------------
#
# Contributor(s): Pekka.Pessi@nokia.com.
#
# Created: Fri Apr  6 12:59:59 2001 ppessi
#

BEGIN {
  "date '+%a %b %e %H:%M:%S %Y'" | getline date;

  ascii =			       \
     "                               " \
    " !\"#$%&'()*+,-./0123456789:;<=>?" \
    "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" \
    "`abcdefghijklmnopqrstuvwxyz{|}~";
  lower_case = "abcdefghijklmnopqrstuvwxyz";

  N=0;
  # Initialize these as arrays
  split("", symbols);
  split("", names);
  split("", comments);
  split("", hashes);
  split("", NAMES);
  split("", Comments);
  split("", COMMENTS);

  template="";
  template1="";
  template2="";
  template3="";
  prefix="";
  tprefix="";
  failed=0;
  success=0;

  ERRNO="error";
}

function name_hash (name)
{
  hash = 0;

  len = split(name, chars, "");

  for (i = 1; i <= len; i++) {
    c = tolower(chars[i]);
    hash = (38501 * (hash + index(ascii, c))) % 65536;
  }

  if (0) {
    # Test that hash algorithm above agrees with the C version
    pipe = ("../msg/msg_name_hash " name);
    pipe | getline;
    close(pipe);
    if (hash != $0) {
      print name ": " hash " != " $0 > "/dev/stderr";
    }
  }

  return hash "";
}

#
# Replace magic patterns in template p with header-specific values
#
function protos (name, comment, hash, since)
{
  NAME=toupper(name);
  sub(/.*[\/][*][*][<][ 	]*/, "", comment);
  sub(/[ 	]*[*][\/].*/, "", comment);
  sub(/[ 	]+/, " ", comment);

  short = match(comment, /[(][a-z][)]/);
  if (short) {
    short = substr(comment, short + 1, 1);
    sub(/ *[(][a-z][)]/, "", comment);
    shorts[index(lower_case, short)] = name;
  }

  do_hash = hash == 0;

  if (do_hash) {
    split(comment, parts, " ");
    name2 = tolower(parts[1]);
    gsub(/-/, "_", name2);
    if (name2 != name && name2 != tprefix "_" name) {
      print name " mismatch with " comment " (" real ")" > "/dev/stderr";
    }

    hash = name_hash(parts[1]);

    hashed[name] = hash;

    if (comment !~ /header/) {
      comment = comment " header";
    }
  }

  Comment = comment;
  if (!do_hash) {
    comment = tolower(comment);
  }
  COMMENT = toupper(comment);

  # Store the various forms into an array for the footer processing
  N++;
  hashes[N] = hash;
  names[N] = name;
  NAMES[N] = NAME;
  comments[N] = comment;
  Comments[N] = comment;
  COMMENTS[N] = COMMENT;

  symbols[name] = comment;

  if (PR) {
    replace(template, hash, name, NAME, comment, Comment, COMMENT, since);
    replace(template1, hash, name, NAME, comment, Comment, COMMENT, since);
    replace(template2, hash, name, NAME, comment, Comment, COMMENT, since);
    replace(template3, hash, name, NAME, comment, Comment, COMMENT, since);
  }
}

function replace (p, hash, name, NAME, comment, Comment, COMMENT, since)
{
  #
  # Replace various forms of header name in template, print it out
  #
  if (p) {
    gsub(/#hash#/, hash, p);
    gsub(/#xxxxxx#/, name, p);
    gsub(/#XXXXXX#/, NAME, p);
    gsub(/#xxxxxxx_xxxxxxx#/, comment, p);
    gsub(/#Xxxxxxx_Xxxxxxx#/, Comment, p);
    gsub(/#XXXXXXX_XXXXXXX#/, COMMENT, p);

    if (since) {
      gsub(/#version#/, since, p);
    }
    else {
      # Remove line with #version#
      gsub(/\n[^\n]*#version#[^\n]*\n/, "\n", p);
    }

    print p > PR;
  }
}

#
# Repeat each line in the footer containing the magic replacement
# pattern with a instance of all headers
#
function process_footer (text)
{
  if (!match(tolower(text), /#(xxxxxx(x_xxxxxxx)?|hash)#/)) {
    n = length(text);
    while (substr(text, n) == "\n") {
      n = n - 1;
      text = substr(text, 1, n);
    }
    if (n > 0)
      print text > PR;
    return;
  }

  n = split(text, lines, RS);

  for (i = 1; i <= n; i++) {
    l = lines[i];
    if (match(tolower(l), /#(xxxxxx(x_xxxxxxx)?|hash)#/)) {
      for (j = 1; j <= N; j++) {
	l = lines[i];
	gsub(/#hash#/, hashes[j], l);
	gsub(/#xxxxxxx_xxxxxxx#/, comments[j], l);
	gsub(/#Xxxxxxx_Xxxxxxx#/, Comments[j], l);
	gsub(/#XXXXXXX_XXXXXXX#/, COMMENTS[j], l);
	gsub(/#xxxxxx#/, names[j], l);
	gsub(/#XXXXXX#/, NAMES[j], l);
	print l > PR;
      }
    } else {
      print l > PR;
    }
  }
}

#
# Read flags used with headers
#
function read_header_flags (flagfile,    line, tokens, name, value)
{
  while ((getline line < flagfile) > 0) {
    sub(/^[ \t]+/, "", line);
    sub(/[ \t]+$/, "", line);
    if (line ~ /^#/ || line ~ /^$/)
      continue;

    split(line, tokens,  /[ \t]*=[ \t]*/);
    name = tolower(tokens[1]);
    gsub(/-/, "_", name);
    gsub(/,/, " ", name);
    # print "FLAG: " name " = " tokens[2]

    if (header_flags[name]) {
      print flagfile ": already defined " tokens[1];
    }
    else if (!symbols[name]) {
      print flagfile ": unknown header \"" tokens[1] "\"";
    }
    else {
      header_flags[name] = tokens[2];
    }
  }
  close(flagfile);
}

#
# Read in templates
#
function templates ()
{
  if (!auto) {
    auto = FILENAME;

    if (!prefix) { prefix = module; }
    if (!tprefix) { tprefix = prefix; }

    sub(/.*\//, "", auto);
    auto = "This file is automatically generated from <" auto "> by msg_parser.awk.";

    if (PR) {
      if (TEMPLATE == "") { TEMPLATE = PR ".in"; }
      RS0=RS; RS="\f\n";
      if ((getline theader < TEMPLATE) < 0) {
	print ( TEMPLATE ": " ERRNO );
	failed=1;
        exit(1);
      }
      getline header < TEMPLATE;
      getline template < TEMPLATE;
      getline footer < TEMPLATE;

      if (TEMPLATE1) {
	if ((getline dummy < TEMPLATE1) < 0) {
	  print(TEMPLATE1 ": " ERRNO);
	  failed=1;
          exit(1);
        }
	getline dummy < TEMPLATE1;
	getline template1 < TEMPLATE1;
	getline dummy < TEMPLATE1;
      }

      if (TEMPLATE2) {
	if ((getline dummy < TEMPLATE2) < 0) {
	  print( TEMPLATE2 ": " ERRNO );
	  failed=1;
	  exit(1);
	}
	getline dummy < TEMPLATE2;
	getline template2 < TEMPLATE2;
	getline dummy < TEMPLATE2;
      }

      if (TEMPLATE3) {
	if ((getline dummy < TEMPLATE3) < 0) {
	  print( TEMPLATE3 ": " ERRNO );
	  failed=1;
	  exit(1);
	}
	getline dummy < TEMPLATE3;
	getline template3 < TEMPLATE3;
	getline dummy < TEMPLATE3;
      }

      sub(/.*[\/]/, "", TEMPLATE);
      gsub(/#AUTO#/, auto, header);
      gsub(/#DATE#/, "@date Generated: " date, header);
      if (PACKAGE_NAME) gsub(/#PACKAGE_NAME#/, PACKAGE_NAME, header);
      if (PACKAGE_VERSION) gsub(/#PACKAGE_VERSION#/, PACKAGE_VERSION, header);
      print header > PR;

      RS=RS0;
    }

    if (!NO_FIRST) {
      protos("request", "/**< Request line */", -1);
      protos("status", "/**< Status line */", -2);
    }
  }
}

/^#### EXTRA HEADER LIST STARTS HERE ####$/ { HLIST=1; templates(); }
HLIST && /^[a-z]/ { protos($1, $0, 0, $2); }
/^#### EXTRA HEADER LIST ENDS HERE ####$/ { HLIST=0;  }

/^ *\/\* === Headers start here \*\// { in_header_list=1;  templates(); }
/^ *\/\* === Headers end here \*\// { in_header_list=0; }

PT && /^ *\/\* === Hash headers end here \*\// { in_header_list=0;}

in_header_list && /^  (sip|rtsp|http|msg|mp)_[a-z_0-9]+_t/ {
  n=$0
  sub(/;.*$/, "", n);
  sub(/^ *(sip|rtsp|http|msg|mp)_[a-z0-9_]*_t[ 	]*/, "", n);
  sub(/^[*](sip|rtsp|http|msg|mp)_/, "", n);

  if ($0 !~ /[\/][*][*][<]/) {
    getline;
  }
  if ($0 !~ /[\/][*][*][<]/) {
    printf "msg_protos.awk: header %s is malformed\n", n;
    failed=1;
    exit 1;
  }

  if (!NO_MIDDLE)
    protos(n, $0, 0);

  headers[total++] = n;
}

END {
  if (failed) { exit };

  if (!NO_LAST) {
    protos("unknown", "/**< Unknown headers */", -3);
    protos("error", "/**< Erroneous headers */", -4);
    protos("separator", "/**< Separator line between headers and payload */", -5);
    protos("payload", "/**< Message payload */", -6);
    if (multipart)
      protos("multipart", "/**< Multipart payload */", -7);
  }

  if (PR) {
    process_footer(footer);
  }
  else if (PT) {
    if (FLAGFILE)
      read_header_flags(FLAGFILE);

    if (TEMPLATE == "") { TEMPLATE = PT ".in"; }
    RS0=RS; RS="\n";
    getline theader < TEMPLATE;
    getline header < TEMPLATE;
    getline template < TEMPLATE;
    getline footer < TEMPLATE;
    RS=RS0;

    sub(/.*[\/]/, "", TEMPLATE);
    gsub(/#AUTO#/, auto, header);
    gsub(/#DATE#/, "@date Generated: " date, header);
    print header > PT;

    if (MC_SHORT_SIZE) {
      printf("static msg_href_t const " \
	     "%s_short_forms[MC_SHORT_SIZE] = \n{\n",
	     module) > PT;

      for (i = 1; i <= MC_SHORT_SIZE; i = i + 1) {
	c = (i == MC_SHORT_SIZE) ? "" : ",";
	if (i in shorts) {
	  n = shorts[i];
        flags = header_flags[n]; if (flags) flags = ",\n      " flags;

	  printf("  { /* %s */ %s_%s_class, offsetof(%s_t, %s_%s)%s }%s\n",
		 substr(lower_case, i, 1),
		 tprefix, n, module, prefix, n, flags, c)	\
	    > PT;
	}
	else {
	  printf("  { NULL }%s\n", c) \
	    > PT;
	}
      }
      printf("};\n\n") > PT;
    }

    # printf("extern msg_hclass_t msg_multipart_class[];\n\n") > PT;

    printf("msg_mclass_t const %s_mclass[1] = \n{{\n", module) > PT;
    printf("# if defined (%s_HCLASS)\n", toupper(module)) > PT;
    printf("  %s_HCLASS,\n", toupper(module)) > PT;
    printf("#else\n") > PT;
    printf("  {{ 0 }},\n") > PT;
    printf("#endif\n") > PT;
    printf("  %s_VERSION_CURRENT,\n", toupper(module)) > PT;
    printf("  %s_PROTOCOL_TAG,\n", toupper(module)) > PT;
    printf("#if defined (%s_PARSER_FLAGS)\n", toupper(module)) > PT;
    printf("  %s_PARSER_FLAGS,\n", toupper(module)) > PT;
    printf("#else\n") > PT;
    printf("  0,\n") > PT;
    printf("#endif\n") > PT;
    printf("  sizeof(%s_t),\n", module) > PT;
    printf("  %s_extract_body,\n", module) > PT;

    len = split("request status separator payload unknown error", unnamed, " ");

    for (i = 1; i <= len; i++) {
      printf("  {{ %s_%s_class, offsetof(%s_t, %s_%s) }},\n",
	     tprefix, unnamed[i], module, prefix, unnamed[i]) > PT;
    }
    if (multipart) {
      printf("  {{ %s_class, offsetof(%s_t, %s_multipart) }},\n",
	     multipart, module, prefix) > PT;
    } else {
      printf("  {{ NULL, 0 }},\n") > PT;
    }
    if (MC_SHORT_SIZE) {
      printf("  %s_short_forms, \n", module) > PT;
    }
    else {
      printf("  NULL, \n") > PT;
    }
    printf("  %d, %d, \n", MC_HASH_SIZE, total) > PT;
    printf("  {\n") > PT;

    for (i = 0; i < total; i++) {
      n = headers[i];
      h = hashed[n];

      if (h < 0)
	continue;

      j = h % MC_HASH_SIZE; if (j == -0) j = 0;

      for (; j in header_hash;) {
	if (++j == MC_HASH_SIZE) {
	  j = 0;
	}
      }

      header_hash[j] = n;
    }

    for (i = 0; i < MC_HASH_SIZE; i++) {
      c = (i + 1 == MC_HASH_SIZE) ? "" : ",";
      if (i in header_hash) {
	n = header_hash[i];
        flags = header_flags[n]; if (flags) flags = ",\n      " flags;

	printf("    { %s_%s_class, offsetof(%s_t, %s_%s)%s }%s\n",
	       tprefix, n, module, prefix, n, flags, c) > PT;
      }
      else {
	printf("    { NULL, 0 }%s\n", c) > PT;
      }
    }
    printf("  }\n}};\n\n") > PT;
  }

  exit success;
}


Commons: add squeeze()

Commons: add squeeze()

####################################################################
# Commons.awk                                                      #
#                                                                  #
# Commonly used functions for string and array operations, logging.#
####################################################################

# Initialize `UrlEncoding`.
# See: <https://en.wikipedia.org/wiki/Percent-encoding>
function initUrlEncoding() {
    UrlEncoding["\n"] = "%0A"
    UrlEncoding[" "]  = "%20"
    UrlEncoding["!"]  = "%21"
    UrlEncoding["\""] = "%22"
    UrlEncoding["#"]  = "%23"
    UrlEncoding["$"]  = "%24"
    UrlEncoding["%"]  = "%25"
    UrlEncoding["&"]  = "%26"
    UrlEncoding["'"]  = "%27"
    UrlEncoding["("]  = "%28"
    UrlEncoding[")"]  = "%29"
    UrlEncoding["*"]  = "%2A"
    UrlEncoding["+"]  = "%2B"
    UrlEncoding[","]  = "%2C"
    UrlEncoding["-"]  = "%2D"
    UrlEncoding["."]  = "%2E"
    UrlEncoding["/"]  = "%2F"
    UrlEncoding[":"]  = "%3A"
    UrlEncoding[";"]  = "%3B"
    UrlEncoding["<"]  = "%3C"
    UrlEncoding["="]  = "%3D"
    UrlEncoding[">"]  = "%3E"
    UrlEncoding["?"]  = "%3F"
    UrlEncoding["@"]  = "%40"
    UrlEncoding["["]  = "%5B"
    UrlEncoding["\\"] = "%5C"
    UrlEncoding["]"]  = "%5D"
    UrlEncoding["^"]  = "%5E"
    UrlEncoding["_"]  = "%5F"
    UrlEncoding["`"]  = "%60"
    UrlEncoding["{"]  = "%7B"
    UrlEncoding["|"]  = "%7C"
    UrlEncoding["}"]  = "%7D"
    UrlEncoding["~"]  = "%7E"
}

# Return the real character represented by an escape sequence.
# Example: escapeChar("n") returns "\n".
# See: <https://en.wikipedia.org/wiki/Escape_character>
#      <https://en.wikipedia.org/wiki/Escape_sequences_in_C>
function escapeChar(char) {
    switch (char) {
    case "b":
        return "\b" # Backspace
    case "f":
        return "\f" # Formfeed
    case "n":
        return "\n" # Newline (Line Feed)
    case "r":
        return "\r" # Carriage Return
    case "t":
        return "\t" # Horizontal Tab
    case "v":
        return "\v" # Vertical Tab
    default:
        return char
    }
}

# Convert a literal-formatted string into its original string.
function literal(string,
                 ####
                 c, escaping, i, s) {
    if (string !~ /^".*"$/)
        return string

    split(string, s, "")
    string = ""
    escaping = 0
    for (i = 2; i < length(s); i++) {
        c = s[i]
        if (escaping) {
            string = string escapeChar(c)
            escaping = 0 # escape ends
        } else {
            if (c == "\\")
                escaping = 1 # escape begins
            else
                string = string c
        }
    }
    return string
}

# Return the URL-encoded string.
function quote(string,    i, r, s) {
    r = ""
    split(string, s, "")
    for (i = 1; i <= length(s); i++)
        r = r (s[i] in UrlEncoding ? UrlEncoding[s[i]] : s[i])
    return r
}

# Replicate a string.
function replicate(string, len,
                   ####
                   i, temp) {
    temp = ""
    for (i = 0; i < len; i++)
        temp = temp string
    return temp
}

# Squeeze a source line of AWK code.
function squeeze(line) {
    # Remove preceding spaces
    gsub(/^[[:space:]]+/, "", line)
    # Remove in-line comment
    gsub(/#[^"]*$/, "", line)
    # Remove trailing spaces
    gsub(/[[:space:]]+$/, "", line)

    return line
}

# Return 1 if the array contains anything; otherwise return 0.
function anything(array,
                  ####
                  i) {
    for (i in array)
        if (array[i]) return 1
    return 0
}

# Append an element into an array (zero-based).
function append(array, element) {
    array[anything(array) ? length(array) : 0] = element
}

# Return an element if it belongs to the array;
# Otherwise, return a null string.
function belongsTo(element, array,
                   ####
                   i) {
    for (i in array)
        if (element == array[i]) return element
    return ""
}

# Return one of the substrings if the string starts with it;
# Otherwise, return a null string.
function startsWithAny(string, substrings,
                       ####
                       i) {
    for (i in substrings)
        if (index(string, substrings[i]) == 1) return substrings[i]
    return ""
}

# Return one of the patterns if the string matches this pattern at the beginning;
# Otherwise, return a null string.
function matchesAny(string, patterns,
                    ####
                    i) {
    for (i in patterns)
        if (string ~ "^" patterns[i]) return patterns[i]
    return ""
}

# Join an array into one string;
# Return the string.
function join(array, separator, sortedIn, preserveNull,
              ####
              i, j, saveSortedIn, temp) {
    # Default parameters
    if (!separator)
        separator = " "
    if (!sortedIn)
        sortedIn = "@ind_num_asc"

    temp = ""
    j = 0
    saveSortedIn = PROCINFO["sorted_in"]
    PROCINFO["sorted_in"] = sortedIn
    for (i in array)
        if (preserveNull || array[i] != "")
            temp = j++ ? temp separator array[i] : array[i]
    PROCINFO["sorted_in"] = saveSortedIn

    return temp
}

# Initialize ANSI escape codes (ANSI X3.64 Standard Control Sequences).
# See: <https://en.wikipedia.org/wiki/ANSI_escape_code>
function initAnsiCode() {
    # Dumb terminal: no ANSI escape code whatsoever
    if(ENVIRON["TERM"] == "dumb") return

    AnsiCode["reset"]         = AnsiCode[0] = "\33[0m"

    AnsiCode["bold"]          = "\33[1m"
    AnsiCode["underline"]     = "\33[4m"
    AnsiCode["negative"]      = "\33[7m"
    AnsiCode["no bold"]       = "\33[21m"
    AnsiCode["no underline"]  = "\33[24m"
    AnsiCode["positive"]      = "\33[27m"

    AnsiCode["black"]         = "\33[30m"
    AnsiCode["red"]           = "\33[31m"
    AnsiCode["green"]         = "\33[32m"
    AnsiCode["yellow"]        = "\33[33m"
    AnsiCode["blue"]          = "\33[34m"
    AnsiCode["magenta"]       = "\33[35m"
    AnsiCode["cyan"]          = "\33[36m"
    AnsiCode["gray"]          = "\33[37m"

    AnsiCode["default"]       = "\33[39m"

    AnsiCode["dark gray"]     = "\33[90m"
    AnsiCode["light red"]     = "\33[91m"
    AnsiCode["light green"]   = "\33[92m"
    AnsiCode["light yellow"]  = "\33[93m"
    AnsiCode["light blue"]    = "\33[94m"
    AnsiCode["light magenta"] = "\33[95m"
    AnsiCode["light cyan"]    = "\33[96m"
    AnsiCode["white"]         = "\33[97m"
}

# Print warning message.
function w(text) {
    print AnsiCode["yellow"] text AnsiCode[0] > "/dev/stderr"
}

# Print error message.
function e(text) {
    print AnsiCode["red"] AnsiCode["bold"] text AnsiCode[0] > "/dev/stderr"
}

# Print debugging message.
function d(text) {
    print AnsiCode["gray"] text AnsiCode[0] > "/dev/stderr"
}

# Log an array.
function da(array, formatString, sortedIn,
            ####
            i, j, saveSortedIn) {
    # Default parameters
    if (!formatString)
        formatString = "_[%s]='%s'"
    if (!sortedIn)
        sortedIn = "@ind_num_asc"

    saveSortedIn = PROCINFO["sorted_in"]
    PROCINFO["sorted_in"] = sortedIn
    for (i in array) {
        split(i, j, SUBSEP)
        d(sprintf(formatString, join(j, ","), array[i]))
    }
    PROCINFO["sorted_in"] = saveSortedIn
}

# Naive assertion.
function assert(x, message) {
    if (!message)
        message = "[ERROR] Assertion failed."

    if (x)
        return x
    else
        e(message)
}

BEGIN {
    initUrlEncoding()
    initAnsiCode()
}

####################################################################
# Commons.awk                                                      #
#                                                                  #
# Commonly used functions for string and array operations, logging.#
####################################################################

# Initialize `UrlEncoding`.
# See: <https://en.wikipedia.org/wiki/Percent-encoding>
function initUrlEncoding() {
    UrlEncoding["\n"] = "%0A"
    UrlEncoding[" "]  = "%20"
    UrlEncoding["!"]  = "%21"
    UrlEncoding["\""] = "%22"
    UrlEncoding["#"]  = "%23"
    UrlEncoding["$"]  = "%24"
    UrlEncoding["%"]  = "%25"
    UrlEncoding["&"]  = "%26"
    UrlEncoding["'"]  = "%27"
    UrlEncoding["("]  = "%28"
    UrlEncoding[")"]  = "%29"
    UrlEncoding["*"]  = "%2A"
    UrlEncoding["+"]  = "%2B"
    UrlEncoding[","]  = "%2C"
    UrlEncoding["-"]  = "%2D"
    UrlEncoding["."]  = "%2E"
    UrlEncoding["/"]  = "%2F"
    UrlEncoding[":"]  = "%3A"
    UrlEncoding[";"]  = "%3B"
    UrlEncoding["<"]  = "%3C"
    UrlEncoding["="]  = "%3D"
    UrlEncoding[">"]  = "%3E"
    UrlEncoding["?"]  = "%3F"
    UrlEncoding["@"]  = "%40"
    UrlEncoding["["]  = "%5B"
    UrlEncoding["\\"] = "%5C"
    UrlEncoding["]"]  = "%5D"
    UrlEncoding["^"]  = "%5E"
    UrlEncoding["_"]  = "%5F"
    UrlEncoding["`"]  = "%60"
    UrlEncoding["{"]  = "%7B"
    UrlEncoding["|"]  = "%7C"
    UrlEncoding["}"]  = "%7D"
    UrlEncoding["~"]  = "%7E"
}

# Return the real character represented by an escape sequence.
# Example: escapeChar("n") returns "\n".
# See: <https://en.wikipedia.org/wiki/Escape_character>
#      <https://en.wikipedia.org/wiki/Escape_sequences_in_C>
function escapeChar(char) {
    switch (char) {
    case "b":
        return "\b" # Backspace
    case "f":
        return "\f" # Formfeed
    case "n":
        return "\n" # Newline (Line Feed)
    case "r":
        return "\r" # Carriage Return
    case "t":
        return "\t" # Horizontal Tab
    case "v":
        return "\v" # Vertical Tab
    default:
        return char
    }
}

# Convert a literal-formatted string into its original string.
function literal(string,
                 ####
                 c, escaping, i, s) {
    if (string !~ /^".*"$/)
        return string

    split(string, s, "")
    string = ""
    escaping = 0
    for (i = 2; i < length(s); i++) {
        c = s[i]
        if (escaping) {
            string = string escapeChar(c)
            escaping = 0 # escape ends
        } else {
            if (c == "\\")
                escaping = 1 # escape begins
            else
                string = string c
        }
    }
    return string
}

# Return the URL-encoded string.
function quote(string,    i, r, s) {
    r = ""
    split(string, s, "")
    for (i = 1; i <= length(s); i++)
        r = r (s[i] in UrlEncoding ? UrlEncoding[s[i]] : s[i])
    return r
}

# Replicate a string.
function replicate(string, len,
                   ####
                   i, temp) {
    temp = ""
    for (i = 0; i < len; i++)
        temp = temp string
    return temp
}

# Return 1 if the array contains anything; otherwise return 0.
function anything(array,
                  ####
                  i) {
    for (i in array)
        if (array[i]) return 1
    return 0
}

# Append an element into an array (zero-based).
function append(array, element) {
    array[anything(array) ? length(array) : 0] = element
}

# Return an element if it belongs to the array;
# Otherwise, return a null string.
function belongsTo(element, array,
                   ####
                   i) {
    for (i in array)
        if (element == array[i]) return element
    return ""
}

# Return one of the substrings if the string starts with it;
# Otherwise, return a null string.
function startsWithAny(string, substrings,
                       ####
                       i) {
    for (i in substrings)
        if (index(string, substrings[i]) == 1) return substrings[i]
    return ""
}

# Return one of the patterns if the string matches this pattern at the beginning;
# Otherwise, return a null string.
function matchesAny(string, patterns,
                    ####
                    i) {
    for (i in patterns)
        if (string ~ "^" patterns[i]) return patterns[i]
    return ""
}

# Join an array into one string;
# Return the string.
function join(array, separator, sortedIn, preserveNull,
              ####
              i, j, saveSortedIn, temp) {
    # Default parameters
    if (!separator)
        separator = " "
    if (!sortedIn)
        sortedIn = "@ind_num_asc"

    temp = ""
    j = 0
    saveSortedIn = PROCINFO["sorted_in"]
    PROCINFO["sorted_in"] = sortedIn
    for (i in array)
        if (preserveNull || array[i] != "")
            temp = j++ ? temp separator array[i] : array[i]
    PROCINFO["sorted_in"] = saveSortedIn

    return temp
}

# Initialize ANSI escape codes (ANSI X3.64 Standard Control Sequences).
# See: <https://en.wikipedia.org/wiki/ANSI_escape_code>
function initAnsiCode() {
    # Dumb terminal: no ANSI escape code whatsoever
    if(ENVIRON["TERM"] == "dumb") return

    AnsiCode["reset"]         = AnsiCode[0] = "\33[0m"

    AnsiCode["bold"]          = "\33[1m"
    AnsiCode["underline"]     = "\33[4m"
    AnsiCode["negative"]      = "\33[7m"
    AnsiCode["no bold"]       = "\33[21m"
    AnsiCode["no underline"]  = "\33[24m"
    AnsiCode["positive"]      = "\33[27m"

    AnsiCode["black"]         = "\33[30m"
    AnsiCode["red"]           = "\33[31m"
    AnsiCode["green"]         = "\33[32m"
    AnsiCode["yellow"]        = "\33[33m"
    AnsiCode["blue"]          = "\33[34m"
    AnsiCode["magenta"]       = "\33[35m"
    AnsiCode["cyan"]          = "\33[36m"
    AnsiCode["gray"]          = "\33[37m"

    AnsiCode["default"]       = "\33[39m"

    AnsiCode["dark gray"]     = "\33[90m"
    AnsiCode["light red"]     = "\33[91m"
    AnsiCode["light green"]   = "\33[92m"
    AnsiCode["light yellow"]  = "\33[93m"
    AnsiCode["light blue"]    = "\33[94m"
    AnsiCode["light magenta"] = "\33[95m"
    AnsiCode["light cyan"]    = "\33[96m"
    AnsiCode["white"]         = "\33[97m"
}

# Print warning message.
function w(text) {
    print AnsiCode["yellow"] text AnsiCode[0] > "/dev/stderr"
}

# Print error message.
function e(text) {
    print AnsiCode["red"] AnsiCode["bold"] text AnsiCode[0] > "/dev/stderr"
}

# Print debugging message.
function d(text) {
    print AnsiCode["gray"] text AnsiCode[0] > "/dev/stderr"
}

# Log an array.
function da(array, formatString, sortedIn,
            ####
            i, j, saveSortedIn) {
    # Default parameters
    if (!formatString)
        formatString = "_[%s]='%s'"
    if (!sortedIn)
        sortedIn = "@ind_num_asc"

    saveSortedIn = PROCINFO["sorted_in"]
    PROCINFO["sorted_in"] = sortedIn
    for (i in array) {
        split(i, j, SUBSEP)
        d(sprintf(formatString, join(j, ","), array[i]))
    }
    PROCINFO["sorted_in"] = saveSortedIn
}

# Naive assertion.
function assert(x, message) {
    if (!message)
        message = "[ERROR] Assertion failed."

    if (x)
        return x
    else
        e(message)
}

BEGIN {
    initUrlEncoding()
    initAnsiCode()
}