#!/bin/bash set -e # # Dumps the source given in argument, # interperced with the error messages # provided on the stdin. # # Usage: gcc $src 2>&1 | listing $src # declare -r caretRegexp='^ *\^' declare -r errorFormat='%6d %s\n' declare -r listiFormat='%6d | %s\n' declare -r caretFormat='%6d |%s\n' function quote(){ local text="$1" echo "$text" } # shellcheck disable=SC2034 messages_text=() # shellcheck disable=SC2034 messages_lino=() function saveMessage(){ local lino="$1" local text="$2" message_lino+=("${lino}") message_text+=("${text}") } function flushMessages(){ local curLino="$1" while [[ ${#message_lino[@]} -gt 0 && "${message_lino[0]}" -lt "${curLino}" ]] ; do printf '%s\n' "${message_text[0]}" message_lino=( "${message_lino[@]:1}" ) message_text=( "${message_text[@]:1}" ) done } lino=1 source=() function advanceToLine(){ local curLino="$1" while [[ "${lino}" -le "${curLino}" ]] ; do flushMessages "${lino}" # shellcheck disable=SC2059 printf "${listiFormat}" "${lino}" "${source[lino]}" lino=$((lino+1)) done } function listing(){ local sourceFile="${1?Missing source file path as first argument.}" local messaRegexp="^$(quote "${sourceFile}"):([0-9][0-9]*):([0-9][0-9]*): (.*)$" lino=1 source=() mapfile -O 1 -t source < "${sourceFile}" IFS='' while read line ; do if [[ "${line}" =~ $messaRegexp ]] ; then curLino="${BASH_REMATCH[1]}" curMess="${BASH_REMATCH[3]}" advanceToLine "${curLino}" # shellcheck disable=SC2059 saveMessage "${curLino}" "$(printf "${errorFormat}" "${curLino}" "${curMess}")" elif [[ "${line}" =~ $caretRegexp ]] ; then # shellcheck disable=SC2059 printf "${caretFormat}" "${curLino}" "${line}" else # ignore the line : fi done advanceToLine ${#source[@]} } function main(){ listing "$@" exit 0 } main "$@"