#!/bin/bash
#SPDX-License-Identifier: Apache-2.0
#Copyright 2018-2025 Gliim LLC.  
#Licensed under Apache License v2. See LICENSE file.
#On the web http://golf-lang.com/ - this file is part of Golf framework.

#Internal diagnostic conversion tool used by gg. Do not use by itself, as it may change.

#Colors that may be used now or in the future
BLACK="\033[30m"
CYAN="\033[36m"
YELLOW="\033[33m"
RED="\033[31m"
GREEN="\033[32m"
BLUE="\033[34m"
WHITE="\033[37m"
PINK="\033[35m"
BOLD="\033[0;1m"
NORMAL="\033[0;39m"

#golf application name. PLAIN is 1 if this is old-style (non-highlighted) diagnostics.
APP="$1"
PLAIN="$2"

#in parallel compiling each invocation of vdiag must own temp files, differentiated by pid, so all files used muse be PID'd or it will be a mess of overwriting between processes
MYPID=$$

if [ "$PLAIN" == "1" ]; then
#push standard input to stderr and exit with status
    cat - 1>&2 
    exit -1
fi

#clear temp files used further down
rm -f $GG_ROOT/var/lib/gg/bld/$APP/.vdiag1_$MYPID || true
rm -f $GG_ROOT/var/lib/gg/bld/$APP/.vdiag2_$MYPID || true
rm -f $GG_ROOT/var/lib/gg/bld/$APP/.GG_TMP_DIAG${MYPID}_* || true


#
#
# Used to highlight diagnostics
# Input: <line> <column> <file>
# <line> is a full expanded line (with *10000+ext)
# <file> is fq source .golf file without .golf extension
# Outputs golf stmt, C/"Generated C" code and a caret to column in generated code.
#
#
function displ() {
#expanded line number (golfline*10000 + genline)
    LN=$1
#get .golf source line
    ((VLN=LN/10000))
#column name, declare 1 if not recognizable
    COL=$2
    if [[ ! "$COL" =~ ^[0-9]+$ ]]; then 
        COL=1
    fi
#golf request or file name  without .golf
    F=$(basename $3)
#analyze generated C code and get the exact line where gcc said the error was, remove leading and trailing whitespaces
    CL=$(sed -n '/#line '$LN'/{ n; p }' $GG_ROOT/var/lib/gg/bld/$APP/__$F.o.c|sed 's/^[ \t]*//;s/[ \t]*$//')
#analyze .golf file name and get source golf line text, remove leading and trailing whitespaces
    VL=$(sed $VLN'q;d' ./$F.golf|sed 's/^[ \t]*//;s/[ \t]*$//')
#determine if the issue is a golf line or just a C line in .golf code. It's C code if the source code line is the same (i.e.
#it matches), because for Golf code it wouldn't.
    IS_GOLF=0
#if in Golf code, display it first, then down below display C code too
    if [ "$CL" != "$VL" ]; then
        echo -e -n "$RED>>> "; echo -n "Golf stmt: [$VL]"; echo -e "$NORMAL"
        IS_GOLF=1
    fi
#for C code, display it and put the caret up, first 
    if [ "$IS_GOLF" == "0" ]; then
        echo -e -n "$RED>>> "; echo -n "C code: $CL"; echo -e "$NORMAL"
#Add 12 for '>>> C code: '
        ((COL=COL-1+12))
        echo -n -e "$RED"
    else
        echo -e -n "$GREEN### "; echo -n "Generated C code: $CL"; echo -e "$NORMAL"
#Add 22 for '### Generated C code: '
        ((COL=COL-1+22))
        echo -n -e "$GREEN"
    fi
#display spaces and 3 carets to point to gen C code
    for ((i=1;i<=COL;i++)); do
        echo -n -e " "
    done
    echo -e "^^^$NORMAL"
}

#from stdin, look in gcc diag output for xxx.golf:yyy:zzz:wwww (source code name xxx with line yyy), but take out last 4 digits (from x10000 when creating #line numbers)
#zzz and www are details about error. Replace with _GG_COLOR, which will be the color in output, golf file name, skip the 4 digits that are artificially added to line
#numbers, put in zzz and wwww and end color; then add _GG_TMP_DIAG${MYPID}_ constant which will be substituted with generated C code diagnostic later
#what's added to this constant is line number in gen C code, error and file name to processed later, so GG_TMP_DIAG${MYPID}_line_column_file
#all goes to temp file .vdiag1_$MYPID in build scratch pad
#since we print a/b/c as source file in v1.c, make sure / is included in a-z etc
#$(cat -) doesn't quite work
sed 's|^\([_a-zA-Z0-9/]\+\)\.golf:\([0-9]\+\)\([0-9]\{4\}\):[[:space:]]*\([^:]\+\)[[:space:]]*:\(.*\)$|__GG_COLOR*** \1.golf:\2:\4:\5__GG_END_COLOR\n.GG_TMP_DIAG'${MYPID}'_\2_\3_\4_\1|g' >  $GG_ROOT/var/lib/gg/bld/$APP/.vdiag1_$MYPID <&0

#if there is no error somehow, then exit with success
if [ -f "$GG_ROOT/var/lib/gg/bld/$APP/.vdiag1_$MYPID" ]; then
    if [ "$(<$GG_ROOT/var/lib/gg/bld/$APP/.vdiag1_$MYPID)" == "" ]; then exit 0; fi
fi

#now get data added to constant _GG_TMP_DIAG${MYPID}_ and process it in displ function, which will output color coded golf source line, gen C line, and caret to point out the error
#the output goes to .vdiag2_$MYPID, which is a short bash script that will echo the error message to .GG_TMP_DIAG${MYPID}_line_column_file
sed -n 's/.GG_TMP_DIAG'${MYPID}'_\([0-9]\+\)_\([0-9]\+\)_\([^_]\+\)_\(.*\)/echo "$(displ \1\2 \3 \4)">$GG_ROOT\/var\/lib\/gg\/bld\/$APP\/.GG_TMP_DIAG'${MYPID}'_\1_\2_\3_\4/gp' $GG_ROOT/var/lib/gg/bld/$APP/.vdiag1_$MYPID >$GG_ROOT/var/lib/gg/bld/$APP/.vdiag2_$MYPID

#execute .vdiag2_$MYPID to produce output to .GG_TMP_DIAG${MYPID}_line_column_file
if [ -f "$GG_ROOT/var/lib/gg/bld/$APP/.vdiag2_$MYPID" ]; then 
    chmod +x $GG_ROOT/var/lib/gg/bld/$APP/.vdiag2_$MYPID
    . $GG_ROOT/var/lib/gg/bld/$APP/.vdiag2_$MYPID 
fi

#now substitute the .GG_TMP_DIAG${MYPID}_line_column_file  constant with the contents of the file with the same name generated above, for each error
CDIR=$(pwd)
cd $GG_ROOT/var/lib/gg/bld/$APP/
#prevent error message if no .GG_TMP_DIAG${MYPID} found
for i in $(ls .GG_TMP_DIAG${MYPID}_* 2>/dev/null); do
    sed -e $"/$i/{r $i" -e 'd}' $GG_ROOT/var/lib/gg/bld/$APP/.vdiag1_$MYPID > $GG_ROOT/var/lib/gg/bld/$APP/.vdiag3_$MYPID
    mv $GG_ROOT/var/lib/gg/bld/$APP/.vdiag3_$MYPID $GG_ROOT/var/lib/gg/bld/$APP/.vdiag1_$MYPID
done
cd "$CDIR"

#make sure stdout goes to stderr, since this is diagnostics
#and also make colors for top diagnostic error
#cat $GG_ROOT/var/lib/gg/bld/$APP/.vdiag1_$MYPID|sed ''/__GG_COLOR/s//$(printf "$BOLD$BLUE")/'' | sed ''/__GG_END_COLOR/s//$(printf "$NORMAL")/'' | cat - 1>&2
#
#The below code, with replacing __ with / seem to be no longer needed, but not sure. Keeping for now
#
#use sed 10 times to convert __ to / (if not preceded by /) - this assumes directory structure is 10 levels deep at most, this is when flat structure is used
#this is for presenting hierarchical request names properly, but it messes up file names for --c-lines. For instance if v1.c doesn't generate the right code,
#this is needed to show hierarchy
cat $GG_ROOT/var/lib/gg/bld/$APP/.vdiag1_$MYPID|sed ''/__GG_COLOR/s//$(printf "$BOLD$BLUE")/'' | sed ''/__GG_END_COLOR/s//$(printf "$NORMAL")/''| sed 's/\([^\/]\)__\([^:]*:\)/\1\/\2/g'  |  sed 's/\([^\/]\)__\([^:]*:\)/\1\/\2/g'  | sed 's/\([^\/]\)__\([^:]*:\)/\1\/\2/g'  | sed 's/\([^\/]\)__\([^:]*:\)/\1\/\2/g'  | sed 's/\([^\/]\)__\([^:]*:\)/\1\/\2/g'  | sed 's/\([^\/]\)__\([^:]*:\)/\1\/\2/g'  | sed 's/\([^\/]\)__\([^:]*:\)/\1\/\2/g'  | sed 's/\([^\/]\)__\([^:]*:\)/\1\/\2/g'  | sed 's/\([^\/]\)__\([^:]*:\)/\1\/\2/g'  | sed 's/\([^\/]\)__\([^:]*:\)/\1\/\2/g'  |cat - 1>&2
#
#
#

rm -f $GG_ROOT/var/lib/gg/bld/$APP/.vdiag1_$MYPID
rm -f $GG_ROOT/var/lib/gg/bld/$APP/.vdiag3_$MYPID
rm -f $GG_ROOT/var/lib/gg/bld/$APP/.vdiag2_$MYPID
rm -f .GG_TMP_DIAG'${MYPID}'

#make sure exit code is failure for these errors
exit -1
