zephyr/scripts/process_gperf.py
Sebastian Bøe 4971d2a084 cmake: Fix "make VERBOSE=1"
It is desired behaviour that when 'make VERBOSE=1' is invoked, the
underlying scripts will be invoked in 'verbose mode', e.g. they have
the flag --verbose passed to them.

This patch modifies all the underlying scripts in the build system to
inject --verbose into the command line when the environment variable
VERBOSE is set.

The environment variable VERBOSE is a CMake concept. CMake will
generate Makefile's that read this environment variable and try to
behave accordingly. Unfortunately, the generated ninja build systems
behave differently and will have to be invoked like this:

VERBOSE=1 ninja -v

This fixes #4851

Signed-off-by: Sebastian Bøe <sebastian.boe@nordicsemi.no>
2018-01-10 22:14:53 -05:00

161 lines
4.4 KiB
Python
Executable File

#!/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("struct _k_object [*]$", 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("-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()