Skip to content

Instantly share code, notes, and snippets.

@ids1024
Last active March 18, 2018 03:00
Show Gist options
  • Save ids1024/9722da9fc3f2beb621f4c9527cf3db70 to your computer and use it in GitHub Desktop.
Save ids1024/9722da9fc3f2beb621f4c9527cf3db70 to your computer and use it in GitHub Desktop.
import os
from urllib.request import urlretrieve
import tarfile
import re
import bs4
from pycparser import c_ast, CParser
TAR = "susv4tc2.tar.bz2"
DLURL = "http://pubs.opengroup.org/onlinepubs/9699919799/download/" + TAR
def parseType(node):
# XXX handle node.quals
if isinstance(node, c_ast.TypeDecl):
if isinstance(node.type, c_ast.IdentifierType):
return ' '.join(node.quals + node.type.names)
else:
return None
if isinstance(node, c_ast.PtrDecl):
ptr = '*'
if node.quals:
ptr += ' ' + ' '.join(node.quals)
if isinstance(node.type, c_ast.FuncDecl):
return '(' + parseType(node.type.type) + ')(' + ptr + ')(' + ', '.join(map(parseType, node.type.args.params)) + ')'
return parseType(node.type) + ' ' + ptr
elif isinstance(node, c_ast.Typename):
return parseType(node.type)
elif isinstance(node, c_ast.ArrayDecl):
return parseType(node.type) + ' [' + node.dim.value + ']'
elif isinstance(node, c_ast.Decl):
return ' '.join(node.quals + [parseType(node.type)])
else:
return None
def parse_c(src):
ast = cparser.parse(''.join('typedef int '+i+';\n' for i in 'size_t div_t ldiv_t lldiv_t wchar_t locale_t uintptr_t'.split()) + src)
fns = {}
for _, i in ast.children():
if not isinstance(i, c_ast.Decl):
continue
if not isinstance(i.type, c_ast.FuncDecl):
continue
params = i.type.args.params
if isinstance(i.type.type, c_ast.PtrDecl):
name = i.type.type.type.declname
else:
name = i.type.type.declname
fns[name] = (parseType(i.type.type), list(map(parseType, params)))
return fns
cparser = CParser()
if not os.path.exists(TAR):
urlretrieve(DLURL, TAR)
os.makedirs("output", exist_ok=True)
with tarfile.open(TAR) as tar:
for i in tar.getmembers():
m = re.match("susv4tc2/basedefs/(.*\\.h)\\.html", i.name)
if not m:
continue
name = m.group(1)
if name != 'string.h':
continue
html = bs4.BeautifulSoup(tar.extractfile(i), 'lxml')
src = '\n'.join(j
for i in html.findAll('pre')
for j in i.text.splitlines()
if not j.startswith('['))
stdfns = parse_c(src)
ourfns = parse_c('\n'.join(i for i in open('target/include/' + name).read().splitlines() if not i.strip().startswith('#')))
for i in stdfns:
if i in ourfns:
std = stdfns[i]
our = ourfns[i]
if std == our:
print("'" + i +"()' definition matches")
else:
if std[0] != our[0]:
print(f"Redox's {i}() returns '{our[0]}', but SUS defines as '{std[0]}'")
for x in range(1, min(len(std[1]), len(our[1]))):
if std[1][x] != our[1][x]:
print(f"Argument {x} of {i}() is type '{our[1][x]}' on Redox, '{std[1][x]}' in SUS")
if len(std[1]) != len(our[1]):
print(f"Redox's {i}() takes {len(our[1])} arguments, but SUS defines it with {len(std[1])} arguments")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment