use crate::core::moniker::Moniker;
use super::super::kinds;
pub(super) fn is_libc_function(name: &[u8]) -> bool {
LIBC_FUNCTIONS
.binary_search_by(|candidate| candidate.as_bytes().cmp(name))
.is_ok()
}
pub(super) fn libc_function_target(root: &Moniker, name: &[u8]) -> Moniker {
let mut builder = crate::lang::sdk::sdk_target_builder(root.as_view().project(), b"c");
builder.segment(kinds::PATH, b"libc");
builder.segment(kinds::FUNC, name);
builder.build()
}
pub(super) fn is_stdlib_header_path(path: &str) -> bool {
let root = path
.split('/')
.find(|piece| !piece.is_empty())
.map(super::syntax::strip_header_suffix)
.unwrap_or_default();
STDLIB_HEADER_ROOTS.binary_search(&root).is_ok()
}
pub(super) const STDLIB_HEADER_ROOTS: &[&str] = &[
"arpa",
"assert",
"complex",
"ctype",
"dirent",
"dlfcn",
"errno",
"fcntl",
"fenv",
"float",
"glob",
"grp",
"iconv",
"inttypes",
"iso646",
"langinfo",
"libgen",
"limits",
"locale",
"math",
"netdb",
"netinet",
"poll",
"pthread",
"pwd",
"regex",
"sched",
"semaphore",
"setjmp",
"signal",
"stdalign",
"stdarg",
"stdatomic",
"stdbool",
"stddef",
"stdint",
"stdio",
"stdlib",
"stdnoreturn",
"string",
"strings",
"sys",
"syslog",
"termios",
"tgmath",
"threads",
"time",
"uchar",
"unistd",
"utime",
"wchar",
"wctype",
];
const LIBC_FUNCTIONS: &[&str] = &[
"abort",
"abs",
"accept",
"access",
"asprintf",
"assert",
"atexit",
"atof",
"atoi",
"atol",
"atoll",
"bind",
"bsearch",
"calloc",
"ceil",
"chdir",
"chmod",
"chown",
"clearerr",
"clock",
"clock_gettime",
"close",
"closedir",
"connect",
"cos",
"difftime",
"dlclose",
"dlerror",
"dlopen",
"dlsym",
"dup",
"dup2",
"execve",
"exit",
"exp",
"fabs",
"fchmod",
"fclose",
"fcntl",
"fdopen",
"feof",
"ferror",
"fflush",
"fgetc",
"fgets",
"fileno",
"floor",
"fmod",
"fopen",
"fork",
"fprintf",
"fputc",
"fputs",
"fread",
"free",
"freeaddrinfo",
"fscanf",
"fseek",
"fseeko",
"fstat",
"fsync",
"ftell",
"ftello",
"ftruncate",
"fwrite",
"getaddrinfo",
"getc",
"getchar",
"getcwd",
"getenv",
"getline",
"getpeername",
"getpid",
"getppid",
"getrlimit",
"getrusage",
"getsockname",
"getsockopt",
"gettimeofday",
"getuid",
"gmtime",
"gmtime_r",
"isalnum",
"isalpha",
"isdigit",
"islower",
"isprint",
"isspace",
"isupper",
"isxdigit",
"kill",
"labs",
"listen",
"localtime",
"localtime_r",
"log",
"log10",
"longjmp",
"lseek",
"lstat",
"malloc",
"memchr",
"memcmp",
"memcpy",
"memmem",
"memmove",
"memset",
"mkdir",
"mkstemp",
"mktime",
"mmap",
"munmap",
"nanosleep",
"open",
"opendir",
"perror",
"pipe",
"poll",
"pow",
"printf",
"pthread_cond_broadcast",
"pthread_cond_destroy",
"pthread_cond_init",
"pthread_cond_signal",
"pthread_cond_wait",
"pthread_create",
"pthread_detach",
"pthread_join",
"pthread_mutex_destroy",
"pthread_mutex_init",
"pthread_mutex_lock",
"pthread_mutex_trylock",
"pthread_mutex_unlock",
"pthread_self",
"putc",
"putchar",
"puts",
"qsort",
"raise",
"rand",
"random",
"read",
"readdir",
"readlink",
"realloc",
"recv",
"regcomp",
"regerror",
"regexec",
"regfree",
"remove",
"rename",
"rewind",
"rmdir",
"round",
"select",
"send",
"setenv",
"setjmp",
"setlocale",
"setrlimit",
"setsockopt",
"setvbuf",
"shutdown",
"sigaction",
"sigemptyset",
"signal",
"sin",
"sleep",
"snprintf",
"socket",
"sprintf",
"sqrt",
"srand",
"srandom",
"sscanf",
"stat",
"strcasecmp",
"strcasestr",
"strcat",
"strchr",
"strcmp",
"strcoll",
"strcpy",
"strcspn",
"strdup",
"strerror",
"strftime",
"strlen",
"strncasecmp",
"strncat",
"strncmp",
"strncpy",
"strndup",
"strpbrk",
"strrchr",
"strspn",
"strstr",
"strtod",
"strtok",
"strtok_r",
"strtol",
"strtoll",
"strtoul",
"strtoull",
"symlink",
"sysconf",
"system",
"tan",
"time",
"tolower",
"toupper",
"ungetc",
"unlink",
"unsetenv",
"usleep",
"vasprintf",
"vfprintf",
"vprintf",
"vsnprintf",
"vsprintf",
"waitpid",
"write",
];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn stdlib_header_roots_sorted_unique() {
for pair in STDLIB_HEADER_ROOTS.windows(2) {
assert!(
pair[0] < pair[1],
"expected sorted unique header roots, got `{}` before `{}`",
pair[0],
pair[1]
);
}
}
#[test]
fn libc_functions_sorted_unique() {
for pair in LIBC_FUNCTIONS.windows(2) {
assert!(
pair[0] < pair[1],
"expected sorted unique libc list, got `{}` before `{}`",
pair[0],
pair[1]
);
}
}
#[test]
fn libc_functions_are_language_contract() {
for name in [
b"assert".as_slice(),
b"malloc".as_slice(),
b"free",
b"printf",
b"memcpy",
b"strlen",
b"open",
b"close",
b"pthread_create",
] {
assert!(is_libc_function(name));
}
assert!(!is_libc_function(b"listCreate"));
assert!(!is_libc_function(b"zmalloc"));
}
}