#!/usr/bin/env python3
#
# Copyright (c) 2017 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0

import sys
import argparse
import os
import re
from distutils.version import LooseVersion

# --- debug stuff ---

"""
gperf C file post-processor

We use gperf to build up a perfect hashtable of pointer values. The way gperf
does this is to create a table 'wordlist' indexed by a string repreesentation
of a pointer address, and then doing memcmp() on a string passed in for
comparison

We are exclusively working with 4-byte pointer values. This script adjusts
the generated code so that we work with pointers directly and not strings.
This saves a considerable amount of space.
"""


def debug(text):
    if not args.verbose:
        return
    sys.stdout.write(os.path.basename(sys.argv[0]) + ": " + text + "\n")


def error(text):
    sys.stderr.write(os.path.basename(sys.argv[0]) + " ERROR: " + text + "\n")
    sys.exit(1)


def warn(text):
    sys.stdout.write(
        os.path.basename(
            sys.argv[0]) +
        " WARNING: " +
        text +
        "\n")


def reformat_str(match_obj):
    addr_str = match_obj.group(0)

    # Nip quotes
    addr_str = addr_str[1:-1]
    addr_vals = [0, 0, 0, 0]
    ctr = 3
    i = 0

    while (True):
        if i >= len(addr_str):
            break

        if addr_str[i] == "\\":
            if addr_str[i + 1].isdigit():
                # Octal escape sequence
                val_str = addr_str[i + 1:i + 4]
                addr_vals[ctr] = int(val_str, 8)
                i += 4
            else:
                # Char value that had to be escaped by C string rules
                addr_vals[ctr] = ord(addr_str[i + 1])
                i += 2

        else:
            addr_vals[ctr] = ord(addr_str[i])
            i += 1

        ctr -= 1

    return "(char *)0x%02x%02x%02x%02x" % tuple(addr_vals)


def process_line(line, fp):
    if line.startswith("#"):
        fp.write(line)
        return

    # Set the lookup function to static inline so it gets rolled into
    # _k_object_find(), nothing else will use it
    if re.search(args.pattern + " [*]$", line):
        fp.write("static inline " + line)
        return

    m = re.search("gperf version (.*) [*][/]$", line)
    if m:
        v = LooseVersion(m.groups()[0])
        v_lo = LooseVersion("3.0")
        v_hi = LooseVersion("3.1")
        if (v < v_lo or v > v_hi):
            warn("gperf %s is not tested, versions %s through %s supported" %
                 (v, v_lo, v_hi))

    # Replace length lookups with constant len of 4 since we're always
    # looking at pointers
    line = re.sub(r'lengthtable\[key\]', r'4', line)

    # Empty wordlist entries to have NULLs instead of ""
    line = re.sub(r'[{]["]["][}]', r'{}', line)

    # Suppress a compiler warning since this table is no longer necessary
    line = re.sub(r'static unsigned char lengthtable',
                  r'static unsigned char __unused lengthtable', line)

    # drop all use of register keyword, let compiler figure that out,
    # we have to do this since we change stuff to take the address of some
    # parameters
    line = re.sub(r'register', r'', line)

    # Hashing the address of the string
    line = re.sub(r"hash [(]str, len[)]",
                  r"hash((const char *)&str, len)", line)

    # Just compare pointers directly instead of using memcmp
    if re.search("if [(][*]str", line):
        fp.write("            if (str == s)\n")
        return

    # Take the strings with the binary information for the pointer values,
    # and just turn them into pointers
    line = re.sub(r'["].*["]', reformat_str, line)

    fp.write(line)


def parse_args():
    global args

    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)

    parser.add_argument("-i", "--input", required=True,
                        help="Input C file from gperf")
    parser.add_argument("-o", "--output", required=True,
                        help="Output C file with processing done")
    parser.add_argument("-p", "--pattern", required=True,
            help="Search pattern for objects")
    parser.add_argument("-v", "--verbose", action="store_true",
                        help="Print extra debugging information")
    args = parser.parse_args()
    if "VERBOSE" in os.environ:
        args.verbose = 1

def main():
    parse_args()

    with open(args.input, "r") as in_fp, open(args.output, "w") as out_fp:
        for line in in_fp.readlines():
            process_line(line, out_fp)


if __name__ == "__main__":
    main()
