<?php
declare(strict_types=1);
return (function() {
// This is a little whacky. `FFI::cdef` isn't smart enough to handle
// preprocessor directives, so we feed it a `gcc -E` version of
// termbox2.h (termbox2.ffi.h, created by the Makefile). On the other
// hand, it's useful to have `#define` constants for tests, so we parse
// those out from the raw `termbox2.h`.
$repo_dir = dirname(__DIR__);
$termbox_h = "$repo_dir/termbox2.h";
$termbox_ffi_h = "$repo_dir/termbox2.ffi.h";
$libtermbox_so = "$repo_dir/libtermbox2.so";
$termbox_h_data = file_get_contents($termbox_h);
// Look at only the content in between `__TERMBOX_H`
$matches = [];
preg_match(
'@#define __TERMBOX_H\n(.*?)#endif /\* __TERMBOX_H \*/@sm',
$termbox_h_data,
$matches
);
$termbox_h_data = $matches[1] ?? '';
// Extract #define values
$defines = [];
$matches = [];
preg_match_all('/^#define\s+(TB_\S+)\s+(.+)$/m', $termbox_h_data, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$define_name = $match[1];
$define_value = $match[2];
// Remove comments
$define_value = trim(preg_replace('|/\*.*$|', '', $define_value));
// Special case for evaluating `(0xFFFF - ...)` values
$match2 = [];
if (preg_match('/^\(0xffff - (\d+)\)$/i', $define_value, $match2)) {
$define_value = 0xffff - (int)$match2[1];
} else if (substr($define_value, 0, 2) === '0x') {
$define_value = hexdec(substr($define_value, 2));
}
$defines[$define_name] = (int)$define_value;
}
// Make FFI
$termbox_ffi_h_data = file_get_contents($termbox_ffi_h);
$ffi = FFI::cdef($termbox_ffi_h_data, $libtermbox_so);
return [ $ffi, $defines ];
})();