Created
August 15, 2019 20:11
-
-
Save Profpatsch/122a08726e0db971c720573124c65be1 to your computer and use it in GitHub Desktop.
Code to generate a sysdeps.h header file from a structured sysdeps file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ lib }: | |
let | |
example = | |
{ | |
target = "aarch64-linux-gnu"; | |
endianness = "little"; | |
has = { | |
clockrt = true; | |
clockmon = true; | |
posixspawn = true; | |
timer = true; | |
nullispointer = true; | |
accept4 = true; | |
cmsgcloexec = true; | |
devurandom = true; | |
dirfd = true; | |
eventfd = true; | |
flock = true; | |
getpeereid = false; | |
sopeercred = true; | |
getpeerucred = false; | |
ipv6 = true; | |
malloc0 = true; | |
msgdontwait = true; | |
odirectory = true; | |
openat = true; | |
linkat = true; | |
memmem = true; | |
pipe2 = true; | |
ppoll = true; | |
revoke = true; | |
sendfile = true; | |
setgroups = true; | |
settimeofday = true; | |
signalfd = true; | |
splice = true; | |
strcasestr = true; | |
strnlen = true; | |
uint64t = true; | |
futimens = true; | |
futimes = true; | |
arc4random = false; | |
arc4random_addrandom = false; | |
getrandom = true; | |
itimer = true; | |
namespaces = true; | |
nsgetparent = true; | |
explicit_bzero = true; | |
emptyregex = true; | |
}; | |
sizeof = { | |
sizeofushort = 2; | |
sizeofuint = 4; | |
sizeofulong = 8; | |
sizeofsize = 8; | |
sizeofuid = 4; | |
sizeofgid = 4; | |
sizeofpid = 4; | |
sizeoftime = 8; | |
sizeofdev = 8; | |
sizeofino = 8; | |
}; | |
signed = { | |
signedsize = false; | |
signeduid = false; | |
signedgid = false; | |
signedpid = true; | |
signedtime = true; | |
signeddev = false; | |
signedino = false; | |
}; | |
}; | |
# sizeTy = with types; enum int [ 2 4 8 ]; | |
# sysdepsTy = with types; product { | |
# target = string; | |
# endianness = enum string [ "little" "big" ]; | |
# has = attrs bool; | |
# sizeof = attrs sizeTy; | |
# signed = attrs bool; | |
# }; | |
# headerFieldsTy = with types; | |
# attrs (union [ | |
# boolean | |
# string | |
# sizeTy | |
# (product { eitherDefined = string; }) | |
# ]); | |
# Convert sysdeps struct to header fields struct | |
sysdepsToHeaderFields = sysdeps: | |
let | |
# A macro for bool value, conditionally defined if true | |
has = lib.mapAttrs' (n: v: { | |
name = "SKALIBS_HAS${lib.toUpper n}"; | |
value = v; | |
}); | |
# A macro for the sizes, defined with uint | |
sizeof = lib.mapAttrs' (n: v: { | |
name = "SKALIBS_${lib.toUpper n}"; | |
value = v; | |
}); | |
# These are slightly different, there’s two possible macro names, | |
# conditionally defined based on the value. | |
signed = lib.mapAttrs' (n: v: { | |
name = if v | |
then "SKALIBS_HAS${lib.toUpper n}" | |
else "SKALIBS_HASUN${lib.toUpper n}"; | |
value = true; | |
}); | |
in { | |
SKALIBS_TARGET = sysdeps.target; | |
SKALIBS_BSD_SUCKS = { | |
eitherDefined = [ | |
"__FreeBSD__" | |
"__OpenBSD__" | |
"__NetBSD__" | |
"__bsdi__" | |
"__DragonFly__" | |
]; | |
}; | |
endianness = sysdeps.endianness; | |
} | |
// (has sysdeps.has) | |
// (sizeof sysdeps.sizeof) | |
// (signed sysdeps.signed); | |
headerFieldsToHeaderFile = headerFields: | |
let | |
print = v: | |
if builtins.isString v | |
then ''"${lib.escape [''"''] v}"'' | |
else lib.generators.mkValueStringDefault {} v; | |
define = n: v: | |
"#define ${n}${if v == null then "" else " ${print v}"}"; | |
maybeDefine = n: v: | |
if builtins.isBool v then | |
if v then define n null else "" | |
else if builtins.isString v then | |
define n v | |
else if builtins.isInt v then | |
define n v | |
else if builtins.isAttrs v then | |
if v ? eitherDefined | |
then '' | |
#if defined ${lib.concatMapStringsSep " || " (s: "defined(${s})") v.eitherDefined} | |
# define SKALIBS_BSD_SUCKS | |
#endif'' | |
else throw "unreachable (programming error)" | |
else throw "unreachable (programming error)"; | |
allFlags = lib.concatStringsSep "\n" (lib.concatLists | |
(lib.mapAttrsToList | |
(n: v: | |
[ | |
"" | |
"#undef ${n}" | |
] ++ | |
(let m = maybeDefine n v; | |
in if m == "" then [] else [m])) | |
headerFields)); | |
in '' | |
#ifndef SYSDEPS_H | |
#define SYSDEPS_H | |
${allFlags} | |
#endif | |
''; | |
in headerFieldsToHeaderFile (sysdepsToHeaderFields example) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment