mirror of
https://github.com/vhaudiquet/cindex.git
synced 2025-12-18 20:26:06 +00:00
Initial commit
This commit is contained in:
267
index.sh
Executable file
267
index.sh
Executable file
@@ -0,0 +1,267 @@
|
||||
#!/bin/sh
|
||||
|
||||
gcc_dumpmachine=$(gcc -dumpmachine)
|
||||
gcc_version=$(gcc -dumpversion)
|
||||
|
||||
gcc_program_output=/tmp/a.out
|
||||
|
||||
# Check for --local-system option
|
||||
if [ "$1" == "--local-system" ]; then
|
||||
local_system=1
|
||||
|
||||
# Check for local system name
|
||||
if [ -z "$2" ]; then
|
||||
echo "Error: local system name not specified"
|
||||
echo "Usage: ./index.sh [--local-system <name> <./lib,./include path>]"
|
||||
return 1 2>/dev/null || exit 1
|
||||
fi
|
||||
local_system_name=$2
|
||||
|
||||
# Check for local system path
|
||||
if [ -z "$3" ]; then
|
||||
echo "Error: local system path not specified"
|
||||
echo "Usage: ./index.sh [--local-system <name> <./lib,./include path>]"
|
||||
return 1 2>/dev/null || exit 1
|
||||
fi
|
||||
local_system_path=$3
|
||||
else
|
||||
local_system=0
|
||||
fi
|
||||
|
||||
# LIBC
|
||||
libc_names=("glibc" "musl" "uClibc-ng" "dietlibc")
|
||||
|
||||
# Present/Absent markers (colors)
|
||||
p="\e[32m"
|
||||
pe="\e[0m"
|
||||
n="\e[31m"
|
||||
ne="\e[0m"
|
||||
|
||||
# Warning markers (colors)
|
||||
w="\e[33m"
|
||||
we="\e[0m"
|
||||
|
||||
# C Standards
|
||||
cstd=("c89" "c99" "c11" "c2x")
|
||||
|
||||
# SuS standards
|
||||
sus=("susv2" "susv3" "susv4")
|
||||
|
||||
# Headers
|
||||
sus_headers=("aio" "arpa/inet" "assert" "complex" "cpio" "ctype" "dirent" "dlfcn" "errno" "fcntl" "fenv" "float" "fmtmsg" "fnmatch" "ftw" "glob" "grp" "iconv" "inttypes" "iso646" "langinfo" "libgen" "limits" "locale" "math" "monetary" "mqueue" "ndbm" "net/if" "netdb" "netinet/in" "netinet/tcp" "nl_types" "poll" "pthread" "pwd" "regex" "sched" "search" "semaphore" "setjmp" "signal" "spawn" "stdarg" "stdbool" "stddef" "stdint" "stdio" "stdlib" "string" "strings" "stropts" "sys/ipc" "sys/mman" "sys/msg" "sys/resource" "sys/select" "sys/sem" "sys/shm" "sys/socket" "sys/stat" "sys/statvfs" "sys/time" "sys/times" "sys/types" "sys/uio" "sys/un" "sys/utsname" "sys/wait" "syslog" "tar" "termios" "tgmath" "time" "trace" "ulimit" "unistd" "utime" "utmpx" "wchar" "wctype" "wordexp")
|
||||
c89=("assert" "ctype" "errno" "float" "limits" "locale" "math" "setjmp" "signal" "stdarg" "stddef" "stdio" "stdlib" "string" "time")
|
||||
c99=(${c89[@]} "complex" "fenv" "inttypes" "iso646" "stdbool" "stdint" "tgmath" "wchar" "wctype")
|
||||
c11=(${c99[@]} "stdalign" "stdatomic" "stdnoreturn" "threads")
|
||||
c2x=(${c11[@]} "stdbit" "stdckdint")
|
||||
|
||||
# Headers list
|
||||
combined=("${sus_headers[@]}" "${c2x[@]}")
|
||||
headers=($(printf '%s\n' ${combined[@]} | sort -u))
|
||||
|
||||
# Import functions
|
||||
source ./stdh.sh
|
||||
|
||||
check_std_c() {
|
||||
for std in ${cstd[@]}; do
|
||||
json+="\"${std}\":"
|
||||
|
||||
# Check if header is included in current standard
|
||||
std_headers=($(eval 'echo ${'$std'[@]}'))
|
||||
printf '%s\0' "${std_headers[@]}" | grep -Fxqz -- $header_name
|
||||
if [ ! $? -eq 0 ]; then
|
||||
json+="false,"
|
||||
echo -e -n $n$std$ne" "
|
||||
continue
|
||||
fi
|
||||
|
||||
# Compile a program doing `if(function)`
|
||||
echo -e "#include <${header_name}.h>\nint main()\n{\n\tif("$f") return 0; else return 1;\n}\n" | gcc -std=$std -xc - -o ${gcc_program_output} >/dev/null 2>&1
|
||||
|
||||
# Check gcc output
|
||||
if [ $? -eq 0 ]; then
|
||||
${gcc_program_output}
|
||||
if [ $? -eq 0 ]; then
|
||||
json+="true"
|
||||
echo -e -n $p$std$pe" "
|
||||
else
|
||||
json+="false"
|
||||
echo -e -n $n$std$ne" "
|
||||
fi
|
||||
else
|
||||
# Check if function is in fact a macro
|
||||
echo -e "#include <${header_name}.h>\nint main()\n{\n\t#ifdef ${f}\n\treturn 0;\n\t#else\n\treturn 1;\n\t#endif\n}\n" | gcc -std=$std -xc - -o ${gcc_program_output} >/dev/null 2>&1
|
||||
if [ ! $? -eq 0 ]; then
|
||||
# This should never fail unless header is broken
|
||||
echo -e "\nFatal: ${f}() in ${header_name} resolution as macro made gcc fail"
|
||||
echo " This should never happen, please report this bug"
|
||||
return 1 2>/dev/null || exit 1
|
||||
fi
|
||||
${gcc_program_output}
|
||||
if [ $? -eq 0 ]; then
|
||||
json+="true"
|
||||
echo -e -n $p$std$pe" "
|
||||
else
|
||||
json+="false"
|
||||
echo -e -n $n$std$ne" "
|
||||
fi
|
||||
fi
|
||||
json+=","
|
||||
done
|
||||
}
|
||||
|
||||
check_for_libc() {
|
||||
lib_name=$1
|
||||
lib_dir=$2
|
||||
lib_path=$2/lib/libc.a
|
||||
|
||||
# Check for symbol in libc
|
||||
json+="\""$lib_name"\":"
|
||||
objdump -t $lib_path | grep -w $f"$" >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
json+="true"
|
||||
echo -e -n $p$lib_name$pe" "
|
||||
else
|
||||
# Function not found in libc : check in other libraries in the same directory
|
||||
found=false
|
||||
other_libs=($(find ${lib_dir}/lib -maxdepth 1 -name "*.a" '!' -name "libc.a"))
|
||||
|
||||
# If header is math.h/complex.h, begin searching in math library
|
||||
if [ $header_name = "math" ] || [ $header_name = "complex" ] || [ $header_name = "fenv" ]; then
|
||||
other_libs+=($other_libs)
|
||||
other_libs[0]="${lib_dir}/lib/libm.a"
|
||||
fi
|
||||
|
||||
# If header is threads.h/pthread.h, begin searching in libpthread
|
||||
if [ $header_name = "threads" ] || [ $header_name = "pthread" ]; then
|
||||
other_libs+=($other_libs)
|
||||
other_libs[0]="${lib_dir}/lib/libpthread.a"
|
||||
fi
|
||||
|
||||
# If header is aio.h, begin searching in librt
|
||||
if [ $header_name = "aio" ]; then
|
||||
other_libs+=($other_libs)
|
||||
other_libs[0]="${lib_dir}/lib/librt.a"
|
||||
fi
|
||||
|
||||
for lib in ${other_libs[@]}; do
|
||||
objdump -t $lib 2>/dev/null | grep -w $f"$" >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
# Obtain library name, and remove extension
|
||||
olib_name=$(basename $lib)
|
||||
olib_name=${olib_name%.*}
|
||||
olib_name=${olib_name%-*}
|
||||
|
||||
found=true
|
||||
json+="true"
|
||||
echo -e -n $p$lib_name"(${olib_name})"$pe" "
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $found = false ]; then
|
||||
# Function not found in any library ; check in headers
|
||||
# Check if header is present
|
||||
if [ -f "${lib_dir}/include/${header_name}.h" ]; then
|
||||
if [ $local_system -eq 0 ]; then
|
||||
link_entry=""
|
||||
# Check for crt1.o, crti.o and crtn.o
|
||||
if [ -f "${lib_dir}/lib/crt1.o" ]; then
|
||||
link_entry+="-l:crt1.o "
|
||||
fi
|
||||
if [ -f "${lib_dir}/lib/crti.o" ]; then
|
||||
link_entry+="-l:crti.o "
|
||||
fi
|
||||
if [ -f "${lib_dir}/lib/crtn.o" ]; then
|
||||
link_entry+="-l:crtn.o "
|
||||
fi
|
||||
|
||||
# Check for start.o
|
||||
if [ -f "${lib_dir}/lib/start.o" ]; then
|
||||
link_entry+="-l:start.o "
|
||||
fi
|
||||
|
||||
echo -e "#include <${header_name}.h>\nint main()\n{\n\t#ifdef ${f}\n\t\treturn 0;\n\t#else\n\t\treturn 1;\n\t#endif\n}" | gcc -o ${gcc_program_output} -ffreestanding -nostdlib -xc -I${lib_dir}/include/ -I/usr/lib/gcc/${gcc_dumpmachine}/${gcc_version}/include - -L${lib_dir}/lib/ ${link_entry} -lc -lgcc -lgcc_eh -static >/dev/null 2>&1
|
||||
else
|
||||
echo -e "#include <${header_name}.h>\nint main()\n{\n\t#ifdef ${f}\n\t\treturn 0;\n\t#else\n\t\treturn 1;\n\t#endif\n}" | gcc -o ${gcc_program_output} -xc - >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
${gcc_program_output}
|
||||
if [ $? -eq 0 ]; then
|
||||
json+="true"
|
||||
echo -e -n $p$lib_name"(macro)"$pe" "
|
||||
else
|
||||
json+="false"
|
||||
echo -e -n $n$lib_name$ne" "
|
||||
fi
|
||||
else
|
||||
json+="false"
|
||||
echo -e -n $n$lib_name$ne$w"(?)"$we" "
|
||||
fi
|
||||
else
|
||||
json+="false"
|
||||
echo -e -n $n$lib_name$ne" "
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
json+=","
|
||||
}
|
||||
|
||||
check_for_sus() {
|
||||
# Check for function file in ./susvx/functions/$f
|
||||
for s in ${sus[@]}; do
|
||||
json+="\""$s"\":"
|
||||
if [ -f "./$s/functions/$f.html" ] || [ -f "./$s/xsh/$f.html" ] || [ -f "./$s/xns/$f.html" ]; then
|
||||
json+="true"
|
||||
echo -e -n $p$s$pe" "
|
||||
else
|
||||
json+="false"
|
||||
echo -e -n $n$s$ne" "
|
||||
fi
|
||||
json+=","
|
||||
done
|
||||
}
|
||||
|
||||
for i in ${!headers[@]}; do
|
||||
header_name=${headers[$i]}
|
||||
echo "header file "$header_name".h:"
|
||||
json="["
|
||||
header_name_clean=$(echo $header_name | sed 's/\//_/g')
|
||||
header_fns=($(eval 'echo ${'$header_name_clean'[@]}'))
|
||||
for f in ${header_fns[@]}; do
|
||||
json+="{\"name\":\""$f"\",\"type\":\"function\","
|
||||
|
||||
echo -n "checking for "$f"()... "
|
||||
|
||||
# Check for symbol in libc
|
||||
if [ $local_system -eq 0 ]; then
|
||||
for i in ${!libc_names[@]}; do
|
||||
lib_name=${libc_names[$i]}
|
||||
lib_dir="./libs/${lib_name}"
|
||||
|
||||
check_for_libc $lib_name $lib_dir
|
||||
done
|
||||
else
|
||||
check_for_libc $local_system_name $local_system_path
|
||||
fi
|
||||
|
||||
# Check for standards
|
||||
if [ $local_system -eq 0 ]; then
|
||||
check_std_c
|
||||
check_for_sus
|
||||
fi
|
||||
|
||||
json+="\"header\":\"${header_name}\"},"
|
||||
echo ""
|
||||
done
|
||||
|
||||
# Output JSON
|
||||
json+="{}"
|
||||
json+=" ]"
|
||||
o="output/${header_name}.json"
|
||||
mkdir -p "${o%/*}"
|
||||
echo -e $json >output/$header_name.json
|
||||
done
|
||||
|
||||
# Cleanup
|
||||
rm -f ${gcc_program_output}
|
||||
Reference in New Issue
Block a user