Files
littlefs/scripts/dbgerr.py
T
Christopher Haster ffc40da878 scripts: Reworked tagrepr -> Tag.repr to rely more on self-parsing
This should make tag editing less tedious/error-prone. We already used
self-parsing to generate -l/--list in dbgtag.py, but this extends the
idea to tagrepr (now Tag.repr), which is used in quite a few more
scripts.

To make this work the little tag encoding spec had to become a bit more
rigorous, fortunately the only real change was the addition of '+'
characters to mark reserved-but-expected-zero bits.

Example:

  TAG_CKSUM = 0x3000  ## v-11 ---- ++++ +pqq
                         ^--^----^----^--^-^-- valid bit, unmatched
                            '----|----|--|-|-- matches 1
                                 '----|--|-|-- matches 0
                                      '--|-|-- reserved 0, unmatched
                                         '-|-- perturb bit, unmatched
                                           '-- phase bits, unmatched

  dbgtag.py 0x3000  =>  cksumq0
  dbgtag.py 0x3007  =>  cksumq3p
  dbgtag.py 0x3017  =>  cksumq3p 0x10
  dbgtag.py 0x3417  =>  0x3417

Though Tag.repr still does a bit of manual formatting for the
differences between shrub/normal/null/alt tags.

Still, this should reduce the number of things that need to be changed
from 2 -> 1 when adding/editing most new tags.
2025-10-24 00:15:21 -05:00

173 lines
4.9 KiB
Python
Executable File

#!/usr/bin/env python3
# prevent local imports
if __name__ == "__main__":
__import__('sys').path.pop(0)
import functools as ft
# Error codes
ERR_OK = 0 # No error
ERR_UNKNOWN = -1 # Unknown error
ERR_INVAL = -22 # Invalid parameter
ERR_NOTSUP = -95 # Operation not supported
ERR_IO = -5 # Error during device operation
ERR_CORRUPT = -84 # Corrupted
ERR_NOENT = -2 # No directory entry
ERR_EXIST = -17 # Entry already exists
ERR_NOTDIR = -20 # Entry is not a dir
ERR_ISDIR = -21 # Entry is a dir
ERR_NOTEMPTY = -39 # Dir is not empty
ERR_FBIG = -27 # File too large
ERR_NOSPC = -28 # No space left on device
ERR_NOMEM = -12 # No more memory available
ERR_NOATTR = -61 # No data/attr available
ERR_NAMETOOLONG = -36 # File name too long
ERR_RANGE = -34 # Result out of range
# self-parsing error codes
class Err:
def __init__(self, name, code, help):
self.name = name
self.code = code
self.help = help
def __repr__(self):
return 'Err(%r, %r, %r)' % (
self.name,
self.code,
self.help)
def __eq__(self, other):
return self.name == other.name
def __ne__(self, other):
return self.name != other.name
def __hash__(self):
return hash(self.name)
def line(self):
return ('LFS3_%s' % self.name, '%d' % self.code, self.help)
@staticmethod
@ft.cache
def errs():
# parse our script's source to figure out errs
import inspect
import re
errs = []
err_pattern = re.compile(
'^(?P<name>ERR_[^ ]*) *= *(?P<code>[^#]*?) *'
'#+ *(?P<help>.*)$')
for line in (inspect.getsource(
inspect.getmodule(inspect.currentframe()))
.replace('\\\n', '')
.splitlines()):
m = err_pattern.match(line)
if m:
errs.append(Err(
m.group('name'),
globals()[m.group('name')],
m.group('help')))
return errs
def main(errs, *,
list=False):
import builtins
list_, list = list, builtins.list
# find errs
errs__ = Err.errs()
lines = []
# list all known error codes
if list_:
for e in errs__:
lines.append(e.line())
# find errs by name or value
else:
for e_ in errs:
found = False
# find by LFS3_ERR_+name
for e in errs__:
if 'LFS3_%s' % e.name.upper() == e_.upper():
lines.append(e.line())
found = True
if found:
continue
# find by ERR_+name
for e in errs__:
if e.name.upper() == e_.upper():
lines.append(e.line())
found = True
if found:
continue
# find by name
for e in errs__:
if e.name.split('_', 1)[1] == e_.upper():
lines.append(e.line())
found = True
if found:
continue
# find by E+name
for e in errs__:
if 'E%s' % e.name.split('_', 1)[1].upper() == e_.upper():
lines.append(e.line())
found = True
if found:
continue
try:
# find by err code
for e in errs__:
if e.code == int(e_, 0):
lines.append(e.line())
found = True
if found:
continue
# find by negated err code
for e in errs__:
if e.code == -int(e_, 0):
lines.append(e.line())
found = True
if found:
continue
except ValueError:
lines.append(('?', e_, 'Unknown err code'))
# first find widths
w = [0, 0]
for l in lines:
w[0] = max(w[0], len(l[0]))
w[1] = max(w[1], len(l[1]))
# then print results
for l in lines:
print('%-*s %-*s %s' % (
w[0], l[0],
w[1], l[1],
l[2]))
if __name__ == "__main__":
import argparse
import sys
parser = argparse.ArgumentParser(
description="Decode littlefs error codes.",
allow_abbrev=False)
parser.add_argument(
'errs',
nargs='*',
help="Error codes or error names to decode.")
parser.add_argument(
'-l', '--list',
action='store_true',
help="List all known error codes.")
sys.exit(main(**{k: v
for k, v in vars(parser.parse_intermixed_args()).items()
if v is not None}))