Skip to content

Commit

Permalink
Cleaned up a number of small tweaks in the scripts
Browse files Browse the repository at this point in the history
- Added the littlefs license note to the scripts.

- Adopted parse_intermixed_args everywhere for more consistent arg
  handling.

- Removed argparse's implicit help text formatting as it does not
  work with perse_intermixed_args and breaks sometimes.

- Used string concatenation for argparse everywhere, uses backslashed
  line continuations only works with argparse because it strips
  redundant whitespace.

- Consistent argparse formatting.

- Consistent openio mode handling.

- Consistent color argument handling.

- Adopted functools.lru_cache in tracebd.py.

- Moved unicode printing behind --subscripts in traceby.py, making all
  scripts ascii by default.

- Renamed pretty_asserts.py -> prettyasserts.py.

- Renamed struct.py -> struct_.py, the original name conflicts with
  Python's built in struct module in horrible ways.
  • Loading branch information
geky committed Nov 15, 2022
1 parent 11d6d12 commit 20ec0be
Show file tree
Hide file tree
Showing 11 changed files with 307 additions and 162 deletions.
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ stack: $(CI)

.PHONY: struct
struct: $(OBJ)
./scripts/struct.py $^ -S $(STRUCTFLAGS)
./scripts/struct_.py $^ -S $(STRUCTFLAGS)

.PHONY: coverage
coverage: $(GCDA)
Expand Down Expand Up @@ -171,7 +171,7 @@ $(BUILDDIR)lfs.stack.csv: $(CI)
./scripts/stack.py $^ -q $(CODEFLAGS) -o $@

$(BUILDDIR)lfs.struct.csv: $(OBJ)
./scripts/struct.py $^ -q $(CODEFLAGS) -o $@
./scripts/struct_.py $^ -q $(CODEFLAGS) -o $@

$(BUILDDIR)lfs.coverage.csv: $(GCDA)
./scripts/coverage.py $^ -q $(COVERAGEFLAGS) -o $@
Expand All @@ -195,10 +195,10 @@ $(BUILDDIR)%.s: %.c
$(CC) -S $(CFLAGS) $< -o $@

$(BUILDDIR)%.a.c: %.c
./scripts/pretty_asserts.py -p LFS_ASSERT $< -o $@
./scripts/prettyasserts.py -p LFS_ASSERT $< -o $@

$(BUILDDIR)%.a.c: $(BUILDDIR)%.c
./scripts/pretty_asserts.py -p LFS_ASSERT $< -o $@
./scripts/prettyasserts.py -p LFS_ASSERT $< -o $@

$(BUILDDIR)%.t.c: %.toml
./scripts/test.py -c $< $(TESTCFLAGS) -o $@
Expand Down
19 changes: 13 additions & 6 deletions scripts/code.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#!/usr/bin/env python3
#
# Script to find code size at the function level. Basically just a bit wrapper
# Script to find code size at the function level. Basically just a big wrapper
# around nm with some extra conveniences for comparing builds. Heavily inspired
# by Linux's Bloat-O-Meter.
#
# Example:
# ./scripts/code.py lfs.o lfs_util.o -S
#
# Copyright (c) 2022, The littlefs authors.
# Copyright (c) 2020, Arm Limited. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#

import collections as co
import csv
Expand Down Expand Up @@ -126,7 +133,7 @@ def __add__(self, other):

def openio(path, mode='r'):
if path == '-':
if 'r' in mode:
if mode == 'r':
return os.fdopen(os.dup(sys.stdin.fileno()), 'r')
else:
return os.fdopen(os.dup(sys.stdout.fileno()), 'w')
Expand Down Expand Up @@ -417,7 +424,7 @@ def main(obj_paths, **args):
nargs='*',
default=OBJ_PATHS,
help="Description of where to find *.o files. May be a directory "
"or a list of paths. Defaults to %(default)r.")
"or a list of paths. Defaults to %r." % OBJ_PATHS)
parser.add_argument(
'-v', '--verbose',
action='store_true',
Expand Down Expand Up @@ -468,16 +475,16 @@ def main(obj_paths, **args):
'--type',
default=TYPE,
help="Type of symbols to report, this uses the same single-character "
"type-names emitted by nm. Defaults to %(default)r.")
"type-names emitted by nm. Defaults to %r." % TYPE)
parser.add_argument(
'--nm-tool',
type=lambda x: x.split(),
default=NM_TOOL,
help="Path to the nm tool to use. Defaults to %(default)r")
help="Path to the nm tool to use. Defaults to %r." % NM_TOOL)
parser.add_argument(
'--build-dir',
help="Specify the relative build directory. Used to map object files "
"to the correct source files.")
sys.exit(main(**{k: v
for k, v in vars(parser.parse_args()).items()
for k, v in vars(parser.parse_intermixed_args()).items()
if v is not None}))
26 changes: 15 additions & 11 deletions scripts/coverage.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
#!/usr/bin/env python3
#
# Script to find test coverage. Basically just a big wrapper around gcov with
# some extra conveniences for comparing builds. Heavily inspired by Linux's
# Bloat-O-Meter.
# Script to find coverage info after running tests.
#
# Example:
# ./scripts/coverage.py lfs.t.a.gcda lfs_util.t.a.gcda -s
#
# Copyright (c) 2022, The littlefs authors.
# Copyright (c) 2020, Arm Limited. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#

import collections as co
Expand Down Expand Up @@ -208,7 +213,7 @@ def __add__(self, other):

def openio(path, mode='r'):
if path == '-':
if 'r' in mode:
if mode == 'r':
return os.fdopen(os.dup(sys.stdin.fileno()), 'r')
else:
return os.fdopen(os.dup(sys.stdout.fileno()), 'w')
Expand Down Expand Up @@ -682,7 +687,7 @@ def main(gcda_paths, **args):
nargs='*',
default=GCDA_PATHS,
help="Description of where to find *.gcda files. May be a directory "
"or a list of paths. Defaults to %(default)r.")
"or a list of paths. Defaults to %r." % GCDA_PATHS)
parser.add_argument(
'-v', '--verbose',
action='store_true',
Expand Down Expand Up @@ -752,18 +757,17 @@ def main(gcda_paths, **args):
'-c', '--context',
type=lambda x: int(x, 0),
default=3,
help="Show a additional lines of context. Defaults to %(default)r.")
help="Show a additional lines of context. Defaults to 3.")
parser.add_argument(
'-W', '--width',
type=lambda x: int(x, 0),
default=80,
help="Assume source is styled with this many columns. Defaults "
"to %(default)r.")
help="Assume source is styled with this many columns. Defaults to 80.")
parser.add_argument(
'--color',
choices=['never', 'always', 'auto'],
default='auto',
help="When to use terminal colors.")
help="When to use terminal colors. Defaults to 'auto'.")
parser.add_argument(
'-e', '--error-on-lines',
action='store_true',
Expand All @@ -780,11 +784,11 @@ def main(gcda_paths, **args):
'--gcov-tool',
default=GCOV_TOOL,
type=lambda x: x.split(),
help="Path to the gcov tool to use. Defaults to %(default)r.")
help="Path to the gcov tool to use. Defaults to %r." % GCOV_TOOL)
parser.add_argument(
'--build-dir',
help="Specify the relative build directory. Used to map object files "
"to the correct source files.")
sys.exit(main(**{k: v
for k, v in vars(parser.parse_args()).items()
for k, v in vars(parser.parse_intermixed_args()).items()
if v is not None}))
17 changes: 12 additions & 5 deletions scripts/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
# around nm with some extra conveniences for comparing builds. Heavily inspired
# by Linux's Bloat-O-Meter.
#
# Example:
# ./scripts/data.py lfs.o lfs_util.o -S
#
# Copyright (c) 2022, The littlefs authors.
# Copyright (c) 2020, Arm Limited. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#

import collections as co
import csv
Expand Down Expand Up @@ -126,7 +133,7 @@ def __add__(self, other):

def openio(path, mode='r'):
if path == '-':
if 'r' in mode:
if mode == 'r':
return os.fdopen(os.dup(sys.stdin.fileno()), 'r')
else:
return os.fdopen(os.dup(sys.stdout.fileno()), 'w')
Expand Down Expand Up @@ -417,7 +424,7 @@ def main(obj_paths, **args):
nargs='*',
default=OBJ_PATHS,
help="Description of where to find *.o files. May be a directory "
"or a list of paths. Defaults to %(default)r.")
"or a list of paths. Defaults to %r." % OBJ_PATHS)
parser.add_argument(
'-v', '--verbose',
action='store_true',
Expand Down Expand Up @@ -468,16 +475,16 @@ def main(obj_paths, **args):
'--type',
default=TYPE,
help="Type of symbols to report, this uses the same single-character "
"type-names emitted by nm. Defaults to %(default)r.")
"type-names emitted by nm. Defaults to %r." % TYPE)
parser.add_argument(
'--nm-tool',
type=lambda x: x.split(),
default=NM_TOOL,
help="Path to the nm tool to use. Defaults to %(default)r")
help="Path to the nm tool to use. Defaults to %r." % NM_TOOL)
parser.add_argument(
'--build-dir',
help="Specify the relative build directory. Used to map object files "
"to the correct source files.")
sys.exit(main(**{k: v
for k, v in vars(parser.parse_args()).items()
for k, v in vars(parser.parse_intermixed_args()).items()
if v is not None}))
36 changes: 27 additions & 9 deletions scripts/pretty_asserts.py → scripts/prettyasserts.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
#!/usr/bin/env python3
#
# Preprocessor that makes asserts easier to debug.
#
# Example:
# ./scripts/prettyasserts.py -p LFS_ASSERT lfs.c -o lfs.a.c
#
# Copyright (c) 2022, The littlefs authors.
# Copyright (c) 2020, Arm Limited. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#

import re
import sys
Expand Down Expand Up @@ -34,7 +44,7 @@

def openio(path, mode='r'):
if path == '-':
if 'r' in mode:
if mode == 'r':
return os.fdopen(os.dup(sys.stdin.fileno()), 'r')
else:
return os.fdopen(os.dup(sys.stdout.fileno()), 'w')
Expand Down Expand Up @@ -414,17 +424,25 @@ def writeln(s=''):
import argparse
import sys
parser = argparse.ArgumentParser(
description="Preprocessor that makes asserts easy to debug.")
parser.add_argument('input',
description="Preprocessor that makes asserts easier to debug.")
parser.add_argument(
'input',
help="Input C file.")
parser.add_argument('-o', '--output', required=True,
parser.add_argument(
'-o', '--output',
required=True,
help="Output C file.")
parser.add_argument('-p', '--pattern', action='append',
parser.add_argument(
'-p', '--pattern',
action='append',
help="Regex patterns to search for starting an assert statement. This"
" implicitly includes \"assert\" and \"=>\".")
parser.add_argument('-l', '--limit',
default=LIMIT, type=lambda x: int(x, 0),
help="Maximum number of characters to display in strcmp and memcmp.")
parser.add_argument(
'-l', '--limit',
type=lambda x: int(x, 0),
default=LIMIT,
help="Maximum number of characters to display in strcmp and memcmp. "
"Defaults to %r." % LIMIT)
sys.exit(main(**{k: v
for k, v in vars(parser.parse_args()).items()
for k, v in vars(parser.parse_intermixed_args()).items()
if v is not None}))
12 changes: 9 additions & 3 deletions scripts/stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
# Script to find stack usage at the function level. Will detect recursion and
# report as infinite stack usage.
#
# Example:
# ./scripts/stack.py lfs.ci lfs_util.ci -S
#
# Copyright (c) 2022, The littlefs authors.
# SPDX-License-Identifier: BSD-3-Clause
#

import collections as co
import csv
Expand Down Expand Up @@ -124,7 +130,7 @@ def __add__(self, other):

def openio(path, mode='r'):
if path == '-':
if 'r' in mode:
if mode == 'r':
return os.fdopen(os.dup(sys.stdin.fileno()), 'r')
else:
return os.fdopen(os.dup(sys.stdout.fileno()), 'w')
Expand Down Expand Up @@ -425,7 +431,7 @@ def table_calls(names_, depth,
prefixes[2+is_last] + "'-> ",
prefixes[2+is_last] + "| ",
prefixes[2+is_last] + " "))


table_calls(names, depth)

Expand Down Expand Up @@ -643,5 +649,5 @@ def main(ci_paths, **args):
help="Specify the relative build directory. Used to map object files "
"to the correct source files.")
sys.exit(main(**{k: v
for k, v in vars(parser.parse_args()).items()
for k, v in vars(parser.parse_intermixed_args()).items()
if v is not None}))
14 changes: 10 additions & 4 deletions scripts/struct.py → scripts/struct_.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
#
# Script to find struct sizes.
#
# Example:
# ./scripts/struct_.py lfs.o lfs_util.o -S
#
# Copyright (c) 2022, The littlefs authors.
# SPDX-License-Identifier: BSD-3-Clause
#

import collections as co
import csv
Expand Down Expand Up @@ -123,7 +129,7 @@ def __add__(self, other):

def openio(path, mode='r'):
if path == '-':
if 'r' in mode:
if mode == 'r':
return os.fdopen(os.dup(sys.stdin.fileno()), 'r')
else:
return os.fdopen(os.dup(sys.stdout.fileno()), 'w')
Expand Down Expand Up @@ -461,7 +467,7 @@ def main(obj_paths, **args):
nargs='*',
default=OBJ_PATHS,
help="Description of where to find *.o files. May be a directory "
"or a list of paths. Defaults to %(default)r.")
"or a list of paths. Defaults to %r." % OBJ_PATHS)
parser.add_argument(
'-v', '--verbose',
action='store_true',
Expand Down Expand Up @@ -512,11 +518,11 @@ def main(obj_paths, **args):
'--objdump-tool',
type=lambda x: x.split(),
default=OBJDUMP_TOOL,
help="Path to the objdump tool to use.")
help="Path to the objdump tool to use. Defaults to %r." % OBJDUMP_TOOL)
parser.add_argument(
'--build-dir',
help="Specify the relative build directory. Used to map object files "
"to the correct source files.")
sys.exit(main(**{k: v
for k, v in vars(parser.parse_args()).items()
for k, v in vars(parser.parse_intermixed_args()).items()
if v is not None}))
15 changes: 12 additions & 3 deletions scripts/summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
#
# Script to summarize the outputs of other scripts. Operates on CSV files.
#
# Example:
# ./scripts/code.py lfs.o lfs_util.o -q -o lfs.code.csv
# ./scripts/data.py lfs.o lfs_util.o -q -o lfs.data.csv
# ./scripts/summary.py lfs.code.csv lfs.data.csv -q -o lfs.csv
# ./scripts/summary.py -Y lfs.csv -f code=code_size,data=data_size
#
# Copyright (c) 2022, The littlefs authors.
# SPDX-License-Identifier: BSD-3-Clause
#

import collections as co
import csv
Expand Down Expand Up @@ -43,7 +52,7 @@

def openio(path, mode='r'):
if path == '-':
if 'r' in mode:
if mode == 'r':
return os.fdopen(os.dup(sys.stdin.fileno()), 'r')
else:
return os.fdopen(os.dup(sys.stdout.fileno()), 'w')
Expand Down Expand Up @@ -660,7 +669,7 @@ def main(csv_paths, *, fields=None, by=None, **args):
nargs='*',
default=CSV_PATHS,
help="Description of where to find *.csv files. May be a directory "
"or list of paths. Defaults to %(default)r.")
"or list of paths. Defaults to %r." % CSV_PATHS)
parser.add_argument(
'-q', '--quiet',
action='store_true',
Expand Down Expand Up @@ -722,5 +731,5 @@ def main(csv_paths, *, fields=None, by=None, **args):
action='store_true',
help="Only show the totals.")
sys.exit(main(**{k: v
for k, v in vars(parser.parse_args()).items()
for k, v in vars(parser.parse_intermixed_args()).items()
if v is not None}))

0 comments on commit 20ec0be

Please sign in to comment.