From 112efa12cee0921222a533fcc6f4f4f31b78c08e Mon Sep 17 00:00:00 2001 From: Jakob Kaivo Date: Sat, 15 Aug 2020 16:01:24 -0400 Subject: move header generation stuff to separate subdirectory --- ftm.m4 | 22 ----- gen/ftm.m4 | 22 +++++ gen/mk.sh | 271 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gen/mkh.sh | 173 +++++++++++++++++++++++++++++++++++++++ mk.sh | 271 ------------------------------------------------------------- mkh.sh | 173 --------------------------------------- 6 files changed, 466 insertions(+), 466 deletions(-) delete mode 100644 ftm.m4 create mode 100644 gen/ftm.m4 create mode 100644 gen/mk.sh create mode 100755 gen/mkh.sh delete mode 100644 mk.sh delete mode 100755 mkh.sh diff --git a/ftm.m4 b/ftm.m4 deleted file mode 100644 index 9b55c423..00000000 --- a/ftm.m4 +++ /dev/null @@ -1,22 +0,0 @@ -define(`STDC', - `ifelse($#, 2, - `ifelse($1, 1, `!defined __STDC_VERSION__ || __STDC_VERSION__ < $2', `defined __STDC_VERSION__ && $1 <= __STDC_VERSION__ && __STDC_VERSION__ < $2')', - `ifelse($1, 1, `', `defined __STDC_VERSION__ && $1 <= __STDC_VERSION__')') -')dnl - -define(`POSIX', - `ifelse($#, 2, - `ifelse($1, 1, `defined _POSIX_SOURCE && (!defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < $2)', `defined _POSIX_C_SOURCE && $1 <= _POSIX_C_SOURCE && _POSIX_C_SOURCE < $2')', - `ifelse($1, 1, `defined _POSIX_SOURCE', `defined _POSIX_C_SOURCE && $1 <= _POSIX_C_SOURCE')') -')dnl - -define(`XEXT', `defined _XOPEN_SOURCE && ((defined _XOPEN_SOURCE_EXTENDED && _XOPEN_SOURCE_EXTENDED == 1) || 500 <= _XOPEN_SOURCE)') -define(`XOPEN', - `ifelse($#, 2, - `ifelse($1, 4, `defined _XOPEN_SOURCE && _XOPEN_SOURCE < $2', - `ifelse($1, 400, `XEXT() && _XOPEN_SOURCE < $2', - `defined _XOPEN_SOURCE && $1 <= _XOPEN_SOURCE && _XOPEN_SOURCE < $2')')', - `ifelse($1, 4, `defined _XOPEN_SOURCE', - `ifelse($1, 400, `XEXT()', - `defined _XOPEN_SOURCE && $1 <= _XOPEN_SOURCE')')') -')dnl diff --git a/gen/ftm.m4 b/gen/ftm.m4 new file mode 100644 index 00000000..9b55c423 --- /dev/null +++ b/gen/ftm.m4 @@ -0,0 +1,22 @@ +define(`STDC', + `ifelse($#, 2, + `ifelse($1, 1, `!defined __STDC_VERSION__ || __STDC_VERSION__ < $2', `defined __STDC_VERSION__ && $1 <= __STDC_VERSION__ && __STDC_VERSION__ < $2')', + `ifelse($1, 1, `', `defined __STDC_VERSION__ && $1 <= __STDC_VERSION__')') +')dnl + +define(`POSIX', + `ifelse($#, 2, + `ifelse($1, 1, `defined _POSIX_SOURCE && (!defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < $2)', `defined _POSIX_C_SOURCE && $1 <= _POSIX_C_SOURCE && _POSIX_C_SOURCE < $2')', + `ifelse($1, 1, `defined _POSIX_SOURCE', `defined _POSIX_C_SOURCE && $1 <= _POSIX_C_SOURCE')') +')dnl + +define(`XEXT', `defined _XOPEN_SOURCE && ((defined _XOPEN_SOURCE_EXTENDED && _XOPEN_SOURCE_EXTENDED == 1) || 500 <= _XOPEN_SOURCE)') +define(`XOPEN', + `ifelse($#, 2, + `ifelse($1, 4, `defined _XOPEN_SOURCE && _XOPEN_SOURCE < $2', + `ifelse($1, 400, `XEXT() && _XOPEN_SOURCE < $2', + `defined _XOPEN_SOURCE && $1 <= _XOPEN_SOURCE && _XOPEN_SOURCE < $2')')', + `ifelse($1, 4, `defined _XOPEN_SOURCE', + `ifelse($1, 400, `XEXT()', + `defined _XOPEN_SOURCE && $1 <= _XOPEN_SOURCE')')') +')dnl diff --git a/gen/mk.sh b/gen/mk.sh new file mode 100644 index 00000000..bbf8c8c1 --- /dev/null +++ b/gen/mk.sh @@ -0,0 +1,271 @@ +#!/bin/sh + +TOPDIR=$(dirname $0) +DEPS=${TOPDIR}/.deps +SRCDIR=${TOPDIR}/src + +classify_source () { + NAME=$(basename $1 .c) + + if grep -q "^REFERENCE(" $1; then + echo REFERENCE + elif grep -q "^#define ${NAME}[ (]" $1; then + echo MACRO + elif grep -q "#undef ${NAME}" $1; then + echo MACRO + elif grep -q '^typedef .*(\*' $1; then + echo FNTYPE + elif grep -q "^typedef " $1; then + echo TYPE + elif grep -q "^struct (^ )*;$" $1; then + echo TYPE + elif grep -q "^typedef .*{$" $1; then + echo TYPE_LONG + elif grep -q "^struct.*{" $1; then + echo RECORD + elif grep -q "^union.*{" $1; then + echo RECORD + elif grep -q "^[A-Za-z_].*[ \*]${NAME}[[;]" $1; then + echo EXTERN + elif grep -q 'TGFN' $1; then + echo TGFN + else + echo FUNCTION + fi +} + +version_guard () { + parsed=/tmp/$(basename $1).v + grep -F -e 'STDC(' -e 'POSIX(' -e 'XOPEN(' $1 | sort | m4 $(dirname $0)/ftm.m4 - | grep . > $parsed + lines=$(wc -l $parsed | cut -f1 -d' ') + + if [ $lines -ne 0 ]; then + printf '#if' + loop=1 + while [ $loop -lt $lines ]; do + printf '\t(%s) || \\\n' "$(sed -ne "${loop}p;q" $parsed)" + loop=$((loop + 1)) + done + + printf '\t(%s)\n' "$(sed -ne "${loop}p" $parsed)" + fi + + rm -f $parsed +} + +get_declaration () { + case ${2:-$(classify_source $1)} in + + REFERENCE) + ref="$(grep -F 'REFERENCE(' $1 | m4 -DREFERENCE='$1')" + if (echo "$ref" | grep -q '<.*>'); then + echo "#include $ref" + else + get_declaration "src/${ref}" + fi + ;; + + MACRO) + if ! (grep -q '#undef' $1 && grep -q 'MAY-BE-UNDEF' $1); then + grep -E '^(#(if|def|undef|el|end)| )' $1 + fi + ;; + + TYPE|TYPE_LONG|RECORD|FNTYPE) + base=$(basename $1 .c) + printf '#ifndef __TYPE_%s_DEFINED__\n#define __TYPE_%s_DEFINED__\n' "$base" "$base" + + if grep -q '^#if' $1; then + sed -ne '/^#if/,/#endif/p' $1 + elif grep -qE '^(typedef|struct|union) .*\{' $1; then + sed -ne '/{$/,/^}/p' $1 + elif grep -qE '^(typedef|struct|union) .*[^;]$' $1; then + grep -E '^(typedef|struct|union| )' $1 + else + grep -E '^(typedef|struct|union) ' $1 + fi + + printf '#endif\n\n' + ;; + + EXTERN) + echo "extern $(grep '^[a-zA-Z_].*;$' $1)" + ;; + + FUNCTION) + echo "$(grep '^[a-zA-Z_].*)' $1 | head -n1);" + ;; + + TGFN) + echo "$(grep 'TGFN.*)$' $1 | m4 -DTGFN='$1' -DTYPE='double');" + echo "$(grep 'TGFN.*)$' $1 | m4 -DTGFN='$1f' -DTYPE='float');" + echo "$(grep 'TGFN.*)$' $1 | m4 -DTGFN='$1l' -DTYPE='long double');" + ;; + + *) + # unknown type, so try guessing + get_declaration $1 + ;; + + esac +} + +stdc_base() { + (grep 'STDC(' $1 | m4 -DSTDC='$1') || echo 0 +} + +posix_base() { + (grep 'POSIX(' $1 | m4 -DPOSIX='$1') || echo 0 +} + +xopen_base() { + (grep 'XOPEN(' $1 | m4 -DXOPEN='$1') || echo 0 +} + +find_all() { + rm -rf "${DEPS}" + mkdir -p "${DEPS}" + find "${SRCDIR}" -name \*.c > "${DEPS}/all.c" + find "${SRCDIR}" -name \*.ref > "${DEPS}/all.ref" + find "${SRCDIR}" -name \*.s > "${DEPS}/all.s" + grep '#include <.*>' $(cat "${DEPS}/all.c" "${DEPS}/all.ref") | + sed 's/^.*<\(.*\.h\)>.*/\1/' | sort -u > "${DEPS}/all.h" +} + +version_sources() { + for file in $(cat "${DEPS}/all.c" "${DEPS}/all.ref"); do + printf '%s\n' "$file" + c_version=$(stdc_base "${file}") + p_version=$(posix_base "${file}") + x_version=$(xopen_base "${file}") + + if [ -n "${c_version}" ]; then + mkdir -p "${DEPS}/c.${c_version}" + echo "$file" >> "${DEPS}/c.${c_version}/sources" + fi + + if [ -n "${p_version}" ]; then + mkdir -p "${DEPS}/p.${p_version}" + echo "$file" >> "${DEPS}/p.${p_version}/sources" + fi + + if [ -n "${x_version}" ]; then + mkdir -p "${DEPS}/x.${x_version}" + echo "$file" >> "${DEPS}/x.${x_version}/sources" + fi + done +} + +make_headers_mk() { + if ! [ -f "${DEPS}/all.h" ]; then + find_all + fi + + rm -f "${TOPDIR}/.headers.mk" + printf '.POSIX:\n.DEFAULT: headers\n\n' > "${TOPDIR}/.headers.mk" + printf 'include .config.mk\n\n' >> "${TOPDIR}/.headers.mk" + + for header in $(cat "${DEPS}/all.h"); do + printf 'Building dependencies for <%s>\n' "$header" + printf '$(INCDIR)/%s: mkh.sh ' "$header" >> "${TOPDIR}/.headers.mk" + mkdir -p $(dirname "${TOPDIR}/.deps/h/${header}.deps") + grep -l "#include <${header}>" $(cat "${DEPS}/all.c" "${DEPS}/all.ref") > "${TOPDIR}/.deps/h/${header}.deps" + sed -e "s#${SRCDIR}#\$(SRCDIR)#" < "${TOPDIR}/.deps/h/${header}.deps" | tr '\n' ' ' >> "${TOPDIR}/.headers.mk" + printf '\n\tINCDIR=$(INCDIR) sh mkh.sh $(INCDIR)/%s\n\n' "${header}" >> "${TOPDIR}/.headers.mk" + done + + printf 'headers: ' >> "${TOPDIR}/.headers.mk" + for header in $(cat "${DEPS}/all.h"); do + printf ' \\\n\t$(INCDIR)/%s' "$header" >> "${TOPDIR}/.headers.mk" + done + + printf '\n' >> "${TOPDIR}/.headers.mk" +} + +make_deps_mk() { + if ! [ -f "${DEPS}/all.c" ]; then + find_all + fi + + rm -f "${TOPDIR}/.deps.mk" + rm -f "${DEPS}"/lib* + + printf '.POSIX:\n.SILENT:\ndefault: all\n\n' > "${TOPDIR}/.deps.mk" + printf 'include .config.mk\n\n' >> "${TOPDIR}/.deps.mk" + printf 'BASE_CFLAGS=-I$(INCDIR) -Isrc -fno-builtin -nostdinc\n' >> "${TOPDIR}/.deps.mk" + printf '\n' >> "${TOPDIR}/.deps.mk" + + printf '.POSIX:\nlibc_C_0_OBJS=' > "${DEPS}/libc.C_0" + # Assume all assembly is useful regardless of standard version + for file in $(sed -e 's/\.[^.]*\.s$/.ARCH.s/g' .deps/all.s | sort -u); do + BASE=$(basename $file .ARCH.s) + SRC=$(echo $file | sed -e 's/\.ARCH\./.$(ARCHITECTURE)-$(WORDSIZE)./') + printf 'libc.a($(OBJDIR)/%s.$(ARCHITECTURE)-$(WORDSIZE).o): $(OBJDIR)/%s.$(ARCHITECTURE)-$(WORDSIZE).o\n' $BASE $BASE >> "${TOPDIR}/.deps.mk" + printf ' \\\n\tlibc.a($(OBJDIR)/%s.$(ARCHITECTURE)-$(WORDSIZE).o)' $BASE >> "${DEPS}/libc.C_0" + printf '$(OBJDIR)/%s.$(ARCHITECTURE)-$(WORDSIZE).o: %s\n' $BASE $SRC >> "${TOPDIR}/.deps.mk" + printf '\t$(CC) $(BASE_CFLAGS) $(CFLAGS) -c %s -o $@\n' $SRC >> "${TOPDIR}/.deps.mk" + printf '\t echo [AS] $@\n\n' >> "${TOPDIR}/.deps.mk" + done + + for file in $(cat "${DEPS}/all.c"); do + printf 'Building dependencies from %s\n' "$file" + type=$(classify_source "${file}") + + if [ ${type} = EXTERN -o ${type} = TGFN -o ${type} = FUNCTION ]; then + LINK=$(grep -F 'LINK(' $file | m4 -DLINK='$1') + LIB=lib${LINK:-c} + OBJ=$(basename $file .c).o + + printf '%s.a(%s): $(OBJDIR)/%s\n' $LIB $OBJ $OBJ >> "${TOPDIR}/.deps.mk" + printf '$(OBJDIR)/%s: %s' "$OBJ" "$file" >> "${TOPDIR}/.deps.mk" + #for header in $(grep '#include' "${file}"); do + #printf ' \\\n\t$(INCDIR)/%s' "$header" >> "${TOPDIR}/.deps.mk" + #done + printf '\n\t$(CC) $(BASE_CFLAGS) $(CFLAGS) -c %s -o $@\n' "$file" >> "${TOPDIR}/.deps.mk" + printf '\techo [CC] $@\n' >> "${TOPDIR}/.deps.mk" + + cver=$(stdc_base $file) + pver=$(posix_base $file) + xver=$(xopen_base $file) + + if [ -n "$cver" ]; then + if ! [ -f "${DEPS}/${LIB}.C_${cver}" ]; then + printf '.POSIX:\n%s_C_%s_OBJS=' "${LIB}" "${cver}" > "${DEPS}/${LIB}.C_${cver}" + fi + printf ' \\\n\t%s.a($(OBJDIR)/%s)' $LIB $OBJ >> "${DEPS}/${LIB}.C_${cver}" + fi + + if [ -n "$pver" ]; then + if ! [ -f "${DEPS}/${LIB}.POSIX_${pver}" ]; then + printf '.POSIX:\n%s_POSIX_%s_OBJS=' "${LIB}" "${pver}" > "${DEPS}/${LIB}.POSIX_${pver}" + fi + printf ' \\\n\t%s.a($(OBJDIR)/%s)' $LIB $OBJ >> "${DEPS}/${LIB}.POSIX_${pver}" + fi + + if [ -n "$xver" ]; then + if ! [ -f "${DEPS}/${LIB}.XOPEN_${xver}" ]; then + printf '.POSIX:\n%s_XOPEN_%s_OBJS=' "${LIB}" "${xver}" > "${DEPS}/${LIB}.XOPEN_${xver}" + fi + printf ' \\\n\t%s.a($(OBJDIR)/%s)' $LIB $OBJ >> "${DEPS}/${LIB}.XOPEN_${xver}" + fi + + if [ -z "$cver" ] && [ -z "$pver" ] && [ -z "$xver" ]; then + if ! [ -f "${DEPS}/${LIB}.C_0" ]; then + printf '.POSIX:\n%s_C_0_OBJS=' "${LIB}" > "${DEPS}/${LIB}.C_0" + fi + printf ' \\\n\t%s.a($(OBJDIR)/%s)' $LIB $OBJ >> "${DEPS}/${LIB}.C_0" + fi + fi + done + + printf '\n' >> "${TOPDIR}/.deps.mk" + + for libdep in ${DEPS}/lib*; do + LIB=$(basename $libdep | sed -e 's/\..*$//') + VER=$(basename $libdep | sed -e 's/^.*\.//') + echo adding dependencies for $LIB v $VER + printf 'include $(TOPDIR)/.deps/%s\n' $(basename $libdep) >> "${TOPDIR}/.deps.mk" + done + + printf '\n' >> "${TOPDIR}/.deps.mk" +} diff --git a/gen/mkh.sh b/gen/mkh.sh new file mode 100755 index 00000000..c4c4d6d4 --- /dev/null +++ b/gen/mkh.sh @@ -0,0 +1,173 @@ +#!/bin/sh + +TOPDIR=$(dirname $0) +if [ -z "${INCDIR}" ]; then + INCDIR="${TOPDIR}/include" +fi +. "${TOPDIR}/mk.sh" + +export LC_ALL=POSIX +export LANG=POSIX +HEADER=$1 +HEADERNAME=$(echo $HEADER | sed -e "s#^${INCDIR}/*##") +GUARD=__$(echo $HEADERNAME | tr a-z/. A-Z__)__ +mkdir -p $(dirname $HEADER) +exec > $HEADER + +if [ $(basename $HEADER) != assert.h ]; then + printf '#ifndef %s\n#define %s\n\n' ${GUARD} ${GUARD} +fi + +printf "/*\nUNG's Not GNU\n\n%s\n*/\n\n" "$(cat LICENSE)" + +rm -rf $HEADER.* +for i in $(cat "${TOPDIR}/.deps/h/${HEADERNAME}.deps" | sort -u); do + # TODO: refs + type=$(classify_source $i) + source=$i + if [ $type = "REFERENCE" ] && ! grep -Fq 'REFERENCE(<' $source; then + source=src/$(grep REFERENCE $i | m4 -DREFERENCE='$1') + type=$(classify_source $source) + fi + version=v$(grep -F -e 'STDC(' -e 'POSIX(' -e 'XOPEN(' $i | sed -e 's/STDC/C/' | sort | tr , - | tr -d '() \n') + mkdir -p $HEADER.$type + echo $source >> $HEADER.$type/$version + + if ! [ -f $(dirname $0)/.deps/ftm/$version ]; then + mkdir -p $(dirname $0)/.deps/ftm + version_guard $source > $(dirname $0)/.deps/ftm/$version + fi + + printf '%s <%s> (%s)\n' "$i" "$HEADER" "$version" >&2 +done + +### +### TODO: prevent _XOPEN_SOURCE expanding to empty string +### +if grep -Fq -e '_XOPEN_SOURCE <' -e '< _XOPEN_SOURCE' $(cat $(HEADER.*/*); then +cat <<-EOF + #if defined _XOPEN_SOURCE && _XOPEN_SOURCE - 1 < 0 + # undef _XOPEN_SOURCE + # define _XOPEN_SOURCE 400 + #endif +EOF +fi + +if grep -Fq 'POSIX(' $(cat $HEADER.*/*); then +cat <<-EOF + #if defined _XOPEN_SOURCE && !defined _POSIX_C_SOURCE + # if (_XOPEN_SOURCE >= 700) + # define _POSIX_C_SOURCE 200809L + # elif (_XOPEN_SOURCE >= 600) + # define _POSIX_C_SOURCE 200112L + # elif (_XOPEN_SOURCE >= 500) + # define _POSIX_C_SOURCE 199506L + # else + # define _POSIX_C_SOURCE 2 + # endif + #endif + + #if defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE + # define _POSIX_SOURCE + #endif + +EOF +fi + +if grep -Fq -e 'POSIX(' -e 'XOPEN(' $(cat $HEADER.*/*); then +cat <<-EOF + #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 19901L + # if (defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 200112L) + # error POSIX.1-2001 and later require a C99 compiler + # elif(defined _XOPEN_SOURCE && _XOPEN_SOURCE >= 600) + # error XOPEN Issue 6 and later require a C99 compiler + # endif + #endif +EOF +fi + +for type in REFERENCE MACRO TYPE TYPE_LONG RECORD FNTYPE EXTERN; do + if [ -d $HEADER.$type ]; then + for v in $HEADER.$type/*; do + version=$(cat $(dirname $0)/.deps/ftm/$(basename $v | sed -e 's/^.*\.//')) + if [ -n "$version" ]; then + printf '%s\n' "$version" + fi + + for i in $(sort -u $v); do + printf '/* %s */\n' $i + get_declaration $i + done + + if [ -n "$version" ]; then + printf '#endif\n' + fi + + printf '\n' + done + rm -rf $HEADER.$type + fi +done + +if [ -d $HEADER.TGFN ]; then + for v in $HEADER.TGFN/*; do + version=$(cat $(dirname $0)/.deps/ftm/$(basename $v | sed -e 's/^.*\.//')) + if [ -n "$version" ]; then + printf '%s\n' "$version" + fi + + for i in $(sort -u $v); do + printf '/* %s */\n' $i + get_declaration $i TGFN + done + + if [ -n "$version" ]; then + printf '#endif\n' + fi + + printf '\n' + done + rm -rf $HEADER.TGFN +fi + +if [ -d $HEADER.FUNCTION ]; then + if grep -q restrict $(cat $HEADER.FUNCTION/*); then + if grep -Fq -e 'STDC(1)' -e 'STDC(1,' -e 'STDC(199409' $(grep -l restrict $(cat $HEADER.FUNCTION/*)) || ! grep -Fq 'STDC(' $(grep -l restrict $(cat $HEADER.FUNCTION/*)); then + printf '#if (!defined __STDC_VERSION__) || (__STDC_VERSION__ < 199901L)\n' + printf '#define restrict\n' + printf '#endif\n\n' + fi + fi + + ### TODO: only if header works with C<11 + if grep -q _Noreturn $(cat $HEADER.FUNCTION/*); then + printf '#if (!defined __STDC_VERSION__) || (__STDC_VERSION__ < 200112L)\n' + printf '#define _Noreturn\n' + printf '#endif\n\n' + fi + + for v in $HEADER.FUNCTION/*; do + version=$(cat $(dirname $0)/.deps/ftm/$(basename $v | sed -e 's/^.*\.//')) + if [ -n "$version" ]; then + printf '%s\n' "$version" + fi + + for i in $(sort -u $v); do + printf '/* %s */\n' $i + get_declaration $i FUNCTION | sed -e 's/\([a-zA-Z_][a-zA-Z_0-9]*\)\([,)]\)/__\1\2/g;s/(__\([a-zA-Z_][a-zA-Z_0-9]*\))/(\1)/g' + done + + if [ -n "$version" ]; then + printf '#endif\n' + fi + + printf '\n' + done + rm -rf $HEADER.FUNCTION +fi + +rm -rf $HEADER.REFERENCE + +if [ $(basename $HEADER) != assert.h ]; then + printf '\n#endif\n' +fi diff --git a/mk.sh b/mk.sh deleted file mode 100644 index bbf8c8c1..00000000 --- a/mk.sh +++ /dev/null @@ -1,271 +0,0 @@ -#!/bin/sh - -TOPDIR=$(dirname $0) -DEPS=${TOPDIR}/.deps -SRCDIR=${TOPDIR}/src - -classify_source () { - NAME=$(basename $1 .c) - - if grep -q "^REFERENCE(" $1; then - echo REFERENCE - elif grep -q "^#define ${NAME}[ (]" $1; then - echo MACRO - elif grep -q "#undef ${NAME}" $1; then - echo MACRO - elif grep -q '^typedef .*(\*' $1; then - echo FNTYPE - elif grep -q "^typedef " $1; then - echo TYPE - elif grep -q "^struct (^ )*;$" $1; then - echo TYPE - elif grep -q "^typedef .*{$" $1; then - echo TYPE_LONG - elif grep -q "^struct.*{" $1; then - echo RECORD - elif grep -q "^union.*{" $1; then - echo RECORD - elif grep -q "^[A-Za-z_].*[ \*]${NAME}[[;]" $1; then - echo EXTERN - elif grep -q 'TGFN' $1; then - echo TGFN - else - echo FUNCTION - fi -} - -version_guard () { - parsed=/tmp/$(basename $1).v - grep -F -e 'STDC(' -e 'POSIX(' -e 'XOPEN(' $1 | sort | m4 $(dirname $0)/ftm.m4 - | grep . > $parsed - lines=$(wc -l $parsed | cut -f1 -d' ') - - if [ $lines -ne 0 ]; then - printf '#if' - loop=1 - while [ $loop -lt $lines ]; do - printf '\t(%s) || \\\n' "$(sed -ne "${loop}p;q" $parsed)" - loop=$((loop + 1)) - done - - printf '\t(%s)\n' "$(sed -ne "${loop}p" $parsed)" - fi - - rm -f $parsed -} - -get_declaration () { - case ${2:-$(classify_source $1)} in - - REFERENCE) - ref="$(grep -F 'REFERENCE(' $1 | m4 -DREFERENCE='$1')" - if (echo "$ref" | grep -q '<.*>'); then - echo "#include $ref" - else - get_declaration "src/${ref}" - fi - ;; - - MACRO) - if ! (grep -q '#undef' $1 && grep -q 'MAY-BE-UNDEF' $1); then - grep -E '^(#(if|def|undef|el|end)| )' $1 - fi - ;; - - TYPE|TYPE_LONG|RECORD|FNTYPE) - base=$(basename $1 .c) - printf '#ifndef __TYPE_%s_DEFINED__\n#define __TYPE_%s_DEFINED__\n' "$base" "$base" - - if grep -q '^#if' $1; then - sed -ne '/^#if/,/#endif/p' $1 - elif grep -qE '^(typedef|struct|union) .*\{' $1; then - sed -ne '/{$/,/^}/p' $1 - elif grep -qE '^(typedef|struct|union) .*[^;]$' $1; then - grep -E '^(typedef|struct|union| )' $1 - else - grep -E '^(typedef|struct|union) ' $1 - fi - - printf '#endif\n\n' - ;; - - EXTERN) - echo "extern $(grep '^[a-zA-Z_].*;$' $1)" - ;; - - FUNCTION) - echo "$(grep '^[a-zA-Z_].*)' $1 | head -n1);" - ;; - - TGFN) - echo "$(grep 'TGFN.*)$' $1 | m4 -DTGFN='$1' -DTYPE='double');" - echo "$(grep 'TGFN.*)$' $1 | m4 -DTGFN='$1f' -DTYPE='float');" - echo "$(grep 'TGFN.*)$' $1 | m4 -DTGFN='$1l' -DTYPE='long double');" - ;; - - *) - # unknown type, so try guessing - get_declaration $1 - ;; - - esac -} - -stdc_base() { - (grep 'STDC(' $1 | m4 -DSTDC='$1') || echo 0 -} - -posix_base() { - (grep 'POSIX(' $1 | m4 -DPOSIX='$1') || echo 0 -} - -xopen_base() { - (grep 'XOPEN(' $1 | m4 -DXOPEN='$1') || echo 0 -} - -find_all() { - rm -rf "${DEPS}" - mkdir -p "${DEPS}" - find "${SRCDIR}" -name \*.c > "${DEPS}/all.c" - find "${SRCDIR}" -name \*.ref > "${DEPS}/all.ref" - find "${SRCDIR}" -name \*.s > "${DEPS}/all.s" - grep '#include <.*>' $(cat "${DEPS}/all.c" "${DEPS}/all.ref") | - sed 's/^.*<\(.*\.h\)>.*/\1/' | sort -u > "${DEPS}/all.h" -} - -version_sources() { - for file in $(cat "${DEPS}/all.c" "${DEPS}/all.ref"); do - printf '%s\n' "$file" - c_version=$(stdc_base "${file}") - p_version=$(posix_base "${file}") - x_version=$(xopen_base "${file}") - - if [ -n "${c_version}" ]; then - mkdir -p "${DEPS}/c.${c_version}" - echo "$file" >> "${DEPS}/c.${c_version}/sources" - fi - - if [ -n "${p_version}" ]; then - mkdir -p "${DEPS}/p.${p_version}" - echo "$file" >> "${DEPS}/p.${p_version}/sources" - fi - - if [ -n "${x_version}" ]; then - mkdir -p "${DEPS}/x.${x_version}" - echo "$file" >> "${DEPS}/x.${x_version}/sources" - fi - done -} - -make_headers_mk() { - if ! [ -f "${DEPS}/all.h" ]; then - find_all - fi - - rm -f "${TOPDIR}/.headers.mk" - printf '.POSIX:\n.DEFAULT: headers\n\n' > "${TOPDIR}/.headers.mk" - printf 'include .config.mk\n\n' >> "${TOPDIR}/.headers.mk" - - for header in $(cat "${DEPS}/all.h"); do - printf 'Building dependencies for <%s>\n' "$header" - printf '$(INCDIR)/%s: mkh.sh ' "$header" >> "${TOPDIR}/.headers.mk" - mkdir -p $(dirname "${TOPDIR}/.deps/h/${header}.deps") - grep -l "#include <${header}>" $(cat "${DEPS}/all.c" "${DEPS}/all.ref") > "${TOPDIR}/.deps/h/${header}.deps" - sed -e "s#${SRCDIR}#\$(SRCDIR)#" < "${TOPDIR}/.deps/h/${header}.deps" | tr '\n' ' ' >> "${TOPDIR}/.headers.mk" - printf '\n\tINCDIR=$(INCDIR) sh mkh.sh $(INCDIR)/%s\n\n' "${header}" >> "${TOPDIR}/.headers.mk" - done - - printf 'headers: ' >> "${TOPDIR}/.headers.mk" - for header in $(cat "${DEPS}/all.h"); do - printf ' \\\n\t$(INCDIR)/%s' "$header" >> "${TOPDIR}/.headers.mk" - done - - printf '\n' >> "${TOPDIR}/.headers.mk" -} - -make_deps_mk() { - if ! [ -f "${DEPS}/all.c" ]; then - find_all - fi - - rm -f "${TOPDIR}/.deps.mk" - rm -f "${DEPS}"/lib* - - printf '.POSIX:\n.SILENT:\ndefault: all\n\n' > "${TOPDIR}/.deps.mk" - printf 'include .config.mk\n\n' >> "${TOPDIR}/.deps.mk" - printf 'BASE_CFLAGS=-I$(INCDIR) -Isrc -fno-builtin -nostdinc\n' >> "${TOPDIR}/.deps.mk" - printf '\n' >> "${TOPDIR}/.deps.mk" - - printf '.POSIX:\nlibc_C_0_OBJS=' > "${DEPS}/libc.C_0" - # Assume all assembly is useful regardless of standard version - for file in $(sed -e 's/\.[^.]*\.s$/.ARCH.s/g' .deps/all.s | sort -u); do - BASE=$(basename $file .ARCH.s) - SRC=$(echo $file | sed -e 's/\.ARCH\./.$(ARCHITECTURE)-$(WORDSIZE)./') - printf 'libc.a($(OBJDIR)/%s.$(ARCHITECTURE)-$(WORDSIZE).o): $(OBJDIR)/%s.$(ARCHITECTURE)-$(WORDSIZE).o\n' $BASE $BASE >> "${TOPDIR}/.deps.mk" - printf ' \\\n\tlibc.a($(OBJDIR)/%s.$(ARCHITECTURE)-$(WORDSIZE).o)' $BASE >> "${DEPS}/libc.C_0" - printf '$(OBJDIR)/%s.$(ARCHITECTURE)-$(WORDSIZE).o: %s\n' $BASE $SRC >> "${TOPDIR}/.deps.mk" - printf '\t$(CC) $(BASE_CFLAGS) $(CFLAGS) -c %s -o $@\n' $SRC >> "${TOPDIR}/.deps.mk" - printf '\t echo [AS] $@\n\n' >> "${TOPDIR}/.deps.mk" - done - - for file in $(cat "${DEPS}/all.c"); do - printf 'Building dependencies from %s\n' "$file" - type=$(classify_source "${file}") - - if [ ${type} = EXTERN -o ${type} = TGFN -o ${type} = FUNCTION ]; then - LINK=$(grep -F 'LINK(' $file | m4 -DLINK='$1') - LIB=lib${LINK:-c} - OBJ=$(basename $file .c).o - - printf '%s.a(%s): $(OBJDIR)/%s\n' $LIB $OBJ $OBJ >> "${TOPDIR}/.deps.mk" - printf '$(OBJDIR)/%s: %s' "$OBJ" "$file" >> "${TOPDIR}/.deps.mk" - #for header in $(grep '#include' "${file}"); do - #printf ' \\\n\t$(INCDIR)/%s' "$header" >> "${TOPDIR}/.deps.mk" - #done - printf '\n\t$(CC) $(BASE_CFLAGS) $(CFLAGS) -c %s -o $@\n' "$file" >> "${TOPDIR}/.deps.mk" - printf '\techo [CC] $@\n' >> "${TOPDIR}/.deps.mk" - - cver=$(stdc_base $file) - pver=$(posix_base $file) - xver=$(xopen_base $file) - - if [ -n "$cver" ]; then - if ! [ -f "${DEPS}/${LIB}.C_${cver}" ]; then - printf '.POSIX:\n%s_C_%s_OBJS=' "${LIB}" "${cver}" > "${DEPS}/${LIB}.C_${cver}" - fi - printf ' \\\n\t%s.a($(OBJDIR)/%s)' $LIB $OBJ >> "${DEPS}/${LIB}.C_${cver}" - fi - - if [ -n "$pver" ]; then - if ! [ -f "${DEPS}/${LIB}.POSIX_${pver}" ]; then - printf '.POSIX:\n%s_POSIX_%s_OBJS=' "${LIB}" "${pver}" > "${DEPS}/${LIB}.POSIX_${pver}" - fi - printf ' \\\n\t%s.a($(OBJDIR)/%s)' $LIB $OBJ >> "${DEPS}/${LIB}.POSIX_${pver}" - fi - - if [ -n "$xver" ]; then - if ! [ -f "${DEPS}/${LIB}.XOPEN_${xver}" ]; then - printf '.POSIX:\n%s_XOPEN_%s_OBJS=' "${LIB}" "${xver}" > "${DEPS}/${LIB}.XOPEN_${xver}" - fi - printf ' \\\n\t%s.a($(OBJDIR)/%s)' $LIB $OBJ >> "${DEPS}/${LIB}.XOPEN_${xver}" - fi - - if [ -z "$cver" ] && [ -z "$pver" ] && [ -z "$xver" ]; then - if ! [ -f "${DEPS}/${LIB}.C_0" ]; then - printf '.POSIX:\n%s_C_0_OBJS=' "${LIB}" > "${DEPS}/${LIB}.C_0" - fi - printf ' \\\n\t%s.a($(OBJDIR)/%s)' $LIB $OBJ >> "${DEPS}/${LIB}.C_0" - fi - fi - done - - printf '\n' >> "${TOPDIR}/.deps.mk" - - for libdep in ${DEPS}/lib*; do - LIB=$(basename $libdep | sed -e 's/\..*$//') - VER=$(basename $libdep | sed -e 's/^.*\.//') - echo adding dependencies for $LIB v $VER - printf 'include $(TOPDIR)/.deps/%s\n' $(basename $libdep) >> "${TOPDIR}/.deps.mk" - done - - printf '\n' >> "${TOPDIR}/.deps.mk" -} diff --git a/mkh.sh b/mkh.sh deleted file mode 100755 index c4c4d6d4..00000000 --- a/mkh.sh +++ /dev/null @@ -1,173 +0,0 @@ -#!/bin/sh - -TOPDIR=$(dirname $0) -if [ -z "${INCDIR}" ]; then - INCDIR="${TOPDIR}/include" -fi -. "${TOPDIR}/mk.sh" - -export LC_ALL=POSIX -export LANG=POSIX -HEADER=$1 -HEADERNAME=$(echo $HEADER | sed -e "s#^${INCDIR}/*##") -GUARD=__$(echo $HEADERNAME | tr a-z/. A-Z__)__ -mkdir -p $(dirname $HEADER) -exec > $HEADER - -if [ $(basename $HEADER) != assert.h ]; then - printf '#ifndef %s\n#define %s\n\n' ${GUARD} ${GUARD} -fi - -printf "/*\nUNG's Not GNU\n\n%s\n*/\n\n" "$(cat LICENSE)" - -rm -rf $HEADER.* -for i in $(cat "${TOPDIR}/.deps/h/${HEADERNAME}.deps" | sort -u); do - # TODO: refs - type=$(classify_source $i) - source=$i - if [ $type = "REFERENCE" ] && ! grep -Fq 'REFERENCE(<' $source; then - source=src/$(grep REFERENCE $i | m4 -DREFERENCE='$1') - type=$(classify_source $source) - fi - version=v$(grep -F -e 'STDC(' -e 'POSIX(' -e 'XOPEN(' $i | sed -e 's/STDC/C/' | sort | tr , - | tr -d '() \n') - mkdir -p $HEADER.$type - echo $source >> $HEADER.$type/$version - - if ! [ -f $(dirname $0)/.deps/ftm/$version ]; then - mkdir -p $(dirname $0)/.deps/ftm - version_guard $source > $(dirname $0)/.deps/ftm/$version - fi - - printf '%s <%s> (%s)\n' "$i" "$HEADER" "$version" >&2 -done - -### -### TODO: prevent _XOPEN_SOURCE expanding to empty string -### -if grep -Fq -e '_XOPEN_SOURCE <' -e '< _XOPEN_SOURCE' $(cat $(HEADER.*/*); then -cat <<-EOF - #if defined _XOPEN_SOURCE && _XOPEN_SOURCE - 1 < 0 - # undef _XOPEN_SOURCE - # define _XOPEN_SOURCE 400 - #endif -EOF -fi - -if grep -Fq 'POSIX(' $(cat $HEADER.*/*); then -cat <<-EOF - #if defined _XOPEN_SOURCE && !defined _POSIX_C_SOURCE - # if (_XOPEN_SOURCE >= 700) - # define _POSIX_C_SOURCE 200809L - # elif (_XOPEN_SOURCE >= 600) - # define _POSIX_C_SOURCE 200112L - # elif (_XOPEN_SOURCE >= 500) - # define _POSIX_C_SOURCE 199506L - # else - # define _POSIX_C_SOURCE 2 - # endif - #endif - - #if defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE - # define _POSIX_SOURCE - #endif - -EOF -fi - -if grep -Fq -e 'POSIX(' -e 'XOPEN(' $(cat $HEADER.*/*); then -cat <<-EOF - #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 19901L - # if (defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 200112L) - # error POSIX.1-2001 and later require a C99 compiler - # elif(defined _XOPEN_SOURCE && _XOPEN_SOURCE >= 600) - # error XOPEN Issue 6 and later require a C99 compiler - # endif - #endif -EOF -fi - -for type in REFERENCE MACRO TYPE TYPE_LONG RECORD FNTYPE EXTERN; do - if [ -d $HEADER.$type ]; then - for v in $HEADER.$type/*; do - version=$(cat $(dirname $0)/.deps/ftm/$(basename $v | sed -e 's/^.*\.//')) - if [ -n "$version" ]; then - printf '%s\n' "$version" - fi - - for i in $(sort -u $v); do - printf '/* %s */\n' $i - get_declaration $i - done - - if [ -n "$version" ]; then - printf '#endif\n' - fi - - printf '\n' - done - rm -rf $HEADER.$type - fi -done - -if [ -d $HEADER.TGFN ]; then - for v in $HEADER.TGFN/*; do - version=$(cat $(dirname $0)/.deps/ftm/$(basename $v | sed -e 's/^.*\.//')) - if [ -n "$version" ]; then - printf '%s\n' "$version" - fi - - for i in $(sort -u $v); do - printf '/* %s */\n' $i - get_declaration $i TGFN - done - - if [ -n "$version" ]; then - printf '#endif\n' - fi - - printf '\n' - done - rm -rf $HEADER.TGFN -fi - -if [ -d $HEADER.FUNCTION ]; then - if grep -q restrict $(cat $HEADER.FUNCTION/*); then - if grep -Fq -e 'STDC(1)' -e 'STDC(1,' -e 'STDC(199409' $(grep -l restrict $(cat $HEADER.FUNCTION/*)) || ! grep -Fq 'STDC(' $(grep -l restrict $(cat $HEADER.FUNCTION/*)); then - printf '#if (!defined __STDC_VERSION__) || (__STDC_VERSION__ < 199901L)\n' - printf '#define restrict\n' - printf '#endif\n\n' - fi - fi - - ### TODO: only if header works with C<11 - if grep -q _Noreturn $(cat $HEADER.FUNCTION/*); then - printf '#if (!defined __STDC_VERSION__) || (__STDC_VERSION__ < 200112L)\n' - printf '#define _Noreturn\n' - printf '#endif\n\n' - fi - - for v in $HEADER.FUNCTION/*; do - version=$(cat $(dirname $0)/.deps/ftm/$(basename $v | sed -e 's/^.*\.//')) - if [ -n "$version" ]; then - printf '%s\n' "$version" - fi - - for i in $(sort -u $v); do - printf '/* %s */\n' $i - get_declaration $i FUNCTION | sed -e 's/\([a-zA-Z_][a-zA-Z_0-9]*\)\([,)]\)/__\1\2/g;s/(__\([a-zA-Z_][a-zA-Z_0-9]*\))/(\1)/g' - done - - if [ -n "$version" ]; then - printf '#endif\n' - fi - - printf '\n' - done - rm -rf $HEADER.FUNCTION -fi - -rm -rf $HEADER.REFERENCE - -if [ $(basename $HEADER) != assert.h ]; then - printf '\n#endif\n' -fi -- cgit v1.2.1