From ea7c6747846502bcee1dad2b06a5f3438401d861 Mon Sep 17 00:00:00 2001 From: iTNTPiston Date: Sat, 6 Feb 2021 19:16:13 -0500 Subject: [PATCH] Add workflow script --- workflow.sh | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100755 workflow.sh diff --git a/workflow.sh b/workflow.sh new file mode 100755 index 00000000..4f89dae9 --- /dev/null +++ b/workflow.sh @@ -0,0 +1,244 @@ +#!/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 _ZN4ksys3evt10OrderParam13addParamActorEPNS_3act8BaseProcERN4sead14SafeStringBaseIcEE +# 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 for the mangled name of a function and update uking_functions.csv" + echo " [-f] Search only, do not update function list" + echo "d|diff 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 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