#!/bin/bash
|
|
|
|
KEEP_FILES=0
|
|
ECHO_COMMANDS=0
|
|
RUN_SCRIPT=0
|
|
DIRECTORY=.
|
|
OUTPUT_DIRECTORY=
|
|
KEEP_GITFILES=0
|
|
DEBUG=0
|
|
|
|
if [[ $# = 0 ]]; then
|
|
set -- '-h'
|
|
fi
|
|
|
|
while (( $# )); do
|
|
case "$1" in
|
|
-d|--directory)
|
|
shift
|
|
DIRECTORY=$1 # source directory
|
|
shift
|
|
;;
|
|
-o|--output)
|
|
shift
|
|
OUTPUT_DIRECTORY=$1
|
|
shift
|
|
;;
|
|
--debug)
|
|
shift
|
|
DEBUG=1
|
|
;;
|
|
-r|--run)
|
|
shift
|
|
RUN_SCRIPT=1
|
|
;;
|
|
-e|--echo)
|
|
shift
|
|
ECHO_COMMANDS=1
|
|
;;
|
|
-k|--keep)
|
|
shift
|
|
KEEP_FILES=1
|
|
;;
|
|
-g|--git)
|
|
shift
|
|
KEEP_GITFILES=1
|
|
;;
|
|
-h|--help)
|
|
shift
|
|
fmt=" %-31s%s\n"
|
|
|
|
printf "%s" "Usage: $(basename ${BASH_SOURCE[0]}) [OPTION?]"
|
|
printf "\n"
|
|
printf "\nThis is a custom pre-processor designed to remove unused flexipatch patches and create a final build."
|
|
printf "\n\n"
|
|
printf "$fmt" "-r, --run" "include this flag to confirm that you really do want to run this script"
|
|
printf "\n"
|
|
printf "$fmt" "-d, --directory <dir>" "the flexipatch source directory to process (defaults to current directory)"
|
|
printf "$fmt" "-o, --output <dir>" "the output directory to store the processed files"
|
|
printf "$fmt" "-h, --help" "display this help section"
|
|
printf "$fmt" "-k, --keep" "keep temporary files and do not replace the original ones"
|
|
printf "$fmt" "-g, --git" "keep .git files"
|
|
printf "$fmt" "-e, --echo" "echo commands that will be run rather than running them"
|
|
printf "$fmt" " --debug" "prints additional debug information to stderr"
|
|
printf "\nWarning! This script alters and removes files within the source directory."
|
|
printf "\nWarning! This process is irreversible! Use with care. Do make a backup before running this."
|
|
printf "\n\n"
|
|
exit
|
|
;;
|
|
*)
|
|
echo "Ignoring unknown argument ($1)"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ $RUN_SCRIPT = 0 ]]; then
|
|
echo "Re-run this command with the --run option to confirm that you really want to run this script."
|
|
echo "The changes this script makes are irreversible."
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z ${OUTPUT_DIRECTORY} ]]; then
|
|
echo "Output directory not specified, see -o"
|
|
exit 1
|
|
fi
|
|
|
|
DIRECTORY=$(readlink -f "${DIRECTORY}")
|
|
OUTPUT_DIRECTORY=$(readlink -f "${OUTPUT_DIRECTORY}")
|
|
if [[ $DIRECTORY != $OUTPUT_DIRECTORY ]]; then
|
|
mkdir -p "${OUTPUT_DIRECTORY}"
|
|
cp -r -f "${DIRECTORY}/." -t "${OUTPUT_DIRECTORY}"
|
|
DIRECTORY=${OUTPUT_DIRECTORY}
|
|
fi
|
|
|
|
if [[ ! -e ${DIRECTORY}/patches.h ]]; then
|
|
printf "No patches.h file found. Make sure you run this script within a flexipatch source directory."
|
|
exit 1
|
|
fi
|
|
|
|
|
|
FILES_TO_DELETE=$(find $DIRECTORY -name "*.c" -o -name "*.h" | awk -v DEBUG="$DEBUG" -v DIRECTORY="$DIRECTORY" '
|
|
function istrue(f) {
|
|
ret = 0
|
|
for ( i = 2; i in f; i++ ) {
|
|
if ( f[i] == "||" ) {
|
|
if ( ret == -1 ) {
|
|
ret = 0
|
|
} else if ( ret == 1 ) {
|
|
break
|
|
}
|
|
continue
|
|
} else if ( f[i] == "&&" ) {
|
|
if ( ret == 0 ) {
|
|
ret = -1
|
|
}
|
|
continue
|
|
} else if ( ret == -1 ) {
|
|
continue
|
|
} else if ( f[i] !~ /_(PATCH|LAYOUT)$/ ) {
|
|
ret = 1
|
|
} else if ( f[i] ~ /^!/ ) {
|
|
ret = !patches[substr(f[i],2)]
|
|
} else {
|
|
ret = patches[f[i]]
|
|
}
|
|
}
|
|
|
|
if ( ret == -1 ) {
|
|
ret = 0
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
function schedule_delete(file) {
|
|
# Skip duplicates
|
|
for ( i = 1; i in files_to_delete; i++ ) {
|
|
if ( files_to_delete[i] == file) {
|
|
return
|
|
}
|
|
}
|
|
if (DEBUG) {
|
|
print "Scheduling file " file " for deletion." > "/dev/stderr"
|
|
}
|
|
files_to_delete[i] = file
|
|
}
|
|
|
|
function is_flexipatch(patch) {
|
|
return patch ~ /_(PATCH|LAYOUT)$/
|
|
}
|
|
|
|
BEGIN {
|
|
# Read patches.h and store patch settings in the patches associative array
|
|
if (DEBUG) {
|
|
print "Reading file " DIRECTORY "/patches.h" > "/dev/stderr"
|
|
}
|
|
while (( getline line < (DIRECTORY"/patches.h") ) > 0 ) {
|
|
split(line,f)
|
|
if ( f[1] ~ /^#define$/ ) {
|
|
if ( f[3] == 0 || f[3] == 1 ) {
|
|
patches[f[2]] = f[3]
|
|
} else {
|
|
patches[f[2]] = istrue(f)
|
|
}
|
|
if (DEBUG) {
|
|
print "Found " f[2] " = " patches[f[2]] > "/dev/stderr"
|
|
}
|
|
}
|
|
}
|
|
files_to_delete[0] = ""
|
|
}
|
|
|
|
{
|
|
level = 0
|
|
do_print[level] = 1
|
|
has_printed[level] = 0
|
|
condition[level] = ""
|
|
|
|
while (( getline line < $0) > 0 ) {
|
|
split(line,f)
|
|
if ( f[1] ~ /^#if$/ ) {
|
|
level++;
|
|
do_print[level] = do_print[level-1]
|
|
has_printed[level] = 0
|
|
condition[level] = f[2]
|
|
if ( do_print[level] ) {
|
|
if ( istrue(f) ) {
|
|
has_printed[level] = 1
|
|
do_print[level] = 1
|
|
} else {
|
|
do_print[level] = 0
|
|
}
|
|
}
|
|
if ( is_flexipatch(condition[level]) ) {
|
|
continue
|
|
}
|
|
} else if ( f[1] ~ /^#ifdef$/ || f[1] ~ /^#ifndef$/ ) {
|
|
level++;
|
|
do_print[level] = do_print[level-1]
|
|
has_printed[level] = 0
|
|
condition[level] = f[2]
|
|
if ( do_print[level] ) {
|
|
has_printed[level] = 1
|
|
do_print[level] = 1
|
|
}
|
|
if ( is_flexipatch(condition[level]) ) {
|
|
continue
|
|
}
|
|
} else if ( f[1] ~ /^#elif$/ ) {
|
|
if ( (!is_flexipatch(condition[level]) || has_printed[level] == 0) && do_print[level-1] == 1 ) {
|
|
if ( istrue(f) ) {
|
|
has_printed[level] = 1
|
|
do_print[level] = 1
|
|
} else {
|
|
do_print[level] = 0
|
|
}
|
|
} else {
|
|
do_print[level] = 0
|
|
}
|
|
if ( is_flexipatch(f[2]) ) {
|
|
continue
|
|
}
|
|
} else if ( f[1] ~ /^#else$/ ) {
|
|
if ( (!is_flexipatch(condition[level]) || has_printed[level] == 0) && do_print[level-1] == 1 ) {
|
|
has_printed[level] = 1
|
|
do_print[level] = 1
|
|
} else {
|
|
do_print[level] = 0
|
|
}
|
|
if ( is_flexipatch(condition[level]) ) {
|
|
continue
|
|
}
|
|
} else if ( f[1] ~ /^#include$/ && f[2] ~ /^"/ && (do_print[level] == 0 || f[2] == "\"patches.h\"") ) {
|
|
dir = ""
|
|
if ( $0 ~ /\// ) {
|
|
dir = $0
|
|
sub("/[^/]+$", "/", dir)
|
|
}
|
|
schedule_delete(dir substr(f[2], 2, length(f[2]) - 2))
|
|
continue
|
|
} else if ( f[1] ~ /^#endif$/ ) {
|
|
if ( is_flexipatch(condition[level]) ) {
|
|
level--
|
|
continue
|
|
}
|
|
level--
|
|
}
|
|
|
|
if ( do_print[level] ) {
|
|
print line > $0 ".~"
|
|
}
|
|
}
|
|
}
|
|
|
|
END {
|
|
for ( i = 1; i in files_to_delete; i++ ) {
|
|
print files_to_delete[i]
|
|
}
|
|
}
|
|
')
|
|
|
|
# Chmod and replace files
|
|
for FILE in $(find $DIRECTORY -name "*.~"); do
|
|
chmod --reference=${FILE%%.~} ${FILE}
|
|
if [[ $KEEP_FILES = 0 ]] || [[ $ECHO_COMMANDS = 1 ]]; then
|
|
if [[ $ECHO_COMMANDS = 1 ]]; then
|
|
echo "mv ${FILE} ${FILE%%.~}"
|
|
else
|
|
mv ${FILE} ${FILE%%.~}
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Delete unnecessary files
|
|
if [[ $KEEP_FILES = 0 ]] || [[ $ECHO_COMMANDS = 1 ]]; then
|
|
|
|
# Remove dwmc shell script if patch not enabled
|
|
if [[ -f ${DIRECTORY}/patch/dwmc ]] && [[ $(grep -cE '^#define DWMC_PATCH +0 *$' ${DIRECTORY}/patches.h) > 0 ]]; then
|
|
if [[ $ECHO_COMMANDS = 1 ]]; then
|
|
echo "rm ${DIRECTORY}/patch/dwmc"
|
|
echo "sed -r -i -e '/cp -f patch\/dwmc/d' \"${DIRECTORY}/Makefile\""
|
|
else
|
|
rm "${DIRECTORY}/patch/dwmc"
|
|
sed -r -i -e '/cp -f patch\/dwmc/d' "${DIRECTORY}/Makefile"
|
|
fi
|
|
fi
|
|
|
|
# Remove layoutmenu.sh shell script if patch not enabled
|
|
if [[ -f ${DIRECTORY}/patch/layoutmenu.sh ]] && [[ $(grep -cE '^#define BAR_LAYOUTMENU_PATCH +0 *$' ${DIRECTORY}/patches.h) > 0 ]]; then
|
|
if [[ $ECHO_COMMANDS = 1 ]]; then
|
|
echo "rm ${DIRECTORY}/patch/layoutmenu.sh"
|
|
else
|
|
rm "${DIRECTORY}/patch/layoutmenu.sh"
|
|
fi
|
|
fi
|
|
|
|
for FILE in $FILES_TO_DELETE ${DIRECTORY}/patches.def.h; do
|
|
if [[ $ECHO_COMMANDS = 1 ]]; then
|
|
echo "rm $FILE"
|
|
else
|
|
rm "$FILE"
|
|
fi
|
|
done
|
|
|
|
if [[ -f $DIRECTORY/README.md ]]; then
|
|
if [[ $ECHO_COMMANDS = 1 ]]; then
|
|
echo "rm $DIRECTORY/README.md"
|
|
else
|
|
rm $DIRECTORY/README.md
|
|
fi
|
|
fi
|
|
|
|
if [[ $KEEP_GITFILES = 0 ]]; then
|
|
rm -rf $DIRECTORY/.git*
|
|
fi
|
|
|
|
# Remove empty include files
|
|
INCLUDE_RE='*patch/*include.[hc]'
|
|
if [[ $ECHO_COMMANDS = 1 ]]; then
|
|
INCLUDE_RE='*patch/*include.[hc][.]~'
|
|
fi
|
|
for FILE in $(find $DIRECTORY -path "$INCLUDE_RE"); do
|
|
if [[ $(grep -c "#include " $FILE) = 0 ]]; then
|
|
if [[ $ECHO_COMMANDS = 1 ]]; then
|
|
echo "rm ${FILE%%.~}"
|
|
else
|
|
rm "$FILE"
|
|
fi
|
|
|
|
for LINE in $(grep -Ern "#include \"patch/$(basename ${FILE%%.~})\"" $DIRECTORY | grep -v '.~:' | awk -F":" '{print $1 ":" $2 }'); do
|
|
INCFILE=$(echo $LINE | cut -d":" -f1)
|
|
LINE_NO=$(echo $LINE | cut -d":" -f2)
|
|
if [[ $ECHO_COMMANDS = 1 ]]; then
|
|
echo "sed -i \"${LINE_NO}d\" ${INCFILE}"
|
|
else
|
|
sed -i "${LINE_NO}d" ${INCFILE}
|
|
fi
|
|
done
|
|
fi
|
|
|
|
done
|
|
fi
|
|
|
|
# Clean up the Makefile
|
|
sed -r -i -e 's/ patches.h$//' -e '/^patches.h:$/{N;N;d;}' "${DIRECTORY}/Makefile"
|