botw/workflow.sh

245 lines
7.2 KiB
Bash
Executable File

#!/usr/bin/bash
# Example usage:
# Search for a function and update uking_functions.csv to include its mangled name
# ./workflow.sh mangle orderparam::doassign
# Diff a function (in this example, OrderParam::doAssign, -v is equivalent to --source in diff.py)
# ./workflow.sh diff -v _ZN4ksys3evt10OrderParam13addParamActorEPNS_3act8BaseProcERN4sead14SafeStringBaseIcEE
# Search for mangle name and diff (-f turns off interaction)
# ./workflow.sh mad -v -f orderparam::doassign
# Get ready to pr
# ./workflow.sh check
#I use this to copy files from and to WSL. Valid options: ON, OFF, AUTO
#ON: Enabled. Will give warning if WORKING_FILES or FILE_SYNC_PY does not exist
#OFF: Disabled. file sync is completely ignored in workflow
#AUTO: Enable file sync if WORKING_FILES and FILE_SYNC_PY exist
FILE_SYNC=AUTO
FILE_SYNC_PY=../file-sync.py
#A list of source code being worked on. If exists, clang-format will only format these files which is faster
WORKING_FILES=../file-list.txt
#Path to uking_functions.csv
UKING_FUNCTIONS=data/uking_functions.csv
#Path to temporarily put the output of tools/print_decomp_symbols.py
SYMBOL_OUT=build/symbols.txt
#Path to diff.py
DIFF_PY=./diff.py
#Path to print_decomp_symbols.py
PRINT_DECOMP_SYMBOLS_PY=tools/print_decomp_symbols.py
#Path to check.py
CHECK_PY=tools/check.py
#clang-format
CLANG_FORMAT=clang-format
STDOUT_COLOR='\033[1;36m'
STDIN_COLOR='\033[1;33m'
STDERR_COLOR='\033[1;31m'
WORKFLOW_TAG='[Workflow]'
OPTION_PATTERN=-[a-zA-Z]
# Flag to turn off interaction in mangle and mad
# In mangle, the functions will only be printed. uking_functions.csv will not update
# In mad, automatically proceed to diff without confirming mangled name
FLAG_MANGLE_NO_INTERACTION='-f'
# Equivalent to --source in diff.py
FLAG_DIFF_SOURCE='-v'
# Only used in file sync
FLAG_WRITE_BACK='-w'
#Helpers
print_info(){
echo -e "$STDOUT_COLOR$WORKFLOW_TAG \033[0m$@"
}
print_error(){
echo -e "$STDOUT_COLOR$WORKFLOW_TAG$STDERR_COLOR Error: \033[0m$@"
}
print_prompt(){
echo -e "$STDIN_COLOR$WORKFLOW_TAG $@\033[0m"
}
if [[ ${FILE_SYNC} == "ON" ]]
then
if ! test -f $WORKING_FILES || ! test -f $FILE_SYNC_PY
then
print_error "File sync is on, but working file list or sync script is not found. File sync will be skipped."
FILE_SYNC=OFF
fi
elif [[ ${FILE_SYNC} == "AUTO" ]]
then
if ! test -f $WORKING_FILES || ! test -f $FILE_SYNC_PY
then
FILE_SYNC=OFF
else
FILE_SYNC=ON
fi
fi
args=$@
func=$1
arg=
for possible_arg in ${@:2}
do
if ! [[ $possible_arg =~ ${OPTION_PATTERN} ]]
then
arg=$possible_arg
break
fi
done
has_option(){
option=$1
[[ " ${args[@]} " =~ " ${option} " ]]
}
do_sync(){
if [[ ${FILE_SYNC} == "ON" ]]
then
print_info "Syncing"
$FILE_SYNC_PY -l $WORKING_FILES $1
fi
}
do_build(){
print_info "Building"
ninja -C build
}
do_diff(){
print_info "Diffing $1"
if has_option $FLAG_DIFF_SOURCE
then
$DIFF_PY --source $1
else
$DIFF_PY $1
fi
}
do_format(){
print_info "Formatting source code"
if test -f $WORKING_FILES
then
cat $WORKING_FILES | xargs $CLANG_FORMAT -i --verbose
else
find src -name *.h | xargs $CLANG_FORMAT -i
find src -name *.cpp | xargs $CLANG_FORMAT -i
fi
}
check_status(){
if [[ $1 -ne 0 ]]; then print_error "Workflow error. Check output above."; exit $1; fi
}
case $func in
sync|s )
do_sync;;
build|b )
do_sync && do_build;;
mangle|m )
while [[ -z ${arg} ]]
do
print_error "Function name is empty!"
read -p "$(print_prompt "Enter function string to search: ")" arg
done
do_sync && do_build
rc=$? && check_status $rc
print_info "Finding $arg"
$PRINT_DECOMP_SYMBOLS_PY -a > $SYMBOL_OUT
grep -i $arg $SYMBOL_OUT --color=always
if ! has_option ${FLAG_MANGLE_NO_INTERACTION}
then
mangled_name=$(grep -i $arg $SYMBOL_OUT | grep -o '_.*$' | head -n 1 | sed 's/).*$//g')
print_prompt "Enter mangled function name:"
mangled_name_in=
read -p "($mangled_name) " mangled_name_in
if [[ -n $mangled_name_in ]]
then
mangled_name=$mangled_name_in
fi
grep -ni $arg $UKING_FUNCTIONS --color=always
line=$(grep -ni $arg $UKING_FUNCTIONS | grep -o '^[0-9]*' | head -n 1)
read -p "$(print_prompt "Enter function line number ($line): ")" line_in
if [[ -n $line_in ]]
then
line=$line_in
fi
while [[ -z ${line} ]]
do
print_error "Line number cannot be empty"
read -p "$(print_prompt "Enter function line number: ")" line
done
print_info "Ready to edit $UKING_FUNCTIONS"
echo "Changing"
current=$(sed $line"q;d" $UKING_FUNCTIONS)
echo " $current"
echo "To"
after=$(echo $current | perl -pe 's/,(.(?!,))*$/,'$mangled_name'/g')
echo " $after"
read -p "$(print_prompt "Press enter to continue, n to exit ")" yn
case $yn in
[Nn]* ) exit;;
*) ;;
esac
sed -i $line"s/.*/$after/g" $UKING_FUNCTIONS && print_info "OK"
fi;;
diff|d )
while [[ -z ${arg} ]]
do
print_error "Mangled name is empty!"
read -p "$(print_prompt "Enter mangled name to diff: ")" arg
done
do_diff $arg;;
mad )
while [[ -z ${arg} ]]
do
print_error "Function name is empty!"
read -p "$(print_prompt "Enter function string to mangle and diff: ")" arg
done
do_sync && do_build
rc=$? && check_status $rc
print_info "Finding $arg"
$PRINT_DECOMP_SYMBOLS_PY -a > $SYMBOL_OUT
grep -i $arg $SYMBOL_OUT --color=always
mangled_name=$(grep -i $arg $SYMBOL_OUT | grep -o '_.*$' | head -n 1 | sed 's/).*$//g')
if ! has_option ${FLAG_MANGLE_NO_INTERACTION}
then
print_prompt "Enter mangled function name:"
mangled_name_in=
read -p "($mangled_name) " mangled_name_in
if [[ -n $mangled_name_in ]]
then
mangled_name=$mangled_name_in
fi
fi
do_diff $mangled_name;;
check|c )
do_sync && do_format
if has_option $FLAG_WRITE_BACK
then
do_sync -r
fi
do_build && print_info "Checking match..." && $CHECK_PY;
rc=$? && check_status $rc
print_info "OK";;
*)
print_error "Unknown command $func"
if [[ ${FILE_SYNC} == "ON" ]]
then
echo "s|sync Sync the directory"
fi
echo "b|build Build"
echo "m|mangle <search> Search for the mangled name of a function and update uking_functions.csv"
echo " [-f] Search only, do not update function list"
echo "d|diff <function> Diff function"
echo " [-v] verbose, show source when diffing"
echo "c|check Format source code and run tools/check.py"
if [[ ${FILE_SYNC} == "ON" ]]
then
echo " [-w] sync formatted code"
fi
echo " |mad <search> Mangle and diff. Search for the mangled name of a function and diff it"
echo " [-v] verbose, show source when diffing"
echo " [-f] force, do not confirm function name before diffing";;
esac