Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save manodeep/c1a4b3d03adc4a48bb56ee195398c576 to your computer and use it in GitHub Desktop.
Save manodeep/c1a4b3d03adc4a48bb56ee195398c576 to your computer and use it in GitHub Desktop.
Code to replace (known + feasible) !CDIR compiler directives to the equivalent !DIR$ directives
#!/bin/bash
## Taken from https://stackoverflow.com/a/28044986
# 1. Create ProgressBar function
# 1.1 Input is currentState($1) and totalState($2)
function ProgressBar {
# Check if output is going to a tty
if [ -t 1 ]; then
# Output progress bar only if output is to tty
let _progress=(${1}*100/${2}*100)/100
_postfix="$3"
let _done=(${_progress}*4)/10
let _left=40-$_done
_fill=$(printf "%${_done}s")
_empty=$(printf "%${_left}s")
printf "\rProgress : [${_fill// /#}${_empty// /-}] ${_progress}%% $_postfix"
fi
}
process_files() {
local subs_file="$1"
shift # This removes the first argument, which is the substitutions file and lets us process the rest as files.
declare -A subs
if [[ -n "$subs_file" && -f "$subs_file" ]]; then
while IFS='=' read -r old new; do
echo "Processing substitution: $old -> $new"
old=$(echo "$old" | tr '[:lower:]' '[:upper:]')
subs["$old"]="$new"
done < "$subs_file"
fi
if [[ "${#subs[@]}" -lt 1 ]]; then
echo "Error: (in process_file) No substitutions found in the 'subs' array. Exiting."
exit 1
fi
local tmpfile
tmpfile=$(mktemp)
numfiles=$#
currfile=0
# This is for pretty-printing the progress bar => otherwise the (longer) filenames
# from previous iterations remain on the terminal and makes the filename look like gibberish.
max_filename_length=0
for file in "$@"; do
filename_length=${#file}
if (( filename_length > max_filename_length )); then
max_filename_length=$filename_length
fi
done
echo -e "\nProcessing $numfiles files ...\n"
for file in "$@"; do
postfix=$(printf "Processing (%d out of %d files): %-${max_filename_length}s " "$currfile" "$numfiles" "$file")
ProgressBar ${currfile} ${numfiles} "$postfix"
currfile=$((currfile + 1))
prev_line=""
while IFS= read -r line || [[ -n "$line" ]]; do
skip_patterns=("!CDIR[[:space:]]+VREG" "!CDIR[[:space:]]+GM_ARRAY" "!CDIR[[:space:]]+COLLAPSE" )
for skip_pattern in "${skip_patterns[@]}"; do
if [[ "$line" =~ "$skip_pattern" ]]; then
echo "Skipping line with '$skip_pattern' directive: '$line'"
continue 2
fi
done
echo "$line" >> "$tmpfile"
if [[ "$line" =~ ^([[:space:]]*!CDIR)[[:space:]]+(.+) ]]; then
# echo "Processing !CDIR directive in file: $file"
# echo "Line: '$line'"
# for i in "${!BASH_REMATCH[@]}"; do
# echo "$i: ${BASH_REMATCH[$i]}"
# done
# Extract the prefix and directive
prefix=$(echo "$line" | awk '{print $1}')
directive=$(echo "$line" | awk '{print $2}')
# Check if directive contains "=*" and remove that from directive, but save to a variable
# if it does. This will handle cases like UNROLL=<value>. We need to match the directive
# as UNROLL, but we want to append the value for later.
if [[ "$directive" == *'='* ]]; then
# echo "Directive contains '=', saving it."
directive_value=$(echo "$directive" | sed 's/.*\(=.*\)/\1/')
# echo "Directive value: '$directive_value'"
directive=$(echo "$directive" | sed 's/=.*//')
else
directive_value=""
fi
# echo "Prefix: '$prefix', directive: '$directive', directive_value: '$directive_value'"
directive_up=$(echo "$directive" | tr '[:lower:]' '[:upper:]')
# echo "Directive (upper case): '$directive_up'"
# Substitute if in list
if [[ -n "${subs[$directive_up]}" ]]; then
# echo "Substituting directive: '$directive' -> '${subs[$directive_up]}'"
new_directive="${subs[$directive_up]}"
else
# echo "No substitution found for directive: '$directive'"
continue
fi
# Peek at next line to make sure the file has not been
# previously processed. There are also cases where the previous
# line contains the relevant !DIR$ directive, so we need to check that too.
IFS='' read -r next_line || next_line=""
new_dir_line="!DIR$ $new_directive$directive_value"
if [[ "$next_line" != "$new_dir_line" ]] || [[ "$prev_line" != "$new_dir_line" ]]; then
# echo "Adding new !DIR directive: '$new_dir_line' to file: $file"
echo "$new_dir_line" >> "$tmpfile"
# echo "$next_line" >> "$tmpfile"
# echo "next line was : '$next_line'"
else
echo "skipping duplicate !DIR directive before/after !CDIR in file: $file"
# echo "Next line: '$next_line'"
# echo "New line: '$new_dir_line'"
fi
# Output the next line if it exists
if [[ -n "$next_line" ]]; then
echo "$next_line" >> "$tmpfile"
fi
fi
prev_line="$line"
done < "$file"
mv "$tmpfile" "$file"
done
echo -e "\nProcessing $numfiles files ...done\n"
}
DIR="$1"
SUBS_FILE="$2"
mapfile -t files_with_cdir < <(grep -rl "^[[:space:]]*\!CDIR" "$DIR" --include="*.f90" --include="*.F90" --include="*.f" --include="*.F")
if [[ "${#files_with_cdir[@]}" -eq 0 ]]; then
echo "No files with !CDIR directive found. Returning ..."
exit 0
fi
echo "Found ${#files_with_cdir[@]} files with !CDIR directive."
echo "Files with !CDIR directive:"
for file in "${files_with_cdir[@]}"; do
echo "$file"
done
# Usage: /path/to/replace-cdir-directives-with-dir-directives.sh /path/to/dir/with/fortran/source substitutions.txt
# substitutions.txt format: OLD_PHRASE=NEW_PHRASE (one per line, phrases in all caps)
process_files "$SUBS_FILE" "${files_with_cdir[@]}"
NODEP=IVDEP
UNROLL=UNROLL
NOVECTOR=NOVECTOR
NOUNROLL=NOUNROLL
EXPAND=UNROLL
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment