get terminal columns if COLUMNS not found

####################################################################
# Main.awk                                                         #
####################################################################

# Detect gawk version.
function initGawk(    group) {
    Gawk = "gawk"
    GawkVersion = PROCINFO["version"]

    split(PROCINFO["version"], group, ".")
    if (group[1] < 4) {
        e("[ERROR] Oops! Your gawk (version " GawkVersion ") appears to be too old.\nYou need at least gawk 4.0.0 to run this program.")
        exit 1
    }
}

# Pre-initialization (before option parsing).
function preInit() {
    initGawk()          #<< AnsiCode

    # Languages
    initBiDi()
    initLocale()
    initLocaleDisplay() #<< Locale, BiDi
    initUserLang()      #<< Locale

    RS = "\n"

    ExitCode = 0

    Option["debug"] = 0

    Option["verbose"] = 1
    if (ENVIRON["COLUMNS"])
        Option["width"] = ENVIRON["COLUMNS"]
    else {
        "tput cols 2>/dev/null" |& getline Option["width"]
        if (!Option["width"]) Option["width"] = 64
    }

    Option["browser"] = ENVIRON["BROWSER"]

    Option["play"] = 0
    Option["player"] = ENVIRON["PLAYER"]

    Option["proxy"] = ENVIRON["HTTP_PROXY"] ? ENVIRON["HTTP_PROXY"] : ENVIRON["http_proxy"]

    Option["interactive"] = 0
    Option["no-rlwrap"] = 0
    Option["emacs"] = 0
    Option["prompt"] = ENVIRON["TRANS_PS"] ? ENVIRON["TRANS_PS"] : "%s>"
    Option["prompt-color"] = ENVIRON["TRANS_PS_COLOR"] ? ENVIRON["TRANS_PS_COLOR"] : "blue"

    Option["input"] = ""
    Option["output"] = "/dev/stdout"

    Option["hl"] = ENVIRON["HOME_LANG"] ? ENVIRON["HOME_LANG"] : UserLang
    Option["sl"] = ENVIRON["SOURCE_LANG"] ? ENVIRON["SOURCE_LANG"] : "auto"
    Option["tl"][1] = ENVIRON["TARGET_LANG"] ? ENVIRON["TARGET_LANG"] : UserLang
}

# Post-initialization (after option parsing).
function postInit() {
    # Translate
    initHttpService()
}

# Main entry point.
BEGIN {
    preInit()

    pos = 0
    while (ARGV[++pos]) {
        # -, -no-op
        match(ARGV[pos], /^-(-?no-op)?$/)
        if (RSTART) continue

        # -V, -version
        match(ARGV[pos], /^--?(vers(i(on?)?)?|V)$/)
        if (RSTART) {
            print getVersion()
            exit
        }

        # -H, -h, -help
        match(ARGV[pos], /^--?(h(e(lp?)?)?|H)$/)
        if (RSTART) {
            if (ENVIRON["TRANS_MANPAGE"])
                system("echo -E \"${TRANS_MANPAGE}\" | " \
                       "groff -Wall -mtty-char -mandoc -Tutf8 -Dutf8 -rLL=${COLUMNS}n -rLT=${COLUMNS}n | " \
                       (system("most 2>/dev/null") ?
                        "less -s -P\"\\ \\Manual page " Command "(1) line %lt (press h for help or q to quit)\"" :
                        "most -Cs"))
            else
                print getHelp()
            exit
        }

        # -r, -reference
        match(ARGV[pos], /^--?r(e(f(e(r(e(n(ce?)?)?)?)?)?)?)?$/)
        if (RSTART) {
            print getReference("endonym")
            exit
        }

        # -R, -reference-english
        match(ARGV[pos], /^--?(reference-(e(n(g(l(i(sh?)?)?)?)?)?)?|R)$/)
        if (RSTART) {
            print getReference("name")
            exit
        }

        # -d, -debug
        match(ARGV[pos], /^--?d(e(b(ug?)?)?)?$/)
        if (RSTART) {
            Option["debug"] = 1
            continue
        }

        # -v, -verbose
        match(ARGV[pos], /^--?v(e(r(b(o(se?)?)?)?)?)?$/)
        if (RSTART) {
            Option["verbose"] = 1 # default value
            continue
        }

        # -b, -brief
        match(ARGV[pos], /^--?b(r(i(ef?)?)?)?$/)
        if (RSTART) {
            Option["verbose"] = 0
            continue
        }

        # -w [num], -width [num]
        match(ARGV[pos], /^--?w(i(d(th?)?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            Option["width"] = group[4] ?
                (group[5] ? group[5] : Option["width"]) :
                ARGV[++pos]
            continue
        }

        # -browser [program]
        match(ARGV[pos], /^--?browser(=(.*)?)?$/, group)
        if (RSTART) {
            Option["browser"] = group[1] ?
                (group[2] ? group[2] : Option["browser"]) :
                ARGV[++pos]
            continue
        }

        # -p, -play
        match(ARGV[pos], /^--?p(l(ay?)?)?$/)
        if (RSTART) {
            Option["play"] = 1
            continue
        }

        # -player [program]
        match(ARGV[pos], /^--?player(=(.*)?)?$/, group)
        if (RSTART) {
            Option["play"] = 1
            Option["player"] = group[1] ?
                (group[2] ? group[2] : Option["player"]) :
                ARGV[++pos]
            continue
        }

        # -x [proxy], -proxy [proxy]
        match(ARGV[pos], /^--?(proxy|x)(=(.*)?)?$/, group)
        if (RSTART) {
            Option["proxy"] = group[2] ?
                (group[3] ? group[3] : Option["proxy"]) :
                ARGV[++pos]
            continue
        }

        # -I, -interactive
        match(ARGV[pos], /^--?(int(e(r(a(c(t(i(ve?)?)?)?)?)?)?)?|I)$/)
        if (RSTART) {
            Option["interactive"] = 1
            continue
        }

        # -no-rlwrap
        match(ARGV[pos], /^--?no-rlwrap/)
        if (RSTART) {
            Option["no-rlwrap"] = 1
            continue
        }

        # -E, -emacs
        match(ARGV[pos], /^--?(emacs|E)$/)
        if (RSTART) {
            Option["emacs"] = 1
            continue
        }

        # -prompt [prompt_string]
        match(ARGV[pos], /^--?prompt(=(.*)?)?$/, group)
        if (RSTART) {
            Option["prompt"] = group[1] ?
                (group[2] ? group[2] : Option["prompt"]) :
                ARGV[++pos]
            continue
        }

        # -prompt-color [color_code]
        match(ARGV[pos], /^--?prompt-color(=(.*)?)?$/, group)
        if (RSTART) {
            Option["prompt-color"] = group[1] ?
                (group[2] ? group[2] : Option["prompt-color"]) :
                ARGV[++pos]
            continue
        }

        # -i [file], -input [file]
        match(ARGV[pos], /^--?i(n(p(ut?)?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            Option["input"] = group[4] ?
                (group[5] ? group[5] : Option["input"]) :
                ARGV[++pos]
            continue
        }

        # -o [file], -output [file]
        match(ARGV[pos], /^--?o(u(t(p(ut?)?)?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            Option["output"] = group[5] ?
                (group[6] ? group[6] : Option["output"]) :
                ARGV[++pos]
            continue
        }

        # -l [code], -lang [code]
        match(ARGV[pos], /^--?l(a(ng?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            Option["hl"] = group[3] ?
                (group[4] ? group[4] : Option["hl"]) :
                ARGV[++pos]
            continue
        }

        # -s [code], -source [code]
        match(ARGV[pos], /^--?s(o(u(r(ce?)?)?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            Option["sl"] = group[5] ?
                (group[6] ? group[6] : Option["sl"]) :
                ARGV[++pos]
            continue
        }

        # -t [codes], -target [codes]
        match(ARGV[pos], /^--?t(a(r(g(et?)?)?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            if (group[5]) {
                if (group[6]) split(group[6], Option["tl"], "+")
            } else
                split(ARGV[++pos], Option["tl"], "+")
            continue
        }

        # Shortcut format
        # '[code]:[code]+...' or '[code]=[code]+...'
        match(ARGV[pos], /^[{([]?([[:alpha:]][[:alpha:]][[:alpha:]]?(-[[:alpha:]][[:alpha:]])?)?(:|=)((@?[[:alpha:]][[:alpha:]][[:alpha:]]?(-[[:alpha:]][[:alpha:]])?\+)*(@?[[:alpha:]][[:alpha:]][[:alpha:]]?(-[[:alpha:]][[:alpha:]])?)?)[})\]]?$/, group)
        if (RSTART) {
            if (group[1]) Option["sl"] = group[1]
            if (group[4]) split(group[4], Option["tl"], "+")
            continue
        }

        # --
        match(ARGV[pos], /^--$/)
        if (RSTART) {
            ++pos # skip the end-of-options option
            break # no more option from here
        }

        break # no more option from here
    }

    # Option parsing finished
    postInit()

    if (Option["interactive"] && !Option["no-rlwrap"]) {
        # Interactive mode
        initRlwrap() # initialize Rlwrap

        if (Rlwrap && (ENVIRON["TRANS_PROGRAM"] || fileExists(EntryPoint))) {
            command = Rlwrap " " Gawk " " (ENVIRON["TRANS_PROGRAM"] ?
                                           "\"${TRANS_PROGRAM}\"" :
                                           "-f " EntryPoint) " -" \
                " -no-rlwrap" # be careful - never fork Rlwrap recursively!
            for (i = 1; i < length(ARGV); i++)
                if (ARGV[i])
                    command = command " " parameterize(ARGV[i])

            if (!system(command))
                exit # child process finished, exit
            else
                ; # skip
        } else
            ; # skip

    } else if (!Option["interactive"] && !Option["no-rlwrap"] && Option["emacs"]) {
        # Emacs interface
        Emacs = "emacs"

        if (ENVIRON["TRANS_PROGRAM"] || fileExists(EntryPoint)) {
            params = ""
            for (i = 1; i < length(ARGV); i++)
                if (ARGV[i])
                    params = params " " (parameterize(ARGV[i], "\""))
            if (ENVIRON["TRANS_PROGRAM"]) {
                el = "(progn (setq trans-program (getenv \"TRANS_PROGRAM\")) " \
                    "(setq explicit-shell-file-name \"" Gawk "\") " \
                    "(setq explicit-" Gawk "-args (cons trans-program '(\"-\" \"-I\" \"-no-rlwrap\"" params "))) " \
                    "(command-execute 'shell) (rename-buffer \"" Name "\"))"
            } else {
                el = "(progn (setq explicit-shell-file-name \"" Gawk "\") " \
                    "(setq explicit-" Gawk "-args '(\"-f\" \"" EntryPoint "\" \"--\" \"-I\" \"-no-rlwrap\"" params ")) " \
                    "(command-execute 'shell) (rename-buffer \"" Name "\"))"
            }
            command = Emacs " --eval " parameterize(el)

            if (!system(command))
                exit # child process finished, exit
            else
                Option["interactive"] = 1 # skip
        } else
            Option["interactive"] = 1 # skip
    }

    if (Option["play"]) {
        # Initialize audio player or speech synthesizer
        if (!Option["player"]) {
            initAudioPlayer()
            Option["player"] = AudioPlayer ? AudioPlayer : Option["player"]
            if (!Option["player"])
                initSpeechSynthesizer()
        }

        if (!Option["player"] && !SpeechSynthesizer) {
            w("[WARNING] No available audio player or speech synthesizer is found.")
            Option["play"] = 0
        }
    }

    # Initialize browser
    if (!Option["browser"]) {
        "xdg-mime query default text/html 2>/dev/null" |& getline Option["browser"]
        match(Option["browser"], "(.*).desktop$", group)
        Option["browser"] = group[1]
    }

    if (pos < ARGC) {
        # More parameters

        # Translate the remaining parameters
        for (i = pos; i < ARGC; i++) {
            # Verbose mode: separator between sources
            if (Option["verbose"] && i > pos)
                print replicate("═", Option["width"])

            translate(ARGV[i], 1) # inline mode
        }

        # If input not specified, we're done
    } else {
        # No more parameter besides options

        # If input not specified, use stdin
        if (!Option["input"]) Option["input"] = "/dev/stdin"
    }

    # If input specified, start translating
    if (Option["input"])
        translateMain()

    exit ExitCode
}

####################################################################
# Main.awk                                                         #
####################################################################

# Detect gawk version.
function initGawk(    group) {
    Gawk = "gawk"
    GawkVersion = PROCINFO["version"]

    split(PROCINFO["version"], group, ".")
    if (group[1] < 4) {
        e("[ERROR] Oops! Your gawk (version " GawkVersion ") appears to be too old.\nYou need at least gawk 4.0.0 to run this program.")
        exit 1
    }
}

# Pre-initialization (before option parsing).
function preInit() {
    initGawk()          #<< AnsiCode

    # Languages
    initBiDi()
    initLocale()
    initLocaleDisplay() #<< Locale, BiDi
    initUserLang()      #<< Locale

    RS = "\n"

    ExitCode = 0

    Option["debug"] = 0

    Option["verbose"] = 1
    Option["width"] = ENVIRON["COLUMNS"] ? ENVIRON["COLUMNS"] : 64

    Option["browser"] = ENVIRON["BROWSER"]

    Option["play"] = 0
    Option["player"] = ENVIRON["PLAYER"]

    Option["proxy"] = ENVIRON["HTTP_PROXY"] ? ENVIRON["HTTP_PROXY"] : ENVIRON["http_proxy"]

    Option["interactive"] = 0
    Option["no-rlwrap"] = 0
    Option["emacs"] = 0
    Option["prompt"] = ENVIRON["TRANS_PS"] ? ENVIRON["TRANS_PS"] : "%s>"
    Option["prompt-color"] = ENVIRON["TRANS_PS_COLOR"] ? ENVIRON["TRANS_PS_COLOR"] : "blue"

    Option["input"] = ""
    Option["output"] = "/dev/stdout"

    Option["hl"] = ENVIRON["HOME_LANG"] ? ENVIRON["HOME_LANG"] : UserLang
    Option["sl"] = ENVIRON["SOURCE_LANG"] ? ENVIRON["SOURCE_LANG"] : "auto"
    Option["tl"][1] = ENVIRON["TARGET_LANG"] ? ENVIRON["TARGET_LANG"] : UserLang
}

# Post-initialization (after option parsing).
function postInit() {
    # Translate
    initHttpService()
}

# Main entry point.
BEGIN {
    preInit()

    pos = 0
    while (ARGV[++pos]) {
        # -, -no-op
        match(ARGV[pos], /^-(-?no-op)?$/)
        if (RSTART) continue

        # -V, -version
        match(ARGV[pos], /^--?(vers(i(on?)?)?|V)$/)
        if (RSTART) {
            print getVersion()
            exit
        }

        # -H, -h, -help
        match(ARGV[pos], /^--?(h(e(lp?)?)?|H)$/)
        if (RSTART) {
            if (ENVIRON["TRANS_MANPAGE"])
                system("echo -E \"${TRANS_MANPAGE}\" | " \
                       "groff -Wall -mtty-char -mandoc -Tutf8 -Dutf8 -rLL=${COLUMNS}n -rLT=${COLUMNS}n | " \
                       (system("most 2>/dev/null") ?
                        "less -s -P\"\\ \\Manual page " Command "(1) line %lt (press h for help or q to quit)\"" :
                        "most -Cs"))
            else
                print getHelp()
            exit
        }

        # -r, -reference
        match(ARGV[pos], /^--?r(e(f(e(r(e(n(ce?)?)?)?)?)?)?)?$/)
        if (RSTART) {
            print getReference("endonym")
            exit
        }

        # -R, -reference-english
        match(ARGV[pos], /^--?(reference-(e(n(g(l(i(sh?)?)?)?)?)?)?|R)$/)
        if (RSTART) {
            print getReference("name")
            exit
        }

        # -d, -debug
        match(ARGV[pos], /^--?d(e(b(ug?)?)?)?$/)
        if (RSTART) {
            Option["debug"] = 1
            continue
        }

        # -v, -verbose
        match(ARGV[pos], /^--?v(e(r(b(o(se?)?)?)?)?)?$/)
        if (RSTART) {
            Option["verbose"] = 1 # default value
            continue
        }

        # -b, -brief
        match(ARGV[pos], /^--?b(r(i(ef?)?)?)?$/)
        if (RSTART) {
            Option["verbose"] = 0
            continue
        }

        # -w [num], -width [num]
        match(ARGV[pos], /^--?w(i(d(th?)?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            Option["width"] = group[4] ?
                (group[5] ? group[5] : Option["width"]) :
                ARGV[++pos]
            continue
        }

        # -browser [program]
        match(ARGV[pos], /^--?browser(=(.*)?)?$/, group)
        if (RSTART) {
            Option["browser"] = group[1] ?
                (group[2] ? group[2] : Option["browser"]) :
                ARGV[++pos]
            continue
        }

        # -p, -play
        match(ARGV[pos], /^--?p(l(ay?)?)?$/)
        if (RSTART) {
            Option["play"] = 1
            continue
        }

        # -player [program]
        match(ARGV[pos], /^--?player(=(.*)?)?$/, group)
        if (RSTART) {
            Option["play"] = 1
            Option["player"] = group[1] ?
                (group[2] ? group[2] : Option["player"]) :
                ARGV[++pos]
            continue
        }

        # -x [proxy], -proxy [proxy]
        match(ARGV[pos], /^--?(proxy|x)(=(.*)?)?$/, group)
        if (RSTART) {
            Option["proxy"] = group[2] ?
                (group[3] ? group[3] : Option["proxy"]) :
                ARGV[++pos]
            continue
        }

        # -I, -interactive
        match(ARGV[pos], /^--?(int(e(r(a(c(t(i(ve?)?)?)?)?)?)?)?|I)$/)
        if (RSTART) {
            Option["interactive"] = 1
            continue
        }

        # -no-rlwrap
        match(ARGV[pos], /^--?no-rlwrap/)
        if (RSTART) {
            Option["no-rlwrap"] = 1
            continue
        }

        # -E, -emacs
        match(ARGV[pos], /^--?(emacs|E)$/)
        if (RSTART) {
            Option["emacs"] = 1
            continue
        }

        # -prompt [prompt_string]
        match(ARGV[pos], /^--?prompt(=(.*)?)?$/, group)
        if (RSTART) {
            Option["prompt"] = group[1] ?
                (group[2] ? group[2] : Option["prompt"]) :
                ARGV[++pos]
            continue
        }

        # -prompt-color [color_code]
        match(ARGV[pos], /^--?prompt-color(=(.*)?)?$/, group)
        if (RSTART) {
            Option["prompt-color"] = group[1] ?
                (group[2] ? group[2] : Option["prompt-color"]) :
                ARGV[++pos]
            continue
        }

        # -i [file], -input [file]
        match(ARGV[pos], /^--?i(n(p(ut?)?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            Option["input"] = group[4] ?
                (group[5] ? group[5] : Option["input"]) :
                ARGV[++pos]
            continue
        }

        # -o [file], -output [file]
        match(ARGV[pos], /^--?o(u(t(p(ut?)?)?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            Option["output"] = group[5] ?
                (group[6] ? group[6] : Option["output"]) :
                ARGV[++pos]
            continue
        }

        # -l [code], -lang [code]
        match(ARGV[pos], /^--?l(a(ng?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            Option["hl"] = group[3] ?
                (group[4] ? group[4] : Option["hl"]) :
                ARGV[++pos]
            continue
        }

        # -s [code], -source [code]
        match(ARGV[pos], /^--?s(o(u(r(ce?)?)?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            Option["sl"] = group[5] ?
                (group[6] ? group[6] : Option["sl"]) :
                ARGV[++pos]
            continue
        }

        # -t [codes], -target [codes]
        match(ARGV[pos], /^--?t(a(r(g(et?)?)?)?)?(=(.*)?)?$/, group)
        if (RSTART) {
            if (group[5]) {
                if (group[6]) split(group[6], Option["tl"], "+")
            } else
                split(ARGV[++pos], Option["tl"], "+")
            continue
        }

        # Shortcut format
        # '[code]:[code]+...' or '[code]=[code]+...'
        match(ARGV[pos], /^[{([]?([[:alpha:]][[:alpha:]][[:alpha:]]?(-[[:alpha:]][[:alpha:]])?)?(:|=)((@?[[:alpha:]][[:alpha:]][[:alpha:]]?(-[[:alpha:]][[:alpha:]])?\+)*(@?[[:alpha:]][[:alpha:]][[:alpha:]]?(-[[:alpha:]][[:alpha:]])?)?)[})\]]?$/, group)
        if (RSTART) {
            if (group[1]) Option["sl"] = group[1]
            if (group[4]) split(group[4], Option["tl"], "+")
            continue
        }

        # --
        match(ARGV[pos], /^--$/)
        if (RSTART) {
            ++pos # skip the end-of-options option
            break # no more option from here
        }

        break # no more option from here
    }

    # Option parsing finished
    postInit()

    if (Option["interactive"] && !Option["no-rlwrap"]) {
        # Interactive mode
        initRlwrap() # initialize Rlwrap

        if (Rlwrap && (ENVIRON["TRANS_PROGRAM"] || fileExists(EntryPoint))) {
            command = Rlwrap " " Gawk " " (ENVIRON["TRANS_PROGRAM"] ?
                                           "\"${TRANS_PROGRAM}\"" :
                                           "-f " EntryPoint) " -" \
                " -no-rlwrap" # be careful - never fork Rlwrap recursively!
            for (i = 1; i < length(ARGV); i++)
                if (ARGV[i])
                    command = command " " parameterize(ARGV[i])

            if (!system(command))
                exit # child process finished, exit
            else
                ; # skip
        } else
            ; # skip

    } else if (!Option["interactive"] && !Option["no-rlwrap"] && Option["emacs"]) {
        # Emacs interface
        Emacs = "emacs"

        if (ENVIRON["TRANS_PROGRAM"] || fileExists(EntryPoint)) {
            params = ""
            for (i = 1; i < length(ARGV); i++)
                if (ARGV[i])
                    params = params " " (parameterize(ARGV[i], "\""))
            if (ENVIRON["TRANS_PROGRAM"]) {
                el = "(progn (setq trans-program (getenv \"TRANS_PROGRAM\")) " \
                    "(setq explicit-shell-file-name \"" Gawk "\") " \
                    "(setq explicit-" Gawk "-args (cons trans-program '(\"-\" \"-I\" \"-no-rlwrap\"" params "))) " \
                    "(command-execute 'shell) (rename-buffer \"" Name "\"))"
            } else {
                el = "(progn (setq explicit-shell-file-name \"" Gawk "\") " \
                    "(setq explicit-" Gawk "-args '(\"-f\" \"" EntryPoint "\" \"--\" \"-I\" \"-no-rlwrap\"" params ")) " \
                    "(command-execute 'shell) (rename-buffer \"" Name "\"))"
            }
            command = Emacs " --eval " parameterize(el)

            if (!system(command))
                exit # child process finished, exit
            else
                Option["interactive"] = 1 # skip
        } else
            Option["interactive"] = 1 # skip
    }

    if (Option["play"]) {
        # Initialize audio player or speech synthesizer
        if (!Option["player"]) {
            initAudioPlayer()
            Option["player"] = AudioPlayer ? AudioPlayer : Option["player"]
            if (!Option["player"])
                initSpeechSynthesizer()
        }

        if (!Option["player"] && !SpeechSynthesizer) {
            w("[WARNING] No available audio player or speech synthesizer is found.")
            Option["play"] = 0
        }
    }

    # Initialize browser
    if (!Option["browser"]) {
        "xdg-mime query default text/html 2>/dev/null" |& getline Option["browser"]
        match(Option["browser"], "(.*).desktop$", group)
        Option["browser"] = group[1]
    }

    if (pos < ARGC) {
        # More parameters

        # Translate the remaining parameters
        for (i = pos; i < ARGC; i++) {
            # Verbose mode: separator between sources
            if (Option["verbose"] && i > pos)
                print replicate("═", Option["width"])

            translate(ARGV[i], 1) # inline mode
        }

        # If input not specified, we're done
    } else {
        # No more parameter besides options

        # If input not specified, use stdin
        if (!Option["input"]) Option["input"] = "/dev/stdin"
    }

    # If input specified, start translating
    if (Option["input"])
        translateMain()

    exit ExitCode
}


Do not increment stale count to infinity

#!/usr/bin/awk -f
BEGIN {
  NUM_ASIC = 6;
  NUM_DIE = 4;
  NUM_DCDC = 8;
  STALE_COUNT = 4;
  for (asic = 0; asic < NUM_ASIC; ++asic) {
    asic_temp[asic] = "";
    asic_temp_cnt[asic] = 0;
    asic_type[asic] = "";
    asic_type_cnt[asic] = 0;
    for (die = 0; die < NUM_DIE; ++die) {
        asic_freq[asic, die] = "";
        asic_freq_cnt[asic, die] = 0;
        asic_volt[asic, die] = "";
        asic_volt_cnt[asic, die] = 0;
    }
    for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
      asic_dcdctemp[asic, dcdc] = "";
      asic_dcdctemp_cnt[asic, dcdc] = 0;
      asic_dcdcVout[asic, dcdc] = "";
      asic_dcdcVout_cnt[asic, dcdc] = 0;
      asic_dcdcIout[asic, dcdc] = "";
      asic_dcdcIout_cnt[asic, dcdc] = 0;
    }
  }
  cur_asic = 0;
 }

/"asic_1"/ { cur_asic = 0 }
/"asic_2"/ { cur_asic = 1 }
/"asic_3"/ { cur_asic = 2 }
/"asic_4"/ { cur_asic = 3 }
/"asic_5"/ { cur_asic = 4 }
/"asic_6"/ { cur_asic = 5 }

/"die0_Freq"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_freq[cur_asic, 0] = $2 }
/"die1_Freq"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_freq[cur_asic, 1] = $2 }
/"die2_Freq"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_freq[cur_asic, 2] = $2 }
/"die3_Freq"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_freq[cur_asic, 3] = $2 }

/"die0_Voffset"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_volt[cur_asic, 0] = $2 }
/"die1_Voffset"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_volt[cur_asic, 1] = $2 }
/"die2_Voffset"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_volt[cur_asic, 2] = $2 }
/"die3_Voffset"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_volt[cur_asic, 3] = $2 }

/"dcdc0_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 0] = $2 }
/"dcdc1_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 1] = $2 }
/"dcdc2_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 2] = $2 }
/"dcdc3_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 3] = $2 }
/"dcdc4_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 4] = $2 }
/"dcdc5_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 5] = $2 }
/"dcdc6_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 6] = $2 }
/"dcdc7_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 7] = $2 }

/"dcdc0_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 0] = $2 }
/"dcdc1_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 1] = $2 }
/"dcdc2_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 2] = $2 }
/"dcdc3_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 3] = $2 }
/"dcdc4_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 4] = $2 }
/"dcdc5_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 5] = $2 }
/"dcdc6_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 6] = $2 }
/"dcdc7_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 7] = $2 }

/"dcdc0_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 0] = $2 }
/"dcdc1_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 1] = $2 }
/"dcdc2_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 2] = $2 }
/"dcdc3_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 3] = $2 }
/"dcdc4_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 4] = $2 }
/"dcdc5_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 5] = $2 }
/"dcdc6_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 6] = $2 }
/"dcdc7_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 7] = $2 }

/BOARD0=/ { gsub(/BOARD0=/, "", $1); asic_type[0] = $1; }
/BOARD1=/ { gsub(/BOARD1=/, "", $1); asic_type[1] = $1; }
/BOARD2=/ { gsub(/BOARD2=/, "", $1); asic_type[2] = $1; }
/BOARD3=/ { gsub(/BOARD3=/, "", $1); asic_type[3] = $1; }
/BOARD4=/ { gsub(/BOARD4=/, "", $1); asic_type[4] = $1; }
/BOARD5=/ { gsub(/BOARD5=/, "", $1); asic_type[5] = $1; }

/"temperature"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_temp[cur_asic] = $2 }

/ASICCACHE/ { asic = $2;
  asic_type_cache[asic] = $3;
  asic_temp_cache[asic] = $4;
  for (die = 0; die < NUM_DIE; ++die) {
    asic_freq_cache[asic, die] = $(5 + die*2);
    asic_volt_cache[asic, die] = $(5 + die*2 + 1);
  }
  for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
    asic_dcdctemp_cache[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3);
    asic_dcdcVout_cache[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3 + 1);
    asic_dcdcIout_cache[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3 + 2);
  }
}

/STALECOUNTERS/ { asic = $2;
  asic_type_cnt[asic] = $3;
  asic_temp_cnt[asic] = $4;
  for (die = 0; die < NUM_DIE; ++die) {
    asic_freq_cnt[asic, die] = $(5 + die*2);
    asic_volt_cnt[asic, die] = $(5 + die*2 + 1);
  }
  for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
    asic_dcdctemp_cnt[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3);
    asic_dcdcVout_cnt[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3 + 1);
    asic_dcdcIout_cnt[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3 + 2);
  }
}

END {
  for (asic = 0; asic < NUM_ASIC; ++asic) {
    if ("" != asic_type[asic]) {
      type = asic_type[asic];
      asic_type_cnt[asic] = 0;
    } else {
      if (++asic_type_cnt[asic] > STALE_COUNT) {
        asic_type_cnt[asic] = STALE_COUNT + 1;
        type = "OFF";
      } else {
        type = asic_type_cache[asic];
      }
    }
    if ("" != asic_temp[asic]) {
      temp = (0.0 + asic_temp[asic]);
      asic_temp_cnt[asic] = 0;
    } else {
      if (++asic_temp_cnt[asic] > STALE_COUNT) {
        asic_temp_cnt[asic] = STALE_COUNT + 1;
        temp = 0.0;
      } else {
        temp = asic_temp_cache[asic];
      }
    }
    for (die = 0; die < NUM_DIE; ++die) {
      if ("" != asic_freq[asic, die]) {
        freq[die] = (0.0 + asic_freq[asic, die]);
        asic_freq_cnt[asic, die] = 0;
      } else {
        if (++asic_freq_cnt[asic, die] > STALE_COUNT) {
          asic_freq_cnt[asic, die] = STALE_COUNT + 1;
          freq[die] = 0.0;
        } else {
          freq[die] = asic_freq_cache[asic, die];
        }
      }
      if ("" != asic_volt[asic, die]) {
        volt[die] = (0.0 + asic_volt[asic, die]);
        asic_volt_cnt[asic, die] = 0;
      } else {
        if (++asic_volt_cnt[asic, die] > STALE_COUNT) {
          asic_volt_cnt[asic, die] = STALE_COUNT + 1;
          volt[die] = 0.0;
        } else {
          volt[die] = asic_volt_cache[asic, die];
        }
      }
    }
    for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
      if ("" != asic_dcdctemp[asic, dcdc]) {
        dcdctemp[dcdc] = (0.0 + asic_dcdctemp[asic, dcdc]);
	asic_dcdctemp_cnt[asic, dcdc] = 0;
      } else {
        if (++asic_dcdctemp_cnt[asic, dcdc] > STALE_COUNT) {
          asic_dcdctemp_cnt[asic, dcdc] = STALE_COUNT + 1;
          dcdctemp[dcdc] = 0.0;
        } else {
          dcdctemp[dcdc] = asic_dcdctemp_cache[asic, dcdc];
        }
      }
      if ("" != asic_dcdcVout[asic, dcdc]) {
        dcdcVout[dcdc] = (0.0 + asic_dcdcVout[asic, dcdc]);
	asic_dcdcVout_cnt[asic, dcdc] = 0;
      } else {
        if (++asic_dcdcVout_cnt[asic, dcdc] > STALE_COUNT) {
          asic_dcdcVout_cnt[asic, dcdc] = STALE_COUNT + 1;
          dcdcVout[dcdc] = 0.0;
        } else {
          dcdcVout[dcdc] = asic_dcdcVout_cache[asic, dcdc];
        }
      }
      if ("" != asic_dcdcIout[asic, dcdc]) {
        dcdcIout[dcdc] = (0.0 + asic_dcdcIout[asic, dcdc]);
	asic_dcdcIout_cnt[asic, dcdc] = 0;
      } else {
        if (++asic_dcdcIout_cnt[asic, dcdc] > STALE_COUNT) {
          asic_dcdcIout_cnt[asic, dcdc] = STALE_COUNT + 1;
          dcdcIout[dcdc] = 0.0;
        } else {
          dcdcIout[dcdc] = asic_dcdcIout_cache[asic, dcdc];
        }
      }
    }
    printf("ASICCACHE %d %s %.1f", asic, type, temp);
    for (die = 0; die < NUM_DIE; ++die) {
      printf(" %d %.4f", freq[die], volt[die]);
    }
    for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
      printf(" %.1f %.4f %.4f", dcdctemp[dcdc], dcdcVout[dcdc], dcdcIout[dcdc]);
    }
    printf("\nSTALECOUNTERS %d %d %d", asic, asic_type_cnt[asic], asic_temp_cnt[asic]);
    for (die = 0; die < NUM_DIE; ++die) {
      printf(" %d %d", asic_freq_cnt[asic, die], asic_volt_cnt[asic, die]);
    }
    for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
      printf(" %d %d %d", asic_dcdctemp_cnt[asic, dcdc], asic_dcdcVout_cnt[asic, dcdc], asic_dcdcIout_cnt[asic, dcdc]);
    }
    printf("\n");
  }
}

#!/usr/bin/awk -f
BEGIN {
  NUM_ASIC = 6;
  NUM_DIE = 4;
  NUM_DCDC = 8;
  STALE_COUNT = 4;
  for (asic = 0; asic < NUM_ASIC; ++asic) {
    asic_temp[asic] = "";
    asic_temp_cnt[asic] = 0;
    asic_type[asic] = "";
    asic_type_cnt[asic] = 0;
    for (die = 0; die < NUM_DIE; ++die) {
        asic_freq[asic, die] = "";
        asic_freq_cnt[asic, die] = 0;
        asic_volt[asic, die] = "";
        asic_volt_cnt[asic, die] = 0;
    }
    for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
      asic_dcdctemp[asic, dcdc] = "";
      asic_dcdctemp_cnt[asic, dcdc] = 0;
      asic_dcdcVout[asic, dcdc] = "";
      asic_dcdcVout_cnt[asic, dcdc] = 0;
      asic_dcdcIout[asic, dcdc] = "";
      asic_dcdcIout_cnt[asic, dcdc] = 0;
    }
  }
  cur_asic = 0;
 }

/"asic_1"/ { cur_asic = 0 }
/"asic_2"/ { cur_asic = 1 }
/"asic_3"/ { cur_asic = 2 }
/"asic_4"/ { cur_asic = 3 }
/"asic_5"/ { cur_asic = 4 }
/"asic_6"/ { cur_asic = 5 }

/"die0_Freq"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_freq[cur_asic, 0] = $2 }
/"die1_Freq"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_freq[cur_asic, 1] = $2 }
/"die2_Freq"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_freq[cur_asic, 2] = $2 }
/"die3_Freq"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_freq[cur_asic, 3] = $2 }

/"die0_Voffset"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_volt[cur_asic, 0] = $2 }
/"die1_Voffset"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_volt[cur_asic, 1] = $2 }
/"die2_Voffset"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_volt[cur_asic, 2] = $2 }
/"die3_Voffset"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_volt[cur_asic, 3] = $2 }

/"dcdc0_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 0] = $2 }
/"dcdc1_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 1] = $2 }
/"dcdc2_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 2] = $2 }
/"dcdc3_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 3] = $2 }
/"dcdc4_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 4] = $2 }
/"dcdc5_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 5] = $2 }
/"dcdc6_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 6] = $2 }
/"dcdc7_Temp"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdctemp[cur_asic, 7] = $2 }

/"dcdc0_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 0] = $2 }
/"dcdc1_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 1] = $2 }
/"dcdc2_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 2] = $2 }
/"dcdc3_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 3] = $2 }
/"dcdc4_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 4] = $2 }
/"dcdc5_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 5] = $2 }
/"dcdc6_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 6] = $2 }
/"dcdc7_Vout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcVout[cur_asic, 7] = $2 }

/"dcdc0_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 0] = $2 }
/"dcdc1_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 1] = $2 }
/"dcdc2_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 2] = $2 }
/"dcdc3_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 3] = $2 }
/"dcdc4_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 4] = $2 }
/"dcdc5_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 5] = $2 }
/"dcdc6_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 6] = $2 }
/"dcdc7_Iout"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_dcdcIout[cur_asic, 7] = $2 }

/BOARD0=/ { gsub(/BOARD0=/, "", $1); asic_type[0] = $1; }
/BOARD1=/ { gsub(/BOARD1=/, "", $1); asic_type[1] = $1; }
/BOARD2=/ { gsub(/BOARD2=/, "", $1); asic_type[2] = $1; }
/BOARD3=/ { gsub(/BOARD3=/, "", $1); asic_type[3] = $1; }
/BOARD4=/ { gsub(/BOARD4=/, "", $1); asic_type[4] = $1; }
/BOARD5=/ { gsub(/BOARD5=/, "", $1); asic_type[5] = $1; }

/"temperature"/ { gsub(/"/, "", $2); gsub(/,/, "", $2); asic_temp[cur_asic] = $2 }

/ASICCACHE/ { asic = $2;
  asic_type_cache[asic] = $3;
  asic_temp_cache[asic] = $4;
  for (die = 0; die < NUM_DIE; ++die) {
    asic_freq_cache[asic, die] = $(5 + die*2);
    asic_volt_cache[asic, die] = $(5 + die*2 + 1);
  }
  for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
    asic_dcdctemp_cache[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3);
    asic_dcdcVout_cache[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3 + 1);
    asic_dcdcIout_cache[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3 + 2);
  }
}

/STALECOUNTERS/ { asic = $2;
  asic_type_cnt[asic] = $3;
  asic_temp_cnt[asic] = $4;
  for (die = 0; die < NUM_DIE; ++die) {
    asic_freq_cnt[asic, die] = $(5 + die*2);
    asic_volt_cnt[asic, die] = $(5 + die*2 + 1);
  }
  for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
    asic_dcdctemp_cnt[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3);
    asic_dcdcVout_cnt[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3 + 1);
    asic_dcdcIout_cnt[asic, dcdc] = $(5 + NUM_DIE*2 + dcdc*3 + 2);
  }
}

END {
  for (asic = 0; asic < NUM_ASIC; ++asic) {
    if ("" != asic_type[asic]) {
      type = asic_type[asic];
      asic_type_cnt[asic] = 0;
    } else {
      if (++asic_type_cnt[asic] > STALE_COUNT) {
        type = "OFF";
      } else {
        type = asic_type_cache[asic];
      }
    }
    if ("" != asic_temp[asic]) {
      temp = (0.0 + asic_temp[asic]);
      asic_temp_cnt[asic] = 0;
    } else {
      if (++asic_temp_cnt[asic] > STALE_COUNT) {
        temp = 0.0;
      } else {
        temp = asic_temp_cache[asic];
      }
    }
    for (die = 0; die < NUM_DIE; ++die) {
      if ("" != asic_freq[asic, die]) {
        freq[die] = (0.0 + asic_freq[asic, die]);
        asic_freq_cnt[asic, die] = 0;
      } else {
        if (++asic_freq_cnt[asic, die] > STALE_COUNT) {
          freq[die] = 0.0;
        } else {
          freq[die] = asic_freq_cache[asic, die];
        }
      }
      if ("" != asic_volt[asic, die]) {
        volt[die] = (0.0 + asic_volt[asic, die]);
        asic_volt_cnt[asic, die] = 0;
      } else {
        if (++asic_volt_cnt[asic, die] > STALE_COUNT) {
          volt[die] = 0.0;
        } else {
          volt[die] = asic_volt_cache[asic, die];
        }
      }
    }
    for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
      if ("" != asic_dcdctemp[asic, dcdc]) {
        dcdctemp[dcdc] = (0.0 + asic_dcdctemp[asic, dcdc]);
	asic_dcdctemp_cnt[asic, dcdc] = 0;
      } else {
        if (++asic_dcdctemp_cnt[asic, dcdc] > STALE_COUNT) {
          dcdctemp[dcdc] = 0.0;
        } else {
          dcdctemp[dcdc] = asic_dcdctemp_cache[asic, dcdc];
        }
      }
      if ("" != asic_dcdcVout[asic, dcdc]) {
        dcdcVout[dcdc] = (0.0 + asic_dcdcVout[asic, dcdc]);
	asic_dcdcVout_cnt[asic, dcdc] = 0;
      } else {
        if (++asic_dcdcVout_cnt[asic, dcdc] > STALE_COUNT) {
          dcdcVout[dcdc] = 0.0;
        } else {
          dcdcVout[dcdc] = asic_dcdcVout_cache[asic, dcdc];
        }
      }
      if ("" != asic_dcdcIout[asic, dcdc]) {
        dcdcIout[dcdc] = (0.0 + asic_dcdcIout[asic, dcdc]);
	asic_dcdcIout_cnt[asic, dcdc] = 0;
      } else {
        if (++asic_dcdcIout_cnt[asic, dcdc] > STALE_COUNT) {
          dcdcIout[dcdc] = 0.0;
        } else {
          dcdcIout[dcdc] = asic_dcdcIout_cache[asic, dcdc];
        }
      }
    }
    printf("ASICCACHE %d %s %.1f", asic, type, temp);
    for (die = 0; die < NUM_DIE; ++die) {
      printf(" %d %.4f", freq[die], volt[die]);
    }
    for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
      printf(" %.1f %.4f %.4f", dcdctemp[dcdc], dcdcVout[dcdc], dcdcIout[dcdc]);
    }
    printf("\nSTALECOUNTERS %d %d %d", asic, asic_type_cnt[asic], asic_temp_cnt[asic]);
    for (die = 0; die < NUM_DIE; ++die) {
      printf(" %d %d", asic_freq_cnt[asic, die], asic_volt_cnt[asic, die]);
    }
    for (dcdc = 0; dcdc < NUM_DCDC; ++dcdc) {
      printf(" %d %d %d", asic_dcdctemp_cnt[asic, dcdc], asic_dcdcVout_cnt[asic, dcdc], asic_dcdcIout_cnt[asic, dcdc]);
    }
    printf("\n");
  }
}


Translators/GoogleTranslate: switch to fallback API, fix (partly) #123

####################################################################
# GoogleTranslate.awk                                              #
####################################################################
#
# Last Updated: 18 Dec 2015
# https://translate.google.com/translate/releases/twsfe_w_20151214_RC03/r/js/desktop_module_main.js
BEGIN { provides("google") }

function genRL(a, x,
               ####
               b, c, d, i, y) {
    tokenize(y, x)
    parseList(b, y)
    i = SUBSEP 0
    for (c = 0; c < length(b[i]) - 2; c += 3) {
        d = b[i][c + 2]
        d = d >= 97 ? d - 87 :
            d - 48 # convert to number
        d = b[i][c + 1] == 43 ? rshift(a, d) : lshift(a, d)
        a = b[i][c] == 43 ? and(a + d, 4294967295) : xor(a, d)
    }
    return a
}

function genTK(text,
               ####
               a, d, dLen, e, tkk, ub, vb) {
    if (TK[text]) return TK[text]

    tkk = systime() / 3600
    ub = "[43,45,51,94,43,98,43,45,102]"
    vb = "[43,45,97,94,43,54]"

    dLen = dump(text, d) # convert to byte array
    a = tkk
    for (e = 1; e <= dLen; e++)
        a = genRL(a + d[e], vb)
    a = genRL(a, ub)
    0 > a && (a = and(a, 2147483647) + 2147483648)
    a %= 1e6
    TK[text] = a "." xor(a, tkk)

    l(text, "text")
    l(tkk, "tkk")
    l(TK[text], "tk")
    return TK[text]
}

function googleInit() {
    HttpProtocol = "http://"
    HttpHost = "translate.googleapis.com"
    HttpPort = 80
}

function googleRequestUrl(text, sl, tl, hl) {
    return HttpPathPrefix "/translate_a/single?client=gtx"              \
        "&ie=UTF-8&oe=UTF-8"                                            \
        "&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&dt=at"  \
        "&sl=" sl "&tl=" tl "&hl=" hl                                   \
        "&q=" preprocess(text)
}

function googleTTSUrl(text, tl) {
    return HttpProtocol HttpHost "/translate_tts?ie=UTF-8&client=gtx"	\
        "&tl=" tl "&q=" preprocess(text)
}

function googleWebTranslateUrl(uri, sl, tl, hl) {
    return "https://translate.google.com/translate?"    \
        "hl=" hl "&sl=" sl "&tl=" tl "&u=" uri
}

# Get the translation of a string.
function googleTranslate(text, sl, tl, hl,
                         isVerbose, toSpeech, returnPlaylist, returnIl,
                         ####
                         r,
                         content, tokens, ast,
                         _sl, _tl, _hl, il, ils, isPhonetic,
                         article, example, explanation, ref, word,
                         translation, translations, phonetics,
                         wordClasses, words, segments, altTranslations,
                         original, oPhonetics, oWordClasses, oWords,
                         oRefs, oSynonymClasses, oSynonyms,
                         oExamples, oSeeAlso,
                         wShowOriginal, wShowOriginalPhonetics,
                         wShowTranslation, wShowTranslationPhonetics,
                         wShowPromptMessage, wShowLanguages,
                         wShowOriginalDictionary, wShowDictionary,
                         wShowAlternatives,
                         hasWordClasses, hasAltTranslations,
                         i, j, k, group, temp, saveSortedIn) {
    isPhonetic = match(tl, /^@/)
    tl = substr(tl, 1 + isPhonetic)

    if (!getCode(tl)) {
        # Check if target language is supported
        w("[WARNING] Unknown target language code: " tl)
    } else if (isRTL(tl)) {
        # Check if target language is R-to-L
        if (!FriBidi)
            w("[WARNING] " getName(tl) " is a right-to-left language, but FriBidi is not found.")
    }

    # Convert codes or aliases to standard codes used by Google Translate
    # If the code or alias cannot be found, use as it is
    _sl = getCode(sl); if (!_sl) _sl = sl
    _tl = getCode(tl); if (!_tl) _tl = tl
    _hl = getCode(hl); if (!_hl) _hl = hl
    content = getResponse(text, _sl, _tl, _hl)
    tokenize(tokens, content)
    parseJsonArray(ast, tokens)

    l(content, "content", 1, 1)
    l(tokens, "tokens", 1, 0, 1)
    l(ast, "ast")
    if (!isarray(ast) || !anything(ast)) {
        e("[ERROR] Oops! Something went wrong and I can't translate it for you :(")
        ExitCode = 1
        return
    }

    saveSortedIn = PROCINFO["sorted_in"]
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (i in ast) {
        if (i ~ "^0" SUBSEP "0" SUBSEP "[[:digit:]]+" SUBSEP "0$")
            append(translations, postprocess(literal(ast[i])))
        if (i ~ "^0" SUBSEP "0" SUBSEP "[[:digit:]]+" SUBSEP "1$")
            append(original, literal(ast[i]))
        if (i ~ "^0" SUBSEP "0" SUBSEP "[[:digit:]]+" SUBSEP "2$")
            append(phonetics, literal(ast[i]))
        if (i ~ "^0" SUBSEP "0" SUBSEP "[[:digit:]]+" SUBSEP "3$")
            append(oPhonetics, literal(ast[i]))

        # 1 - word classes and explanations
        if (match(i, "^0" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            wordClasses[group[1]] = literal(ast[i])
        if (match(i, "^0" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "2" SUBSEP "([[:digit:]]+)" SUBSEP "([[:digit:]]+)$", group))
            words[group[1]][group[2]][group[3]] = literal(ast[i])
        if (match(i, "^0" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "2" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)$", group))
            words[group[1]][group[2]]["1"][group[3]] = literal(ast[i])

        # 5 - alternative translations
        if (match(i, "^0" SUBSEP "5" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group)) {
            segments[group[1]] = literal(ast[i])
            altTranslations[group[1]][0] = ""
        }
        if (match(i, "^0" SUBSEP "5" SUBSEP "([[:digit:]]+)" SUBSEP "2" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            altTranslations[group[1]][group[2]] = postprocess(literal(ast[i]))

        # 8 - identified source languages
        if (i ~ "^0" SUBSEP "8" SUBSEP "0" SUBSEP "[[:digit:]]+$" ||
            i ~ "^0" SUBSEP "2$")
            append(ils, literal(ast[i]))

        # 11 - (original) word classes and synonyms
        if (match(i, "^0" SUBSEP "11" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            oSynonymClasses[group[1]] = literal(ast[i])
        if (match(i, "^0" SUBSEP "11" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "1$", group))
            if (ast[i]) {
                oRefs[literal(ast[i])][1] = group[1]
                oRefs[literal(ast[i])][2] = group[2]
            }
        if (match(i, "^0" SUBSEP "11" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "0" SUBSEP "([[:digit:]]+)$", group))
            oSynonyms[group[1]][group[2]][group[3]] = literal(ast[i])

        # 12 - (original) word classes and explanations
        if (match(i, "^0" SUBSEP "12" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            oWordClasses[group[1]] = literal(ast[i])
        if (match(i, "^0" SUBSEP "12" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            oWords[group[1]][group[2]][0] = literal(ast[i])
        if (match(i, "^0" SUBSEP "12" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "1$", group))
            oWords[group[1]][group[2]][1] = literal(ast[i])
        if (match(i, "^0" SUBSEP "12" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "2$", group))
            oWords[group[1]][group[2]][2] = postprocess(literal(ast[i]))

        # 13 - (original) examples
        if (match(i, "^0" SUBSEP "13" SUBSEP "0" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            oExamples[group[1]] = postprocess(literal(ast[i]))

        # 14 - (original) see also
        if (match(i, "^0" SUBSEP "14" SUBSEP "0" SUBSEP "([[:digit:]]+)$", group))
            oSeeAlso[group[1]] = literal(ast[i])
    }
    PROCINFO["sorted_in"] = saveSortedIn

    translation = join(translations)

    returnIl[0] = il = !anything(ils) || belongsTo(sl, ils) ? sl : ils[0]
    if (Option["verbose"] < 0)
        return getList(il)

    # Generate output
    if (!isVerbose) {
        # Brief mode

        r = isPhonetic && anything(phonetics) ?
            prettify("brief-translation-phonetics", join(phonetics)) :
            prettify("brief-translation", s(translation, tl))

        if (toSpeech) {
            returnPlaylist[0]["text"] = translation
            returnPlaylist[0]["tl"] = tl
        }

    } else {
        # Verbose mode

        wShowOriginal = Option["show-original"]
        wShowOriginalPhonetics = Option["show-original-phonetics"]
        wShowTranslation = Option["show-translation"]
        wShowTranslationPhonetics = Option["show-translation-phonetics"]
        wShowPromptMessage = Option["show-prompt-message"]
        wShowLanguages = Option["show-languages"]
        wShowOriginalDictionary = Option["show-original-dictionary"]
        wShowDictionary = Option["show-dictionary"]
        wShowAlternatives = Option["show-alternatives"]

        if (!anything(oPhonetics)) wShowOriginalPhonetics = 0
        if (!anything(phonetics)) wShowTranslationPhonetics = 0
        if (getCode(il) == getCode(tl) &&                               \
            (isarray(oWordClasses) || isarray(oSynonymClasses) ||       \
             isarray(oExamples) || isarray(oSeeAlso))) {
            wShowOriginalDictionary = 1
            wShowTranslation = 0
        }
        hasWordClasses = exists(wordClasses)
        hasAltTranslations = exists(altTranslations[0])
        if (!hasWordClasses && !hasAltTranslations)
            wShowPromptMessage = wShowLanguages = 0
        if (!hasWordClasses) wShowDictionary = 0
        if (hasWordClasses || !hasAltTranslations) wShowAlternatives = 0

        if (wShowOriginal) {
            # Display: original text & phonetics
            if (r) r = r RS RS
            r = r m("-- display original text & phonetics")
            r = r prettify("original", s(join(original), il))
            if (wShowOriginalPhonetics)
                r = r RS prettify("original-phonetics", showPhonetics(join(oPhonetics), il))
        }

        if (wShowTranslation) {
            # Display: major translation & phonetics
            if (r) r = r RS RS
            r = r m("-- display major translation & phonetics")
            r = r prettify("translation", s(translation, tl))
            if (wShowTranslationPhonetics)
                r = r RS prettify("translation-phonetics", showPhonetics(join(phonetics), tl))
        }

        if (wShowPromptMessage || wShowLanguages)
            if (r) r = r RS
        if (wShowPromptMessage) {
            if (hasWordClasses) {
                # Display: prompt message (Definitions of ...)
                if (r) r = r RS
                r = r m("-- display prompt message (Definitions of ...)")
                if (isRTL(hl)) # home language is R-to-L
                    r = r prettify("prompt-message", s(showDefinitionsOf(hl, join(original))))
                else { # home language is L-to-R
                    split(showDefinitionsOf(hl, "\0%s\0"), group, "\0")
                    for (i = 1; i <= length(group); i++) {
                        if (group[i] == "%s")
                            r = r prettify("prompt-message-original", show(join(original), il))
                        else
                            r = r prettify("prompt-message", group[i])
                    }
                }
            } else if (hasAltTranslations) {
                # Display: prompt message (Translations of ...)
                if (r) r = r RS
                r = r m("-- display prompt message (Translations of ...)")
                if (isRTL(hl)) # home language is R-to-L
                    r = r prettify("prompt-message", s(showTranslationsOf(hl, join(original))))
                else { # home language is L-to-R
                    split(showTranslationsOf(hl, "\0%s\0"), group, "\0")
                    for (i = 1; i <= length(group); i++) {
                        if (group[i] == "%s")
                            r = r prettify("prompt-message-original", show(join(original), il))
                        else
                            r = r prettify("prompt-message", group[i])
                    }
                }
            }
        }
        if (wShowLanguages) {
            # Display: source language -> target language
            if (r) r = r RS
            r = r m("-- display source language -> target language")
            temp = Option["fmt-languages"]
            if (!temp) temp = "[ %s -> %t ]"
            split(temp, group, /(%s|%S|%t|%T)/)
            r = r prettify("languages", group[1])
            if (temp ~ /%s/)
                r = r prettify("languages-sl", getDisplay(il))
            if (temp ~ /%S/)
                r = r prettify("languages-sl", getName(il))
            r = r prettify("languages", group[2])
            if (temp ~ /%t/)
                r = r prettify("languages-tl", getDisplay(tl))
            if (temp ~ /%T/)
                r = r prettify("languages-tl", getName(tl))
            r = r prettify("languages", group[3])
        }

        if (wShowOriginalDictionary) {
            # Display: original dictionary
            if (exists(oWordClasses)) {
                # Detailed explanations
                if (r) r = r RS
                r = r m("-- display original dictionary (detailed explanations)")
                for (i = 0; i < length(oWordClasses); i++) {
                    r = (i > 0 ? r RS : r) RS prettify("original-dictionary-detailed-word-class", s(oWordClasses[i], hl))
                    for (j = 0; j < length(oWords[i]); j++) {
                        explanation = oWords[i][j][0]
                        ref = oWords[i][j][1]
                        example = oWords[i][j][2]

                        r = (j > 0 ? r RS : r) RS prettify("original-dictionary-detailed-explanation", ins(1, explanation, il))
                        if (example)
                            r = r RS prettify("original-dictionary-detailed-example", ins(2, "- \"" example "\"", il))
                        if (ref && isarray(oRefs[ref])) {
                            temp = prettify("original-dictionary-detailed-synonyms", ins(1, show(showSynonyms(hl), hl) ": "))
                            temp = temp prettify("original-dictionary-detailed-synonyms-item", show(oSynonyms[oRefs[ref][1]][oRefs[ref][2]][0], il))
                            for (k = 1; k < length(oSynonyms[oRefs[ref][1]][oRefs[ref][2]]); k++)
                                temp = temp prettify("original-dictionary-detailed-synonyms", ", ") \
                                    prettify("original-dictionary-detailed-synonyms-item", show(oSynonyms[oRefs[ref][1]][oRefs[ref][2]][k], il))
                            r = r RS temp
                        }
                    }
                }
            }
            if (exists(oSynonymClasses)) {
                # Synonyms
                r = r RS RS
                r = r m("-- display original dictionary (synonyms)")
                r = r prettify("original-dictionary-synonyms", s(showSynonyms(hl), hl))
                for (i = 0; i < length(oSynonymClasses); i++) {
                    r = (i > 0 ? r RS : r) RS prettify("original-dictionary-synonyms-word-class", ins(1, oSynonymClasses[i], hl))
                    for (j = 0; j < length(oSynonyms[i]); j++) {
                        temp = prettify("original-dictionary-synonyms-synonyms", ins(2, "- "))
                        temp = temp prettify("original-dictionary-synonyms-synonyms-item", show(oSynonyms[i][j][0], il))
                        for (k = 1; k < length(oSynonyms[i][j]); k++)
                            temp = temp prettify("original-dictionary-synonyms-synonyms", ", ") \
                                prettify("original-dictionary-synonyms-synonyms-item", show(oSynonyms[i][j][k], il))
                        r = r RS temp
                    }
                }
            }
            if (exists(oExamples)) {
                # Examples
                r = r RS RS
                r = r m("-- display original dictionary (examples)")
                r = r prettify("original-dictionary-examples", s(showExamples(hl), hl))
                for (i = 0; i < length(oExamples); i++) {
                    example = oExamples[i]

                    temp = prettify("original-dictionary-examples-example", ins(1, "- "))
                    split(example, group, /(\u003cb\u003e|\u003c\/b\u003e)/)
                    if (isRTL(il)) # target language is R-to-L
                        temp = temp show(group[1] group[2] group[3], il)
                    else # target language is L-to-R
                        temp = temp prettify("original-dictionary-examples-example", group[1]) \
                            prettify("original-dictionary-examples-original", group[2]) \
                            prettify("original-dictionary-examples-example", group[3])
                    r = (i > 0 ? r RS : r) RS temp
                }
            }
            if (exists(oSeeAlso)) {
                # See also
                r = r RS RS
                r = r m("-- display original dictionary (see also)")
                r = r prettify("original-dictionary-see-also", s(showSeeAlso(hl), hl))
                temp = ins(1, prettify("original-dictionary-see-also-phrases-item", show(oSeeAlso[0], il)))
                for (k = 1; k < length(oSeeAlso); k++)
                    temp = temp prettify("original-dictionary-see-also-phrases", ", ") \
                        prettify("original-dictionary-see-also-phrases-item", show(oSeeAlso[k], il))
                r = r RS temp
            }
        }

        if (wShowDictionary) {
            # Display: dictionary entries
            if (r) r = r RS
            r = r m("-- display dictionary entries")
            for (i = 0; i < length(wordClasses); i++) {
                r = (i > 0 ? r RS : r) RS prettify("dictionary-word-class", s(wordClasses[i], hl))
                for (j = 0; j < length(words[i]); j++) {
                    word = words[i][j][0]
                    article = words[i][j][4]
                    if (isRTL(il))
                        explanation = join(words[i][j][1], ", ")
                    else {
                        explanation = prettify("dictionary-explanation-item", words[i][j][1][0])
                        for (k = 1; k < length(words[i][j][1]); k++)
                            explanation = explanation prettify("dictionary-explanation", ", ") \
                                prettify("dictionary-explanation-item", words[i][j][1][k])
                    }

                    r = r RS prettify("dictionary-word", ins(1, (article ? "(" article ") " : "") word, tl))
                    if (isRTL(il))
                        r = r RS prettify("dictionary-explanation-item", ins(2, explanation, il))
                    else
                        r = r RS ins(2, explanation)
                }
            }
        }

        if (wShowAlternatives) {
            # Display: alternative translations
            if (r) r = r RS RS
            r = r m("-- display alternative translations")
            for (i = 0; i < length(altTranslations); i++) {
                r = (i > 0 ? r RS : r) prettify("alternatives-original", show(segments[i], il))
                if (isRTL(tl)) {
                    temp = join(altTranslations[i], ", ")
                    r = r RS prettify("alternatives-translations-item", ins(1, temp, tl))
                } else {
                    temp = prettify("alternatives-translations-item", altTranslations[i][0])
                    for (j = 1; j < length(altTranslations[i]); j++)
                        temp = temp prettify("alternatives-translations", ", ") \
                            prettify("alternatives-translations-item", altTranslations[i][j])
                    r = r RS ins(1, temp)
                }
            }
        }

        if (toSpeech) {
            if (index(showTranslationsOf(hl, "%s"), "%s") > 2) {
                returnPlaylist[0]["text"] = showTranslationsOf(hl)
                returnPlaylist[0]["tl"] = hl
                returnPlaylist[1]["text"] = join(original)
                returnPlaylist[1]["tl"] = il
            } else {
                returnPlaylist[0]["text"] = join(original)
                returnPlaylist[0]["tl"] = il
                returnPlaylist[1]["text"] = showTranslationsOf(hl)
                returnPlaylist[1]["tl"] = hl
            }
            returnPlaylist[2]["text"] = translation
            returnPlaylist[2]["tl"] = tl
        }
    }

    return r
}

####################################################################
# GoogleTranslate.awk                                              #
####################################################################
#
# Last Updated: 18 Dec 2015
# https://translate.google.com/translate/releases/twsfe_w_20151214_RC03/r/js/desktop_module_main.js
BEGIN { provides("google") }

function genRL(a, x,
               ####
               b, c, d, i, y) {
    tokenize(y, x)
    parseList(b, y)
    i = SUBSEP 0
    for (c = 0; c < length(b[i]) - 2; c += 3) {
        d = b[i][c + 2]
        d = d >= 97 ? d - 87 :
            d - 48 # convert to number
        d = b[i][c + 1] == 43 ? rshift(a, d) : lshift(a, d)
        a = b[i][c] == 43 ? and(a + d, 4294967295) : xor(a, d)
    }
    return a
}

function genTK(text,
               ####
               a, d, dLen, e, tkk, ub, vb) {
    if (TK[text]) return TK[text]

    tkk = systime() / 3600
    ub = "[43,45,51,94,43,98,43,45,102]"
    vb = "[43,45,97,94,43,54]"

    dLen = dump(text, d) # convert to byte array
    a = tkk
    for (e = 1; e <= dLen; e++)
        a = genRL(a + d[e], vb)
    a = genRL(a, ub)
    0 > a && (a = and(a, 2147483647) + 2147483648)
    a %= 1e6
    TK[text] = a "." xor(a, tkk)

    l(text, "text")
    l(tkk, "tkk")
    l(TK[text], "tk")
    return TK[text]
}

function googleInit() {
    HttpProtocol = "http://"
    HttpHost = "translate.google.com"
    HttpPort = 80
}

function googleRequestUrl(text, sl, tl, hl) {
    return HttpPathPrefix "/translate_a/single?client=t"                \
        "&ie=UTF-8&oe=UTF-8"                                            \
        "&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&dt=at"  \
        "&sl=" sl "&tl=" tl "&hl=" hl                                   \
        "&tk=" genTK(text) "&q=" preprocess(text)
}

function googleTTSUrl(text, tl) {
    return HttpProtocol HttpHost "/translate_tts?ie=UTF-8&client=t"	\
        "&tl=" tl "&tk=" genTK(text) "&q=" preprocess(text)
}

function googleWebTranslateUrl(uri, sl, tl, hl) {
    return "https://translate.google.com/translate?"    \
        "hl=" hl "&sl=" sl "&tl=" tl "&u=" uri
}

# Get the translation of a string.
function googleTranslate(text, sl, tl, hl,
                         isVerbose, toSpeech, returnPlaylist, returnIl,
                         ####
                         r,
                         content, tokens, ast,
                         _sl, _tl, _hl, il, ils, isPhonetic,
                         article, example, explanation, ref, word,
                         translation, translations, phonetics,
                         wordClasses, words, segments, altTranslations,
                         original, oPhonetics, oWordClasses, oWords,
                         oRefs, oSynonymClasses, oSynonyms,
                         oExamples, oSeeAlso,
                         wShowOriginal, wShowOriginalPhonetics,
                         wShowTranslation, wShowTranslationPhonetics,
                         wShowPromptMessage, wShowLanguages,
                         wShowOriginalDictionary, wShowDictionary,
                         wShowAlternatives,
                         hasWordClasses, hasAltTranslations,
                         i, j, k, group, temp, saveSortedIn) {
    isPhonetic = match(tl, /^@/)
    tl = substr(tl, 1 + isPhonetic)

    if (!getCode(tl)) {
        # Check if target language is supported
        w("[WARNING] Unknown target language code: " tl)
    } else if (isRTL(tl)) {
        # Check if target language is R-to-L
        if (!FriBidi)
            w("[WARNING] " getName(tl) " is a right-to-left language, but FriBidi is not found.")
    }

    # Convert codes or aliases to standard codes used by Google Translate
    # If the code or alias cannot be found, use as it is
    _sl = getCode(sl); if (!_sl) _sl = sl
    _tl = getCode(tl); if (!_tl) _tl = tl
    _hl = getCode(hl); if (!_hl) _hl = hl
    content = getResponse(text, _sl, _tl, _hl)
    tokenize(tokens, content)
    parseJsonArray(ast, tokens)

    l(content, "content", 1, 1)
    l(tokens, "tokens", 1, 0, 1)
    l(ast, "ast")
    if (!isarray(ast) || !anything(ast)) {
        e("[ERROR] Oops! Something went wrong and I can't translate it for you :(")
        ExitCode = 1
        return
    }

    saveSortedIn = PROCINFO["sorted_in"]
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (i in ast) {
        if (i ~ "^0" SUBSEP "0" SUBSEP "[[:digit:]]+" SUBSEP "0$")
            append(translations, postprocess(literal(ast[i])))
        if (i ~ "^0" SUBSEP "0" SUBSEP "[[:digit:]]+" SUBSEP "1$")
            append(original, literal(ast[i]))
        if (i ~ "^0" SUBSEP "0" SUBSEP "[[:digit:]]+" SUBSEP "2$")
            append(phonetics, literal(ast[i]))
        if (i ~ "^0" SUBSEP "0" SUBSEP "[[:digit:]]+" SUBSEP "3$")
            append(oPhonetics, literal(ast[i]))

        # 1 - word classes and explanations
        if (match(i, "^0" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            wordClasses[group[1]] = literal(ast[i])
        if (match(i, "^0" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "2" SUBSEP "([[:digit:]]+)" SUBSEP "([[:digit:]]+)$", group))
            words[group[1]][group[2]][group[3]] = literal(ast[i])
        if (match(i, "^0" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "2" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)$", group))
            words[group[1]][group[2]]["1"][group[3]] = literal(ast[i])

        # 5 - alternative translations
        if (match(i, "^0" SUBSEP "5" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group)) {
            segments[group[1]] = literal(ast[i])
            altTranslations[group[1]][0] = ""
        }
        if (match(i, "^0" SUBSEP "5" SUBSEP "([[:digit:]]+)" SUBSEP "2" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            altTranslations[group[1]][group[2]] = postprocess(literal(ast[i]))

        # 8 - identified source languages
        if (i ~ "^0" SUBSEP "8" SUBSEP "0" SUBSEP "[[:digit:]]+$" ||
            i ~ "^0" SUBSEP "2$")
            append(ils, literal(ast[i]))

        # 11 - (original) word classes and synonyms
        if (match(i, "^0" SUBSEP "11" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            oSynonymClasses[group[1]] = literal(ast[i])
        if (match(i, "^0" SUBSEP "11" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "1$", group))
            if (ast[i]) {
                oRefs[literal(ast[i])][1] = group[1]
                oRefs[literal(ast[i])][2] = group[2]
            }
        if (match(i, "^0" SUBSEP "11" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "0" SUBSEP "([[:digit:]]+)$", group))
            oSynonyms[group[1]][group[2]][group[3]] = literal(ast[i])

        # 12 - (original) word classes and explanations
        if (match(i, "^0" SUBSEP "12" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            oWordClasses[group[1]] = literal(ast[i])
        if (match(i, "^0" SUBSEP "12" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            oWords[group[1]][group[2]][0] = literal(ast[i])
        if (match(i, "^0" SUBSEP "12" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "1$", group))
            oWords[group[1]][group[2]][1] = literal(ast[i])
        if (match(i, "^0" SUBSEP "12" SUBSEP "([[:digit:]]+)" SUBSEP "1" SUBSEP "([[:digit:]]+)" SUBSEP "2$", group))
            oWords[group[1]][group[2]][2] = postprocess(literal(ast[i]))

        # 13 - (original) examples
        if (match(i, "^0" SUBSEP "13" SUBSEP "0" SUBSEP "([[:digit:]]+)" SUBSEP "0$", group))
            oExamples[group[1]] = postprocess(literal(ast[i]))

        # 14 - (original) see also
        if (match(i, "^0" SUBSEP "14" SUBSEP "0" SUBSEP "([[:digit:]]+)$", group))
            oSeeAlso[group[1]] = literal(ast[i])
    }
    PROCINFO["sorted_in"] = saveSortedIn

    translation = join(translations)

    returnIl[0] = il = !anything(ils) || belongsTo(sl, ils) ? sl : ils[0]
    if (Option["verbose"] < 0)
        return getList(il)

    # Generate output
    if (!isVerbose) {
        # Brief mode

        r = isPhonetic && anything(phonetics) ?
            prettify("brief-translation-phonetics", join(phonetics)) :
            prettify("brief-translation", s(translation, tl))

        if (toSpeech) {
            returnPlaylist[0]["text"] = translation
            returnPlaylist[0]["tl"] = tl
        }

    } else {
        # Verbose mode

        wShowOriginal = Option["show-original"]
        wShowOriginalPhonetics = Option["show-original-phonetics"]
        wShowTranslation = Option["show-translation"]
        wShowTranslationPhonetics = Option["show-translation-phonetics"]
        wShowPromptMessage = Option["show-prompt-message"]
        wShowLanguages = Option["show-languages"]
        wShowOriginalDictionary = Option["show-original-dictionary"]
        wShowDictionary = Option["show-dictionary"]
        wShowAlternatives = Option["show-alternatives"]

        if (!anything(oPhonetics)) wShowOriginalPhonetics = 0
        if (!anything(phonetics)) wShowTranslationPhonetics = 0
        if (getCode(il) == getCode(tl) &&                               \
            (isarray(oWordClasses) || isarray(oSynonymClasses) ||       \
             isarray(oExamples) || isarray(oSeeAlso))) {
            wShowOriginalDictionary = 1
            wShowTranslation = 0
        }
        hasWordClasses = exists(wordClasses)
        hasAltTranslations = exists(altTranslations[0])
        if (!hasWordClasses && !hasAltTranslations)
            wShowPromptMessage = wShowLanguages = 0
        if (!hasWordClasses) wShowDictionary = 0
        if (hasWordClasses || !hasAltTranslations) wShowAlternatives = 0

        if (wShowOriginal) {
            # Display: original text & phonetics
            if (r) r = r RS RS
            r = r m("-- display original text & phonetics")
            r = r prettify("original", s(join(original), il))
            if (wShowOriginalPhonetics)
                r = r RS prettify("original-phonetics", showPhonetics(join(oPhonetics), il))
        }

        if (wShowTranslation) {
            # Display: major translation & phonetics
            if (r) r = r RS RS
            r = r m("-- display major translation & phonetics")
            r = r prettify("translation", s(translation, tl))
            if (wShowTranslationPhonetics)
                r = r RS prettify("translation-phonetics", showPhonetics(join(phonetics), tl))
        }

        if (wShowPromptMessage || wShowLanguages)
            if (r) r = r RS
        if (wShowPromptMessage) {
            if (hasWordClasses) {
                # Display: prompt message (Definitions of ...)
                if (r) r = r RS
                r = r m("-- display prompt message (Definitions of ...)")
                if (isRTL(hl)) # home language is R-to-L
                    r = r prettify("prompt-message", s(showDefinitionsOf(hl, join(original))))
                else { # home language is L-to-R
                    split(showDefinitionsOf(hl, "\0%s\0"), group, "\0")
                    for (i = 1; i <= length(group); i++) {
                        if (group[i] == "%s")
                            r = r prettify("prompt-message-original", show(join(original), il))
                        else
                            r = r prettify("prompt-message", group[i])
                    }
                }
            } else if (hasAltTranslations) {
                # Display: prompt message (Translations of ...)
                if (r) r = r RS
                r = r m("-- display prompt message (Translations of ...)")
                if (isRTL(hl)) # home language is R-to-L
                    r = r prettify("prompt-message", s(showTranslationsOf(hl, join(original))))
                else { # home language is L-to-R
                    split(showTranslationsOf(hl, "\0%s\0"), group, "\0")
                    for (i = 1; i <= length(group); i++) {
                        if (group[i] == "%s")
                            r = r prettify("prompt-message-original", show(join(original), il))
                        else
                            r = r prettify("prompt-message", group[i])
                    }
                }
            }
        }
        if (wShowLanguages) {
            # Display: source language -> target language
            if (r) r = r RS
            r = r m("-- display source language -> target language")
            temp = Option["fmt-languages"]
            if (!temp) temp = "[ %s -> %t ]"
            split(temp, group, /(%s|%S|%t|%T)/)
            r = r prettify("languages", group[1])
            if (temp ~ /%s/)
                r = r prettify("languages-sl", getDisplay(il))
            if (temp ~ /%S/)
                r = r prettify("languages-sl", getName(il))
            r = r prettify("languages", group[2])
            if (temp ~ /%t/)
                r = r prettify("languages-tl", getDisplay(tl))
            if (temp ~ /%T/)
                r = r prettify("languages-tl", getName(tl))
            r = r prettify("languages", group[3])
        }

        if (wShowOriginalDictionary) {
            # Display: original dictionary
            if (exists(oWordClasses)) {
                # Detailed explanations
                if (r) r = r RS
                r = r m("-- display original dictionary (detailed explanations)")
                for (i = 0; i < length(oWordClasses); i++) {
                    r = (i > 0 ? r RS : r) RS prettify("original-dictionary-detailed-word-class", s(oWordClasses[i], hl))
                    for (j = 0; j < length(oWords[i]); j++) {
                        explanation = oWords[i][j][0]
                        ref = oWords[i][j][1]
                        example = oWords[i][j][2]

                        r = (j > 0 ? r RS : r) RS prettify("original-dictionary-detailed-explanation", ins(1, explanation, il))
                        if (example)
                            r = r RS prettify("original-dictionary-detailed-example", ins(2, "- \"" example "\"", il))
                        if (ref && isarray(oRefs[ref])) {
                            temp = prettify("original-dictionary-detailed-synonyms", ins(1, show(showSynonyms(hl), hl) ": "))
                            temp = temp prettify("original-dictionary-detailed-synonyms-item", show(oSynonyms[oRefs[ref][1]][oRefs[ref][2]][0], il))
                            for (k = 1; k < length(oSynonyms[oRefs[ref][1]][oRefs[ref][2]]); k++)
                                temp = temp prettify("original-dictionary-detailed-synonyms", ", ") \
                                    prettify("original-dictionary-detailed-synonyms-item", show(oSynonyms[oRefs[ref][1]][oRefs[ref][2]][k], il))
                            r = r RS temp
                        }
                    }
                }
            }
            if (exists(oSynonymClasses)) {
                # Synonyms
                r = r RS RS
                r = r m("-- display original dictionary (synonyms)")
                r = r prettify("original-dictionary-synonyms", s(showSynonyms(hl), hl))
                for (i = 0; i < length(oSynonymClasses); i++) {
                    r = (i > 0 ? r RS : r) RS prettify("original-dictionary-synonyms-word-class", ins(1, oSynonymClasses[i], hl))
                    for (j = 0; j < length(oSynonyms[i]); j++) {
                        temp = prettify("original-dictionary-synonyms-synonyms", ins(2, "- "))
                        temp = temp prettify("original-dictionary-synonyms-synonyms-item", show(oSynonyms[i][j][0], il))
                        for (k = 1; k < length(oSynonyms[i][j]); k++)
                            temp = temp prettify("original-dictionary-synonyms-synonyms", ", ") \
                                prettify("original-dictionary-synonyms-synonyms-item", show(oSynonyms[i][j][k], il))
                        r = r RS temp
                    }
                }
            }
            if (exists(oExamples)) {
                # Examples
                r = r RS RS
                r = r m("-- display original dictionary (examples)")
                r = r prettify("original-dictionary-examples", s(showExamples(hl), hl))
                for (i = 0; i < length(oExamples); i++) {
                    example = oExamples[i]

                    temp = prettify("original-dictionary-examples-example", ins(1, "- "))
                    split(example, group, /(\u003cb\u003e|\u003c\/b\u003e)/)
                    if (isRTL(il)) # target language is R-to-L
                        temp = temp show(group[1] group[2] group[3], il)
                    else # target language is L-to-R
                        temp = temp prettify("original-dictionary-examples-example", group[1]) \
                            prettify("original-dictionary-examples-original", group[2]) \
                            prettify("original-dictionary-examples-example", group[3])
                    r = (i > 0 ? r RS : r) RS temp
                }
            }
            if (exists(oSeeAlso)) {
                # See also
                r = r RS RS
                r = r m("-- display original dictionary (see also)")
                r = r prettify("original-dictionary-see-also", s(showSeeAlso(hl), hl))
                temp = ins(1, prettify("original-dictionary-see-also-phrases-item", show(oSeeAlso[0], il)))
                for (k = 1; k < length(oSeeAlso); k++)
                    temp = temp prettify("original-dictionary-see-also-phrases", ", ") \
                        prettify("original-dictionary-see-also-phrases-item", show(oSeeAlso[k], il))
                r = r RS temp
            }
        }

        if (wShowDictionary) {
            # Display: dictionary entries
            if (r) r = r RS
            r = r m("-- display dictionary entries")
            for (i = 0; i < length(wordClasses); i++) {
                r = (i > 0 ? r RS : r) RS prettify("dictionary-word-class", s(wordClasses[i], hl))
                for (j = 0; j < length(words[i]); j++) {
                    word = words[i][j][0]
                    article = words[i][j][4]
                    if (isRTL(il))
                        explanation = join(words[i][j][1], ", ")
                    else {
                        explanation = prettify("dictionary-explanation-item", words[i][j][1][0])
                        for (k = 1; k < length(words[i][j][1]); k++)
                            explanation = explanation prettify("dictionary-explanation", ", ") \
                                prettify("dictionary-explanation-item", words[i][j][1][k])
                    }

                    r = r RS prettify("dictionary-word", ins(1, (article ? "(" article ") " : "") word, tl))
                    if (isRTL(il))
                        r = r RS prettify("dictionary-explanation-item", ins(2, explanation, il))
                    else
                        r = r RS ins(2, explanation)
                }
            }
        }

        if (wShowAlternatives) {
            # Display: alternative translations
            if (r) r = r RS RS
            r = r m("-- display alternative translations")
            for (i = 0; i < length(altTranslations); i++) {
                r = (i > 0 ? r RS : r) prettify("alternatives-original", show(segments[i], il))
                if (isRTL(tl)) {
                    temp = join(altTranslations[i], ", ")
                    r = r RS prettify("alternatives-translations-item", ins(1, temp, tl))
                } else {
                    temp = prettify("alternatives-translations-item", altTranslations[i][0])
                    for (j = 1; j < length(altTranslations[i]); j++)
                        temp = temp prettify("alternatives-translations", ", ") \
                            prettify("alternatives-translations-item", altTranslations[i][j])
                    r = r RS ins(1, temp)
                }
            }
        }

        if (toSpeech) {
            if (index(showTranslationsOf(hl, "%s"), "%s") > 2) {
                returnPlaylist[0]["text"] = showTranslationsOf(hl)
                returnPlaylist[0]["tl"] = hl
                returnPlaylist[1]["text"] = join(original)
                returnPlaylist[1]["tl"] = il
            } else {
                returnPlaylist[0]["text"] = join(original)
                returnPlaylist[0]["tl"] = il
                returnPlaylist[1]["text"] = showTranslationsOf(hl)
                returnPlaylist[1]["tl"] = hl
            }
            returnPlaylist[2]["text"] = translation
            returnPlaylist[2]["tl"] = tl
        }
    }

    return r
}


Update filter_en_uk.awk

Update filter_en_uk.awk

Added spacing using a JavaScript online service I hope nothing breaks

BEGIN {}
/^macro:[:alpha: ]+/ {
    macroLine = ""
    # I check every field from the second one(the first one is "macro:")
    for (x = 2; x <= NF; x++) {
        do {
            # I found a keys being kept pressed or just released, I print it as it is
            # This works because (probably) I don't want to keep pressed keys that need to be translated such as symbols
            if (length($x) > 1 && (substr($x, 1, 1) == "+" || substr($x, 1, 1) == "-")) {
                macroLine = macroLine $x;
                break;
            }
            # An upper-case key, I need to press shift to do it. Using the != toupper I avoid triggering things like "," == tolower(",") and "," == toupper(",")
            if ($x != tolower($x)) {
                macroLine = macroLine "+lshift,+" tolower($x) ",-" tolower($x) ",-lshift";
                break;
            }
            if ($x == "`") {
                macroLine = macroLine "+grave,-grave";
                break;
            }
            if ($x == "-") {
                macroLine = macroLine "+minus,-minus";
                break;
            }
            if ($x == "[") {
                macroLine = macroLine "+lbrace,-lbrace";
                break;
            }
            if ($x == "]") {
                macroLine = macroLine "+rbrace,-rbrace";
                break;
            }
            if ($x == ";") {
                macroLine = macroLine "+colon,-colon";
                break;
            }
            if ($x == "'") {
                macroLine = macroLine "+quote,-quote";
                break;
            }
            if ($x == "\\") {
                macroLine = macroLine "+bslash_iso,-bslash_iso";
                break;
            }
            if ($x == ",") {
                macroLine = macroLine "+comma,-comma";
                break;
            }
            if ($x == ".") {
                macroLine = macroLine "+dot,-dot";
                break;
            }
            if ($x == "#") {
                macroLine = macroLine "+hash,-hash";
                break;
            }
            if ($x == "=") {
                macroLine = macroLine "+equal,-equal";
                break;
            }
            if ($x == "/") {
                macroLine = macroLine "+slash,-slash";
                break;
            }#
            if ($x == "/") {
                macroLine = macroLine "+numslash,-numslash";
                break;
            }#
            if ($x == "!") {
                macroLine = macroLine "+exclam,-exclam";
                break;
            }
            if ($x == "!") {
                macroLine = macroLine "+lctrl,+lshift,+u,+0,-0,+0,-0,+2,-2,+1,-1,-u,-lshift,-lctrl";
                break;
            }
            if ($x == "?") {
                macroLine = macroLine "+lctrl,+lshift,+u,+0,-0,+0,-0,+3,-3,+f,-f,-u,-lshift,-lctrl";
                break;
            }
            if ($x == "(") {
                macroLine = macroLine "+lctrl,+lshift,+u,+0,-0,+0,-0,+2,-2,+8,-8,-u,-lshift,-lctrl";
                break;
            }
            if ($x == ")") {
                macroLine = macroLine "+lctrl,+lshift,+u,+0,-0,+0,-0,+2,-2,+9,-9,-u,-lshift,-lctrl";
                break;
            }
            if ($x == "\"") {
                macroLine = macroLine "+lctrl,+lshift,+u,+2,-2,+0,-0,+1,-1,+c,-c,-u,-lshift,-lctrl";
                break;
            }

            # A normal key, press and release it, catches all the remaining cases
            macroLine = macroLine "+" $x ",-" $x
        }
        while (0)
        # 0 means it runs only once instead of endlessly looping in case oferrors

        # I add a comma between this key and the next unless I 'm at the last one
        if (x < NF)
            macroLine = macroLine ","
        else
            # Finished reading the macro, sending it macro to the output
            print macroLine
    }
}
END {}

BEGIN {}
/^macro:[:alpha: ]+/ {
    macroLine=""
    # I check every field from the second one (the first one is "macro:")
    for(x=2;x<=NF;x++){
        do{
            # I found a keys being kept pressed or just released, I print it as it is
            # This works because (probably) I don't want to keep pressed keys that need to be translated such as symbols
            if(length($x)>1&&(substr($x,1,1)=="+"||substr($x,1,1)=="-")){macroLine=macroLine $x; break;}
            # An upper-case key, I need to press shift to do it. Using the !=toupper I avoid triggering things like ","==tolower(",") and ","==toupper(",")
            if($x!=tolower($x)){macroLine=macroLine "+lshift," "+" tolower($x) ",-" tolower($x) ",-lshift"; break;}
            if($x=="`"){ macroLine=macroLine "+grave,-grave"; break;}
            if($x=="-"){ macroLine=macroLine "+minus,-minus"; break;}
            if($x=="["){ macroLine=macroLine "+lbrace,-lbrace"; break;}
            if($x=="]"){ macroLine=macroLine "+rbrace,-rbrace"; break;}
            if($x==";"){ macroLine=macroLine "+colon,-colon"; break;}
            if($x=="'"){ macroLine=macroLine "+quote,-quote"; break;}
            if($x=="\\"){ macroLine=macroLine "+bslash_iso,-bslash_iso"; break;}
            if($x==","){ macroLine=macroLine "+comma,-comma"; break;}
            if($x=="."){ macroLine=macroLine "+dot,-dot"; break;}
            if($x=="#"){ macroLine=macroLine "+hash,-hash"; break;}
            if($x=="="){ macroLine=macroLine "+equal,-equal"; break;}
            if($x=="/"){ macroLine=macroLine "+slash,-slash"; break;}
            #if($x=="/"){ macroLine=macroLine "+numslash,-numslash"; break;}
            #if($x=="!"){ macroLine=macroLine "+exclam,-exclam"; break;}
            if($x=="!"){ macroLine=macroLine "+lctrl,+lshift,+u,+0,-0,+0,-0,+2,-2,+1,-1,-u,-lshift,-lctrl"; break;}
            if($x=="?"){ macroLine=macroLine "+lctrl,+lshift,+u,+0,-0,+0,-0,+3,-3,+f,-f,-u,-lshift,-lctrl"; break;}
            if($x=="("){ macroLine=macroLine "+lctrl,+lshift,+u,+0,-0,+0,-0,+2,-2,+8,-8,-u,-lshift,-lctrl"; break;}
            if($x==")"){ macroLine=macroLine "+lctrl,+lshift,+u,+0,-0,+0,-0,+2,-2,+9,-9,-u,-lshift,-lctrl"; break;}
            if($x=="\""){ macroLine=macroLine "+lctrl,+lshift,+u,+2,-2,+0,-0,+1,-1,+c,-c,-u,-lshift,-lctrl"; break;}

            # A normal key, press and release it, catches all the remaining cases
            macroLine=macroLine "+" $x ",-" $x
        }
        while(0)  # 0 means it runs only once instead of endlessly looping in case of errors

        if(x<NF)
        # I add a comma between this key and the next unless I'm at the last one
            macroLine=macroLine ","
        else
        # sending the macro to the output
            print macroLine
        }
}
END {}


fix gawk warning

fix gawk warning

BEGIN {
    interesting = 1
}

{
    sub(/<title>Haskell: Functional Programming, Solid Code, Big Data<\/title>/, "<title>Intro \"Functional Programming\"</title>")
    sub(/<meta name="date" content="2011-09-18" \/>/, "<meta name=\"date\" content=\"2011-10-19\" />")
    sub(/<meta name="author" content="Bryan O'Sullivan" \/>/, "<meta name=\"author\" content=\"Gabor Greif\" />")
}

/^<body>/ {
    interesting = 0
    print
    next
}

interesting {
    print
    next
}

BEGIN {
    interesting = 1
}

{
    sub(/<title>Haskell: Functional Programming, Solid Code, Big Data<\/title>/, "<title>Intro \"Functional Programming\"<\/title>")
    sub(/<meta name="date" content="2011-09-18" \/>/, "<meta name=\"date\" content=\"2011-10-19\" />")
    sub(/<meta name="author" content="Bryan O'Sullivan" \/>/, "<meta name=\"author\" content=\"Gabor Greif\" />")
}

/^<body>/ {
    interesting = 0
    print
    next
}

interesting {
    print
    next
}