Extended prettyasserts.py to support unreachable statements
The main benefit is control over error reporting and avoiding the dive into stdlib layers when debugging thanks to __builtin_trap(). This changes -p/--pattern -> -a/--assert And adds -u/--unreachable
This commit is contained in:
@@ -522,10 +522,10 @@ $(BUILDDIR)/%.s: %.c
|
|||||||
$(CC) -S $(CFLAGS) $< -o $@
|
$(CC) -S $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
$(BUILDDIR)/%.c: %.a.c
|
$(BUILDDIR)/%.c: %.a.c
|
||||||
./scripts/prettyasserts.py -p LFS_ASSERT $< -o $@
|
./scripts/prettyasserts.py -a LFS_ASSERT -u LFS_UNREACHABLE $< -o $@
|
||||||
|
|
||||||
$(BUILDDIR)/%.c: $(BUILDDIR)/%.a.c
|
$(BUILDDIR)/%.c: $(BUILDDIR)/%.a.c
|
||||||
./scripts/prettyasserts.py -p LFS_ASSERT $< -o $@
|
./scripts/prettyasserts.py -a LFS_ASSERT -u LFS_UNREACHABLE $< -o $@
|
||||||
|
|
||||||
$(BUILDDIR)/%.t.a.c: %.toml
|
$(BUILDDIR)/%.t.a.c: %.toml
|
||||||
./scripts/test.py -c $< $(TESTCFLAGS) -o $@
|
./scripts/test.py -c $< $(TESTCFLAGS) -o $@
|
||||||
|
|||||||
+52
-14
@@ -25,15 +25,17 @@ CMP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LEXEMES = {
|
LEXEMES = {
|
||||||
'ws': [r'(?:\s|\n|#.*?(?<!\\)\n|//.*?(?<!\\)\n|/\*.*?\*/)+'],
|
'ws': [r'(?:\s|\n|#.*?(?<!\\)\n|//.*?(?<!\\)\n|/\*.*?\*/)+'],
|
||||||
'assert': ['assert'],
|
'assert': ['__builtin_assert', 'assert'],
|
||||||
'arrow': ['=>'],
|
'unreachable': ['__builtin_unreachable', 'unreachable'],
|
||||||
'string': [r'"(?:\\.|[^"])*"', r"'(?:\\.|[^'])\'"],
|
'arrow': ['=>'],
|
||||||
'paren': ['\(', '\)'],
|
'string': [r'"(?:\\.|[^"])*"', r"'(?:\\.|[^'])\'"],
|
||||||
'cmp': CMP.keys(),
|
'paren': ['\(', '\)'],
|
||||||
'logic': ['\&\&', '\|\|'],
|
'cmp': CMP.keys(),
|
||||||
'sep': [':', ';', '\{', '\}', ','],
|
'logic': ['\&\&', '\|\|'],
|
||||||
'op': ['->', '>>', '<<'], # specifically ops that conflict with cmp
|
'sep': [':', ';', '\{', '\}', ','],
|
||||||
|
# specifically ops that conflict with cmp
|
||||||
|
'op': ['->', '>>', '<<'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -117,6 +119,14 @@ def write_header(f, limit=LIMIT):
|
|||||||
f.writeln(" fflush(NULL);")
|
f.writeln(" fflush(NULL);")
|
||||||
f.writeln("}")
|
f.writeln("}")
|
||||||
f.writeln()
|
f.writeln()
|
||||||
|
f.writeln("__attribute__((unused))")
|
||||||
|
f.writeln("static void __pretty_assert_print_unreachable(")
|
||||||
|
f.writeln(" const char *file, int line) {")
|
||||||
|
f.writeln(" printf(\"%s:%d:unreachable: \"")
|
||||||
|
f.writeln(" \"unreachable statement reached\\n\", file, line);")
|
||||||
|
f.writeln(" fflush(NULL);")
|
||||||
|
f.writeln("}")
|
||||||
|
f.writeln()
|
||||||
|
|
||||||
# write assert macros
|
# write assert macros
|
||||||
for op, cmp in sorted(CMP.items()):
|
for op, cmp in sorted(CMP.items()):
|
||||||
@@ -183,6 +193,12 @@ def write_header(f, limit=LIMIT):
|
|||||||
f.writeln(" } \\")
|
f.writeln(" } \\")
|
||||||
f.writeln("} while (0)")
|
f.writeln("} while (0)")
|
||||||
f.writeln()
|
f.writeln()
|
||||||
|
f.writeln("#define __PRETTY_ASSERT_UNREACHABLE() do { \\")
|
||||||
|
f.writeln(" __pretty_assert_print_unreachable( \\")
|
||||||
|
f.writeln(" __FILE__, __LINE__); \\")
|
||||||
|
f.writeln(" __builtin_trap(); \\")
|
||||||
|
f.writeln("} while (0)")
|
||||||
|
f.writeln()
|
||||||
f.writeln()
|
f.writeln()
|
||||||
|
|
||||||
def mkassert(type, cmp, lh, rh, size=None):
|
def mkassert(type, cmp, lh, rh, size=None):
|
||||||
@@ -193,6 +209,9 @@ def mkassert(type, cmp, lh, rh, size=None):
|
|||||||
return ("__PRETTY_ASSERT_%s_%s(%s, %s)"
|
return ("__PRETTY_ASSERT_%s_%s(%s, %s)"
|
||||||
% (type.upper(), cmp.upper(), lh, rh))
|
% (type.upper(), cmp.upper(), lh, rh))
|
||||||
|
|
||||||
|
def mkunreachable():
|
||||||
|
return "__PRETTY_ASSERT_UNREACHABLE()"
|
||||||
|
|
||||||
|
|
||||||
# simple recursive descent parser
|
# simple recursive descent parser
|
||||||
class ParseFailure(Exception):
|
class ParseFailure(Exception):
|
||||||
@@ -311,6 +330,13 @@ def p_assert(p):
|
|||||||
p.expect(')')
|
p.expect(')')
|
||||||
return mkassert('bool', 'eq', lh, 'true')
|
return mkassert('bool', 'eq', lh, 'true')
|
||||||
|
|
||||||
|
def p_unreachable(p):
|
||||||
|
# unreachable()?
|
||||||
|
p.expect('unreachable') ; p.accept('ws')
|
||||||
|
p.expect('(') ; p.accept('ws')
|
||||||
|
p.expect(')')
|
||||||
|
return mkunreachable()
|
||||||
|
|
||||||
def p_expr(p):
|
def p_expr(p):
|
||||||
res = []
|
res = []
|
||||||
while True:
|
while True:
|
||||||
@@ -330,6 +356,13 @@ def p_expr(p):
|
|||||||
except ParseFailure:
|
except ParseFailure:
|
||||||
p.pop(state)
|
p.pop(state)
|
||||||
res.append(p.expect('assert'))
|
res.append(p.expect('assert'))
|
||||||
|
elif p.lookahead('unreachable'):
|
||||||
|
state = p.push()
|
||||||
|
try:
|
||||||
|
res.append(p_unreachable(p))
|
||||||
|
except ParseFailure:
|
||||||
|
p.pop(state)
|
||||||
|
res.append(p.expect('unreachable'))
|
||||||
elif p.accept('string', 'op', 'ws', None):
|
elif p.accept('string', 'op', 'ws', None):
|
||||||
res.append(p.m)
|
res.append(p.m)
|
||||||
else:
|
else:
|
||||||
@@ -388,11 +421,12 @@ def p_stmt(p):
|
|||||||
else:
|
else:
|
||||||
return ws + lh
|
return ws + lh
|
||||||
|
|
||||||
def main(input=None, output=None, pattern=[], limit=LIMIT):
|
def main(input=None, output=None, assert_=[], unreachable=[], limit=LIMIT):
|
||||||
with openio(input or '-', 'r') as in_f:
|
with openio(input or '-', 'r') as in_f:
|
||||||
# create parser
|
# create parser
|
||||||
lexemes = LEXEMES.copy()
|
lexemes = LEXEMES.copy()
|
||||||
lexemes['assert'] += pattern
|
lexemes['assert'] += assert_
|
||||||
|
lexemes['unreachable'] += unreachable
|
||||||
p = Parser(in_f, lexemes)
|
p = Parser(in_f, lexemes)
|
||||||
|
|
||||||
with openio(output or '-', 'w') as f:
|
with openio(output or '-', 'w') as f:
|
||||||
@@ -436,10 +470,14 @@ if __name__ == "__main__":
|
|||||||
required=True,
|
required=True,
|
||||||
help="Output C file.")
|
help="Output C file.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-p', '--pattern',
|
'-a', '--assert',
|
||||||
|
dest='assert_',
|
||||||
action='append',
|
action='append',
|
||||||
help="Regex patterns to search for starting an assert statement. This"
|
help="Additional symbols for assert statements.")
|
||||||
" implicitly includes \"assert\" and \"=>\".")
|
parser.add_argument(
|
||||||
|
'-u', '--unreachable',
|
||||||
|
action='append',
|
||||||
|
help="Additional symbols for unreachable statements.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-l', '--limit',
|
'-l', '--limit',
|
||||||
type=lambda x: int(x, 0),
|
type=lambda x: int(x, 0),
|
||||||
|
|||||||
Reference in New Issue
Block a user