#!/usr/bin/env bash
#  ____         ____
# | __ )  __ _ / ___|___  _ __
# |  _ \ / _` | |   / _ \| '_ \
# | |_) | (_| | |__| (_) | | | |   --= A Shell BASIC-to-C converter =--
# |____/ \__,_|\____\___/|_| |_|
#
# Peter van Eerten - March 2009/November 2019. License: MIT License.
#
#---------------------------------------------------------------------------------------------------------------------
# CREDITS to all people of the BaCon forum. Without them BaCon would not be as it is now.
#---------------------------------------------------------------------------------------------------------------------
#
# This script should work with the following shells:
#
#   - Bourne Again Shell (BASH) 4.0 or higher
#   - AT&T Kornshell 93
#   - MirBSD Korn Shell (MKSH)
#   - ZShell (ZSH) 4.x or higher
#
#---------------------------------------------------------------------------------------------------------------------
# GLOBAL INITIALIZATIONS
#---------------------------------------------------------------------------------------------------------------------

# Are we using BASH?
if [[ -n $BASH ]]
then
    if [[ ${BASH_VERSINFO[0]}$((${BASH_VERSINFO[1]}+0)) -lt 40 ]]
    then
        echo "System error: this is BASH version ${BASH_VERSION}. BaCon needs BASH 4.0 or higher to run!"
        exit 1
    fi
    # Set the extended globbing option in BASH
    shopt -s extglob
else
    # Check Kornshell version
    if [[ ${KSH_VERSION} = +(*MIRBSD*) || -n ${ZSH_NAME} ]]
    then
        alias echo="print -R"
    else
        ulimit -s unlimited
    fi

    # If run with Zshell then emulate KSH
    if [[ -n $ZSH_NAME ]]
    then
        if [[ ${ZSH_VERSION%%.*} -lt 4 ]]
        then
	    echo "System error: this is ZShell version ${ZSH_VERSION}. BaCon needs ZShell 4.x or higher to run!"
	    exit 1
        else
	    emulate ksh
        fi
    fi
fi

# Unset grep options
unset GREP_OPTIONS

# Version of BACON
typeset -rx g_VERSION="3.9.3"

# Our numerical environment is POSIX
export LC_NUMERIC="POSIX"

# Find coretools
if [[ -z `which cat` || -z `which rm` || -z `which tr` || -z `which touch` || -z `which uname` || -z `which head` || -z `which head` ]]
then
    echo "System error: 'cat', 'rm', 'tr', 'touch', 'uname', 'head' or 'pwd' not found on this system!"
    exit 1
fi

# Link flags
g_LDFLAGS="-L. -lm"

# Solaris
if [[ `uname` = +(*SunOS*) ]]
then
    g_LDFLAGS="$g_LDFLAGS -lnsl -lsocket"
fi

# Global constant for miniparsing
typeset -rx g_PARSEVAR=`echo -e "\001"`

# Global to define '$', '%' and '#'-replacement
typeset -rx g_STRINGSIGN="__b2c__string_var"
typeset -rx g_LONGSIGN="__b2c__long_var"
typeset -rx g_FLOATSIGN="__b2c__float_var"

# Global to define '"'-symbol
typeset -rx g_DQUOTESIGN=`echo -e "\042"`

# Global to define '''-symbol
typeset -rx g_SQUOTESIGN=`echo -e "\047"`

# Global to define CRLF combination
typeset -rx g_CRLF=`echo -e "\015\012"`

# Global to define TAB
typeset -rx g_TAB=`echo -e "\011"`

# Remember the original field separator
typeset -rx g_ORGIFS="${IFS}"

# Needed to prevent accidental variable names using C keywords
typeset -rx g_C_KEYWORDS="asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while|y0|y1|yn|y0f|y1f|ynf|y0l|y1l|ynl"

# Associative vars to keep track of BaCon variables
typeset -A g_ALL_MAIN_VARS g_ALL_FUNC_VARS

#-------------------------------------------------------$1 = variable name, $2 = function name

function Get_Var
{
    typeset VAR RECORD

    # In case of array assignments: exit
    if [[ ${1} = +(*\{*) || $(echo ${1}) = +(* *) ]]
    then
        return
    fi

    # Get rid of assignment notation
    if [[ ${1} = +(*\=*) ]]
    then
        VAR=$(echo ${1%%=*})
    else
        VAR=$(echo ${1})
    fi

    # Get rid of '*' sign in variable name
    VAR=${VAR//\*/}

    # Get rid of '&' sign in variable name
    VAR=${VAR//&/}

    # Get rid of recordname 
    if [[ ${VAR} = +(*.*) ]]
    then
        RECORD=${VAR%%.*}
        VAR=${VAR##*.}
    else
        RECORD=${g_RECORDVAR}
    fi
    RECORD="${RECORD%%\[*}"

    # If there is a record name then add a "."
    if [[ -n $RECORD ]]
    then
        RECORD="${RECORD}."
    fi

    # Get rid of array notation
    if [[ ${VAR} = +(*\[*) ]]
    then
        VAR=${VAR%%\[*}
    fi

    # Get rid of brackets in case of function pointer or assoc var
    if [[ ${VAR} = +(*\(*) ]]
    then
        VAR=$(echo ${VAR%%\(*})
    fi

    # Get rid of $ sign
    if [[ $VAR = +(*\$*) ]]
    then
        VAR=${VAR//\$/$g_STRINGSIGN}
    elif [[ $VAR = +(*#*) ]]
    then
        VAR=${VAR//#/$g_FLOATSIGN}
    elif [[ $VAR = +(*%*) ]]
    then
        VAR=${VAR//%/$g_LONGSIGN}
    fi

    # If plain text, skip. Also skip '}' to avoid eval clash.
    if [[ -n ${VAR} && "${VAR%%\(*}" != +(*${g_DQUOTESIGN}*) && "${VAR%%\(*}" != +(*\}*) ]]
    then
        # Always lookup type in MAIN
        echo ${g_ALL_MAIN_VARS[${RECORD}${VAR}]}

        # Lookup type in function if given
        if [[ -n ${2} && -z ${g_ALL_MAIN_VARS[${RECORD}${VAR}]} ]]
        then
            echo ${g_ALL_FUNC_VARS[${RECORD}${VAR}___${2}]}
        fi
    fi
}

function Save_Main_Var
{
    typeset STR TYPE NR VAR

    # Make sure the asterisk is attached to type
    if [[ ${1} = +(\**) ]]
    then
        STR=$(echo ${1//\*/})
        let NR=${#1}-${#STR}
        TYPE="$2"
        until [[ ${NR} -eq 0 ]]
        do
            TYPE="${TYPE}*"
            ((NR-=1))
        done
    else
        STR="$1"
        TYPE="$2"
    fi

    # Get rid of assignment notation
    if [[ ${STR} = +(*=*) ]]
    then
        STR=$(echo ${STR%%=*})
    else
        STR=$(echo ${STR})
    fi

    # Get rid of array notation
    if [[ ${STR} = +(*\[*\]*) ]]
    then
        STR=${STR%%\[*}
    fi

    if [[ -n ${g_RECORDVAR} ]]
    then
        VAR="${g_RECORDVAR%%\[*}.${STR}"
    else
        VAR="${STR}"
    fi

    g_ALL_MAIN_VARS[${VAR}]=${TYPE}
}

function Save_Func_Var
{
    typeset STR TYPE NR VAR

    # If there is a function pointer, skip this function
    if [[ ${1} = +(\(*\)*) ]]
    then
        return
    fi

    # Make sure the asterisk is attached to type
    if [[ ${1} = +(\**) ]]
    then
        STR=$(echo ${1//\*/})
        let NR=${#1}-${#STR}
        TYPE="$3"
        until [[ ${NR} -eq 0 ]]
        do
            TYPE="${TYPE}*"
            ((NR-=1))
        done
    else
        STR="$1"
        TYPE="$3"
    fi

    # Get rid of assignment notation
    if [[ "${STR}" = +(*=*) ]]
    then
        STR=$(echo ${STR%%=*})
    else
        STR=$(echo ${STR})
    fi

    # Get rid of array notation
    if [[ ${STR} = +(*\[*\]*) ]]
    then
        STR=${STR%%\[*}
    fi

    if [[ -n ${g_RECORDVAR} ]]
    then
        VAR="${g_RECORDVAR%%\[*}.${STR}___${2}"
    else
        VAR="${STR}___${2}"
    fi

    g_ALL_FUNC_VARS[${VAR}]=${TYPE}
}

function Debug_Vars
{
    typeset i

    echo
    for i in ${!g_ALL_MAIN_VARS[@]}
    do
        i=${i//_____/.}
        echo -n "${g_ALL_MAIN_VARS[$i]}:MAIN:${i} "
    done

    echo
    for i in ${!g_ALL_FUNC_VARS[@]}
    do
        i=${i//_____/.}
        echo -n "${g_ALL_FUNC_VARS[$i]}:${i##*___}:${i%%___*} "
    done
    echo
}

# This function registers variables. $1 = var to be declared, if $2-$3-$4 etc is double then $1 should be double.
function Register_Numeric
{
    if [[ $g_OPTION_EXPLICIT = "1" || $g_OPTION_EXPLICIT = "TRUE" ]]
    then
	echo -e "\nSyntax error: OPTION EXPLICIT forces explicit variable declaration at line $g_COUNTER in file '$g_CURFILE'!"
        exit 1
    fi

    if [[ ${1} != +(*::*) ]]
    then
        if [[ ${1} = +(*${g_FLOATSIGN}) ]]
        then
	    echo "double ${1};" >> $g_HFILE
            Save_Main_Var "${1}" "double"
        else
            echo "${g_VARTYPE} ${1};" >> $g_HFILE
            Save_Main_Var "${1}" "${g_VARTYPE}"
        fi
    fi
}

function Register_String
{
    if [[ $g_OPTION_EXPLICIT = "1" || $g_OPTION_EXPLICIT = "TRUE" ]]
    then
	echo -e "\nSyntax error: OPTION EXPLICIT forces explicit variable declaration at line $g_COUNTER in file '$g_CURFILE'!"
        exit 1
    fi

    echo "char* ${1} = NULL;" >> $g_HFILE
    Save_Main_Var "${1}" "char*"
}

# This function saves the dimension of arrays (SORT)
function Save_Dim
{
    typeset STR

    # Get rid of record '.'
    if [[ ${1} = +(*.*) ]]
    then
        STR=${1##*.}
    else
        STR=${1}
    fi

    eval dim_"${g_RECORDVAR%%\[*}${STR}_${g_FUNCNAME}"='${2}'
}

# This function gets the dimension of arrays (SORT)
function Get_Dim
{
    typeset STR RECORD RESULT

    # Get rid of record '.'
    if [[ ${1} = +(*.*) ]]
    then
        RECORD=${1%%.*}
        STR=${1##*.}
    else
        RECORD=${g_RECORDVAR%%\[*}
        STR=${1}
    fi

    RESULT=`eval echo '${dim_'"${RECORD}${STR}_"'}'`
    if [[ -z ${RESULT} ]]
    then
        RESULT=`eval echo '${dim_'"${RECORD}${STR}_${g_FUNCNAME}"'}'`
    fi

    echo ${RESULT}
}

#-----------------------------------------------------------
# Mini parser to obtain chunk of text separated by comma. The comma in function arguments is ignored.
# This function will attach the last ")" in case of a function and then jump out.

function Mini_Parser
{
    # Local variables
    typeset LINE TOKEN LEN CHAR
    typeset -i IN_STRING IN_FUNC ESCAPED

    let ESCAPED=0
    let IN_STRING=0
    let IN_FUNC=0

    LINE=$(echo ${1// /${g_PARSEVAR}})
    TOKEN=
    LEN=${#LINE}

    # Get the characters
    until [[ $LEN -eq 0 || $IN_FUNC -lt 0 ]]
    do
        if [[ -n ${2} ]]
        then
	    CHAR="${LINE:0:3}"
            case $CHAR in
                ${2})
		    if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]]
		    then
                        if [[ ${#TOKEN} -gt 0 ]]
                        then
                            break
                        fi
		    fi;;
            esac
        fi
	CHAR="${LINE:0:1}"
	case $CHAR in
	    ","|";")
		if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]]
		then
                    if [[ ${#TOKEN} -gt 0 ]]
                    then
                        break
                    fi
		fi;;
	    "\\")
		if [[ $ESCAPED -eq 0 ]]
		then
		    ESCAPED=1
		else
		    ESCAPED=0
		fi;;
	    "\"")
		if [[ $ESCAPED -eq 0 ]]
		then
		    if [[ $IN_STRING -eq 0 ]]
		    then
			IN_STRING=1
		    else
			IN_STRING=0
		    fi
		fi
		ESCAPED=0;;
	    "(")
		if [[ $IN_STRING -eq 0 ]]
		then
		    ((IN_FUNC=$IN_FUNC+1))
		fi
		ESCAPED=0;;
	    ")")
		if [[ $IN_STRING -eq 0 ]]
		then
		    ((IN_FUNC=$IN_FUNC-1))
		fi
		ESCAPED=0;;
	    *)
		ESCAPED=0;;
	esac
	# Convert back to space
	if [[ "${CHAR}" = "${g_PARSEVAR}" ]]
	then
	    TOKEN="${TOKEN} "
	else
	    TOKEN="${TOKEN}${CHAR}"
	fi
	let LEN=${#LINE}-1
	LINE="${LINE: -$LEN}"
    done

    echo "${TOKEN}"
}

#-----------------------------------------------------------

function Check_String_Type
{
    typeset VAR TYPE

    # Get rid of casting in array indicators
    VAR="${1//\(uint64_t\)/}"

    # Remove part after '(' in case of function or assoc array
    VAR=$(echo ${VAR%%\(*})

    # It contains double quotes or ends with $
    if [[ "${VAR}" = +(*${g_DQUOTESIGN}*) || "${VAR}" = +(*\$) ]]
    then
	echo 1
    else
        # Check variable registration
	TYPE=$(Get_Var "${VAR}" ${g_FUNCNAME})
    
	# Verify type
	if [[ "${VAR}" = +(*${g_STRINGSIGN}*) || "${VAR}" = +(gettext*|ngettext*) || ${TYPE} = +(*char\**|*STRING*) && "${VAR}" != +(*\[*\]*) ]]
	then
	    echo 1
	else
	    echo 0
	fi
    fi
}

#----------------------------------------------------------- $2 = stdout or stderr

function Print_Element
{
    # If argument 1 does not contain an actual string
    if [[ ${1} = "stdout" || ${1} = "stderr" ]]
    then
        return
    fi

    # Check if var is string var
    if [[ $(Check_String_Type ${1}) -eq 1 ]]
    then
        echo "__b2c__assign = (char*)${1}; if(__b2c__assign != NULL) { fputs(__b2c__assign, ${2}); }" >> $g_CFILE
    else
	echo "fputs(STR${g_STRINGSIGN}(${1}), ${2});" >> $g_CFILE
    fi
}

#----------------------------------------------------------- $2 = stdout or stderr

function Handle_Print
{
    typeset FORMAT EXP LEN TOKEN TO CHECK SIZE TOPARSE
    typeset -i AM1 AM2

    # If no argument, do nothing
    if [[ "$1" != "PRINT" && "$1" != "EPRINT" ]]
    then
	# Get expression without ;
	if [[ -z ${1##*;} ]]
	then
	    let LEN="${#1}"-1
	    EXP="${1:0:$LEN}"
	else
	    EXP="${1}"
	fi
        # Get rid of escaped quote
        TOPARSE="${EXP//\\\\\"/  }"
        # Prepare for parsing
        AM1=`echo ${TOPARSE%FORMAT *} | tr -d -c "\"" | wc -c`
        AM2=`echo ${TOPARSE%TO *} | tr -d -c "\"" | wc -c`
	# If there is FORMAT/format argument
	if [[ "${EXP}" = +(* FORMAT *) && $((${AM1} % 2)) -eq 0 ]]
	then
	    FORMAT="${EXP##* FORMAT}"
            EXP="${EXP%FORMAT *}"
	    # Optional TO argument?
	    if [[ $FORMAT = +(* TO *) ]]
	    then
		TO=${FORMAT##* TO }
            fi
        elif [[ "${EXP}" = +(* TO *) && $((${AM2} % 2)) -eq 0 ]]
        then
	    TO=${EXP##* TO }
            FORMAT="\"%s\""
            EXP="${EXP%TO *}"
        fi
        if [[ ${TO} = +(* SIZE *) ]]
        then
            SIZE=${TO##* SIZE }
            TO=${TO%% SIZE *}
        else
            SIZE=${g_BUFFER_SIZE}
        fi
        if [[ -n $FORMAT ]]
        then
            if [[ -n $TO ]]
            then
                # Check if string is declared
                if [[ "${TO}" = +(*${g_STRINGSIGN}) && "${TO}" != +(*.*) ]]
                then
                    if [[ -z $(Get_Var ${TO} ${g_FUNCNAME}) ]]
	            then
                        Register_String "${TO}"
	            fi
                fi
		echo "__b2c__assign = (char*)calloc($SIZE+1, sizeof(char));" >> $g_CFILE
		echo "snprintf(__b2c__assign, $SIZE+1, ${FORMAT%% TO*}, ${EXP});" >> $g_CFILE
	        # Now see if we have a assoc or a normal variable
	        if [[ "${TO}" = +(*\(*\)) ]]
	        then
	            STR=${TO#*\(}
	            echo "__b2c__${TO%%\(*}_loc = __b2c__${TO%%\(*}__add(${STR};" >> $g_CFILE
	            echo "__b2c__STRFREE(__b2c__${TO%%\(*}_loc->value); __b2c__${TO%%\(*}_loc->value = __b2c__assign;" >> $g_CFILE
	            # Check for relations
	            Relate_Recurse "${TO%%\(*}" "${STR}" "${TO}" "-1"
	        else
	            echo "__b2c__STRFREE(${TO}); ${TO} = __b2c__assign;" >> $g_CFILE
	        fi
	    else
		echo "fprintf(${2}, ${FORMAT%%;*}, ${EXP});" >> $g_CFILE
	    fi
	else
	    # Start miniparser
            while [[ -n ${EXP} ]]
            do
                TOKEN=$(Mini_Parser "${EXP}")
	        Print_Element "${TOKEN}" "${2}"
                EXP="${EXP:${#TOKEN}+1}"
            done

            # If line ends with ';' then skip newline
	    if [[ -n $(echo ${1##*;}) ]]
	    then
		echo "fputs(\"\n\", ${2});" >> $g_CFILE
	    fi
	fi
    else
	echo "fputs(\"\n\", ${2});" >> $g_CFILE
    fi

    # Flush buffer
    echo "fflush(${2});" >> $g_CFILE
}

#-----------------------------------------------------------

function Handle_Input
{
    # Local variables
    typeset CHECK VAR STR EXP TOKEN

    # Check if we have an argument at all
    if [[ "$1" = "INPUT" ]]
    then
	echo -e "\nSyntax error: empty INPUT at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    EXP="${1}"

    # Start miniparser to see if we need to print something
    while [[ -n ${EXP} ]]
    do
        TOKEN=$(Mini_Parser "${EXP}")
        EXP="${EXP:${#TOKEN}+1}"
        if [[ -n ${EXP} ]]
        then
	    Print_Element "${TOKEN}" "stdout"
        fi
    done

    # Remove spaces in variable
    VAR=$(echo ${TOKEN})

    # Check if string is declared
    if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]]
    then
        if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	then
            Register_String "${VAR}"
	fi
    # Not a string?
    elif [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) && "$VAR" != +(*\(*\)*) && "$VAR" != +(*-\>*) ]]
    then
        if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	then
            Register_Numeric "${VAR}"
	fi
    fi

    # Check type of var, string?
    if [[ $(Check_String_Type ${VAR}) -eq 1 ]]
    then
        # Translate function to C function
        echo "__b2c__counter = 1; __b2c__assign = NULL; do {memset(__b2c__input__buffer, 0, $g_BUFFER_SIZE); if(fgets(__b2c__input__buffer, $g_BUFFER_SIZE, stdin) == NULL && !feof(stdin))" >> $g_CFILE
	echo "{if(__b2c__trap){ERROR = 35; if(!__b2c__catch_set) RUNTIMEERROR(\"INPUT\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE

	# Obtain input from STDIN
        echo "__b2c__assign = (char*)realloc(__b2c__assign, $g_BUFFER_SIZE*__b2c__counter);" >> $g_CFILE
        echo "if(__b2c__counter == 1) __b2c__assign[0] = '\0'; strncat(__b2c__assign, __b2c__input__buffer, $g_BUFFER_SIZE); __b2c__counter++;" >> $g_CFILE
        echo "} while (!strstr(__b2c__input__buffer, ${g_OPTION_INPUT}) && !feof(stdin));" >> $g_CFILE
        # Content should be cut off at termination symbol
        echo "if(__b2c__assign != NULL && !feof(stdin)) {*(strstr(__b2c__assign, ${g_OPTION_INPUT})) = '\0';}" >> $g_CFILE

	# Now see if we have a assoc or a normal variable
	if [[ "${VAR}" = +(*\(*\)) ]]
	then
	    STR=${VAR#*\(}
	    echo "__b2c__${VAR%%\(*}_loc = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE
	    echo "__b2c__STRFREE(__b2c__${VAR%%\(*}_loc->value); __b2c__${VAR%%\(*}_loc->value = __b2c__assign;" >> $g_CFILE
	    # Check for relations
	    Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1"
	else
	    echo "__b2c__STRFREE($VAR); $VAR = __b2c__assign;" >> $g_CFILE
	fi
    # Var is numeric
    else
	# Translate function to C function
	echo "memset(__b2c__input__buffer, '\0', $g_BUFFER_SIZE); if(fgets(__b2c__input__buffer, $g_BUFFER_SIZE, stdin)==NULL)" >> $g_CFILE
	echo "{if(__b2c__trap){ERROR = 35; if(!__b2c__catch_set) RUNTIMEERROR(\"INPUT\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE

	# Get the type
	CHECK=$(Get_Var ${VAR} ${g_FUNCNAME})

	# Now see if we have an assoc or a normal variable
	if [[ "${VAR}" = +(*\(*\)) ]]
	then
	    STR=${VAR#*\(}
	    echo "__b2c__${VAR%%\(*}_loc = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE
	    if [[ "$CHECK" = +(*double*) || "$CHECK" = +(*float*) || "$CHECK" = +(*FLOATING*) ]]
	    then
		echo "__b2c__${VAR%%\(*}_loc->value = atof(__b2c__input__buffer);" >> $g_CFILE
	    elif [[ "$CHECK" = +(*long*) || "$CHECK" = +(*NUMBER*) ]]
	    then
		echo "__b2c__${VAR%%\(*}_loc->value = atol(__b2c__input__buffer);" >> $g_CFILE
	    else
		echo "__b2c__${VAR%%\(*}_loc->value = atoi(__b2c__input__buffer);" >> $g_CFILE
	    fi
	    # Check for relations
	    Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1"
	else
	    if [[ "$CHECK" = +(*double*) || "$CHECK" = +(*float*) || "$CHECK" = +(*FLOATING*) ]]
	    then
		echo "$VAR = atof(__b2c__input__buffer);" >> $g_CFILE
	    elif [[ "$CHECK" = +(*long*) || "$CHECK" = +(*NUMBER*) ]]
	    then
		echo "$VAR = atol(__b2c__input__buffer);" >> $g_CFILE
	    else
		echo "$VAR = atoi(__b2c__input__buffer);" >> $g_CFILE
	    fi
	fi
    fi
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi
}

#-----------------------------------------------------------

function Handle_For
{
    # Local variables
    typeset FROM TO TMP VAR STEP STR

    # Check if TO is available
    if [[ "${1}" != +(* TO *) && "${1}" != +(* DOWNTO *) && "${1}" != +(* IN *) ]]
    then
	echo -e "\nSyntax error: missing IN/TO/DOWNTO in FOR statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # What kind of FOR are we dealing with
    if [[ "${1}" = +(* TO *) || "${1}" = +(* DOWNTO *) ]]
    then
        # Get the variablename without (surrounding) spaces
        VAR=`echo "${1%%=*}" | tr -d "\040"`; TMP=`echo "${1#*=}"`

        # Get the starting and ending value
        if [[ "${1}" = +(* TO *) ]]
        then
            FROM=`echo "${TMP%% TO *}"`
            TO=`echo "${TMP##* TO }"`
        else
            FROM=`echo "${TMP%% DOWNTO *}"`
            TO=`echo "${TMP##* DOWNTO }"`
        fi

        # Check if there is a STEP
        if [[ "$TO" = +(* STEP *) ]]
        then
	    STEP="${TO##* STEP }"
	    TO="${TO%% STEP *}"
        else
	    STEP=1
        fi
        if [[ "${1}" = +(* DOWNTO *) ]]
        then
            STEP="-${STEP}"
        fi
    else
        # Get the variablename without (surrounding) spaces
        VAR=`echo "${1%% IN *}" | tr -d "\040"`; TMP=`echo "${1#* IN }"`
        # Check if there is a STEP
        if [[ "$TMP" = +(* STEP *) ]]
        then
	    STEP="${TMP##* STEP }"
	    TMP="${TMP%% STEP *}"
        else
	    STEP="\" \""
        fi
        # Define help variables
        if [[ -n $g_FUNCNAME ]]
        then
	    if [[ ${g_STRINGARGS} != +(*__b2c__forin_${VAR}_ptr*) ]]
	    then
                g_STRINGARGS="${g_STRINGARGS} char* __b2c__forin_${VAR}_ptr;"
                Save_Func_Var "__b2c__forin_${VAR}_ptr" "${g_FUNCNAME}" "char*"
                g_STRINGARGS="${g_STRINGARGS} char* __b2c__forin_${VAR}_org = NULL;"
                Save_Func_Var "__b2c__forin_${VAR}_org" "${g_FUNCNAME}" "char*"
                g_STRINGARGS="${g_STRINGARGS} long __b2c__forin_${VAR}_amount;"
                Save_Func_Var "__b2c__forin_${VAR}_amount" "${g_FUNCNAME}" "long"
                g_STRINGARRAYS="${g_STRINGARRAYS} __b2c__STRFREE(__b2c__forin_${VAR}_org); __b2c__forin_${VAR}_org = NULL;"
            fi
        else
            if [[ -z $(Get_Var __b2c__forin_${VAR}_ptr) ]]
	    then
                echo "char* __b2c__forin_${VAR}_ptr;" >> $g_HFILE
                Save_Main_Var "__b2c__forin_${VAR}_ptr" "char*"
                echo "char* __b2c__forin_${VAR}_org = NULL;" >> $g_HFILE
                Save_Main_Var "__b2c__forin_${VAR}_org" "char*"
                echo "long __b2c__forin_${VAR}_amount;" >> $g_HFILE
                Save_Main_Var "__b2c__forin_${VAR}_amount" "long"
            fi
        fi
    fi

    # Check if string is declared
    if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]]
    then
        if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	then
            Register_String "${VAR}"
	fi
    # Not a string?
    elif [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) && "$VAR" != +(*\(*\)*) && "$VAR" != +(*-\>*) ]]
    then
        if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	then
            if [[ $FROM$TO$STEP = +(*[0-9]*.*[0-9]*) || $(Get_Var ${STEP#*-} ${g_FUNCNAME}) = +(*double*|*float*|*FLOATING*) ]]
            then
	        echo "double $VAR;" >> $g_HFILE
                Save_Main_Var "${VAR}" "double"
            else 
                Register_Numeric ${VAR}
            fi
	fi
    fi

    # Check type of var, string?
    if [[ $(Check_String_Type ${VAR}) -eq 1 ]]
    then
        echo "__b2c__start = __b2c__delim_engine(2, &__b2c__forin_${VAR}_amount, ${TMP}, ${STEP}, 0); if(__b2c__forin_${VAR}_amount) { __b2c__forin_${VAR}_ptr = __b2c__strdup(${TMP}); __b2c__forin_${VAR}_org = __b2c__forin_${VAR}_ptr;" >> $g_CFILE
	echo "__b2c__STRFREE(${VAR}); ${VAR} = NULL; } while(__b2c__forin_${VAR}_amount) { __b2c__start = __b2c__delim_engine(1, &__b2c__length, __b2c__forin_${VAR}_ptr, ${STEP}, 1);" >> $g_CFILE
	echo "${VAR} = (char*)__b2c_str_realloc(${VAR}, __b2c__length + 1); memmove(${VAR}, __b2c__forin_${VAR}_ptr + __b2c__start, __b2c__length); __b2c__SETLEN(${VAR}, __b2c__length);" >> $g_CFILE
	echo "${VAR}[__b2c__length] = '\0'; __b2c__forin_${VAR}_ptr += __b2c__start + __b2c__length + __b2c__len(${STEP}); __b2c__forin_${VAR}_amount--; if(!__b2c__forin_${VAR}_amount) { free(__b2c__forin_${VAR}_org); __b2c__forin_${VAR}_org = NULL; }" >> $g_CFILE
    # Var is numeric
    else
        # Translate function to C function
        if [[ "${STEP}" = +(*-*) ]]
        then
	    echo "for($VAR=$FROM; $VAR >= $TO; $VAR+=$STEP){" >> $g_CFILE
        else
	    echo "for($VAR=$FROM; $VAR <= $TO; $VAR+=$STEP){" >> $g_CFILE
        fi
    fi
}

#-----------------------------------------------------------

function Handle_While
{
    # Check if DO is available
    if [[ "$1" != +(* DO) ]]
    then
        Parse_Equation "${1}"
    else
        Parse_Equation "${1% *}"
    fi
    echo "while(${g_EQUATION}){" >> $g_CFILE
}

#-----------------------------------------------------------
# $1: name of ASSOC variable
# $2: name of index
# $3: actual value to assign
# $4: recursion level

function Relate_Recurse
{
    typeset CTR REL LVL

    # Check endless recursion
    LVL=$4; ((LVL+=1))
    if [[ $LVL -gt $g_RELATE_CTR ]]
    then
	echo -e "\nSyntax error: endless recursion in RELATE statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Now add relation
    CTR=0

    while [[ $CTR -lt $g_RELATE_CTR ]]
    do
	if [[ ${g_RELATE[${CTR}]} = +(${1}*) ]]
	then
	    REL=${g_RELATE[${CTR}]##* }
	    echo "__b2c__${REL}_loc = __b2c__${REL}__add(${2};" >> $g_CFILE
	    if [[ "${REL}" = +(*${g_STRINGSIGN}*) ]]
	    then
                echo "__b2c__${REL}_loc->value = (char*)__b2c_Copy_String(__b2c__${REL}_loc->value, ${3});" >> $g_CFILE
	    else
	        echo "__b2c__${REL}_loc->value = ${3};" >> $g_CFILE
	    fi
	    Relate_Recurse ${REL} ${2} ${3} ${LVL}
	fi
	((CTR+=1))
    done
}

#-----------------------------------------------------------

function Handle_Let
{
    # Local variables
    typeset VAR TYPE TMP STR ARG PTR CHAR ESCAPED IN_STRING LINE IN_FUNC
    typeset -i POS LEN

    # Start miniparser to find last unquoted '='
    POS=0
    LEN=${#1}
    LINE="$1"

    # Get the characters
    until [[ $LEN -eq 0 ]]
    do
	CHAR="${LINE:0:1}"
	case $CHAR in
	    "\\")
		if [[ $ESCAPED -eq 1 ]]
		then
		    ESCAPED=0
                else
		    ESCAPED=1
                fi;;
	    "\"")
		if [[ $ESCAPED -eq 0 ]]
		then
		    if [[ $IN_STRING -eq 0 ]]
		    then
			IN_STRING=1
		    else
			IN_STRING=0
		    fi
		fi
		ESCAPED=0;;
	    "(")
		if [[ $IN_STRING -eq 0 ]]
		then
		    ((IN_FUNC=$IN_FUNC+1))
		fi
		ESCAPED=0;;
	    ")")
		if [[ $IN_STRING -eq 0 ]]
		then
		    ((IN_FUNC=$IN_FUNC-1))
		fi
		ESCAPED=0;;

	    "=")
		if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]]
		then
		    let POS=${#1}-${LEN}
		fi
		ESCAPED=0;;
	    *)
		ESCAPED=0;;
	esac
	let LEN=${#LINE}-1
	LINE="${LINE: -$LEN}"
    done

    # Check if there is an assignment at all, if not exit
    if [[ ${POS} -eq 0 ]]
    then
        if [[ $g_IGNORE_PARSE = "0" || $g_IGNORE_PARSE = "FALSE" ]]
        then
            echo "$1;" >> $g_CFILE
            return
        else
	    echo -e "\nSyntax error: could not parse line $g_COUNTER in file '$g_CURFILE': \"${1}\""
	    exit 1
        fi
    fi

    # Get the variablename without surrounding spaces
    VAR=$(echo ${1:0:${POS}})
    ((POS+=1))
    TMP="${1:${POS}}"

    # Check for MEMORY allocation
    if [[ ${TMP} = +(*MEMORY*\(*) || ${TMP} = +(*BLOAD*\(*) ]]
    then
	g_SEMANTIC_MEMFREE="@'${VAR}' at line $g_COUNTER in file '$g_CURFILE' ${VAR}@${g_SEMANTIC_MEMFREE}"
    fi

    # Check if var is string var, exclude RECORD elements
    if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) && "$VAR" != +(*\-\>*) && $g_DYNAMICARRAYS != +(*${VAR}@${g_FUNCNAME}*) ]]
    then
        if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	then
            Register_String "${VAR}"
	fi

    # Assume number, exclude RECORD and ASSOC elements
    elif [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) && "$VAR" != "ERROR" && "$VAR" != "RETVAL" && "$VAR" != +(*\(*\)*) && "$VAR" != +(*-\>*) && "$VAR" != +(*=*) ]]
    then
        if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
        then
	    if [[ ${TMP} = +(*[0-9].[0-9]*) && "$TMP" != +(*$g_DQUOTESIGN*) ]]
            then
                if [[ $g_OPTION_EXPLICIT = "1" || $g_OPTION_EXPLICIT = "TRUE" ]]
                then
	            echo -e "\nSyntax error: OPTION EXPLICIT forces explicit variable declaration at line $g_COUNTER in file '$g_CURFILE'!"
                    exit 1
                fi
	        echo "double $VAR;" >> $g_HFILE
                Save_Main_Var "${VAR}" "double"
            else
                Register_Numeric ${VAR}
            fi
	fi
    fi

    # Check if there is associative array assignment
    if [[ "${VAR}" = +(*\(*\)) ]]
    then
        if [[ "${TMP}" = +(*\(\)) ]]
        then
            echo "__b2c__${TMP%%\(*}_tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__${TMP%%\(*}_tab);" >> $g_CFILE
            echo "for(__b2c__ctr = 0; __b2c__ctr < __b2c__hashtable_count(&__b2c__${TMP%%\(*}_tab); __b2c__ctr++) {" >> $g_CFILE
            echo "__b2c__${TMP%%\(*}_loc = (__b2c__${TMP%%\(*}_typ*)__b2c__hashtable_find(&__b2c__${TMP%%\(*}_tab, (HASHTABLE_U64)__b2c__${TMP%%\(*}_tmp[__b2c__ctr]);" >> $g_CFILE
            echo "__b2c__${VAR%%\(*}_loc = __b2c__${VAR%%\(*}__add(__b2c__${TMP%%\(*}_loc->key);" >> $g_CFILE
            if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) ]]
            then
                echo "__b2c__${VAR%%\(*}_loc->value = (char*)__b2c_Copy_String(__b2c__${VAR%%\(*}_loc->value, __b2c__${TMP%%\(*}_loc->value);" >> $g_CFILE
            else
	        echo "__b2c__${VAR%%\(*}_loc->value = __b2c__${TMP%%\(*}_loc->value;" >> $g_CFILE
            fi
            echo "}" >> $g_CFILE
        else
	    STR=${VAR#*\(}
            echo "__b2c__${VAR%%\(*}_loc = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE
	    if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) ]]
	    then
                echo "__b2c__${VAR%%\(*}_loc->value = (char*)__b2c_Copy_String(__b2c__${VAR%%\(*}_loc->value, ${TMP});" >> $g_CFILE
	    else
	        echo "__b2c__${VAR%%\(*}_loc->value = ${TMP};" >> $g_CFILE
	    fi
	    # Check for relations
	    Relate_Recurse "${VAR%%\(*}" "${STR}" "${TMP}" "-1"
        fi

    # Is there an array variable without subscript (dynamic array) -> assignment to STATIC returned arrays
    elif [[ "${VAR}" != +(*\[*\]*) && $g_DYNAMICARRAYS = +(* ${VAR}@${g_FUNCNAME}|* ${VAR}@${g_FUNCNAME} *) ]]
    then
	if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]]
        then
            echo "for(__b2c__ctr=0; __b2c__ctr<__b2c_array_$VAR; __b2c__ctr++) { __b2c__STRFREE($VAR[__b2c__ctr+$g_OPTION_BASE]); }" >> $g_CFILE
        fi
        echo "free($VAR);" >> $g_CFILE
	echo "${g_WITHVAR}${1};" >> $g_CFILE

    # Do we have a STRING variable or STRING array?
    elif [[ $(Check_String_Type ${VAR}) -eq 1 && ${VAR} = +(*${g_STRINGSIGN}*) ]]
    then
        TYPE=$(Get_Var ${VAR} ${g_FUNCNAME})
        # Check if it is some variable directly assigned
        if [[ $TYPE = +(*const*) ]]
        then
            echo "${g_WITHVAR}${VAR} = (char*)__b2c__strdup((const char*)${TMP});" >> $g_CFILE
	    if [[ -n ${g_FUNCNAME} ]]
            then
	        Save_Func_Var "${VAR}" "${g_FUNCNAME}" "${TYPE##*const }"
            else
                Save_Main_Var "${VAR}" "${TYPE##*const }"
            fi
        else
            # Make sure to handle string pointers
            if [[ $(Check_String_Type ${TMP}) -eq 1 ]]
            then
                echo "${g_WITHVAR}${VAR} = __b2c_Assign_String(&${g_WITHVAR}${VAR}, ${TMP});" >> $g_CFILE
            else
                echo "__b2c__STRFREE(${g_WITHVAR}${VAR}); ${g_WITHVAR}${VAR} = __b2c__strdup((const char*)${TMP});" >> $g_CFILE
            fi
        fi
	# Also check if string var already is used for IMPORT, if so, perform dlopen again
        PTR="${VAR//[[:punct:]]/}"
        if [[ -n $(Get_Var __b2c__dlopen__pointer_$PTR) ]]
	then
	    echo "__b2c__dlopen__pointer_$PTR = dlopen($VAR, RTLD_LAZY);" >> $g_CFILE
	fi
	# Check for array member in RECORD
	if [[ ${VAR} = +(*\.*) && ${VAR%%.*} = +(*\[*\]*) && -n ${g_FUNCNAME} && -z $(Get_Var ${VAR}) ]]
	then
	    if [[ ${g_LOCALSTRINGS} != "${VAR}" && ${VAR#*.} != +(*\[*\]*) ]]
	    then
		g_LOCALSTRINGS="$VAR $g_LOCALSTRINGS"
	    fi
	fi
    # Pointer type
    elif [[ ${VAR} = +(*\-\>*) ]]
    then
	echo "${g_WITHVAR}${1};" >> $g_CFILE
    # Pointer to string
    elif [[ "${VAR}" != +(*${g_STRINGSIGN}) && ${TMP} = +(*${g_STRINGSIGN}) ]]
    then
        TYPE=$(Get_Var ${VAR} ${g_FUNCNAME})
        echo "${g_WITHVAR}${VAR}=(${TYPE})(${TMP});" >> $g_CFILE
        echo "__b2c__INVALIDATE(${TMP});" >> $g_CFILE
    # Numeric or foreign type
    else
        TYPE=$(Get_Var ${VAR} ${g_FUNCNAME})
        TYPE=${TYPE//static/}
        # Cast the expression to type of variable, divide symbol needs extra cast
        if [[ ${TYPE} = +(*float*|*double*|*FLOATING*) && ${TYPE} != +(*\**) ]]
        then
            # FIXME: the '/' sign in string literals (if they occur) now also is converted, but should not happen
            echo "${g_WITHVAR}${VAR}=(${TYPE})(${TMP//\///(${TYPE})});" >> $g_CFILE
        elif [[ ${VAR} = +(*\[*\]*) && ${TYPE} = +(*\**) ]]
        then
	    echo "${g_WITHVAR}${1};" >> $g_CFILE
        # If var is pointer then skip casting
        elif [[ -n ${TYPE} && $VAR != +(*\**) ]]
        then
            echo "${g_WITHVAR}${VAR}=(${TYPE})(${TMP});" >> $g_CFILE
        # Other type
        else
	    echo "${g_WITHVAR}${1};" >> $g_CFILE
        fi
    fi
}

#-----------------------------------------------------------

function Handle_Open
{
    # Local variables
    typeset MODE HANDLE TMP CHECK LABEL CTR TOKEN ADDRESS SOURCE BND STR EXP
    typeset -a FILE FROM CTR

    # Check if FOR is available
    if [[ "$1" != +(* FOR *) ]]
    then
	echo -e "\nSyntax error: missing FOR in OPEN statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if AS is available
    if [[ "$1" != +(* AS *) ]]
    then
	echo -e "\nSyntax error: missing AS in OPEN statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    let CTR=0
    EXP=`echo "${1%% FOR *}"`

    # Start miniparser
    while [[ -n ${EXP} ]]
    do
        TOKEN=$(Mini_Parser "${EXP}")
	FILE[$CTR]="${TOKEN}"
        ((CTR+=1))
        EXP="${EXP:${#TOKEN}+1}"
    done
    ((CTR-=1))

    # Get the mode and handle
    TMP=$(echo ${1##* FOR })
    MODE=$(echo ${TMP%% AS *})
    HANDLE=$(echo ${TMP##* AS })

    let BND=0

    # Check for SOURCE address
    if [[ ${HANDLE} = +(*FROM*) ]]
    then
        EXP=$(echo ${HANDLE##* FROM })
        # Start miniparser, convert spaces
        while [[ -n ${EXP} ]]
        do
            TOKEN=$(Mini_Parser "${EXP}")
	    FROM[$BND]="${TOKEN}"
            ((BND+=1))
            EXP="${EXP:${#TOKEN}+1}"
        done
        HANDLE=$(echo ${HANDLE%% FROM *})
        ((BND-=1))
    fi

    # Check if var is string var
    if [[ "${HANDLE}" = +(*${g_STRINGSIGN}) && $MODE != "MEMORY" ]]
    then
	echo -e "\nSyntax error: variable for OPEN at line $g_COUNTER in file '$g_CURFILE' cannot be string!"
	exit 1
    fi

    # Check for OPEN/CLOSE pair
    g_SEMANTIC_OPENCLOSE="@'${HANDLE}' at line $g_COUNTER in file '$g_CURFILE' ${HANDLE}@${g_SEMANTIC_OPENCLOSE}"

    # Check if variable was declared
    if [[ "$HANDLE" != +(*.*) ]]
    then
        CHECK=$(Get_Var ${HANDLE} ${g_FUNCNAME})
    else
        CHECK="1"
    fi

    # File or dir?
    if [[ -z $CHECK ]]
    then
        if [[ $g_OPTION_EXPLICIT = "1" || $g_OPTION_EXPLICIT = "TRUE" ]]
        then
	    echo -e "\nSyntax error: OPTION EXPLICIT forces explicit variable declaration at line $g_COUNTER in file '$g_CURFILE'!"
            exit 1
        fi
    fi

    if [[ $MODE = "DIRECTORY" ]]
    then
	if [[ -z $CHECK ]]
	then
	    echo "DIR *$HANDLE;" >> $g_HFILE
            Save_Main_Var "${HANDLE}" "DIR*"
	fi
    elif [[ $MODE = "MEMORY" ]]
    then
        if [[ -z $(Get_Var ${HANDLE} ${g_FUNCNAME}) ]]
	then
	    echo "char *$HANDLE = NULL;" >> $g_HFILE
            Save_Main_Var "${HANDLE}" "char*"
	fi
        if [[ -z $(Get_Var __b2c_mem_$HANDLE ${g_FUNCNAME}) ]]
	then
	    echo "long __b2c_mem_$HANDLE;" >> $g_HFILE
            Save_Main_Var "__b2c_mem_${HANDLE}" "long"
	fi
    elif [[ $MODE = "NETWORK" || $MODE = "SERVER" || $MODE = "UDP" || $MODE = "DEVICE" ]]
    then
	if [[ -z $CHECK ]]
	then
	    echo "int $HANDLE;" >> $g_HFILE
            Save_Main_Var "${HANDLE}" "int"
	fi
    else
	if [[ -z $CHECK ]]
	then
	    echo "FILE* $HANDLE;" >> $g_HFILE
            Save_Main_Var "${HANDLE}" "FILE*"
	fi
    fi

    # Convert to C syntax
    case $MODE in
	@(READING) )
	    echo "$HANDLE = fopen((const char*)${FILE[0]}, \"r\");" >> $g_CFILE
	    echo "if($HANDLE == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR READING\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;;
	@(WRITING) )
	    echo "$HANDLE = fopen((const char*)${FILE[0]}, \"w\");" >> $g_CFILE
	    echo "if($HANDLE == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR WRITING\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;;
	@(APPENDING) )
	    echo "$HANDLE = fopen((const char*)${FILE[0]}, \"a\");" >> $g_CFILE
	    echo "if($HANDLE == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR APPENDING\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;;
	@(READWRITE) )
	    echo "$HANDLE = fopen((const char*)${FILE[0]}, \"r+\");" >> $g_CFILE
	    echo "if($HANDLE == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR READWRITE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;;
	@(DIRECTORY) )
	    echo "$HANDLE = opendir(${FILE[0]});" >> $g_CFILE
	    echo "if($HANDLE == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR DIRECTORY\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;;
	@(MEMORY) )
            if [[ "${HANDLE}" = +(*${g_STRINGSIGN}*) ]]
            then
	        echo "__b2c__STRFREE(${HANDLE});" >> $g_CFILE
            fi
	    echo "$HANDLE = (char*)${FILE[0]}; __b2c_mem_$HANDLE = ${FILE[0]};" >> $g_CFILE
	    echo "if(__b2c__trap){if(__b2c__memory__check($HANDLE, sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR MEMORY\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;;
        @(NETWORK) )
	    # Network code
            TMP=${CTR}

            # Setup the array of addresses
            echo "__b2c__addr = (struct sockaddr_in*)calloc(${CTR}+1, sizeof(*__b2c__addr));" >> $g_CFILE
            until [[ ${TMP} -lt 0 ]]
            do
	        echo "if (strstr(${FILE[$TMP]}, \":\") == NULL) {ERROR = 10; RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!__b2c__error_callback && !setjmp(__b2c__jump)) goto $g_CATCHGOTO;}" >> $g_CFILE
	        echo "strncpy(__b2c__data_client, ${FILE[${TMP}]}, ${g_BUFFER_SIZE}-1); __b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\"); __b2c__he = gethostbyname(__b2c__host);" >> $g_CFILE
	        echo "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(__b2c__trap){ERROR = 11;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                echo "__b2c__addr[$TMP].sin_family = AF_INET; __b2c__addr[$TMP].sin_port = htons((long)atol(__b2c__port));" >> $g_CFILE
	        echo "__b2c__addr[$TMP].sin_addr = *((struct in_addr *)__b2c__he->h_addr);" >> $g_CFILE
                ((TMP-=1))
	    done

            # Create the socket
            if [[ ${g_NETWORKTYPE} = "SCTP" ]]
            then
                echo "$HANDLE = socket(AF_INET, ${g_SOCKTYPE}, IPPROTO_SCTP);" >> $g_CFILE
            else
                echo "$HANDLE = socket(AF_INET, ${g_SOCKTYPE}, 0);" >> $g_CFILE
            fi
	    echo "if ($HANDLE == -1) {if(__b2c__trap){ERROR = 12;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE

            # Set socket options
	    echo "__b2c__to.tv_sec = $g_OPTION_SOCKET; __b2c__to.tv_usec = 0; setsockopt($HANDLE, SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" >> $g_CFILE
            if [[ ${g_NETWORKTYPE} = "BROADCAST" ]]
	    then
		echo "setsockopt($HANDLE, SOL_SOCKET, SO_BROADCAST, &__b2c__yes, sizeof(int));" >> $g_CFILE
	    elif [[ ${g_NETWORKTYPE} = "MULTICAST" ]]
	    then
		echo "setsockopt($HANDLE, IPPROTO_IP, IP_MULTICAST_LOOP, &__b2c__yes, sizeof(int));" >> $g_CFILE
		echo "__b2c__ttl=${g_MULTICAST_TTL}; setsockopt($HANDLE, IPPROTO_IP, IP_MULTICAST_TTL, &__b2c__ttl, sizeof(unsigned char));" >> $g_CFILE
            elif [[ ${g_NETWORKTYPE} = "SCTP" ]]
	    then
                echo "memset(&__b2c__initmsg, 0, sizeof(__b2c__initmsg)); __b2c__initmsg.sinit_max_attempts = 3;" >> $g_CFILE
                echo "__b2c__initmsg.sinit_num_ostreams = ${g_SCTP_STREAMS}; __b2c__initmsg.sinit_max_instreams = ${g_SCTP_STREAMS};" >> $g_CFILE
                echo "setsockopt(${HANDLE}, IPPROTO_SCTP, SCTP_INITMSG, &__b2c__initmsg, sizeof(__b2c__initmsg));" >> $g_CFILE
	    fi
	    echo "setsockopt($HANDLE, SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int));" >> $g_CFILE

            # Do we need to specify a source address?
            if [[ -n ${FROM[${BND}]} ]]
            then
                TMP=${BND}
                echo "__b2c__from = (struct sockaddr_in*)calloc(${BND}+1, sizeof(*__b2c__from));" >> $g_CFILE
                until [[ ${TMP} -lt 0 ]]
                do
                    echo "strncpy(__b2c__data_client, ${FROM[${TMP}]}, $g_BUFFER_SIZE); __b2c__assign = __b2c__host;" >> $g_CFILE
                    if [[ ${FROM[${TMP}]} = +(*:*) ]]
                    then
	                echo "__b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\");" >> $g_CFILE
                    else
	                echo "__b2c__host = __b2c__data_client;" >> $g_CFILE
                    fi
	            echo "__b2c__he = gethostbyname(__b2c__host);" >> $g_CFILE
	            echo "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(__b2c__trap){ERROR = 11;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                    echo "__b2c__from[$TMP].sin_family = AF_INET;" >> $g_CFILE
                    if [[ ${FROM[${TMP}]} = +(*:*) ]]
                    then
                        echo "__b2c__from[$TMP].sin_port = htons((long)atol(__b2c__port));" >> $g_CFILE
                    fi
	            echo "__b2c__from[$TMP].sin_addr = *((struct in_addr *)__b2c__he->h_addr);" >> $g_CFILE
                    echo "__b2c__host = __b2c__assign;" >> $g_CFILE
                    ((TMP-=1))
	        done

                # Set source address
                if [[ ${g_NETWORKTYPE} = "SCTP" ]]
                then
                    # Perform a one-one SCTP bind for multiple homes
                    echo "__b2c__result = sctp_bindx($HANDLE, (struct sockaddr *)__b2c__from, ${BND}+1, SCTP_BINDX_ADD_ADDR);" >> $g_CFILE
                else
                    # Perform a bind for TCP or UDP
                    echo "__b2c__result = bind($HANDLE, (struct sockaddr *)__b2c__from, sizeof(struct sockaddr));" >> $g_CFILE
                fi
	        echo "free(__b2c__from); if(__b2c__result == -1){if(__b2c__trap){ERROR = 17;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
            fi

            # Setup connection
            if [[ ${g_NETWORKTYPE} = "SCTP" ]]
            then
                # Create a one-one SCTP socket to multiple homes
                echo "#ifdef SCTP_SOCKOPT_CONNECTX_OLD" >> $g_CFILE
                echo " __b2c__result = sctp_connectx($HANDLE, (struct sockaddr *)__b2c__addr, ${CTR}+1, NULL);" >> $g_CFILE
                echo "#else" >> $g_CFILE
                echo " __b2c__result = sctp_connectx($HANDLE, (struct sockaddr *)__b2c__addr, ${CTR}+1);" >> $g_CFILE
                echo "#endif" >> $g_CFILE
            else
                # Create a socket for TCP or UDP
                echo "__b2c__result = connect($HANDLE, (struct sockaddr *)__b2c__addr, sizeof(struct sockaddr));" >> $g_CFILE
            fi
            echo "free(__b2c__addr); if(__b2c__result == -1) {if(__b2c__trap){ERROR = 13; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE

            # Prepare SSL socket if option was set
            if [[ ${g_OPTION_TLS} = +(1*|TRUE*) ]]
            then
                echo "if(${HANDLE} >= ${g_MAX_SSL_FDS}){ if(__b2c__trap){ERROR = 41; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                echo "else { SSL_library_init(); __b2c_ctx_ptr[${HANDLE}] = (void*)SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_verify((SSL_CTX*)__b2c_ctx_ptr[${HANDLE}], __b2c__capeer, NULL);" >> $g_CFILE
                if [[ ${g_LIB_TLS} = +(*-lssl*|*-lwolfssl*) ]]
                then
                    echo "SSL_CTX_load_verify_locations((SSL_CTX*)__b2c_ctx_ptr[${HANDLE}], __b2c__cacerts, NULL);" >> $g_CFILE
                fi
                echo "__b2c_ssl_ptr[${HANDLE}] = (void*)SSL_new(__b2c_ctx_ptr[${HANDLE}]); SSL_set_tlsext_host_name((SSL*)__b2c_ssl_ptr[${HANDLE}], __b2c__host);" >> $g_CFILE
                echo "if(SSL_set_fd((SSL*)__b2c_ssl_ptr[${HANDLE}], ${HANDLE}) == 0){if(__b2c__trap){ERROR = 40; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                echo "if((__b2c__ctr = SSL_connect((SSL*)__b2c_ssl_ptr[${HANDLE}]))<=0){if(__b2c__trap){ERROR = SSL_get_error(__b2c_ssl_ptr[${HANDLE}], __b2c__ctr); if(!__b2c__catch_set) { fprintf(stderr, \"SSL error: %d\n\", ERROR);" >> $g_CFILE
                echo "RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); } else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} } }" >> $g_CFILE
            fi;;

	@(SERVER) )
	    # Network code
            ADDRESS=`echo "${1%% FOR *}" | tr "," " " | tr "\"" " "`
            echo "if(strcmp(__b2c__data_server, \"${ADDRESS}\")) {strncpy(__b2c__data_server, \"${ADDRESS}\", $g_BUFFER_SIZE);" >> $g_CFILE

            # Setup the array of addresses
            TMP=${CTR}
            echo "__b2c__addr = (struct sockaddr_in*)calloc(${CTR}+1, sizeof(*__b2c__addr));" >> $g_CFILE
            until [[ ${TMP} -lt 0 ]]
            do
	        echo "if (strstr(${FILE[$TMP]}, \":\") == NULL) {ERROR = 10; RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!__b2c__error_callback && !setjmp(__b2c__jump)) goto $g_CATCHGOTO;}" >> $g_CFILE
	        echo "strncpy(__b2c__data_client, ${FILE[${TMP}]}, $g_BUFFER_SIZE); __b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\");" >> $g_CFILE
		echo "if (strstr(${FILE[$TMP]}, \"INADDR_ANY:\") || strstr(${FILE[$TMP]}, \"*:\")){__b2c__addr[$TMP].sin_addr.s_addr = htonl(INADDR_ANY);} else" >> $g_CFILE
		echo "{ __b2c__he = gethostbyname(__b2c__host); if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(__b2c__trap){ERROR = 11;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
		echo "__b2c__addr[$TMP].sin_addr = *((struct in_addr *)__b2c__he->h_addr);}" >> $g_CFILE
                echo "__b2c__addr[$TMP].sin_family = AF_INET; __b2c__addr[$TMP].sin_port = htons((long)atol(__b2c__port));" >> $g_CFILE
                ((TMP-=1))
	    done

            if [[ ${g_NETWORKTYPE} = "SCTP" ]]
            then
                echo "__b2c__handle = socket(AF_INET, ${g_SOCKTYPE}, IPPROTO_SCTP);" >> $g_CFILE
            else
                echo "__b2c__handle = socket(AF_INET, ${g_SOCKTYPE}, 0);" >> $g_CFILE
            fi
            echo "if (__b2c__handle == -1) {if(__b2c__trap){ERROR = 12;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE

            if [[ ${g_NETWORKTYPE} = "SCTP" ]]
	    then
                echo "memset(&__b2c__initmsg, 0, sizeof(__b2c__initmsg)); __b2c__initmsg.sinit_max_attempts = 3;" >> $g_CFILE
                echo "__b2c__initmsg.sinit_num_ostreams = ${g_SCTP_STREAMS}; __b2c__initmsg.sinit_max_instreams = ${g_SCTP_STREAMS};" >> $g_CFILE
                echo "setsockopt(${HANDLE}, IPPROTO_SCTP, SCTP_INITMSG, &__b2c__initmsg, sizeof(__b2c__initmsg));" >> $g_CFILE
	    fi

            echo "__b2c__to.tv_sec = $g_OPTION_SOCKET; __b2c__to.tv_usec = 0; setsockopt(__b2c__handle, SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" >> $g_CFILE
            echo "setsockopt(__b2c__handle, SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int));" >> $g_CFILE

            # Setup connection
            if [[ ${g_NETWORKTYPE} = "SCTP" ]]
            then
                # Perform a one-one SCTP bind for multiple homes
                echo "__b2c__result = sctp_bindx(__b2c__handle, (struct sockaddr *)__b2c__addr, ${CTR}+1, SCTP_BINDX_ADD_ADDR);" >> $g_CFILE
            else
                # Perform a bind for TCP or UDP
                echo "__b2c__result = bind(__b2c__handle, (struct sockaddr *)__b2c__addr, sizeof(struct sockaddr));" >> $g_CFILE
            fi
	    echo "free(__b2c__addr); if(__b2c__result == -1){if(__b2c__trap){ERROR = 17;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE

            if [[ ${g_NETWORKTYPE} = "MULTICAST" ]]
	    then
		echo "__b2c__imreq.imr_multiaddr.s_addr = inet_addr(__b2c__host); __b2c__imreq.imr_interface.s_addr = INADDR_ANY;" >> $g_CFILE
		echo "setsockopt(__b2c__handle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &__b2c__imreq, sizeof(__b2c__imreq));" >> $g_CFILE
	    fi
            if [[ ${g_NETWORKTYPE} = "UDP" || ${g_NETWORKTYPE} = "BROADCAST" || ${g_NETWORKTYPE} = "MULTICAST" ]]
            then
	        echo "$HANDLE = __b2c__handle; }" >> $g_CFILE
            else
	        echo "__b2c__result = listen(__b2c__handle, $g_MAX_BACKLOG);" >> $g_CFILE
	        echo "if(__b2c__result == -1){if(__b2c__trap){ERROR = 18;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} } }" >> $g_CFILE
	        echo "__b2c__result = accept(__b2c__handle, NULL, 0);" >> $g_CFILE
	        echo "if(__b2c__result == -1){if(__b2c__trap){ERROR = 19;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
	        echo "$HANDLE= __b2c__result;" >> $g_CFILE
            fi;;
	@(DEVICE) )
	    echo "$HANDLE = open(${FILE[0]}, __b2c__option_open, S_IRUSR|S_IWUSR);" >> $g_CFILE
	    echo "if($HANDLE < 0){if(__b2c__trap){ERROR = 32; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR DEVICE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;;
    esac
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi
}

#-----------------------------------------------------------

function Handle_Readln
{
    # Local variables
    typeset VAR FROM STR

    # Check if FROM is available
    if [[ "$1" != +(* FROM *) ]]
    then
	echo -e "\nSyntax error: missing FROM in READLN statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the variablename without surrounding spaces
    VAR=$(echo ${1%% FROM *})

    # Get filedescriptor
    FROM=$(echo ${1##* FROM })

    # Check if var is string var
    if [[ $(Check_String_Type ${VAR}) -eq 0 ]]
    then
	echo -e "\nSyntax error: variable for READLN at line $g_COUNTER in file '$g_CURFILE' must be string!"
	exit 1
    fi

    # Check if string variable, and if so, if declared
    if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]]
    then
        if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	then
            Register_String "${VAR}"
	fi
    fi

    # Translate function to C function
    echo "__b2c__counter = 1; __b2c__assign = (char*)calloc(1, sizeof(char)); do{ if(fgets(__b2c__input__buffer, $g_BUFFER_SIZE, $FROM) == NULL) break;" >> $g_CFILE

    # Make sure internal var is copied to var of program
    echo "__b2c__assign = (char*)realloc(__b2c__assign, $g_BUFFER_SIZE*__b2c__counter*sizeof(char));" >> $g_CFILE
    echo " strncat(__b2c__assign, __b2c__input__buffer, $g_BUFFER_SIZE); __b2c__counter++;" >> $g_CFILE
    echo "} while (!strstr(__b2c__input__buffer, \"\n\") && strlen(__b2c__input__buffer));" >> $g_CFILE
    # Cut off last newline
    echo "if(__b2c__assign != NULL) {__b2c__ctr = strlen(__b2c__assign); if(__b2c__ctr > 0 && __b2c__assign[__b2c__ctr-1] == 10) __b2c__assign[__b2c__ctr-1] = '\0';}" >> $g_CFILE

    # Now see if we have a assoc or a normal variable
    if [[ "${VAR}" = +(*\(*\)) ]]
    then
        STR=${VAR#*\(}
        echo "__b2c__${VAR%%\(*}_loc = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE
        echo "__b2c__STRFREE(__b2c__${VAR%%\(*}_loc->value); __b2c__${VAR%%\(*}_loc->value = __b2c__assign;" >> $g_CFILE
        # Check for relations
        Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1"
    else
        echo "__b2c__STRFREE($VAR); $VAR = __b2c__assign;" >> $g_CFILE
    fi
}

#-----------------------------------------------------------

function Handle_Writeln
{
    # Local variables
    typeset VAR TO EXP TOKEN ORG

    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in WRITELN statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get line to write to file
    EXP=$(echo "${1% TO *}")
    ORG="${EXP}"

    # Get filedescriptor
    TO=$(echo ${1##* TO })

    # Start miniparser to see if we need to print something
    while [[ -n ${EXP} ]]
    do
        TOKEN=$(Mini_Parser "${EXP}")
        Print_Element "${TOKEN}" "${TO}"
        EXP="${EXP:${#TOKEN}+1}"
    done

    # If line ends with ';' then skip newline
    if [[ -n $(echo ${ORG##*;}) ]]
    then
	echo "fputs(\"\n\", ${TO});" >> $g_CFILE
    fi

    echo "fflush($TO);" >> $g_CFILE
}

#-----------------------------------------------------------

function Handle_Getbyte
{
    # Local variables
    typeset POS FROM SIZE CHECK CHUNK

    # Check if FROM is available
    if [[ "$1" != +(* FROM *) ]]
    then
	echo -e "\nSyntax error: missing FROM in GETBYTE statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the variablename without surrounding spaces
    POS=$(echo ${1%% FROM *})

    # Get filedescriptor
    FROM=$(echo ${1##* FROM })

    # Check for optional chunksize
    if [[ $1 = +(* CHUNK *) ]]
    then
	CHUNK=${1##* CHUNK }
	FROM=${FROM%% CHUNK *}
    else
	CHUNK=
    fi

    # Check for optional return variable
    if [[ $1 = +(* SIZE *) ]]
    then
        FROM=${FROM%% SIZE *}
	SIZE=${1##* SIZE }
        if [[ -z $CHUNK ]]
        then
            CHUNK=$SIZE
	    SIZE="__b2c__counter"
        else
	    CHUNK=${CHUNK%% SIZE *}
        fi
    else
        if [[ -z $CHUNK ]]
        then
            CHUNK=1
        fi
	SIZE="__b2c__counter"
    fi

    # Variable may not be array, these should be defined with DECLARE
    if [[ -n $SIZE && "${SIZE}" != +(*\[*\]*) && "${SIZE}" != +(*.*) && "${SIZE}" != +(*\(*\)*) && "${SIZE}" != +(*-\>*) && "$SIZE" != "__b2c__counter" ]]
    then
	# Declare variable if not done yet, assuming long
        if [[ -z $(Get_Var ${SIZE} ${g_FUNCNAME}) ]]
	then
            Register_Numeric ${SIZE}
        fi
    fi

    # Type of file descriptor
    CHECK=$(Get_Var ${FROM} ${g_FUNCNAME})

    # Translate function to C function
    echo "if(__b2c__trap){if(__b2c__memory__check((char*)$POS, sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"GETBYTE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
    if [[ $CHECK = +(*int*) ]]
    then
        echo "if((${SIZE} = read($FROM, (void*)($POS), $CHUNK)) < 0)" >> $g_CFILE
        echo "{if(__b2c__trap){ERROR = 34; if(!__b2c__catch_set) RUNTIMEERROR(\"GETBYTE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
    else
        echo "${SIZE} = fread((void*)($POS), sizeof(__b2c__MEMTYPE), $CHUNK, $FROM);" >> $g_CFILE
    fi
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi
}

#-----------------------------------------------------------

function Handle_Putbyte
{
    # Local variables
    typeset VAR TO SIZE POS CHECK CHUNK

    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in PUTBYTE statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the variablename without surrounding spaces
    POS=$(echo ${1%% TO *})

    # Get filedescriptor
    TO=$(echo ${1##* TO })

    # Check for optional chunksize
    if [[ $1 = +(* CHUNK *) ]]
    then
	CHUNK=${1##* CHUNK }
	TO=${TO%% CHUNK *}
    else
	CHUNK=
    fi

    # Check for optional return variable
    if [[ $1 = +(* SIZE *) ]]
    then
        TO=${TO%% SIZE *}
	SIZE=${1##* SIZE }
        if [[ -z $CHUNK ]]
        then
            CHUNK=$SIZE
	    SIZE="__b2c__counter"
        else
	    CHUNK=${CHUNK%% SIZE *}
        fi
    else
        if [[ -z $CHUNK ]]
        then
            CHUNK=1
        fi
	SIZE="__b2c__counter"
    fi

    # Variable may not be array, these should be defined with DECLARE
    if [[ -n $SIZE && "${SIZE}" != +(*\[*\]*) && "${SIZE}" != +(*.*) && "${SIZE}" != +(*\(*\)*) && "${SIZE}" != +(*-\>*) && "$SIZE" != "__b2c__counter" ]]
    then
	# Declare variable if not done yet, assuming long
	if [[ -z $(Get_Var ${SIZE} ${g_FUNCNAME}) ]]
	then
            Register_Numeric ${SIZE}
	fi
    fi

    # Type of file descriptor
    CHECK=$(Get_Var ${TO} ${g_FUNCNAME})

    # Translate function to C function
    echo "if(__b2c__trap){if(__b2c__memory__check((char*)$POS, sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"PUTBYTE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
    if [[ $CHECK = +(*int*) ]]
    then
        echo "if(($SIZE = write(${TO}, (void*)($POS), $CHUNK)) < 0)" >> $g_CFILE
        echo "{if(__b2c__trap){ERROR = 34; if(!__b2c__catch_set) RUNTIMEERROR(\"PUTBYTE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
    else
        echo "$SIZE = fwrite((void*)($POS), sizeof(__b2c__MEMTYPE), $CHUNK, $TO); fflush($TO);" >> $g_CFILE
    fi
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi
}

#-----------------------------------------------------------

function Handle_Getfile
{
    # Local variables
    typeset VAR FROM SIZE STR

    # Check if FROM is available
    if [[ "$1" != +(* FROM *) ]]
    then
	echo -e "\nSyntax error: missing FROM in GETFILE statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the variablename without surrounding spaces
    VAR=$(echo ${1%% FROM *})

    # Get dirdescriptor
    FROM=$(echo ${1##* FROM })

    # Check if var is string var
    if [[ $(Check_String_Type ${VAR}) -eq 0 ]]
    then
	echo -e "\nSyntax error: variable for GETFILE at line $g_COUNTER in file '$g_CURFILE' must be string!"
	exit 1
    fi

    # Check if string is declared
    if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]]
    then
        if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	then
            Register_String "${VAR}"
	fi
    fi

    # Translate function to C function
    echo "__b2c__dir = readdir($FROM);" >> $g_CFILE

    # Make sure internal var is copied to var of program
    echo "if(__b2c__dir != NULL) __b2c__assign = __b2c__strdup(__b2c__dir->d_name);" >> $g_CFILE
    echo "else __b2c__assign = (char*)calloc(1, sizeof(char));" >> $g_CFILE
    # Now see if we have an assoc or a normal variable
    if [[ "${VAR}" = +(*\(*\)) ]]
    then
	STR=${VAR#*\(}
	echo "__b2c__${VAR%%\(*}_loc = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE
	echo "__b2c__STRFREE(__b2c__${VAR%%\(*}_loc->value); __b2c__${VAR%%\(*}_loc->value = __b2c__assign;" >> $g_CFILE
	# Check for relations
	Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1"
    else
	echo "__b2c__STRFREE($VAR); $VAR = __b2c__assign;" >> $g_CFILE
    fi
}

#-----------------------------------------------------------

function Handle_Receive
{
    # Local variables
    typeset VAR FROM STR CHUNK SIZE

    # Check if FROM is available
    if [[ "$1" != +(* FROM *) ]]
    then
	echo -e "\nSyntax error: missing FROM in RECEIVE statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the variablename without surrounding spaces
    VAR=$(echo ${1%% FROM *})

    # Get filedescriptor
    FROM=$(echo ${1##* FROM })

   # Check for optional chunksize
    if [[ $1 = +(* CHUNK *) ]]
    then
	CHUNK=${1##* CHUNK }
	FROM=${FROM%% CHUNK *}
    else
        if [[ ${g_OPTION_TLS} = +(1*|TRUE*) ]]
        then
	    CHUNK=32768
        else
	    CHUNK=$g_BUFFER_SIZE
        fi
    fi

    # Check for optional return variable
    if [[ $1 = +(* SIZE *) ]]
    then
        FROM=${FROM%% SIZE *}
	SIZE=${1##* SIZE }
	CHUNK=${CHUNK%% SIZE *}
    else
	SIZE=
    fi

    # Variable may not be array, these should be defined with DECLARE
    if [[ -n $SIZE && "${SIZE}" != +(*\[*\]*) && "${SIZE}" != +(*.*) && "${SIZE}" != +(*\(*\)*) && "${SIZE}" != +(*-\>*) ]]
    then
	# Declare variable if not done yet, assuming long
	if [[ -z $(Get_Var ${SIZE} ${g_FUNCNAME}) ]]
	then
            Register_Numeric ${SIZE}
	fi
    else
        if [[ -z $SIZE ]]
        then
	    SIZE="__b2c__counter"
        fi
    fi

    # Check if string variable, and if so, if declared
    if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]]
    then
	if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	then
            Register_String "${VAR}"
	fi
    fi

    # Translate function to C function
    echo "__b2c__assign = (char*)calloc(($CHUNK+1), sizeof(char));" >> $g_CFILE
    if [[ ${g_NETWORKTYPE} = "SCTP" ]]
    then
	echo "if(($SIZE = sctp_recvmsg($FROM, (void*)__b2c__assign, $CHUNK, 0, 0, 0, 0)) < 0)" >> $g_CFILE
    else
        # Receive from SSL socket if option was set
        if [[ ${g_OPTION_TLS} = +(1*|TRUE*) ]]
        then
            echo "if(($SIZE = SSL_read((SSL*)__b2c_ssl_ptr[${FROM}], (void*)__b2c__assign, $CHUNK)) <= 0)" >> $g_CFILE
        else
	    echo "if(($SIZE = recv($FROM, (void*)__b2c__assign, $CHUNK, 0)) < 0)" >> $g_CFILE
        fi
    fi
    echo "{if(__b2c__trap){ERROR = 14;if(!__b2c__catch_set) RUNTIMEERROR(\"RECEIVE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE

    # Now see if we have an assoc or a normal variable
    if [[ "${VAR}" = +(*\(*\)) ]]
    then
	STR=${VAR#*\(}
	echo "__b2c__${VAR%%\(*}_loc = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE
	echo "__b2c__STRFREE(__b2c__${VAR%%\(*}_loc->value); __b2c__${VAR%%\(*}_loc->value = __b2c__assign;" >> $g_CFILE
	# Check for relations
	Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1"
    elif [[ "${VAR}" = +(*${g_STRINGSIGN}) || "${VAR%%\[*}" = +(*${g_STRINGSIGN}) ]]
    then
	echo "__b2c__STRFREE($VAR); $VAR = __b2c__assign;" >> $g_CFILE
    else
        echo "memcpy((void*)(${VAR}), (void*)__b2c__assign, ${SIZE}); free(__b2c__assign);" >> $g_CFILE
    fi
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi
}

#-----------------------------------------------------------

function Handle_Send
{
    # Local variables
    typeset VAR TO CHUNK SIZE

    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in SEND statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the variablename without surrounding spaces
    VAR=$(echo ${1%% TO *})

    # Get filedescriptor
    TO=$(echo ${1##* TO })

   # Check for optional chunksize
    if [[ $1 = +(* CHUNK *) ]]
    then
	CHUNK=${1##* CHUNK }
	TO=${TO%% CHUNK *}
    else
	CHUNK="strlen($VAR)"
    fi

    # Check for optional return variable
    if [[ $1 = +(* SIZE *) ]]
    then
        TO=${TO%% SIZE *}
	SIZE=${1##* SIZE }
        if [[ $CHUNK = +(* SIZE *) ]]
        then
	    CHUNK=${CHUNK%% SIZE *}
        fi
    else
	SIZE=
    fi

    # Variable may not be array, these should be defined with DECLARE
    if [[ -n $SIZE && "${SIZE}" != +(*\[*\]*) && "${SIZE}" != +(*.*) && "${SIZE}" != +(*\(*\)*) && "${SIZE}" != +(*-\>*) ]]
    then
	# Declare variable if not done yet, assuming long
	if [[ -z $(Get_Var ${SIZE} ${g_FUNCNAME}) ]]
	then
            Register_Numeric ${SIZE}
	fi
    else
        if [[ -z $SIZE ]]
        then
	    SIZE="__b2c__counter"
        fi
    fi

    # Translate function to C function
    if [[ ${g_NETWORKTYPE} = "SCTP" ]]
    then
        echo "if(($SIZE = sctp_sendmsg($TO, (void*)($VAR), $CHUNK, NULL, 0, 0, 0, 0, 0, 0)) < 0)" >> $g_CFILE
    else
        # Send to SSL socket if option was set
        if [[ ${g_OPTION_TLS} = +(1*|TRUE*) ]]
        then
            echo "if(($SIZE = SSL_write((SSL*)__b2c_ssl_ptr[${TO}], (const void*)($VAR), $CHUNK)) < 0)" >> $g_CFILE
        else
            echo "if(($SIZE = send($TO, (void*)($VAR), $CHUNK, 0)) < 0)" >> $g_CFILE
        fi
    fi
    echo "{if(__b2c__trap){ERROR = 15; if(!__b2c__catch_set) RUNTIMEERROR(\"SEND\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi
}

#-----------------------------------------------------------

function Handle_Getline
{
    # Local variables
    typeset VAR FROM STR

    # Check if FROM is available
    if [[ "$1" != +(* FROM *) ]]
    then
	echo -e "\nSyntax error: missing FROM in GETLINE statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the variablename without surrounding spaces
    VAR=$(echo ${1%% FROM *})

    # Get filedescriptor
    FROM=$(echo ${1##* FROM })

    # Check if var is string var
    if [[ $(Check_String_Type ${VAR}) -eq 0 ]]
    then
	echo -e "\nSyntax error: variable for GETLINE at line $g_COUNTER in file '$g_CURFILE' must be string!"
	exit 1
    fi

    # Check if string variable, and if so, if declared
    if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]]
    then
	if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	then
            Register_String "${VAR}"
	fi
    fi

    # Translate function to C function
    echo "if ($FROM == NULL || *$FROM == '\0') {__b2c__assign = (char*)calloc(1, sizeof(char));} else { __b2c__assign = $FROM; while(*$FROM != '\0' && *$FROM != '\n') { $FROM++; }" >> $g_CFILE

    # Make sure internal var is copied to var of program
    echo "__b2c__assign = __b2c__strndup(__b2c__assign, (size_t)($FROM-__b2c__assign+1)); __b2c__assign[strlen(__b2c__assign)-1]='\0'; if(*$FROM == '\n') $FROM++;}" >> $g_CFILE

    # Now see if we have an assoc or a normal variable
    if [[ "${VAR}" = +(*\(*\)) ]]
    then
	STR=${VAR#*\(}
	echo "__b2c__${VAR%%\(*}_loc = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE
	echo "__b2c__STRFREE(__b2c__${VAR%%\(*}_loc->value); __b2c__${VAR%%\(*}_loc->value = __b2c__assign;" >> $g_CFILE
	# Check for relations
	Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1"
    else
	echo "__b2c__STRFREE($VAR); $VAR = __b2c__assign;" >> $g_CFILE
    fi
}

#-----------------------------------------------------------

function Handle_Putline
{
    # Local variables
    typeset VAR TO EXP TOKEN

    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in PUTLINE statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get text to add
    EXP=$(echo ${1% TO *})

    # Get memorydescriptor
    TO=$(echo ${1##* TO })

    # Start miniparser to see if we need to print something
    while [[ -n ${EXP} ]]
    do
        TOKEN=$(Mini_Parser "${EXP}")
	# Check if var is string var
	if [[ $(Check_String_Type ${TOKEN}) -eq 1 ]]
	then
	    echo "strcat($TO, $TOKEN); $TO+=strlen($TOKEN);" >> $g_CFILE
	else
	    echo "strcat($TO, STR${g_STRINGSIGN}($TOKEN)); $TO+=strlen(STR${g_STRINGSIGN}($TOKEN));" >> $g_CFILE
	fi
        EXP="${EXP:${#TOKEN}+1}"
    done

    echo "strcat($TO, \"\n\"); $TO+=1;" >> $g_CFILE
}

#-----------------------------------------------------------

function Handle_Import
{
    # Local variables
    typeset TMP SYM LIB CHECK TOKEN PTR TYPE ALIAS TYPE

    # Check if FROM is available
    if [[ "$1" != +(* FROM *) ]]
    then
	echo -e "\nSyntax error: missing FROM in IMPORT statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the symbolname without surrounding spaces
    if [[ "$1" = +(*\(*) ]]
    then
	SYM="`echo ${1%%\(*}`"; TMP=${1#* FROM }
	TOKEN=$(echo ${1%\)*})
    else
	SYM=`echo ${1%% FROM *}`; TMP=${1#* FROM }
	TOKEN=
    fi

    # Make sure we have a symbol surrounded correctly with double quotes
    SYM="\"${SYM//\"/}\""

    # Check if TYPE is available
    if [[ "$1" != +(* TYPE *) ]]
    then
	echo -e "\nSyntax error: missing TYPE in IMPORT statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get library and type
    LIB=$(echo ${TMP%% TYPE *})
    TYPE=$(echo ${TMP##* TYPE })

    # Check if ALIAS is there
    if [[ $TYPE = +(* ALIAS *) ]]
    then
	ALIAS=`echo ${TYPE##* ALIAS } | tr -d "\042"`
	g_IMPORTED="$ALIAS $g_IMPORTED"
	TYPE=${TYPE%% ALIAS *}
    fi

    # If library is libm or libc, skip dlopen as we're linking with those anyway
    if [[ $LIB != +(*libc.so*) && $LIB != +(*libm.so*) ]]
    then
        # Link flags
        if [[ `uname` != "OSF1" && `uname` != +(*BSD*) && ${g_LDFLAGS} != +(*ldl*) ]]
        then
            g_LDFLAGS="${g_LDFLAGS} -ldl"
        fi

	# Create name from libname
        PTR="${LIB//[[:punct:]]/}"

	# Check if variable was declared
	if [[ -z $(Get_Var __b2c__dlopen__pointer_$PTR) ]]
	then
	    echo "void* __b2c__dlopen__pointer_$PTR = NULL;" >> $g_HFILE
            Save_Main_Var "__b2c__dlopen__pointer_${PTR}" "void*"
	fi
	echo "if(__b2c__dlopen__pointer_$PTR == NULL){__b2c__dlopen__pointer_$PTR = dlopen($LIB, RTLD_LAZY); if(__b2c__dlopen__pointer_$PTR == NULL) {" >> $g_CFILE
	echo "if(__b2c__trap){ERROR = 3; if(!__b2c__catch_set) RUNTIMEERROR(\"IMPORT\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} } }" >> $g_CFILE

        # Create prototype
        if [[ $LIB != "NULL" ]]
        then
	    echo "$TYPE (*${SYM//\"/})(${TOKEN#*\(});" >> $g_HFILE
	    echo "*(${TYPE}**) (&${SYM//\"/}) = (${TYPE}*)dlsym(__b2c__dlopen__pointer_$PTR, $SYM);" >> $g_CFILE
	    echo "if($SYM == NULL) {if(__b2c__trap){ERROR = 4; if(!__b2c__catch_set) RUNTIMEERROR(\"IMPORT\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
        else
	    echo "$TYPE (*$ALIAS)(${TOKEN#*\(});" >> $g_HFILE
	    echo "*(${TYPE}**) (&$ALIAS) = (${TYPE}*)dlsym(__b2c__dlopen__pointer_$PTR, $SYM);" >> $g_CFILE
	    echo "if($ALIAS == NULL) {if(__b2c__trap){ERROR = 4; if(!__b2c__catch_set) RUNTIMEERROR(\"IMPORT\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
        fi

    fi

    # Make symbol known to parser
    if [[ $LIB != "NULL" ]]
    then
	if [[ -n $g_IMPORTED && ${g_IMPORTED} = +(* ${SYM//\"/} *) ]]
	then
            if [[ $g_SEMANTIC -eq 0 ]]
            then
	        echo -e "\nWarning: duplicate symbol '${SYM//\"/}' at line $g_COUNTER in file '$g_CURFILE'!"
            fi
	else
	    g_IMPORTED=" ${SYM//\"/} $g_IMPORTED"
	fi
	if [[ -n $ALIAS ]]
	then
	    echo "#define $ALIAS ${SYM//\"/}" >> $g_HFILE
	fi
    fi

    # Announce runtime error usage
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi
}

#-----------------------------------------------------------
# $1 = TYPE - $2 = VAR - $3 = ARRAY - $4 = static - $5 = is_local

function Normal_Dyn_Array
{
    typeset i j TYPE NR OLD TMP_ARR IDX END ORG_TYPE AM

    for i in $2
    do
        TYPE="$1"
        g_DYNAMICARRAYS="${g_DYNAMICARRAYS} $i@${g_FUNCNAME}"

	# Initialize strings
	if [[ "${TYPE}" = +(*STRING*|*char\*) || "${i}" = +(*${g_STRINGSIGN}*) ]]
	then
            if [[ ${3%%\(*} = +(*,*) ]]
            then
	        echo -e "\nSyntax error: string array cannot have more than one dimension line $g_COUNTER in file '$g_CURFILE'!"
	        exit 1
            fi
            if [[ $5 -eq 1 ]]
            then
                echo "$TYPE* $i;" >> $g_CFILE
                Save_Func_Var "${i}" "${g_FUNCNAME}" "${TYPE}"
                g_STRINGARGS="$g_STRINGARGS long __b2c_array_$i;"
                if [[ $4 -eq 0 ]]
                then
                    g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<__b2c_array_$i; __b2c__ctr++) { __b2c__STRFREE($i[__b2c__ctr+$g_OPTION_BASE]); }"
		    g_LOCALSTRINGS="$g_LOCALSTRINGS ${i}"
                fi
            else
                echo "$TYPE* $i;" >> $g_HFILE
                Save_Main_Var "${i}" "${TYPE}"
	        echo "long __b2c_array_$i;" >> $g_HFILE
            fi
	    echo "$i = (${TYPE}*)calloc(${3}+$g_OPTION_BASE, sizeof(${TYPE}));" >> $g_CFILE
            echo "__b2c_array_$i = ${3};" >> $g_CFILE
	    echo "for(__b2c__ctr=0; __b2c__ctr < $3+$g_OPTION_BASE; __b2c__ctr++) $i[__b2c__ctr] = (char*)calloc(1, sizeof(char));" >> $g_CFILE
        else
            ORG_TYPE="${TYPE}"
            # Count elements
            NR=0
            for j in $3                
            do
                ((NR+=1))
                TYPE="${TYPE}*"
            done

            # Declare top most dimension
            if [[ $5 -eq 1 ]]
            then
                echo "$TYPE $i;" >> $g_CFILE
                Save_Func_Var "${i}" "${g_FUNCNAME}" "${ORG_TYPE}"
                g_STRINGARGS="$g_STRINGARGS long __b2c_array_$i;"
                if [[ $4 -eq 0 ]]
                then
		    g_LOCALSTRINGS="$g_LOCALSTRINGS ${i}"
                else
                    AM=`echo ${TYPE} | tr -d -c "\*" | wc -c`
                    g_STATICARRAYS="$g_STATICARRAYS ${i}:${AM}"
                fi
            else
                echo "$TYPE $i;" >> $g_HFILE
                Save_Main_Var "${i}" "${ORG_TYPE}"
	        echo "long __b2c_array_$i;" >> $g_HFILE
            fi
            echo "$i = (${TYPE})calloc((size_t)${3%% *}+$g_OPTION_BASE, sizeof(${TYPE%\**}));" >> $g_CFILE

            # Proceed with other dimensions in array
            if [[ $NR -gt 1 ]]
            then
                OLD=${3%% *}
                TMP_ARR=${3#* }
                NR=0
                IDX="$i"
                END=

                # Construct array initialization
                for j in $TMP_ARR
                do
                    ((NR+=1))
                    if [[ $5 -eq 1 ]]
                    then
                        g_STRINGARGS="$g_STRINGARGS int __b2c_${i}${NR};"
                    else
                        echo "int __b2c_${i}${NR};" >> $g_HFILE
                    fi
                    IDX="$IDX[__b2c_${i}${NR}]"
                    echo "for(__b2c_${i}${NR} = 0; __b2c_${i}${NR} < $OLD+$g_OPTION_BASE; __b2c_${i}${NR}++){" >> $g_CFILE
                    TYPE="${TYPE%\**}"
                    echo "${IDX} = (${TYPE})calloc((size_t)${j}+$g_OPTION_BASE, sizeof(${TYPE%\**}));" >> $g_CFILE
                    END="$END }"
                    OLD="$j"
                done
                echo ${END} >> $g_CFILE
                TYPE="${TYPE%\**}"

                # De-initialize array members in case of FUNCTION
                if [[ $5 -eq 1 && $NR -gt 0 ]]
                then
                    NR=1
                    END=
                    for j in ${3% *}
                    do
                        if [[ $4 -eq 0 ]]
                        then
                            g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c_${i}${NR} = 0; __b2c_${i}${NR} < $j+$g_OPTION_BASE; __b2c_${i}${NR}++){"
                            END="${END} __b2c__STRFREE(${IDX}); }"
                            IDX="${IDX%\[*}"
                            ((NR+=1))
                        fi
                    done
                    if [[ $4 -eq 0 ]]
                    then
                        g_STRINGARRAYS="$g_STRINGARRAYS $END"
                    fi
                fi
            fi
        fi
    done
}

#-----------------------------------------------------------
# $1 = TYPE - $2 = VAR - $3 = ARRAY - $4 = static

function Record_Dyn_Array
{
    typeset i j TYPE NR OLD TMP_ARR IDX END ORG_TYPE AM

    if [[ -n ${g_RECORDARRAY} ]]
    then
	echo -e "\nSyntax error: dynamic array cannot be declared within a dynamic RECORD array at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    for i in $2
    do
        TYPE="$1"
        g_DYNAMICARRAYS="${g_DYNAMICARRAYS} $i@${g_FUNCNAME}"

	# Initialize strings
	if [[ "${TYPE}" = +(*STRING*|*char\*) || "${i}" = +(*${g_STRINGSIGN}*) ]]
	then
            if [[ ${3%%\(*} = +(*,*) ]]
            then
	        echo -e "\nSyntax error: string array cannot have more than one dimension line $g_COUNTER in file '$g_CURFILE'!"
	        exit 1
            fi
	    g_RECORDEND_BODY="${g_RECORDEND_BODY} $g_RECORDVAR.$i = (${TYPE}*)calloc(${3}+$g_OPTION_BASE, sizeof(${TYPE}));"
            if [[ -n $g_FUNCNAME ]]
            then
                echo "$TYPE* $i;" >> $g_CFILE
                Save_Func_Var "${i}" "${g_FUNCNAME}" "${TYPE}"
		g_RECORDEND_BODY="${g_RECORDEND_BODY} long __b2c_array_$i; __b2c_array_$i = ${3}; for(__b2c__ctr=0; __b2c__ctr<${3}+$g_OPTION_BASE; __b2c__ctr++) $g_RECORDVAR.$i[__b2c__ctr] = (char*)calloc(1, sizeof(char));"
                if [[ $4 -eq 0 ]]
                then
		    g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<__b2c_array_$i; __b2c__ctr++) { __b2c__STRFREE($g_RECORDVAR.$i[__b2c__ctr+$g_OPTION_BASE]); }"
		    g_LOCALSTRINGS="$g_LOCALSTRINGS $g_RECORDVAR.${i}"
                fi
            else
                echo "$TYPE* $i;" >> $g_HFILE
                Save_Main_Var "${i}" "${TYPE}"
                g_RECORDEND_HEADER="${g_RECORDEND_HEADER} long __b2c_array_$i;"
		g_RECORDEND_BODY="${g_RECORDEND_BODY} __b2c_array_$i = $3; for(__b2c__ctr=0; __b2c__ctr<$3+$g_OPTION_BASE; __b2c__ctr++) $g_RECORDVAR.$i[__b2c__ctr] = (char*)calloc(1, sizeof(char));"
            fi
        else
            ORG_TYPE="${TYPE}"
            # Count elements
            NR=0
            for j in $3                
            do
                ((NR+=1))
                TYPE="${TYPE}*"
            done

            # Declare top most dimension
            if [[ -n $g_FUNCNAME ]]
            then
                echo "$TYPE $i;" >> $g_CFILE
                Save_Func_Var "${i}" "${g_FUNCNAME}" "${ORG_TYPE}"
		g_RECORDEND_BODY="${g_RECORDEND_BODY} long __b2c_array_$i;"
                if [[ $4 -eq 0 ]]
                then
		    g_LOCALSTRINGS="$g_LOCALSTRINGS $g_RECORDVAR.${i}"
                else
                    AM=`echo ${TYPE} | tr -d -c "\*" | wc -c`
                    g_STATICARRAYS="$g_STATICARRAYS ${i}:${AM}"
                fi
            else
                echo "$TYPE $i;" >> $g_HFILE
                Save_Main_Var "${i}" "${ORG_TYPE}"
                g_RECORDEND_HEADER="${g_RECORDEND_HEADER} long __b2c_array_$i;"
            fi
	    g_RECORDEND_BODY="${g_RECORDEND_BODY} $g_RECORDVAR.$i = (${TYPE})calloc((size_t)${3%% *}+$g_OPTION_BASE, sizeof(${TYPE%\**}));"

            # Proceed with other dimensions in array
            if [[ $NR -gt 1 ]]
            then
                OLD=${3%% *}
                TMP_ARR=${3#* }
                NR=0
                IDX="$g_RECORDVAR.$i"
                END=

                # Construct array initialization
                for j in $TMP_ARR
                do
                    ((NR+=1))
                    if [[ -n $g_FUNCNAME ]]
                    then
                        g_STRINGARGS="${g_STRINGARGS} int __b2c_${i}${NR};"
                    else
                        g_RECORDEND_HEADER="${g_RECORDEND_HEADER} int __b2c_${i}${NR};"
                    fi
                    IDX="$IDX[__b2c_${i}${NR}]"
                    g_RECORDEND_BODY="${g_RECORDEND_BODY} for(__b2c_${i}${NR} = 0; __b2c_${i}${NR} < $OLD+$g_OPTION_BASE; __b2c_${i}${NR}++){"
                    TYPE="${TYPE%\**}"
                    g_RECORDEND_BODY="${g_RECORDEND_BODY} ${IDX} = (${TYPE})calloc((size_t)${j}+$g_OPTION_BASE, sizeof(${TYPE%\**}));"
                    END="$END }"
                    OLD="$j"
                done
                g_RECORDEND_BODY="${g_RECORDEND_BODY} ${END}"
                TYPE="${TYPE%\**}"

                # De-initialize array members in case of FUNCTION
                if [[ -n $g_FUNCNAME && $NR -gt 0 ]]
                then
                    NR=1
                    END=
                    for j in ${3% *}
                    do
                        if [[ $4 -eq 0 ]]
                        then
                            g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c_${i}${NR} = 0; __b2c_${i}${NR} < $j+$g_OPTION_BASE; __b2c_${i}${NR}++){"
                            END="${END} __b2c__STRFREE(${IDX}); }"
                            IDX="${IDX%\[*}"
                            ((NR+=1))
                        fi
                    done
                    if [[ $4 -eq 0 ]]
                    then
                        g_STRINGARRAYS="$g_STRINGARRAYS $END"
                    fi
                fi
            fi
        fi
    done
}

#-----------------------------------------------------------

function Assoc_Array
{
    typeset F

    if [[ $3 -eq 1 ]]
    then
        F="${g_FUNCNAME}"
    fi

    for i in ${1//,/ }
    do
	if [[ -z $(Get_Var __b2c__${i}_type_${F}) ]]
	then
            # Check if name not already global
            if [[ -n ${F} && -n $(Get_Var ${i}) ]]
            then
	        echo -e "\nSyntax error: associative array '${i}' in LOCAL statement at line $g_COUNTER in file '$g_CURFILE' was defined previously!"
                exit 1
            fi

	    echo "typedef struct __b2c__${i}_type_${F} {char *key; ${2} value;} __b2c__${i}_type_${F};" >> $g_HFILE
            echo "__b2c__hashtable_t __b2c__${i}_table_${F};" >> $g_HFILE
            echo "__b2c__${i}_type_${F} *__b2c__${i}_location_${F} = { NULL }; HASHTABLE_U64 *__b2c__${i}_temp_${F};" >> $g_HFILE
            Save_Main_Var "__b2c__${i}_type_${F}" "__b2c__${i}_type_${F}"

            echo "int __b2c_${F}_${i}_sort(const void *m1, const void *m2){" >> $g_HFILE
	    echo "struct __b2c__${i}_type_${F} *mi1 = (struct __b2c__${i}_type_${F} *) m1;" >> $g_HFILE
	    echo "struct __b2c__${i}_type_${F} *mi2 = (struct __b2c__${i}_type_${F} *) m2;" >> $g_HFILE
            if [[ ${i} = +(*${g_STRINGSIGN}*) || ${2} = +(*STRING*) || ${2} = +(*char\**) ]]
	    then
		echo "if(mi1->value == NULL && mi2->value == NULL) return 0;" >> $g_HFILE
		echo "if(mi1->value == NULL && mi2->value != NULL) return 1;" >> $g_HFILE
		echo "if(mi1->value != NULL && mi2->value == NULL) return -1;" >> $g_HFILE
		echo "return strcmp(mi1->value, mi2->value); }" >> $g_HFILE
	    else
		echo "if(mi1->value == mi2->value) return 0;" >> $g_HFILE
		echo "else {if(mi1->value < mi2->value) return -1;" >> $g_HFILE
		echo "else return 1; } }" >> $g_HFILE
            fi

            echo "int __b2c_${F}_${i}_sort_down(const void *m1, const void *m2){" >> $g_HFILE
	    echo "struct __b2c__${i}_type_${F} *mi1 = (struct __b2c__${i}_type_${F} *) m1;" >> $g_HFILE
	    echo "struct __b2c__${i}_type_${F} *mi2 = (struct __b2c__${i}_type_${F} *) m2;" >> $g_HFILE
            if [[ ${i} = +(*${g_STRINGSIGN}*) || ${2} = +(*STRING*) || ${2} = +(*char\**) ]]
	    then
		echo "if(mi1->value == NULL && mi2->value == NULL) return 0;" >> $g_HFILE
		echo "if(mi1->value == NULL && mi2->value != NULL) return -1;" >> $g_HFILE
		echo "if(mi1->value != NULL && mi2->value == NULL) return 1;" >> $g_HFILE
		echo "return strcmp(mi2->value, mi1->value); }" >> $g_HFILE
	    else
		echo "if(mi1->value == mi2->value) return 0;" >> $g_HFILE
		echo "else {if(mi1->value < mi2->value) return 1;" >> $g_HFILE
		echo "else return -1; } }" >> $g_HFILE
            fi

	    echo "struct __b2c__${i}_type_${F} *__b2c__${i}__add_secure_${F}(int action, char *idx, ...){__b2c__${i}_type_${F} *result = NULL, *tmp; char *key = NULL, *nxt; va_list ap;" >> $g_HFILE
            echo "va_start (ap, idx); while((nxt = va_arg (ap, char *)) != NULL){if(key == NULL) { key = __b2c__strdup (idx); }" >> $g_HFILE
            echo "key = (char*)realloc(key, (strlen(key)+strlen(nxt)+2)*sizeof(char)); strcat(key, \" \"); strcat(key, nxt); } va_end (ap);" >> $g_HFILE
            echo "result = (__b2c__${i}_type_${F}*)__b2c__hashtable_find(&__b2c__${i}_table_${F}, (HASHTABLE_U64)(uintptr_t)( (key == NULL ? idx : key) ));" >> $g_HFILE
            echo "if(result == NULL && action == 1){tmp = (__b2c__${i}_type_${F} *)calloc(1,sizeof (__b2c__${i}_type_${F}));" >> $g_HFILE
	    echo "result = (__b2c__${i}_type_${F}*)__b2c__hashtable_insert(&__b2c__${i}_table_${F}, (HASHTABLE_U64)(uintptr_t)(key == NULL ? __b2c__strdup(idx) : __b2c__strdup(key)), &tmp); result->key = (key == NULL ? __b2c__strdup(idx) : key); result->value = 0; free(tmp);}" >> $g_HFILE
            echo "else {if(key) free(key); } return(result);}" >> $g_HFILE

	    echo "void __b2c__${i}__delete_${F}(char *idx, ...){__b2c__${i}_type_${F} *result = NULL; char *key = NULL, *nxt; va_list ap; key = __b2c__strdup (idx);" >> $g_HFILE
            echo "va_start (ap, idx); while((nxt = va_arg (ap, char *)) != NULL){" >> $g_HFILE
            echo "key = (char*)realloc(key, (strlen(key)+strlen(nxt)+2)*sizeof(char)); strcat(key, \" \"); strcat(key, nxt); } va_end (ap);" >> $g_HFILE
	    echo "result = (__b2c__${i}_type_${F}*)__b2c__hashtable_find(&__b2c__${i}_table_${F}, (HASHTABLE_U64)(uintptr_t)(key)); if(result != NULL) {" >> $g_HFILE
	    if [[ ${i} = +(*${g_STRINGSIGN}*) || ${2} = +(*STRING*) || ${2} = +(*char\**) ]]
	    then
		echo "__b2c__STRFREE(result->value);" >> $g_HFILE
	    fi
            echo "result->value = 0; free(result->key); result->key = NULL; __b2c__hashtable_remove(&__b2c__${i}_table_${F}, (HASHTABLE_U64)(uintptr_t)(key)); } free(key); }" >> $g_HFILE

	    echo "${2} _${i}_${F}(char *idx, ...){__b2c__${i}_type_${F} *result = NULL; char *key = NULL, *nxt; va_list ap;" >> $g_HFILE
            echo "va_start (ap, idx); while((nxt = va_arg (ap, char *)) != NULL){if(key == NULL) { key = __b2c__strdup (idx); }" >> $g_HFILE
            echo "key = (char*)realloc(key, (strlen(key)+strlen(nxt)+2)*sizeof(char)); strcat(key, \" \"); strcat(key, nxt); } va_end (ap);" >> $g_HFILE
            echo "result = (__b2c__${i}_type_${F}*)__b2c__hashtable_find(&__b2c__${i}_table_${F}, (HASHTABLE_U64)(uintptr_t)( (key == NULL ? idx : key) )); if(key) { free(key); }" >> $g_HFILE
	    if [[ ${i} = +(*${g_STRINGSIGN}*) || ${2} = +(*STRING*) || ${2} = +(*char\**) ]]
	    then
		echo "if(result == NULL) { return(EmptyString); } return(result->value);}" >> $g_HFILE
	    else
		echo "if(result == NULL) { return(0); } return(result->value);}" >> $g_HFILE
	    fi

            echo "char* __b2c__${i}_obtain_${F}(char *delim) {__b2c__${i}_type_${F} *result; HASHTABLE_U64 *tmp; long idx, ctr, dlen, len, buck, total=0; buck = __b2c__hashtable_count(&__b2c__${i}_table_${F});" >> $g_HFILE
            echo "if(buck==0) { return(EmptyString); } if(delim == NULL) { delim = __b2c__option_delim; } " >> $g_HFILE
            echo "tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__${i}_table_${F}); dlen = __b2c__len(delim); idx = __sbuf_malloc_handle(dlen); for(ctr = 0; ctr < buck; ctr++)" >> $g_HFILE
            echo "{ result = (__b2c__${i}_type_${F}*)__b2c__hashtable_find(&__b2c__${i}_table_${F}, (HASHTABLE_U64)tmp[ctr]); len = __b2c__len(result->key); __sbuf_need_realloc(idx, total+len+dlen);" >> $g_HFILE
            echo "memmove(__b2c__sbuffer[idx]+total, result->key, len); total +=len; if(ctr<buck-1) {memmove(__b2c__sbuffer[idx]+total, delim, dlen); total+=dlen;} }" >> $g_HFILE
            echo "__b2c__SETLEN(__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\0'; return (char*)(__b2c__sbuffer[idx]); }" >> $g_HFILE
        fi

        echo "#ifndef ${i}" >> $g_HFILE
            echo "#define __b2c__${i}__add(...) __b2c_INDIRECT(__b2c__${i}__add_secure_, __b2c_assoc_${i})(1, __VA_ARGS__, NULL)" >> $g_HFILE
            echo "#define __b2c__${i}__del(...) __b2c_INDIRECT(__b2c__${i}__delete_, __b2c_assoc_${i})(__VA_ARGS__, NULL)" >> $g_HFILE
            echo "#define ${i}(...) __b2c_INDIRECT(_${i}_, __b2c_assoc_${i})(__VA_ARGS__, NULL)" >> $g_HFILE
            echo "#define __b2c__${i}_loc __b2c_INDIRECT(__b2c__${i}_location_, __b2c_assoc_${i})" >> $g_HFILE
            echo "#define __b2c__${i}_tmp __b2c_INDIRECT(__b2c__${i}_temp_, __b2c_assoc_${i})" >> $g_HFILE
            echo "#define __b2c__${i}_tab __b2c_INDIRECT(__b2c__${i}_table_, __b2c_assoc_${i})" >> $g_HFILE
            echo "#define __b2c__${i}_typ __b2c_INDIRECT(__b2c__${i}_type_, __b2c_assoc_${i})" >> $g_HFILE
        echo "#endif" >> $g_HFILE

        if [[ $3 -eq 1 ]]
        then
            echo "#undef __b2c_assoc_${i}" >> $g_CFILE
            echo "#define __b2c_assoc_${i} ${F}" >> $g_CFILE
            g_STRINGARRAYS="$g_STRINGARRAYS __b2c__${i}_tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__${i}_tab); while(__b2c__hashtable_count(&__b2c__${i}_tab))"
            g_STRINGARRAYS="$g_STRINGARRAYS {__b2c__${i}_loc = (__b2c__${i}_typ*)__b2c__hashtable_find(&__b2c__${i}_tab, (HASHTABLE_U64)__b2c__${i}_tmp[0]); __b2c__${i}__del(__b2c__${i}_loc->key);}"
            g_STRINGARRAYS="$g_STRINGARRAYS __b2c__hashtable_clear(&__b2c__${i}_tab); __b2c__hashtable_term(&__b2c__${i}_tab);"
            Save_Func_Var "${i}" "${F}" "${2}"
            echo "__b2c__hashtable_init(&__b2c__${i}_tab, sizeof(__b2c__${i}_typ), 10240, 0);" >> $g_CFILE
        else
            echo "#define __b2c_assoc_${i}" >> $g_HFILE
            Save_Main_Var "${i}" "${2}"
            if [[ -n ${g_FUNCNAME} ]]
            then
                echo "__b2c__hashtable_init(&__b2c__${i}_tab, sizeof(__b2c__${i}_typ), 10240, 0);" >> $g_COPY_CFILE
            else
                echo "__b2c__hashtable_init(&__b2c__${i}_tab, sizeof(__b2c__${i}_typ), 10240, 0);" >> $g_CFILE
            fi
        fi
    done
}

#-----------------------------------------------------------

function Handle_Declare
{
    # Local variables
    typeset VAR TYPE CHECK NEW VALUE OPTION ARRAY i PTR TOKEN
    typeset -i CTR

    if [[ -n $g_RECORDNAME ]]
    then
	echo -e "\nSyntax error: DECLARE/GLOBAL cannot be used within a RECORD at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    #  Check on a GLOBAL RECORD
    if [[ "$1" = +(*RECORD *) ]]
    then
	# Translate to C typedef struct
	g_RECORDNAME="RECORD_${g_COUNTER}"
	echo "typedef struct {" >> $g_HFILE
	g_RECORDVAR=${1#* }
	if [[ $g_RECORDVAR = +(* ARRAY *) ]]
	then
	    g_RECORDARRAY=${g_RECORDVAR#* ARRAY }
	    g_RECORDVAR="${g_RECORDVAR%% ARRAY *}[$g_RECORDARRAY]"
	fi
	# Store current function name
	if [[ -n $g_FUNCNAME ]]
	then
	    g_RECORDCACHE=$g_FUNCNAME
	    g_FUNCNAME=
	fi
    else
	# Get the variablename and type
	if [[ "$1" = +(* TYPE *) ]]
	then
            VAR=$(echo "${1%% TYPE *}")
	    TYPE=$(echo "${1##* TYPE }")
	    if [[ ${TYPE} = +(* ARRAY *) ]]
	    then
		ARRAY=${TYPE##* ARRAY }
		TYPE=${TYPE%% ARRAY *}
	    fi
	elif [[ "$1" = +(* ASSOC *) ]]
	then
	    VAR=$(echo "${1%% ASSOC *}")
	    TYPE=$(echo "${1##* ASSOC }")
	else
	    if [[ "${1}" = +(* ARRAY *) ]]
	    then
		ARRAY=${1##* ARRAY }
	        VAR=$(echo "${1%% ARRAY *}")
            elif [[ "${@}" = +(DIR|FILE|*int|*short|*long|*float|*double|*char|void|STRING|NUMBER|FLOATING) && "${@}" != +(*TYPE*) ]]
            then
	        echo -e "\nSyntax error: missing TYPE keyword in DECLARE/GLOBAL at line $g_COUNTER in file '$g_CURFILE'!"
	        exit 1
            else
	        VAR=$(echo "${1}")
	    fi
	    if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]]
	    then
		TYPE="char*"
	    elif [[ "${VAR}" = +(*${g_FLOATSIGN}*) ]]
	    then
		TYPE="double"
	    else
		TYPE="${g_VARTYPE}"
	    fi
	fi

        # Check if variable was already declared - no record and not a function pointer?
        if [[ "$VAR" != +(*.*) && "$VAR" != +(\(*) ]]
        then
            IFS=","
	    for i in ${VAR// /}
            do
                # Check for C keywords
                if [[ "${i%%=*}" = +(${g_C_KEYWORDS}) ]]
                then
	            echo -e "\nSyntax error: variable '${i}' in DECLARE/GLOBAL statement at line $g_COUNTER in file '$g_CURFILE' is a C keyword or function!"
	            exit 1
                fi
                # Previous definitions
                if [[ -n $(Get_Var "${i%%=*}") ]]
                then
	            echo -e "\nSyntax error: variable '${i}' in DECLARE/GLOBAL statement at line $g_COUNTER in file '$g_CURFILE' was defined previously!"
	            exit 1
                fi
            done
            IFS="${g_ORGIFS}"
        fi

	# Check for associative array
	if [[ "${1}" = +(* ASSOC *) ]]
	then
            Assoc_Array "${VAR}" "${TYPE}" 0

        # Check if it is a known type, if not BaCon has to use external .h file
        elif [[ ${TYPE%%\**} != +(DIR|FILE|*short|*int|*long|*float|*double|*char|void|STRING|NUMBER|FLOATING) ]]
        then
	    if [[ "$VAR" = +(*=*) ]]
	    then
	        echo "$TYPE $VAR;" >> $g_HFILE
		Save_Main_Var "${VAR}" "${TYPE}"
	    else
		for i in ${VAR//,/ }
		do
	            echo "$TYPE $i;" >> $g_HFILE
		    Save_Main_Var "${i}" "${TYPE}"
		done
	    fi

	#  Check for dynamic array declaration
	elif [[ -n ${ARRAY} ]]
	then
            Normal_Dyn_Array "$TYPE" "${VAR//,/ }" "${ARRAY}" 0

	# Check if var is string var
	elif [[ ( "${VAR}" = +(*${g_STRINGSIGN}*) || "${TYPE}" = +(STRING|char\*) ) && "${VAR}" != +(*=*) ]]
	then
	    for i in ${VAR//,/ }
	    do
                if [[ -z $(Get_Var ${i}) ]]
	        then
		    if [[ "${i}" = +(*\[*\]*) ]]
		    then
			echo "char *${i//]/+$g_OPTION_BASE]} = { NULL };" >> $g_HFILE
			# Determine dimension needed for SORT
			VALUE=${i#*\[}
                        Save_Dim "${i%%\[*}" "${VALUE%\]*}"
                        # Save type
                        Save_Main_Var "${i}" "char**"
                    elif [[ ${i} = +(*\(*\)*) ]]
                    then
                        # Function pointer
		        echo "$TYPE $i;" >> $g_HFILE
                        i=`echo ${i%%\)*} | tr -d "\052"`
                        Save_Main_Var "${i##*\(}" "void*"
		    else
			echo "char *$i = NULL;" >> $g_HFILE
                        Save_Main_Var "${i}" "char*"
		    fi
	        fi
	    done
        # Var is string array assignment
	elif [[ ( "${VAR}" = +(*${g_STRINGSIGN}*) || "${TYPE}" = +(*STRING*|*char\**) ) && "${VAR}" = +(*=*) ]]
        then
            if [[ -z $(Get_Var ${VAR}) ]]
	    then
		if [[ "${VAR}" = +(*\[*\]*) ]]
		then
		    # Determine dimensions to declare array
                    VALUE=`echo ${VAR} | tr -d -c "," | wc -c`
                    ((VALUE+=1))
		    echo "char *${VAR%%\[*}[$VALUE] = { NULL };" >> $g_HFILE
		    # Set dimension needed for SORT
		    Save_Dim "${VAR%%\[*}" "${VALUE}"
                    # Save type
                    Save_Main_Var "${VAR}" "char**"
		    # Copy elements
		    CTR=$g_OPTION_BASE
		    ARRAY=${VAR#*\{}
		    while [[ -n ${ARRAY} ]]
		    do
                        TOKEN=$(Mini_Parser "${ARRAY%\}*}")
			echo "${VAR%%\[*}[${CTR}] = __b2c_Copy_String(${VAR%%\[*}[${CTR}], ${TOKEN});" >> $g_CFILE
                        ARRAY="${ARRAY:${#TOKEN}+1}"
			((CTR+=1))
		    done
                else
                    while [[ -n ${VAR} ]]
                    do
                        TOKEN=$(Mini_Parser "${VAR}")
		        echo "char *${TOKEN%%=*} = NULL;" >> $g_HFILE
			echo "${TOKEN%%=*} = __b2c_Copy_String(${TOKEN%%=*}, ${TOKEN##*=});" >> $g_CFILE
                        Save_Main_Var "${TOKEN%%=*}" "char*"
                        VAR="${VAR:${#TOKEN}+1}"
                    done
                fi
            fi
	# Assume char assignment or number
	else
	    if [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]]
	    then
                IFS=","
		for i in ${VAR// /}
		do
		    echo "$TYPE ${i//]/+$g_OPTION_BASE]} = { 0 };" >> $g_HFILE
		    # Determine dimension needed for SORT
		    VALUE=${i#*\[}
                    Save_Dim "${i%%\[*}" "${VALUE%\]*}"
                    # Save type
                    Save_Main_Var "${i}" "${TYPE}"
		done
                IFS="${g_ORGIFS}"
	    elif [[ "$VAR" = +(*\[*\]*) && "$VAR" = +(*=*) ]]
            then
                # Numeric array assignment
                echo "$TYPE ${VAR%%\{*} {" >> $g_HFILE
                OPTION=$g_OPTION_BASE
                CTR=`echo ${VAR} | tr -d -c "[" | wc -c` ; PTR=
                if [[ ${OPTION} -gt 0 && $CTR -gt 1 ]]
                then
	            echo -e "\nWARNING: OPTION BASE has no impact on multidimensional array '${VAR%%\[*}' in DECLARE/GLOBAL statement at line $g_COUNTER in file '$g_CURFILE'!"
                fi
                while [[ ${OPTION} -gt 0 && $CTR -eq 1 ]]
                do
                    echo " 0, " >> $g_HFILE
                    ((OPTION-=1))
                done
	        echo "${VAR#*\{};" >> $g_HFILE
                # Count elements of array
                CTR=`echo ${VAR} | tr -d -c "," | wc -c`
                ((CTR+=1))
                Save_Dim "${VAR%%\[*}" "${CTR}"
                Save_Main_Var "${VAR%%\[*}" "${TYPE}"
            elif [[ ${VAR} = +(*\(*\)*) ]]
            then
                # Function pointer
		echo "$TYPE $VAR;" >> $g_HFILE
                VAR=`echo ${VAR%%\)*} | tr -d "\052"`
                Save_Main_Var "${VAR##*\(}" "void*"
	    else
                IFS=","
                for i in ${VAR// /}
                do
		    echo "$TYPE $i;" >> $g_HFILE
                    if [[ "$i" != +(*=*) && "$i" != +(*\**) && "${TYPE}" = +(*char*|*short*|*int*|*long*|*double*|*float*|*NUMBER*|*FLOATING*) ]]
                    then
		        echo "${i} = 0;" >> $g_CFILE
                    fi
                    Save_Main_Var "${i}" "${TYPE}"
                done
                IFS="${g_ORGIFS}"
            fi
	fi
    fi
}

#-----------------------------------------------------------

function Handle_Local
{
    # Local variables
    typeset VAR TYPE DIM DIM2 NEW VALUE i OPTION ARRAY STATIC PTR TOKEN
    typeset -i CTR

    # Get the variablename and type
    if [[ "$1" = +(* TYPE *) ]]
    then
	VAR=$(echo "${1%% TYPE *}")
	TYPE=$(echo "${1##* TYPE }")
	if [[ ${TYPE} = +(* ARRAY *) ]]
	then
	    ARRAY=${TYPE##* ARRAY }
	    TYPE=${TYPE%% ARRAY *}
	fi
    elif [[ "$1" = +(* ASSOC *) ]]
    then
	VAR=$(echo "${1%% ASSOC *}")
	TYPE=$(echo "${1##* ASSOC }")
    else
	if [[ "${1}" = +(* ARRAY *) ]]
	then
	    ARRAY=${1##* ARRAY }
	    VAR=$(echo "${1%% ARRAY *}")
        elif [[ "${@}" = +(DIR|FILE|*int|*short|*long|*float|*double|*char|void|STRING|NUMBER|FLOATING) && "${@}" != +(*TYPE*) ]]
        then
	    echo -e "\nSyntax error: missing TYPE keyword in LOCAL at line $g_COUNTER in file '$g_CURFILE'!"
	    exit 1
        else
	    VAR=$(echo "${1}")
	fi
        # This construction needed for KSH93
	if [[ "${VAR//${g_STRINGSIGN}/}" != ${VAR} ]]
	then
	    TYPE="char*"
	elif [[ "${VAR//${g_FLOATSIGN}/}" != ${VAR} ]]
	then
	    TYPE="double"
	else
	    TYPE="long"
	fi
    fi

    # Check if variable was already declared - no record and not function pointer?
    if [[ "$VAR" != +(*.*) && "$VAR" != +(\(*) ]]
    then
        IFS=","
	for i in ${VAR// /}
        do
            # Check for C keywords
            if [[ "${i%%=*}" = +(${g_C_KEYWORDS}) ]]
            then
	        echo -e "\nSyntax error: variable '${i}' in LOCAL statement at line $g_COUNTER in file '$g_CURFILE' is a C keyword or function!"
	        exit 1
            fi
            # Previous definitions
            if [[ -n $(Get_Var "${i%%=*}" ${g_FUNCNAME}) ]]
            then
	        echo -e "\nSyntax error: variable '${i}' in LOCAL statement at line $g_COUNTER in file '$g_CURFILE' was defined previously!"
	        exit 1
            fi
        done
        IFS="${g_ORGIFS}"
    fi

    # Check for associative array
    if [[ "${1}" = +(* ASSOC *) ]]
    then
        Assoc_Array "${VAR}" "${TYPE}" 1

    # Check if it is a known type, if not BaCon has to use external .h file
    elif [[ ${TYPE%%\**} != +(DIR|FILE|*int|*short|*long|*float|*double|*char|void|STRING|NUMBER|FLOATING) && -z $g_RECORDNAME ]]
    then
	if [[ "$VAR" = +(*=*) ]]
	then
	    echo "$TYPE $VAR;" >> $g_CFILE
	    if [[ -z ${g_FUNCNAME} ]]
	    then
		Save_Main_Var "${VAR}" "${TYPE}"
	    else
		Save_Func_Var "${VAR}" "${g_FUNCNAME}" "${TYPE}"
	    fi
	else
	    for i in ${VAR//,/ }
	    do
		if [[ -z ${g_FUNCNAME} ]]
		then
	            echo "$TYPE $i;" >> $g_HFILE
		    Save_Main_Var "${i}" "${TYPE}"
		else
	            echo "$TYPE $i;" >> $g_CFILE
		    Save_Func_Var "${i}" "${g_FUNCNAME}" "${TYPE}"
		fi
	    done
	fi

    # Check for dynamic array declaration
    elif [[ -n ${ARRAY} ]]
    then
        if [[ $ARRAY = +(*STATIC*) ]]
        then
            STATIC=1
	    ARRAY=`echo ${ARRAY%% STATIC*} | tr "," " "`
        else
            STATIC=0
	    ARRAY="${ARRAY//,/ }"
        fi
        if [[ -n $g_RECORDNAME ]]
        then
            Record_Dyn_Array "$TYPE" "${VAR//,/ }" "$ARRAY" $STATIC
        else
            Normal_Dyn_Array "$TYPE" "${VAR//,/ }" "$ARRAY" $STATIC 1
        fi

    # Check if var is string var
    elif [[ ( "${TYPE}" = +(STRING|*char\*) || "${VAR}" = +(*${g_STRINGSIGN}*) ) && "${VAR}" != +(*=*) && "${VAR}" != +(*\[*${g_STRINGSIGN}\]*) ]]
    then
	for i in ${VAR//,/ }
	do
            if [[ -z $(Get_Var ${i} ${g_FUNCNAME}) ]]
	    then
		# Check on multidimensional stringarrays
		if [[ "${i}" = +(*\[*\]*\]*) ]]
		then
		    echo -e "\nSyntax error: multidimensional stringarrays at line $g_COUNTER in file '$g_CURFILE' are not supported!"
		    exit 1
		fi
		# Are we in a function?
		if [[ -n $g_FUNCNAME ]]
		then
		    if [[ -n $g_RECORDNAME ]]
		    then
			if [[ "${i}" = +(*\[*\]*) ]]
			then
			    echo "char *${i//]/+$g_OPTION_BASE]};" >> $g_CFILE
			    DIM=${i##*\[}; DIM=${DIM%%\]*}
                            Save_Dim "${i%%\[*}" "$DIM"
                            if [[ "${g_RECORDVAR}" = +(*\[*\]*) ]]
                            then
				if [[ -n ${g_RECORDARRAY} ]]
				then
				    DIM2="__b2c_record_${g_RECORDNAME%_*}"
				else
				    DIM2=${g_RECORDVAR##*\[}; DIM2=${DIM2%%\]*}
				fi
                                g_RECORDEND_BODY="${g_RECORDEND_BODY} for(__b2c__counter=0; __b2c__counter<$DIM2; __b2c__counter++){for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++) ${g_RECORDVAR%%\[*}[__b2c__counter].${i%%\[*}[__b2c__ctr]=NULL;}"
			        g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__counter=0; __b2c__counter<$DIM2; __b2c__counter++){for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++) { __b2c__STRFREE(${g_RECORDVAR%%\[*}[__b2c__counter].${i%%\[*}[__b2c__ctr]);} }"
                            else
                                g_RECORDEND_BODY="${g_RECORDEND_BODY} for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++) $g_RECORDVAR.${i%%\[*}[__b2c__ctr] = NULL;"
			        g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++) { __b2c__STRFREE($g_RECORDVAR.${i%%\[*}[__b2c__ctr]); }"
                            fi
			else
			    echo "char *$i;" >> $g_CFILE
			    # Pointer var should not be initialized
			    if [[ "${i}" = +(*${g_STRINGSIGN}*) && "${g_RECORDVAR}" != +(*\[*\]*) && -z ${g_RECORDARRAY} ]]
			    then
                                g_RECORDEND_BODY="${g_RECORDEND_BODY} $g_RECORDVAR.$i = NULL;"
			        g_LOCALSTRINGS="$g_LOCALSTRINGS ${g_RECORDVAR}.${i}"
                            fi
			fi
                        Save_Func_Var "${i}" "${g_FUNCNAME}" "char*"
		    else
			if [[ "${i}" = +(*\[*\]*) ]]
			then
			    echo "char *${i//]/+$g_OPTION_BASE]} = { NULL };" >> $g_CFILE
			    # Determine dimension needed for SORT
			    VALUE=${i#*\[}
                            Save_Dim "${i%%\[*}" "${VALUE%\]*}"
			    DIM=${i##*\[}; DIM=${DIM%%\]*}
			    g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++) { __b2c__STRFREE(${g_WITHVAR}${i%%\[*}[__b2c__ctr]); }"
			    # Save type
                            Save_Func_Var "${i}" "${g_FUNCNAME}" "char**"
                        elif [[ ${i} = +(*\(*\)*) ]]
                        then
                            # Function pointer
		            echo "$TYPE $i;" >> $g_CFILE
                            i=`echo ${i%%\)*} | tr -d "\052"`
                            Save_Func_Var "${i##*\(}" "${g_FUNCNAME}" "void*"
			else
			    echo "char *$i = NULL;" >> $g_CFILE
                            Save_Func_Var "${i}" "${g_FUNCNAME}" "char*"
                            # Defined as string?
			    if [[ "${i}" = +(*${g_STRINGSIGN}*) ]]
			    then
			        echo "$i = __b2c_Copy_String($i, EmptyString);" >> $g_CFILE
				g_LOCALSTRINGS="$g_LOCALSTRINGS ${i}"
                            fi
			fi
		    fi
		# We are in the mainprogram
		else
		    if [[ -n $g_RECORDNAME ]]
		    then
			if [[ "${i}" = +(*\[*\]*) ]]
			then
			    echo "char *${i//]/+$g_OPTION_BASE]};" >> $g_HFILE
                        else
			    echo "char *$i;" >> $g_HFILE
			    # Pointer var should not be initialized
			    if [[ "${i}" = +(*${g_STRINGSIGN}*) && "${g_RECORDVAR}" != +(*\[*\]*) && -z ${g_RECORDARRAY} ]]
			    then
                                g_RECORDEND_BODY="${g_RECORDEND_BODY} $g_RECORDVAR.$i = NULL;"
                            fi
                        fi
                        Save_Main_Var "${i}" "char*"
		    else
			if [[ "${i}" = +(*\[*\]*) ]]
			then
			    echo "char *${i//]/+$g_OPTION_BASE]} = { NULL };" >> $g_HFILE
			    # Determine dimension needed for SORT
			    VALUE=${i#*\[}
                            Save_Dim "${i%%\[*}" "${VALUE%\]*}"
			    # Save type
                            Save_Main_Var "${i}" "char**"
                        elif [[ ${i} = +(*\(*\)*) ]]
                        then
                            # Function pointer
		            echo "$TYPE $i;" >> $g_HFILE
                            i=`echo ${i%%\)*} | tr -d "\052"`
                            Save_Main_Var "${i##*\(}" "void*"
			else
			    echo "char *$i = NULL;" >> $g_HFILE
                            Save_Main_Var "${i}" "char*"
			fi
		    fi
		fi
	    fi
	done
    elif [[ ( "${VAR}" = +(*${g_STRINGSIGN}*) || "${TYPE}" = +(*STRING*|*char\**) ) && "${VAR}" = +(*=*) ]]
    then
        if [[ -n $g_FUNCNAME ]]
	then
            if [[ -z $(Get_Var ${VAR}) ]]
	    then
		if [[ "${VAR}" = +(*\[*\]*) ]]
		then
		    # Determine dimensions to declare array
                    VALUE=`echo ${VAR} | tr -d -c "," | wc -c`
                    ((VALUE+=1))
		    echo "static char *${VAR%%\[*}[$VALUE] = { NULL };" >> $g_CFILE
		    # Set dimension needed for SORT
		    Save_Dim "${VAR%%\[*}" "${VALUE}"
                    # Save type
                    Save_Func_Var "${VAR}" "${g_FUNCNAME}" "char**"
		    # Copy elements
		    CTR=$g_OPTION_BASE
		    ARRAY=${VAR#*\{}
		    while [[ -n ${ARRAY} ]]
		    do
                        TOKEN=$(Mini_Parser "${ARRAY%\}*}")
			echo "${VAR%%\[*}[${CTR}] = __b2c_Copy_String(${VAR%%\[*}[${CTR}], ${TOKEN});" >> $g_CFILE
                        ARRAY="${ARRAY:${#TOKEN}+1}"
			((CTR+=1))
		    done
                else
                    while [[ -n ${VAR} ]]
                    do
                        TOKEN=$(Mini_Parser "${VAR}")
		        echo "static char *${TOKEN%%=*} = NULL;" >> $g_CFILE
			echo "${TOKEN%%=*} = __b2c_Copy_String(${TOKEN%%=*}, ${TOKEN##*=});" >> $g_CFILE
                        Save_Func_Var "${TOKEN%%=*}" "${g_FUNCNAME}" "char*"
                        VAR="${VAR:${#TOKEN}+1}"
                    done
                fi
            fi
        else
            if [[ -z $(Get_Var ${VAR}) ]]
	    then
		if [[ "${VAR}" = +(*\[*\]*) ]]
		then
		    # Determine dimensions to declare array
                    VALUE=`echo ${VAR} | tr -d -c "," | wc -c`
                    ((VALUE+=1))
		    echo "char *${VAR%%\[*}[$VALUE] = { NULL };" >> $g_HFILE
		    # Set dimension needed for SORT
		    Save_Dim "${VAR%%\[*}" "${VALUE}"
                    # Save type
                    Save_Main_Var "${VAR}" "char**"
		    # Copy elements
		    CTR=$g_OPTION_BASE
		    ARRAY=${VAR#*\{}
		    while [[ -n ${ARRAY} ]]
		    do
                        TOKEN=$(Mini_Parser "${ARRAY%\}*}")
			echo "${VAR%%\[*}[${CTR}] = __b2c_Copy_String(${VAR%%\[*}[${CTR}], ${TOKEN});" >> $g_CFILE
                        ARRAY="${ARRAY:${#TOKEN}+1}"
			((CTR+=1))
		    done
                else
                    while [[ -n ${VAR} ]]
                    do
                        TOKEN=$(Mini_Parser "${VAR}")
		        echo "char *${TOKEN%%=*} = NULL;" >> $g_HFILE
			echo "${TOKEN%%=*} = __b2c_Copy_String(${TOKEN%%=*}, ${TOKEN##*=});" >> $g_CFILE
                        Save_Main_Var "${TOKEN%%=*}" "char*"
                        VAR="${VAR:${#TOKEN}+1}"
                    done
                fi
            fi
        fi
    # Assume number or complicated type
    else
	if [[ -n $g_FUNCNAME ]]
	then
	    if [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]]
	    then
                IFS=","
		for i in ${VAR// /}
		do
                    if [[ -z $g_RECORDNAME ]]
                    then
			echo "$TYPE ${i//]/+$g_OPTION_BASE]} = { 0 };" >> $g_CFILE
                    else
			echo "$TYPE ${i//]/+$g_OPTION_BASE]};" >> $g_CFILE
                    fi
		    # Determine dimension needed for SORT
		    VALUE=${i#*\[}
                    Save_Dim "${i%%\[*}" "${VALUE%\]*}"
                    Save_Func_Var "${i}" "${g_FUNCNAME}" "${TYPE}"
		done
                IFS="${g_ORGIFS}"
	    elif [[ "$VAR" = +(*\[*\]*) && "$VAR" = +(*=*) ]]
            then
                # Numeric array assignment
                echo "$TYPE ${VAR%%\{*} {" >> $g_CFILE
                OPTION=$g_OPTION_BASE
                CTR=`echo ${VAR} | tr -d -c "[" | wc -c` ; PTR=
                if [[ ${OPTION} -gt 0 && $CTR -gt 1 ]]
                then
	            echo -e "\nWARNING: OPTION BASE has no impact on multidimensional array '${VAR%%\[*}' in LOCAL statement at line $g_COUNTER in file '$g_CURFILE'!"
                fi
                while [[ ${OPTION} -gt 0 && $CTR -eq 1 ]]
                do
                    echo " 0, " >> $g_CFILE
                    ((OPTION-=1))
                done
	        echo "${VAR#*\{};" >> $g_CFILE
                # Count elements of array
                CTR=`echo ${VAR} | tr -d -c "," | wc -c`
                ((CTR+=1))
                Save_Dim "${VAR%%\[*}" "${CTR}"
                Save_Func_Var "${VAR}" "${g_FUNCNAME}" "${TYPE}"
            elif [[ ${VAR} = +(*\(*\)*) ]]
            then
                # Function pointer
		echo "$TYPE $VAR;" >> $g_CFILE
                VAR=`echo ${VAR%%\)*} | tr -d "\052"`
                Save_Func_Var "${VAR##*\(}" "${g_FUNCNAME}" "void*"
	    else
                IFS=","
                for i in ${VAR// /}
                do
		    echo "$TYPE $i;" >> $g_CFILE
                    if [[ "$i" != +(*=*) && "$i" != +(*\**) && -z ${g_RECORDVAR} && "${TYPE}" = +(*char*|*short*|*int*|*long*|*double*|*float*|*NUMBER*|*FLOATING*) ]]
                    then
		        echo "${i} = 0;" >> $g_CFILE
                    fi
                    Save_Func_Var "${i}" "${g_FUNCNAME}" "${TYPE}"
                done
                IFS="${g_ORGIFS}"
	    fi
	else
	    if [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]]
	    then
                IFS=","
		for i in ${VAR// /}
		do
                    if [[ -z $g_RECORDNAME ]]
                    then
			echo "$TYPE ${i//]/+$g_OPTION_BASE]} = { 0 };" >> $g_HFILE
                    else
			echo "$TYPE ${i//]/+$g_OPTION_BASE]};" >> $g_HFILE
                    fi
		    # Determine dimension needed for SORT
		    VALUE=${i#*\[}
                    Save_Dim "${i%%\[*}" "${VALUE%\]*}"
                    Save_Main_Var "${i}" "${TYPE}"
		done
                IFS="${g_ORGIFS}"
	    elif [[ "$VAR" = +(*\[*\]*) && "$VAR" = +(*=*) ]]
            then
                # Numeric array assignment
                echo "$TYPE ${VAR%%\{*} {" >> $g_HFILE
                OPTION=$g_OPTION_BASE
                CTR=`echo ${VAR} | tr -d -c "[" | wc -c` ; PTR=
                if [[ ${OPTION} -gt 0 && $CTR -gt 1 ]]
                then
	            echo -e "\nWARNING: OPTION BASE has no impact on multidimensional array '${VAR%%\[*}' in LOCAL statement at line $g_COUNTER in file '$g_CURFILE'!"
                fi
                while [[ ${OPTION} -gt 0 && $CTR -eq 1 ]]
                do
                    echo " 0, " >> $g_HFILE
                    ((OPTION-=1))
                done
	        echo "${VAR#*\{};" >> $g_HFILE
                # Count elements of array
                CTR=`echo ${VAR} | tr -d -c "," | wc -c`
                ((CTR+=1))
                Save_Dim "${VAR%%\[*}" "${CTR}"
                Save_Main_Var "${VAR}" "${TYPE}"
            elif [[ ${VAR} = +(*\(*\)*) ]]
            then
                # Function pointer
		echo "$TYPE $VAR;" >> $g_HFILE
                VAR=`echo ${VAR%%\)*} | tr -d "\052"`
                Save_Main_Var "${VAR##*\(}" "void*"
            else
                IFS=","
                for i in ${VAR// /}
                do
		    echo "$TYPE $i;" >> $g_HFILE
                    if [[ "$i" != +(*=*) && "$i" != +(*\**) && -z ${g_RECORDVAR} && "${TYPE}" = +(*char*|*short*|*int*|*long*|*double*|*float*|*NUMBER*|*FLOATING*) ]]
                    then
		        echo "${i} = 0;" >> $g_CFILE
                    fi
                    Save_Main_Var "${i}" "${TYPE}"
                done
                IFS="${g_ORGIFS}"
	    fi
	fi
    fi
}

#-----------------------------------------------------------

function Handle_Read
{
    # Local variables
    typeset CHECK STR ITEM

    # Check if we have an argument at all
    if [[ "$1" = "READ" ]]
    then
	echo -e "\nSyntax error: empty READ at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    for ITEM in ${1//,/ }
    do
	# Check if string variable, and if so, if declared
	if [[ "${ITEM}" = +(*${g_STRINGSIGN}) && "$ITEM" != +(*.*) ]]
	then
            if [[ -z $(Get_Var ${ITEM} ${g_FUNCNAME}) ]]
	    then
                Register_String "${ITEM}"
	    fi
	    CHECK="char*"
        # Variable may not be array, these should be defined with DECLARE
	elif [[ "${ITEM}" != +(*\[*\]*) && "${ITEM}" != +(*.*) && "$ITEM" != +(*\(*\)*) && "$ITEM" != +(*-\>*) ]]
	then
	    # Not declared? Assume long
            if [[ -z $(Get_Var ${ITEM} ${g_FUNCNAME}) ]]
	    then
                Register_Numeric ${ITEM}
                CHECK=$(Get_Var ${ITEM} ${g_FUNCNAME})
            else
                CHECK=$(Get_Var ${ITEM} ${g_FUNCNAME})
	    fi
	else
	    # See how var was declared
            CHECK=$(Get_Var ${ITEM} ${g_FUNCNAME})
	fi

        # Check type of var, string?
	if [[ $(Check_String_Type ${ITEM}) -eq 1 ]]
	then
	    # Convert to C
	    echo "__b2c__assign = (char*)calloc((strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1), sizeof(char));" >> $g_CFILE
	    echo "strcpy(__b2c__assign, __b2c__stringarray[__b2c__stringarray_ptr]); __b2c__stringarray_ptr++;" >> $g_CFILE
	    if [[ "${ITEM}" = +(*\(*\)) ]]
	    then
		STR=${ITEM#*\(}
		echo "__b2c__${ITEM%%\(*}_loc = __b2c__${ITEM%%\(*}__add(${STR};" >> $g_CFILE
		echo "__b2c__STRFREE(__b2c__${ITEM%%\(*}_loc->value); __b2c__${ITEM%%\(*}_loc->value = __b2c__assign;" >> $g_CFILE
		# Check for relations
		Relate_Recurse "${ITEM%%\(*}" "${STR}" "${ITEM}" "-1"
	    else
		echo "__b2c__STRFREE($ITEM); $ITEM = __b2c__assign;" >> $g_CFILE
	    fi
        else
	    # Now see if we have an assoc or a normal variable
	    if [[ "${ITEM}" = +(*\(*\)) ]]
	    then
	        echo "__b2c__${ITEM%%\(*}_loc = __b2c__${ITEM%%\(*}__add(${ITEM#*\(};" >> $g_CFILE
		echo "__b2c__${ITEM%%\(*}_loc->value = (${CHECK})__b2c__floatarray[__b2c__floatarray_ptr];" >> $g_CFILE
	        echo "__b2c__floatarray_ptr++;" >> $g_CFILE
		# Check for relations
		Relate_Recurse "${ITEM%%\(*}" "${STR}" "${ITEM}" "-1"
            else
	        echo "${ITEM} = (${CHECK})__b2c__floatarray[__b2c__floatarray_ptr];" >> $g_CFILE
	        echo "__b2c__floatarray_ptr++;" >> $g_CFILE
            fi
        fi
    done
}

#-----------------------------------------------------------

function Handle_Endfunction
{
    typeset TFIL

    # Check if we're in a FUNCTION
    if [[ -z $g_FUNCNAME ]]
    then
	echo -e "\nSyntax error: ENDFUNCTION outside FUNCTION at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if return was found
    if [[ -z $g_FUNCTYPE ]]
    then
	echo -e "\nSyntax error: function '$g_FUNCNAME' was defined without returning a value or string!"
	exit 1
    fi

    # Put prototype to header file
    if [[ ${g_PROTOTYPE} != +(*::*) ]]
    then
        echo "$g_FUNCTYPE ${g_PROTOTYPE};" >> $g_HFILE
    fi
    g_PROTOTYPE=

    TFIL=${g_CURFILE##*/}
    # Now setup function in main program
    echo "/* Created with Shell BaCon $g_VERSION - (c) Peter van Eerten - MIT License */" > ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "#undef __b2c_filename" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "#define __b2c_filename \"$g_CURFILE\"" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "#undef __b2c__exitval" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "#define __b2c__exitval 0" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    if [[ $g_ORIGFUNCNAME != +(*\(*\)*) ]]
    then
	echo "$g_FUNCTYPE $g_ORIGFUNCNAME(void) {" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    else
	echo "$g_FUNCTYPE $g_ORIGFUNCNAME {" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    fi

    # Add function body
    echo "${g_STRINGARGS}" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    cat $g_CFILE >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    if [[ $g_CATCH_USED -eq 1 ]]
    then
        echo "__B2C__PROGRAM__EXIT: ;" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    fi

    # Make sure pointers are always reset
    echo "__b2c__catch_set = __b2c__catch_set_backup; __b2c__sbuffer = __b2c__sbuffer_backup; __b2c__sbuffer_ptr = __b2c__sbuffer_ptr_backup;" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h

    # Make sure the function always returns something
    if [[ $g_FUNCTYPE = +(*char\*|*STRING) ]]
    then
	echo "return (NULL);}" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    elif [[ $g_FUNCTYPE = +(*char|*short|*int|*long|*double|*float|*NUMBER|*FLOATING) ]]
    then
	echo "return(0);}" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    else
	echo "}" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    fi

    echo "#undef __b2c_lineno" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "#define __b2c_lineno $g_COUNTER" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h

    # Include header file
    if [[ ${g_INCLUDE_FILES} != +(*${TFIL%.*}.$g_FUNCNAME.h*) ]]
    then
	g_INCLUDE_FILES="$g_INCLUDE_FILES ${TFIL%.*}.$g_FUNCNAME.h"
    fi

    # Add to total filelist
    g_TMP_FILES="$g_TMP_FILES ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h"

    # Delete temp funcfile
    rm $g_CFILE

    # Restore mainfile
    g_CFILE=$g_COPY_CFILE

    # Restore CATCH routine
    g_CATCHGOTO="$g_ORIGCATCHGOTO"
    g_CATCH_USED=${g_ORIGCATCH_USED}

    # Clear function variables
    g_ORIGFUNCNAME=
    g_FUNCNAME=
    g_FUNCTYPE=
    g_LOCALSTRINGS=
    g_STRINGARRAYS=
    g_STRINGARGS=
}

#-----------------------------------------------------------

function Handle_Return
{
    # Local variables
    typeset CHECK STR ARG LEN
    typeset -i CTR

    # Check if we have an argument at all, if not, we return from a GOSUB
    if [[ "${1}" = "RETURN" ]]
    then
	echo "if(__b2c__gosub_buffer_ptr >= 0) longjmp(__b2c__gosub_buffer[__b2c__gosub_buffer_ptr], 1);" >> $g_CFILE
	return
    fi

    CHECK=$(Get_Var ${1%%\(*} ${g_FUNCNAME})

    # Check type of returned var, is it a string?
    if [[ -n ${g_FUNCTYPE} ]]
    then
	ARG="${1}"
    elif [[ $(Check_String_Type ${1}) -eq 1 ]]
    then
        # Static dynamic array or array created by SPLIT or LOOKUP
        if [[ ${g_DYNAMICARRAYS} = +(* ${1}@${g_FUNCNAME}*) || ${g_STRINGARGS} = +(* __b2c_array_${1} *) ]]
        then
	    g_FUNCTYPE="char**"
	    ARG="${1}"
        # We return a string
        else
	    g_FUNCTYPE="char*"
            g_STRINGARGS="$g_STRINGARGS char* __b2c__tmp = NULL;"
	    echo "__b2c__tmp = $1; if(__b2c__tmp != NULL){ __b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= $g_MAX_RBUFFERS) __b2c__rbuffer_ptr=0;" >> $g_CFILE
	    echo "__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)__rbuf_realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen(__b2c__tmp)+1)*sizeof(char));" >> $g_CFILE
	    echo "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], __b2c__tmp);}" >> $g_CFILE
	    echo "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)calloc(1, sizeof(char));}" >> $g_CFILE
	    ARG="__b2c__rbuffer[__b2c__rbuffer_ptr]"
        fi

    # Assume variable, check if declared before
    elif [[ -n $CHECK ]]
    then
	ARG="${1}"
        if [[ ${ARG} = +(*\[*\]*) ]]
        then
            CTR=`echo ${ARG} | tr -d -c "[" | wc -c`
            until [[ $CTR -eq 0 ]]
            do
                if [[ ${CHECK} = +(*\*) ]]
                then
		    let LEN=${#CHECK}-1
		    CHECK="${CHECK:0:$LEN}"
                fi
                let CTR=${CTR}-1
            done
        else
            for STR in $g_STATICARRAYS
            do
                if [[ $STR = +(*${ARG}*) ]]
                then
                    CTR=${STR##*:}
                    until [[ $CTR -eq 0 ]]
                    do
                        CHECK="${CHECK}*"
                        let CTR=${CTR}-1
                    done
                fi
            done
        fi
	g_FUNCTYPE="${CHECK}"

    # Not declared, assume actual value
    else
        if [[ "${1}" = +(*.*) || "${1}" = +(*${g_FLOATSIGN}) || ${g_FUNCNAME} = +(*${g_FLOATSIGN}) ]]
        then
	    g_FUNCTYPE="double"
        else
	    g_FUNCTYPE="${g_VARTYPE}"
        fi
	ARG="${1}"
    fi

    # Free strings variables if there are any
    echo "${g_STRINGARRAYS}" >> $g_CFILE
    for STR in $g_LOCALSTRINGS
    do
	echo "__b2c__STRFREE($STR);" >> $g_CFILE

        # If return argument contains string, make sure to point to return buffer
        if [[ ${ARG} = +(*${STR}*) ]]
        then
            echo "${STR} = __b2c__rbuffer[__b2c__rbuffer_ptr];" >> $g_CFILE
        fi
    done

    # The actual return value
    echo "__b2c__catch_set = __b2c__catch_set_backup; __b2c__sbuffer = __b2c__sbuffer_backup; __b2c__sbuffer_ptr = __b2c__sbuffer_ptr_backup;" >> $g_CFILE
    echo "return (${ARG});" >> $g_CFILE
}

#-----------------------------------------------------------

function Handle_Push
{
    # Local variables
    typeset CHECK

    # Check if we have an argument at all
    if [[ "$1" = "PUSH" ]]
    then
	echo -e "\nSyntax error: empty PUSH at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    if [[ "$VAR" != +(*.*) ]]
    then
        CHECK=$(Get_Var ${1} ${g_FUNCNAME})
    fi

    # Allocate space for type
    echo "__b2c__typestack = (int*)realloc(__b2c__typestack, (__b2c__stackptr+1)*sizeof(int));" >> $g_CFILE

    # Check type of var, string?
    if [[ $(Check_String_Type ${1}) -eq 1 ]]
    then
	echo "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" >> $g_CFILE
	echo "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = (char*)realloc(__b2c__stringstack[__b2c__stackptr], (strlen($1)+1)*sizeof(char));" >> $g_CFILE
	echo "strcpy(__b2c__stringstack[__b2c__stackptr], $1);} else __b2c__stringstack[__b2c__stackptr] = __b2c__strdup($1);" >> $g_CFILE
	echo "__b2c__typestack[__b2c__stackptr] = 1;" >> $g_CFILE
    # Check if float
    elif [[ "$1" = +(*.*) ]]
    then
	echo "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" >> $g_CFILE
	echo "__b2c__doublestack[__b2c__stackptr] = $1;" >> $g_CFILE
	echo "__b2c__typestack[__b2c__stackptr] = 2;" >> $g_CFILE
    # Check if no alpha chars (then integer value)
    elif [[ "$1" = +(![a-zA-Z]) ]]
    then
	echo "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE
	echo "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE
	echo "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE
    # Assume variable, check if declared before
    elif [[ -n $CHECK ]]
    then
	if [[ $CHECK = +(double*) || $CHECK = +(float*) || $CHECK = +(FLOATING*) ]]
	then
	    echo "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" >> $g_CFILE
	    echo "__b2c__doublestack[__b2c__stackptr] = $1;" >> $g_CFILE
	    echo "__b2c__typestack[__b2c__stackptr] = 2;" >> $g_CFILE
	else
	    echo "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE
	    echo "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE
	    echo "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE
	fi
    # Not declared, assume integer variable
    else
	echo "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE
	echo "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE
	echo "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE
    fi

    # Increase stackpointer
    echo "__b2c__stackptr++;" >> $g_CFILE
}

#-----------------------------------------------------------

function Handle_Pull
{
    typeset CHECK STR

    # Check if we have an argument at all
    if [[ "$1" = "PULL" ]]
    then
	echo -e "\nSyntax error: empty PULL at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Argument must be a variable
    if [[ "$1" = +(![a-zA-Z]) ]]
    then
	echo -e "\nSyntax error: argument in PULL statement at line $g_COUNTER in file '$g_CURFILE' is not a variable!"
	exit 1
    fi

    # Check if string is declared
    if [[ "${1}" = +(*${g_STRINGSIGN}) && "${1}" != +(*.*) ]]
    then
        if [[ -z $(Get_Var ${1} ${g_FUNCNAME}) ]]
	then
            Register_String "${1}"
	fi
	CHECK="char*"
    # Not a string?
    elif [[ "${1}" != +(*\[*\]*) && "${1}" != +(*.*) && "${1}" != +(*\(*\)*) && "${1}" != +(*-\>*) ]]
    then
        CHECK=$(Get_Var ${1} ${g_FUNCNAME})
        if [[ -z ${CHECK} ]]
	then
            Register_Numeric ${1}
            CHECK=$(Get_Var ${1} ${g_FUNCNAME})
	fi
    fi

    # Decrease stackpointer again
    echo "__b2c__stackptr--; if(__b2c__stackptr < 0) __b2c__stackptr=0;" >> $g_CFILE

    # Get the string from stack
    if [[ $(Check_String_Type ${1}) -eq 1 ]]
    then
	echo "if(__b2c__typestack[__b2c__stackptr] == 1) {__b2c__assign = (char*)calloc(strlen(__b2c__stringstack[__b2c__stackptr])+1, sizeof(char));" >> $g_CFILE
	echo "strcpy(__b2c__assign, __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" >> $g_CFILE
	# Now see if we have a assoc or a normal variable
	if [[ "${1}" = +(*\(*\)) ]]
	then
	    STR=${1#*\(}
	    echo "__b2c__${1%%\(*}_loc = __b2c__${1%%\(*}__add(${STR};" >> $g_CFILE
	    echo "__b2c__STRFREE(__b2c__${1%%\(*}_loc->value); __b2c__${1%%\(*}_loc->value = __b2c__assign;" >> $g_CFILE
	    # Check for relations
	    Relate_Recurse "${1%%\(*}" "${STR}" "${1}" "-1"
	else
	    echo "__b2c__STRFREE(${1}); ${1} = __b2c__assign;" >> $g_CFILE
	fi
    else
	# Now see if we have an assoc or a normal variable
	if [[ "${1}" = +(*\(*\)) ]]
	then
	    STR=${1#*\(}
	    echo "__b2c__${1%%\(*}_loc = __b2c__${1%%\(*}__add(${STR};" >> $g_CFILE
	    if [[ "$CHECK" = +(*double*) || "$CHECK" = +(*float*) || "$CHECK" = +(*FLOATING*) ]]
	    then
		echo "__b2c__${1%%\(*}_loc->value = __b2c__doublestack[__b2c__stackptr];" >> $g_CFILE
	    else
		echo "__b2c__${1%%\(*}_loc->value = __b2c__longstack[__b2c__stackptr];" >> $g_CFILE
	    fi
	    # Check for relations
	    Relate_Recurse "${1%%\(*}" "${STR}" "${1}" "-1"
	else
	    if [[ "$CHECK" = +(*double*) || "$CHECK" = +(*float*) || "$CHECK" = +(*FLOATING*) ]]
	    then
		echo "if(__b2c__typestack[__b2c__stackptr] == 2) ${1} = __b2c__doublestack[__b2c__stackptr];" >> $g_CFILE
	    else
		echo "if(__b2c__typestack[__b2c__stackptr] == 3) ${1} = __b2c__longstack[__b2c__stackptr];" >> $g_CFILE
	    fi
	fi
    fi
}

#-----------------------------------------------------------

function Handle_SubFunc
{
    typeset ARGS TOKEN LEN CHAR DIM ARR CHECK SIZE CURFUNC

    # Check argument
    if [[ $(echo ${1}) = "SUB" || $(echo ${1}) = "FUNCTION" ]]
    then
	echo -e "\nSyntax error: empty SUB/FUNCTION at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if we are in a sub already
    if [[ -n $g_FUNCNAME ]]
    then
	echo -e "\nSyntax error: cannot define a SUB/FUNCTION within a SUB/FUNCTION at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the funcname
    if [[ ${1} = +(*\(*) ]]
    then
        g_ORIGFUNCNAME=$(echo ${1%%\(*}"(")
        g_PROTOTYPE=$(echo ${1%%\(*}"(")
        if [[ ${1} = +(* TYPE *) ]]
        then
            g_FUNCTYPE=${1##* TYPE }
        fi
    else
        if [[ ${1} = +(* TYPE *) ]]
        then
            g_FUNCTYPE=${1##* TYPE }
            g_ORIGFUNCNAME="${1%% TYPE *}("
            g_PROTOTYPE="${1%% TYPE *}("
        else
            g_ORIGFUNCNAME=$(echo ${1}"(")
            g_PROTOTYPE=$(echo ${1}"(")
        fi
    fi
    CURFUNC=$(echo ${g_ORIGFUNCNAME%%\(*})

    if [[ "${1}" = +(* TYPE *) ]]
    then
	ARGS=$(echo ${1%% TYPE *})
    else
	ARGS=$(echo ${1})
    fi

    # Get original function name
    if [[ "${ARGS}" = +(*\(*\)*) ]]
    then
	g_FUNCNAME=$(echo ${ARGS%%\(*})
    else
	g_FUNCNAME=$(echo ${ARGS})
    fi

    # Start miniparser to duplicate string arguments, convert spaces
    ARGS=$(echo "${ARGS#*\(}")

    # If there are no arguments to the function at all
    if [[ ${ARGS} != +(*\)) || -z $(echo ${ARGS%%\)*}) ]]
    then
	g_ORIGFUNCNAME="${g_ORIGFUNCNAME} void)"
	g_PROTOTYPE="${g_PROTOTYPE} void)"
    else
        while [[ -n ${ARGS} ]]
        do
	    # Get the arguments
            TOKEN=$(Mini_Parser "${ARGS}")
            ARGS="${ARGS:${#TOKEN}+1}"

	    if [[ $TOKEN = +(*VAR *) ]]
	    then
	        TOKEN=$(echo ${TOKEN//\)/})
		if [[ $ARGS = +(*,*) ]]
		then
		    echo -e "\nSyntax error: variable argument list cannot be followed by other arguments at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		elif [[ $g_PROTOTYPE = +(*,*) ]]
		then
		    echo -e "\nSyntax error: variable argument list cannot be preceded by other arguments at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		fi
		if [[ "${TOKEN}" != +(* SIZE *) ]]
		then
		    echo -e "\nSyntax error: variable argument list lacks SIZE argument at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		fi
		ARR=${TOKEN#* }; ARR=${ARR%%SIZE *}; SIZE=${TOKEN##* }
		if [[ "${ARR}" != +(*${g_STRINGSIGN}*) ]]
		then
		    echo -e "\nSyntax error: variable argument list is not string at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		fi
		# These are in the function header, and do not exist yet - no need to check with Get_Var
		g_STRINGARGS="$g_STRINGARGS long ${SIZE};"
		Save_Func_Var ${SIZE} "${CURFUNC}" "long"
		Save_Func_Var ${ARR} "${CURFUNC}" "char**"
		g_STRINGARGS="$g_STRINGARGS long __b2c__var_$ARR = $g_OPTION_BASE; va_list __b2c__ap; char **${ARR} = NULL; char* __b2c__va = NULL; $ARR = (char **)realloc($ARR, (__b2c__var_$ARR+1) * sizeof(char*));"
		g_STRINGARGS="$g_STRINGARGS va_start(__b2c__ap, __b2c__name); if(__b2c__name != NULL) ${ARR}[__b2c__var_$ARR] = __b2c__strdup(__b2c__name); else ${ARR}[__b2c__var_$ARR] = NULL; while (${ARR}[__b2c__var_$ARR] != NULL) {__b2c__var_$ARR++; $ARR = (char **)realloc($ARR, (__b2c__var_$ARR+1) * sizeof(char*));"
		g_STRINGARGS="$g_STRINGARGS __b2c__va = va_arg(__b2c__ap, char*); if(__b2c__va!=NULL) ${ARR}[__b2c__var_$ARR] = __b2c__strdup(__b2c__va); else ${ARR}[__b2c__var_$ARR] = NULL; }"
		g_STRINGARGS="$g_STRINGARGS va_end(__b2c__ap); ${SIZE} = __b2c__var_$ARR - $g_OPTION_BASE; if(__b2c__var_$ARR > 0) __b2c__var_$ARR--;"
		g_PROTOTYPE="__${g_PROTOTYPE}char*, ..."
		g_ORIGFUNCNAME="${g_ORIGFUNCNAME}char *__b2c__name, ..."
		g_STRINGARRAYS="$g_STRINGARRAYS if($ARR != NULL) {for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr<=__b2c__var_$ARR; __b2c__ctr++) { __b2c__STRFREE($ARR[__b2c__ctr]); } free($ARR);}"
		# Add macro in case of VAR argument
		echo "#define ${g_FUNCNAME}(...) __${g_FUNCNAME}(__VA_ARGS__, NULL)" >> $g_HFILE
		g_ORIGFUNCNAME="__${g_ORIGFUNCNAME}"
	    elif [[ ${TOKEN} = +(*STRING *) || ${TOKEN} = +(*char\* *) || ${TOKEN} = +(*${g_STRINGSIGN}*) ]]
	    then
                TOKEN=$(echo ${TOKEN%\)*})
		# Add type if it is missing
		if [[ ${TOKEN} != +(* *) ]]
		then
		    TOKEN="char* ${TOKEN}"
		fi
                # Check if already declared
                if [[ -z $(Get_Var ${TOKEN##* } ${g_FUNCNAME}) ]]
	        then
		    Save_Func_Var "${TOKEN##* }" "${CURFUNC}" "${TOKEN% *}"
                else
                    if [[ $g_SEMANTIC -eq 0 ]]
                    then
	                echo -e "\nWarning: variable '${TOKEN##* }' in function header at line $g_COUNTER in file '$g_CURFILE' was defined previously!"
                    fi
	        fi
		DIM=${TOKEN##*\[}; ARR=${TOKEN##* }
		if [[ $TOKEN != +(*${g_STRINGSIGN}*) && $TOKEN = +(*\[*\]*) ]]
		then
		    g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE]"
		    g_STRINGARGS="$g_STRINGARGS char** ${ARR%%\[*} = __b2c_${ARR%%\[*};"
		    g_PROTOTYPE="$g_PROTOTYPE ${TOKEN}"
		elif [[ $TOKEN != +(*${g_STRINGSIGN}*) ]]
		then
		    g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN% *} __b2c_${TOKEN##* }"
		    g_STRINGARGS="$g_STRINGARGS ${TOKEN% *} ${TOKEN##* } = __b2c_${TOKEN##* };"
		    g_PROTOTYPE="$g_PROTOTYPE ${TOKEN}"
		elif [[ $TOKEN = +(*\[*\]*) ]]
		then
		    if [[ -z ${DIM%%\]*} ]]
		    then
			g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN}"
			g_PROTOTYPE="$g_PROTOTYPE ${TOKEN}"
		    else
			g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE]"
			g_STRINGARGS="$g_STRINGARGS char *${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE] = { NULL };"
			g_STRINGARGS="$g_STRINGARGS for(__b2c__ctr=0; __b2c__ctr<${DIM%%\]*}+$g_OPTION_BASE; __b2c__ctr++){if(__b2c_${ARR%%\[*}[__b2c__ctr]!=NULL) ${ARR%%\[*}[__b2c__ctr] = __b2c__strdup(__b2c_${ARR%%\[*}[__b2c__ctr]);}"
			g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<${DIM%%\]*}+$g_OPTION_BASE; __b2c__ctr++) { __b2c__STRFREE(${ARR%%\[*}[__b2c__ctr]); }"
			g_PROTOTYPE="$g_PROTOTYPE char *__b2c_${TOKEN##* }"
		    fi
		else
		    g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${TOKEN##* }"
		    g_STRINGARGS="$g_STRINGARGS char*${TOKEN##* } = NULL; ${TOKEN##* } = __b2c_Copy_String(${TOKEN##* }, __b2c_${TOKEN##* });"
		    g_LOCALSTRINGS="$g_LOCALSTRINGS ${TOKEN##* }"
		    g_PROTOTYPE="$g_PROTOTYPE ${TOKEN}"
		fi
	    else
                TOKEN=$(echo ${TOKEN%\)*})
		# Add type if it is missing
		if [[ ${TOKEN} != +(* *) && ${TOKEN} != +(DIR*|FILE*|int*|short*|long*|float*|double*|char*|void*|STRING*|NUMBER*|FLOATING*) ]]
		then
		    if [[ ${TOKEN} = +(*${g_FLOATSIGN}) ]]
		    then
			TOKEN="double ${TOKEN}"
		    else
			TOKEN="${g_VARTYPE} ${TOKEN}"
		    fi
                fi
                # Check if already declared
                if [[ -z $(Get_Var ${TOKEN##* } ${g_FUNCNAME}) ]]
	        then
		    Save_Func_Var "${TOKEN##* }" "${CURFUNC}" "${TOKEN% *}"
                else
                    if [[ $g_SEMANTIC -eq 0 ]]
                    then
	                echo -e "\nWarning: variable '${TOKEN##* }' in function header at line $g_COUNTER in file '$g_CURFILE' was defined previously!"
                    fi
	        fi
		if [[ $TOKEN = +(*\[*\]*\]*) ]]
		then
		    echo -e "\nSyntax error: cannot pass multidimensional numeric array at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		elif [[ $TOKEN = +(*\[\]*) ]]
		then
		    g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN}"
		elif [[ $TOKEN = +(*\[*\]*) ]]
		then
		    DIM=${TOKEN##*\[}; ARR=${TOKEN##* }
		    g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN%% *} __b2c_${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE]"
		    g_STRINGARGS="$g_STRINGARGS ${TOKEN%% *} ${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE] = { 0 };"
                    g_STRINGARGS="$g_STRINGARGS memmove(${ARR%%\[*}, __b2c_${ARR%%\[*}, (${DIM%%\]*}+$g_OPTION_BASE)*sizeof(${TOKEN%% *}));"
		elif [[ $TOKEN = +(*VAR *) ]]
		then
		    echo -e "\nSyntax error: variable argument list cannot be followed by other arguments at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN}"
		fi
		g_PROTOTYPE="$g_PROTOTYPE ${TOKEN}"
	    fi
	    if [[ -n ${ARGS} ]]
	    then
		g_ORIGFUNCNAME="${g_ORIGFUNCNAME},"
		g_PROTOTYPE="${g_PROTOTYPE},"
	    else
		g_ORIGFUNCNAME="${g_ORIGFUNCNAME})"
		g_PROTOTYPE="${g_PROTOTYPE})"
	    fi
        done
    fi

    # Make symbol known to parser
    g_IMPORTED="$g_FUNCNAME $g_IMPORTED"

    # Save CATCH routine
    g_ORIGCATCHGOTO="$g_CATCHGOTO"
    g_ORIGCATCH_USED=${g_CATCH_USED}
    g_CATCHGOTO="__B2C__PROGRAM__EXIT"
    g_CATCH_USED=0
    g_STRINGARGS="$g_STRINGARGS __b2c__catch_set_backup = __b2c__catch_set; __b2c__catch_set = 0;"
    
    # Local string buffer
    g_LOCAL_SBUFFER="${g_LOCAL_SBUFFER} char* __b2c__sbuffer_${g_FUNCNAME}[__b2c_STRING_FUNC] = { NULL };"
    g_STRINGARGS="$g_STRINGARGS char **__b2c__sbuffer_backup = __b2c__sbuffer; __b2c__sbuffer = __b2c__sbuffer_${g_FUNCNAME}; int __b2c__sbuffer_ptr_backup = __b2c__sbuffer_ptr;"

    # Switch to header file
    g_COPY_CFILE=$g_CFILE
    g_COPY_COUNTER=$g_COUNTER
    g_CFILE=${g_CFILE%.*}.${g_FUNCNAME}.tmp

    touch $g_CFILE
}

#-----------------------------------------------------------

function Handle_Endsub
{
    typeset STR TFIL i TYPE

    # Check if we're in a SUB
    if [[ -z $g_FUNCNAME ]]
    then
	echo -e "\nSyntax error: ENDSUB outside SUB at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Put prototype to header file
    if [[ ${g_PROTOTYPE} != +(*::*) ]]
    then
        echo "void ${g_PROTOTYPE};" >> $g_HFILE
    fi
    g_PROTOTYPE=

    # Get original function name
    TFIL=${g_CURFILE##*/}
    echo "/* Created with Shell BaCon $g_VERSION - (c) Peter van Eerten - MIT License */" > ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "#undef __b2c_filename" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "#define __b2c_filename \"$g_CURFILE\"" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "#undef __b2c__exitval" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "#define __b2c__exitval" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    if [[ "$g_ORIGFUNCNAME" = +(* \(*\)*) ]]
    then
	echo "void ${g_ORIGFUNCNAME} {" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    elif [[ "$g_ORIGFUNCNAME" = +(*\(*\)*) ]]
    then
	echo "void ${g_ORIGFUNCNAME} {" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    else
	echo "void ${g_FUNCNAME}(void) {" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    fi

    # Finalize sub
    echo "${g_STRINGARGS}" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    cat $g_CFILE >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h

    # Free strings variables if there are any
    echo "${g_STRINGARRAYS}" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    for STR in $g_LOCALSTRINGS
    do
	echo "__b2c__STRFREE(${STR});" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    done
    if [[ $g_CATCH_USED -eq 1 ]]
    then
        echo "__B2C__PROGRAM__EXIT: ;" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    fi
    echo "__b2c__catch_set = __b2c__catch_set_backup; __b2c__sbuffer = __b2c__sbuffer_backup; __b2c__sbuffer_ptr = __b2c__sbuffer_ptr_backup;" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "}" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h

    echo "#undef __b2c_lineno" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h
    echo "#define __b2c_lineno $g_COUNTER" >> ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h

    # Include header file
    if [[ ${g_INCLUDE_FILES} != +(*${TFIL%.*}.$g_FUNCNAME.h*) ]]
    then
	g_INCLUDE_FILES="$g_INCLUDE_FILES ${TFIL%.*}.$g_FUNCNAME.h"
    fi

    # Add to total filelist
    g_TMP_FILES="$g_TMP_FILES ${g_TEMPDIR}/${TFIL%.*}.$g_FUNCNAME.h"

    # Delete temp funcfile
    rm $g_CFILE

    # Restore mainfile
    g_CFILE=$g_COPY_CFILE

    # Restore CATCH routine
    g_CATCHGOTO="$g_ORIGCATCHGOTO"
    g_CATCH_USED=${g_ORIGCATCH_USED}

    # Reset variables
    g_ORIGFUNCNAME=
    g_FUNCNAME=
    g_LOCALSTRINGS=
    g_STRINGARRAYS=
    g_STRINGARGS=
}

#-----------------------------------------------------------

function Handle_Deffn
{
    typeset SYM STR
    typeset -i CNT
	
    # Check if we have an argument at all
    if [[ "$1" = "DEF" ]]
    then
	echo -e "\nSyntax error: empty DEF FN at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Translate to C macro
    SYM=${1#* }

    STR=${SYM#*=}

    echo "#define ${SYM%%=*} (${STR})" >> $g_HFILE

    if [[ $(echo ${SYM%%=*}) = +(*${g_STRINGSIGN}) ]]
    then
        # Count the amount of string functions by counting '$('
        let CNT=0
        while [[ $STR = +(*$g_STRINGSIGN\(*) ]]
        do
            STR=${STR#*$g_STRINGSIGN\(}
            ((CNT+=1))
        done
        ((g_STRING_FUNC+=$CNT))
    fi

    # Make symbol known to parser
    g_IMPORTED="${SYM%%\(*} $g_IMPORTED"
}

#-----------------------------------------------------------

function Handle_Const
{
    typeset STR
    typeset -i CNT

    # Check if we have an argument at all
    if [[ "$1" = "CONST" ]]
    then
	echo -e "\nSyntax error: empty CONST at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    STR=$(echo ${1#*=})

    if [[ $(echo ${1%%=*}) = +(*${g_STRINGSIGN}) ]]
    then
        echo "#define $(echo ${1%%=*}) ${STR}" >> $g_HFILE
        # Count the amount of string functions by counting '$('
        let CNT=0
        while [[ $STR = +(*$g_STRINGSIGN\(*) ]]
        do
            STR=${STR#*$g_STRINGSIGN\(}
            ((CNT+=1))
        done
        ((g_STRING_FUNC+=$CNT))
    else
        echo "#define $(echo ${1%%=*}) (${STR})" >> $g_HFILE
    fi
}

#-----------------------------------------------------------

function Handle_Seek
{
    typeset FILE OFFSET WHENCE

    # Check if we have an argument at all
    if [[ "$1" = "SEEK" ]]
    then
	echo -e "\nSyntax error: empty SEEK at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if TO is available
    if [[ "$1" != +(* OFFSET *) ]]
    then
	echo -e "\nSyntax error: missing OFFSET in SEEK statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the variablename without surrounding spaces
    FILE=$(echo ${1%% OFFSET *})

    # Get filedescriptor
    OFFSET=$(echo ${1##* OFFSET })

    WHENCE=

    # Check if WHENCE is available
    if [[ "$1" = +(* WHENCE *) ]]
    then
	WHENCE=${OFFSET##* WHENCE }
	OFFSET=${OFFSET%% WHENCE *}
    fi

    # Convert to C function
    case $WHENCE in
	+(START) )
	    echo "fseek($FILE, $OFFSET, SEEK_SET);" >> $g_CFILE;;
	+(CURRENT) )
	    echo "fseek($FILE, $OFFSET, SEEK_CUR);" >> $g_CFILE;;
	+(END) )
	    echo "fseek($FILE, $OFFSET, SEEK_END);" >> $g_CFILE;;
	*)
	    echo "fseek($FILE, $OFFSET, SEEK_SET);" >> $g_CFILE;;
    esac
}

#-----------------------------------------------------------

function Handle_Copy
{
    typeset FROM TO SIZE

    # Check if we have an argument at all
    if [[ "$1" = "COPY" ]]
    then
	echo -e "\nSyntax error: empty COPY at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in COPY statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the filename and copyname
    FROM=$(echo ${1%% TO *})
    TO=$(echo ${1##* TO })

    if [[ ${TO} = +(* SIZE *) ]]
    then
        SIZE=$(echo ${TO##* SIZE })
        TO=$(echo ${TO%% SIZE *})
    fi

    # Translate to C function
    if [[ -z $SIZE ]]
    then
        echo "__b2c__inFile = fopen((const char*)$FROM, \"r\"); __b2c__outFile = fopen((const char*)$TO, \"w\");" >> $g_CFILE
        echo "while ((__b2c__Byte = fread(__b2c__input__buffer, sizeof(char), sizeof(__b2c__input__buffer), __b2c__inFile)) > 0){" >> $g_CFILE
        echo "if (fwrite(__b2c__input__buffer, sizeof(char), __b2c__Byte, __b2c__outFile) != __b2c__Byte) {if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"COPY\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
        echo "} fclose(__b2c__inFile); fclose(__b2c__outFile);" >> $g_CFILE
    else
	echo "if (__b2c__trap){if(__b2c__memory__check((char*)${TO}, sizeof(__b2c__MEMTYPE)*${SIZE})) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"COPY\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
        if [[ ${FROM} = +(*${g_STRINGSIGN}*) ]]
        then
            echo "for(__b2c__ctr=0;__b2c__ctr<${SIZE};__b2c__ctr++){__b2c__STRFREE(${TO}[__b2c__ctr+$g_OPTION_BASE]); ${TO}[__b2c__ctr+$g_OPTION_BASE] = NULL;" >> $g_CFILE
            echo "if(${FROM}[__b2c__ctr+$g_OPTION_BASE]!=NULL) ${TO}[__b2c__ctr+$g_OPTION_BASE]=strdup(${FROM}[__b2c__ctr+$g_OPTION_BASE]);}" >> $g_CFILE
        else
            echo "memmove((void*)${TO}, (void*)${FROM}, sizeof(__b2c__MEMTYPE)*${SIZE});" >> $g_CFILE
        fi
    fi
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi
}

#-----------------------------------------------------------

function Handle_Rename
{
    typeset FROM TO

    # Check if we have an argument at all
    if [[ "$1" = "RENAME" ]]
    then
	echo -e "\nSyntax error: empty RENAME at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi
    
    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in RENAME statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the filename and copyname
    FROM=$(echo ${1%% TO *})
    TO=$(echo ${1##* TO })

    # Translate to C function
    echo "if(rename($FROM, $TO) < 0) {if(__b2c__trap){ERROR = 9; if(!__b2c__catch_set) RUNTIMEERROR(\"RENAME\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi
}

#-----------------------------------------------------------

function Handle_Color
{
    typeset TO FROM BFG COL

    # Check if we have an argument at all
    if [[ "$1" = "COLOR" ]]
    then
	echo -e "\nSyntax error: empty COLOR at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if we need to reset
    if [[ "$1" = +(*RESET*) ]]
    then
	echo "fputs(\"\033[0m\", stdout); fflush(stdout);" >> $g_CFILE
    elif [[ "$1" = +(*INTENSE*) ]]
    then
	echo "fputs(\"\033[1m\", stdout); fflush(stdout);" >> $g_CFILE
    elif [[ "$1" = +(*INVERSE*) ]]
    then
	echo "fputs(\"\033[7m\", stdout); fflush(stdout);" >> $g_CFILE
    elif [[ "$1" = +(*NORMAL*) ]]
    then
	echo "fputs(\"\033[22m\", stdout); fflush(stdout);" >> $g_CFILE
    # Check if TO is available
    elif [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in COLOR statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    else
	# Get the target and colorname
	FROM=$(echo ${1%% TO *})
	case $FROM in
	    FG)
		BFG=3;;
	    BG)
		BFG=4;;
	    [01])
		((BFG=${FROM}+3));;
	    *)
		BFG=${FROM};;
	esac

	TO=$(echo ${1##* TO })
	case $TO in
	    BLACK)
		COL=0;;
	    RED)
		COL=1;;
	    GREEN)
		COL=2;;
	    YELLOW)
		COL=3;;
	    BLUE)
		COL=4;;
	    MAGENTA)
		COL=5;;
	    CYAN)
		COL=6;;
	    WHITE)
		COL=7;;
	    *)
		COL=${TO};;
	esac

	# Now select color
	echo "fprintf(stdout,\"\033[%ld%ldm\", (long)${BFG}, (long)${COL}); fflush(stdout);" >> $g_CFILE
    fi
}

#-----------------------------------------------------------

function Handle_Gotoxy
{
    typeset ARG TOKEN

    # Check if we have an argument at all
    if [[ "$1" = "GOTOXY" ]]
    then
	echo -e "\nSyntax error: empty GOTOXY at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the target and colorname
    if [[ "$1" = +(*,*) ]]
    then
        TOKEN=$(Mini_Parser "${1}")
        ARG="${1:${#TOKEN}+1}"
    else
	echo -e "\nSyntax error: missing coordinate in GOTOXY at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Translate to C
    echo "fprintf(stdout, \"\033[%ld;%ldH\",(long)(${ARG}),(long)(${TOKEN}));fflush(stdout);" >> $g_CFILE
}

#-----------------------------------------------------------

function Handle_Split
{
    typeset SOURCE REST BY TO SIZE STATIC

    # Check if we have an argument at all
    if [[ "$1" = "SPLIT" ]]
    then
	echo -e "\nSyntax error: empty SPLIT at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi
    
    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in SPLIT statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if SIZE is available
    if [[ "$1" != +(* SIZE *) ]]
    then
	echo -e "\nSyntax error: missing SIZE in SPLIT statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Split up arguments
    if [[ "$1" != +(* BY *) ]]
    then
	SOURCE=$(echo ${1%% TO *})
	REST=$(echo ${1##* TO })
	BY="__b2c__option_delim"
    else
        SOURCE=$(echo ${1%% BY *})
        REST=$(echo ${1##* BY })
        BY=$(echo ${REST%% TO *})
        REST=$(echo ${REST##* TO })
    fi

    TO=$(echo ${REST%% SIZE *})
    SIZE=$(echo ${REST##* SIZE })

    if [[ $SIZE = +(* STATIC*) ]]
    then
        SIZE=${SIZE%% STATIC*}
        STATIC=1
    else
        STATIC=0
    fi

    # Variable may not be array, these should be defined with DECLARE
    if [[ "${SIZE}" != +(*\[*\]*) && "${SIZE}" != +(*.*) && "${SIZE}" != +(*\(*\)*) && "${SIZE}" != +(*-\>*) ]]
    then
	# Declare variable if not done yet, assuming long
        if [[ -z $(Get_Var ${SIZE} ${g_FUNCNAME}) ]]
	then
            Register_Numeric ${SIZE}
	fi
    fi

    # Translate to C code
    if [[ -n $g_FUNCNAME ]]
    then
	if [[ $g_STRINGARGS != +(*${TO}*) ]]
	then
	    g_STRINGARGS="$g_STRINGARGS char **${TO} = NULL;" 
            Save_Func_Var "${TO}" "$g_FUNCNAME" "char*"
	fi
    else
        if [[ -z $(Get_Var ${TO}) ]]
	then
	    echo "char **$TO = NULL;" >> $g_HFILE
            Save_Main_Var "${TO}" "char*"
	fi
    fi

    # If the split array was used before in a loop, clear it
    if [[ $TO = +(*${g_STRINGSIGN}*) ]]
    then
        echo "if($TO != NULL) {for(__b2c__ctr=0; __b2c__ctr < __b2c_array_${TO}; __b2c__ctr++) {__b2c__STRFREE($TO[__b2c__ctr+$g_OPTION_BASE]); $TO[__b2c__ctr+$g_OPTION_BASE] = NULL;} free($TO); $TO = NULL;}" >> $g_CFILE
    fi

    # Save information needed for a REDIM
    if [[ -n $g_FUNCNAME ]]
    then
        if [[ $g_STRINGARGS != +(*__b2c_array_${TO}*) ]]
        then
            g_STRINGARGS="$g_STRINGARGS long __b2c_array_${TO} = 0;"
            Save_Func_Var "__b2c_array_${TO}" "$g_FUNCNAME" "long"
        fi
    else
	echo "long __b2c_array_${TO} = 0;" >> $g_HFILE
        Save_Main_Var "__b2c_array_${TO}" "long"
    fi

    # Run the SPLIT code
    if [[ $(Check_String_Type ${BY}) -eq 1 || ${BY} = "__b2c__option_delim" ]]
    then
        echo "__b2c__start = __b2c__delim_engine(2, &__b2c_array_${TO}, ${SOURCE}, ${BY}, 0); __b2c__assign = ${SOURCE}; for(__b2c__ctr = 0; __b2c__ctr < __b2c_array_${TO}; __b2c__ctr++)" >> $g_CFILE
        echo "{ __b2c__start = __b2c__delim_engine(1, &__b2c__length, __b2c__assign, ${BY}, 1);" >> $g_CFILE
        echo "${TO} = (char**)realloc(${TO}, (__b2c__ctr + 1 + $g_OPTION_BASE)*sizeof(char*));" >> $g_CFILE
        echo "${TO}[__b2c__ctr+$g_OPTION_BASE] = __b2c__strndup(__b2c__assign + __b2c__start, __b2c__length); __b2c__assign += __b2c__start + __b2c__length + __b2c__len(${BY}); }" >> $g_CFILE
    else
	echo "__b2c__counter = ${BY}; __b2c__length = __b2c__len(${SOURCE}); if(__b2c__counter > __b2c__length) { __b2c__counter = __b2c__length; }" >> $g_CFILE
        echo "__b2c_array_${TO} = (__b2c__length/__b2c__counter)+(__b2c__length%__b2c__counter != 0 ? 1 : 0); ${TO} = (char**)realloc(${TO}, (__b2c_array_${TO}+$g_OPTION_BASE)*sizeof(char*));" >> $g_CFILE
        echo "if(__b2c__counter > 0){ for(__b2c__ctr = 0; __b2c__ctr < __b2c_array_${TO}; __b2c__ctr++)" >> $g_CFILE
	echo "{ ${TO}[__b2c__ctr+$g_OPTION_BASE] = __b2c__strndup(${SOURCE}+__b2c__ctr*__b2c__counter, __b2c__counter); } }" >> $g_CFILE
    fi
    echo "${SIZE} = __b2c_array_${TO};" >> $g_CFILE

    # Add declared array to array list if we are in a function
    if [[ -n $g_FUNCNAME && $g_STRINGARRAYS != +(*${TO}*) ]]
    then
        if [[ $STATIC -eq 0 ]]
        then
            if [[ $TO = +(*${g_STRINGSIGN}*) ]]
	    then
                g_STRINGARRAYS="$g_STRINGARRAYS if(${TO} != NULL) {for(__b2c__ctr=0; __b2c__ctr<__b2c_array_${TO}; __b2c__ctr++) {__b2c__STRFREE($TO[__b2c__ctr+${g_OPTION_BASE}]);} }"
            fi
            g_LOCALSTRINGS="$g_LOCALSTRINGS $TO"
        fi
    fi
}

#-----------------------------------------------------------

function Handle_Join
{
    typeset SOURCE REST BY TO SIZE STR

    # Check if we have an argument at all
    if [[ "$1" = "JOIN" ]]
    then
	echo -e "\nSyntax error: empty JOIN at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi
    
    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in JOIN statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if SIZE is available
    if [[ "$1" != +(* SIZE *) ]]
    then
	echo -e "\nSyntax error: missing SIZE in JOIN statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Split up arguments
    if [[ "$1" != +(* BY *) ]]
    then
	SOURCE=$(echo ${1%% TO *})
	REST=$(echo ${1##* TO })
	BY="EmptyString"
    else
	SOURCE=$(echo ${1%% BY *})
	REST=$(echo ${1##* BY })
	BY=$(echo ${REST%% TO *})
	REST=$(echo ${REST##* TO })
    fi

    TO=$(echo ${REST%% SIZE *})
    SIZE=$(echo ${REST##* SIZE })

    # Check type of var, string?
    if [[ $(Check_String_Type ${TO}) -eq 0 ]]
    then
	echo -e "\nSyntax error: variable ${TO} in JOIN statement must be string at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    else
        if [[ "${TO}" = +(*${g_STRINGSIGN}) && "${TO}" != +(*.*) ]]
	then
            if [[ -z $(Get_Var ${TO} ${g_FUNCNAME}) ]]
	    then
                Register_String "${TO}"
		echo "$TO = __b2c_Copy_String($TO, EmptyString);" >> $g_CFILE
	    fi
	fi
    fi

    echo "${TO} = (char*)__b2c_str_realloc(${TO}, (strlen(${SOURCE}[0+$g_OPTION_BASE])+1)*sizeof(char)); strcpy(${TO}, ${SOURCE}[0+$g_OPTION_BASE]);" >> $g_CFILE

    echo "for(__b2c__ctr=1; __b2c__ctr < ${SIZE}; __b2c__ctr++){if(${SOURCE}[__b2c__ctr+$g_OPTION_BASE]!=NULL){" >> $g_CFILE
    echo "${TO} = (char*)__b2c_str_realloc(${TO}, (strlen(${TO})+strlen(${BY})+strlen(${SOURCE}[__b2c__ctr+$g_OPTION_BASE])+1)*sizeof(char));" >> $g_CFILE
    echo "strcat(${TO}, ${BY}); strcat(${TO}, ${SOURCE}[__b2c__ctr+$g_OPTION_BASE]);} __b2c__SETLEN(${TO}, strlen(${TO})); }" >> $g_CFILE
}

#-----------------------------------------------------------

function Handle_Sort
{
    typeset STR CHECK DIM TYPE VAR TMP DOWN ARG

    # Check if we have an argument at all
    if [[ "$1" = "SORT" ]]
    then
	echo -e "\nSyntax error: empty SORT at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check on SIZE argument
    if [[ ${1} = +(* SIZE *) ]]
    then
	DIM=${1##* SIZE }
	VAR=${1%% SIZE *}
    else
	VAR=${1}
    fi

    # Check on DOWN argument
    if [[ ${1} = +(* DOWN*) ]]
    then
	DIM=${DIM%% DOWN}
	VAR=${VAR%% DOWN}
	DOWN="_down"
    else
	DOWN=
    fi

    # What kind of array are we dealing with? Associative
    CHECK="$(Get_Var __b2c__${VAR}_type_)$(Get_Var __b2c__${VAR}_type_${g_FUNCNAME} ${g_FUNCNAME})"
    if [[ -n $CHECK ]]
    then
        CHECK="assoc"
    else
        # Static Array? Determine data type
        CHECK=$(Get_Var ${VAR} ${g_FUNCNAME})
        if [[ -n $CHECK && ${g_DYNAMICARRAYS} != +(*${VAR}@${g_FUNCNAME}*) ]]
        then
            if [[ -z $DIM ]]
            then
	        if [[ -n $(Get_Var __b2c_array_${VAR} ${g_FUNCNAME}) ]]
                then
	            DIM="__b2c_array_${VAR}"
                else
	            DIM="$(Get_Dim ${VAR})"
                fi
            fi
        else
            # Assuming dynamic array - determine data type
            if [[ -n $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
            then
                if [[ -z $DIM ]]
                then
	            echo -e "\nSyntax error: SORT needs SIZE in case of dynamic array '${VAR}' at line $g_COUNTER in file '$g_CURFILE'!"
	            exit 1
                fi
            fi
        fi
    fi

    # Check DIM size
    echo "if((${DIM}-${g_OPTION_BASE}) < 0) {if(__b2c__trap){ERROR=36; if(!__b2c__catch_set) RUNTIMEERROR(\"SORT\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi

    # Check if it is an assoc array - using Bubble Sort
    if [[ "${CHECK}" = "assoc" ]]
    then
        echo "__b2c__${VAR}_tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__${VAR}_tab); __b2c__counter = __b2c__hashtable_count(&__b2c__${VAR}_tab); while(__b2c__counter > 1) {" >> $g_CFILE
        echo "for(__b2c__ctr = 0; __b2c__ctr < __b2c__counter-1; __b2c__ctr++) {" >> $g_CFILE
        echo "if(__b2c_${ARG}_${VAR}_sort$DOWN(__b2c__hashtable_find(&__b2c__${VAR}_tab, (HASHTABLE_U64)__b2c__${VAR}_tmp[__b2c__ctr]), __b2c__hashtable_find(&__b2c__${VAR}_tab, (HASHTABLE_U64)__b2c__${VAR}_tmp[__b2c__ctr+1])) > 0)" >> $g_CFILE
        echo "{ __b2c__hashtable_swap(&__b2c__${VAR}_tab, __b2c__ctr, __b2c__ctr+1); } } __b2c__counter--; }" >> $g_CFILE
    # Check if we have a string
    elif [[ "${VAR}" = +(*${g_STRINGSIGN}) ]]
    then
	echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}, sizeof(char*), __b2c__sortstr$DOWN);" >> $g_CFILE
    # It is a value
    else
	TYPE=${CHECK}
	if [[ $TYPE = +(*double*) || $TYPE = +(*FLOATING*) ]]
	then
	    echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}, sizeof(double), __b2c__sortnrd$DOWN);" >> $g_CFILE
	elif [[ $TYPE = +(*float*) ]]
	then
	    echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}, sizeof(float), __b2c__sortnrf$DOWN);" >> $g_CFILE
	elif [[ $TYPE = +(*long*) ||  $TYPE = +(*NUMBER*) ]]
	then
	    echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}, sizeof(long), __b2c__sortnrl$DOWN);" >> $g_CFILE
	elif [[ $TYPE = +(*int*) ]]
	then
	    echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}, sizeof(int), __b2c__sortnri$DOWN);" >> $g_CFILE
	elif [[ $TYPE = +(*short*) ]]
	then
	    echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}, sizeof(short), __b2c__sortnrs$DOWN);" >> $g_CFILE
        else
	    echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}, sizeof(char), __b2c__sortnrc$DOWN);" >> $g_CFILE
	fi
    fi
}

#-----------------------------------------------------------

function Handle_Alias
{
    typeset ORG NEW

    # Check if we have an argument at all
    if [[ "$1" = "ALIAS" ]]
    then
	echo -e "\nSyntax error: empty ALIAS at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in ALIAS statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the source string
    ORG=`echo ${1%% TO *} | tr -d "\042"`
    NEW=`echo ${1##* TO } | tr -d "\042"`

    echo "#define $NEW $ORG" >> $g_HFILE
    g_IMPORTED="$NEW $g_IMPORTED"
}

#-----------------------------------------------------------

function Handle_Lookup
{
    typeset SOURCE REST TO SIZE CHECK STATIC ARG

    # Check if we have an argument at all
    if [[ "$1" = "LOOKUP" ]]
    then
	echo -e "\nSyntax error: empty LOOKUP at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in LOOKUP statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if SIZE is available
    if [[ "$1" != +(* SIZE *) ]]
    then
	echo -e "\nSyntax error: missing SIZE in LOOKUP statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the source string
    SOURCE=$(echo ${1%% TO *})
    REST=$(echo ${1##* TO })

    TO=$(echo ${REST%% SIZE *})
    SIZE=$(echo ${REST##* SIZE })

    if [[ $SIZE = +(* STATIC*) ]]
    then
        SIZE=${SIZE%% STATIC*}
        STATIC=1
    else
        STATIC=0
    fi

    # Variable may not be array, these should be defined with DECLARE
    if [[ "${SIZE}" != +(*\[*\]*) && "${SIZE}" != +(*.*) && "${SIZE}" != +(*\(*\)*) && "${SIZE}" != +(*-\>*) ]]
    then
	# Declare variable if not done yet, assuming long
        if [[ -z $(Get_Var ${SIZE} ${g_FUNCNAME}) ]]
	then
            Register_Numeric ${SIZE}
	fi
    fi

    # Translate to C code
    if [[ -n $g_FUNCNAME ]]
    then
	if [[ $g_STRINGARGS != +(*\*\*$TO*) ]]
	then
	    g_STRINGARGS="$g_STRINGARGS char **$TO = NULL; int __b2c_array_$TO = $g_OPTION_BASE;" 
            Save_Func_Var "${TO}" "$g_FUNCNAME" "char*"
            Save_Func_Var "__b2c_array_${TO}" "$g_FUNCNAME" "int"
	fi
    else
        if [[ -z $(Get_Var ${TO}) ]]
	then
	    echo "char **$TO = NULL; int __b2c_array_$TO = $g_OPTION_BASE;" >> $g_HFILE
            Save_Main_Var "${TO}" "char*"
            Save_Main_Var "__b2c_array_${TO}" "int"
	fi
    fi

    # If the split array was used before in a loop, clear it
    echo "if($TO != NULL) {for(__b2c__ctr=0; __b2c__ctr < __b2c_array_$TO; __b2c__ctr++)" >> $g_CFILE
    echo "{__b2c__STRFREE($TO[__b2c__ctr+${g_OPTION_BASE}]);} free($TO); $TO = NULL;} __b2c_array_$TO = $g_OPTION_BASE;" >> $g_CFILE

    # Run the LOOKUP code
    echo "__b2c__${SOURCE}_tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__${SOURCE}_tab); for(__b2c__ctr = 0; __b2c__ctr < __b2c__hashtable_count(&__b2c__${SOURCE}_tab); __b2c__ctr++) {$TO = (char **)realloc($TO, (__b2c_array_$TO + 1) * sizeof(char*));" >> $g_CFILE
    if [[ $TO = +(*${g_STRINGSIGN}*) ]]
    then
        echo "__b2c__${SOURCE}_loc = (__b2c__${SOURCE}_typ*)__b2c__hashtable_find(&__b2c__${SOURCE}_tab, (HASHTABLE_U64)__b2c__${SOURCE}_tmp[__b2c__ctr]); $TO[__b2c_array_$TO++] = __b2c__strdup(__b2c__${SOURCE}_loc->key);" >> $g_CFILE
    else
        echo "$TO[__b2c_array_$TO++] = __b2c__${SOURCE}_loc->key;" >> $g_CFILE
    fi
    echo "} $SIZE = __b2c_array_$TO - $g_OPTION_BASE; if(__b2c_array_$TO > 0) __b2c_array_$TO--;" >> $g_CFILE

    echo "__b2c_array_${TO} = ${SIZE};" >> $g_CFILE

    # Add declared array to array list if we are in a function
    if [[ -n $g_FUNCNAME && $g_STRINGARRAYS != +(*${TO}*) ]]
    then
        if [[ $STATIC -eq 0 ]]
        then
            if [[ $TO = +(*${g_STRINGSIGN}*) ]]
	    then
                g_STRINGARRAYS="$g_STRINGARRAYS if($TO != NULL) {for(__b2c__ctr=0; __b2c__ctr<__b2c_array_$TO; __b2c__ctr++) {__b2c__STRFREE($TO[__b2c__ctr+${g_OPTION_BASE}]);} }"
            fi
            g_LOCALSTRINGS="$g_LOCALSTRINGS $TO"
        fi
    fi
}

#-----------------------------------------------------------

function Handle_Relate
{
    typeset SOURCE TO STR

    # Check if we have an argument at all
    if [[ "$1" = "RELATE" ]]
    then
	echo -e "\nSyntax error: empty RELATE at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in RELATE statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the source string
    SOURCE=$(echo ${1%% TO *})
    TO=`echo ${1##* TO } | tr "," " "`

    # Check if variable is declared as ASSOC
    if [[ -z $(Get_Var __b2c__${SOURCE}_type_)$(Get_Var __b2c__${SOURCE}_type_${g_FUNCNAME} ${g_FUNCNAME}) ]]
    then
	echo -e "\nSyntax error: variable '$SOURCE' not declared as ASSOC in RELATE statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Assign relations
    for STR in ${TO}
    do
        if [[ -z $(Get_Var __b2c__${STR}_type_)$(Get_Var __b2c__${STR}_type_${g_FUNCNAME} ${g_FUNCNAME}) ]]
	then
	    echo -e "\nSyntax error: variable '$STR' not declared as ASSOC in RELATE statement at line $g_COUNTER in file '$g_CURFILE'!"
	    exit 1
	fi
	g_RELATE[${g_RELATE_CTR}]="$SOURCE ${STR}"
	((g_RELATE_CTR+=1))
    done
}

#-----------------------------------------------------------

function Handle_Data
{
    typeset LINE EXP TOKEN

    # Check if we have an argument at all
    if [[ "$1" = "DATA" ]]
    then
	echo -e "\nSyntax error: empty DATA at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    EXP="$1"

    # Start miniparser to see if we need to print something
    while [[ -n ${EXP} ]]
    do
        TOKEN=$(Mini_Parser "${EXP}")
	if [[ "${TOKEN}" = +(*${g_DQUOTESIGN}*) ]]
	then
	    echo -n "${TOKEN}, " >> $STRINGARRAYFILE
            ((g_CCTR+=1))
	else
	    echo -n "${TOKEN}, " >> $FLOATARRAYFILE
            ((g_FCTR+=1))
	fi
        EXP="${EXP:${#TOKEN}+1}"
    done

    # Align properly
    if [[ "${TOKEN}" = +(*${g_DQUOTESIGN}*) ]]
    then
	echo >> $STRINGARRAYFILE
    else
        echo >> $FLOATARRAYFILE
    fi
}

#-----------------------------------------------------------

function Handle_Redim
{
    typeset VAR TO CHECK TYPE

    # Check if we have an argument at all
    if [[ "$1" = "REDIM" ]]
    then
	echo -e "\nSyntax error: empty REDIM at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in REDIM statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the variable and resize
    VAR=$(echo ${1%% TO *})
    TO=$(echo ${1##* TO })

    CHECK=$(Get_Var ${VAR} ${g_FUNCNAME})
    if [[ -z $CHECK ]]
    then
	echo -e "\nSyntax error: cannot REDIM array which is not declared previously at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Delete old data from strings if new size is smaller
    if [[ $(Check_String_Type ${VAR}) -eq 1 ]]
    then
	echo "if(${TO}<__b2c_array_${VAR##*.}) {for(__b2c__ctr=${TO}; __b2c__ctr<__b2c_array_${VAR##*.}; __b2c__ctr++) {__b2c__STRFREE($VAR[__b2c__ctr+$g_OPTION_BASE]);} }" >> $g_CFILE
    fi

    # Realloc
    TYPE=${CHECK}
    echo "${VAR} = (${TYPE}*)realloc(${VAR}, (${TO}+$g_OPTION_BASE)*sizeof(${TYPE}));" >> $g_CFILE

    # Re-initialize records if new area is bigger
    if [[ ${CHECK} = +(*_type) || ${CHECK} = +(*_TYPE) ]]
    then
	echo "if(__b2c_record_${VAR##*.} < ${TO}) { for(__b2c__ctr=__b2c_record_${VAR##*.}+$g_OPTION_BASE; __b2c__ctr<${TO}+$g_OPTION_BASE; __b2c__ctr++) memset(&$VAR[__b2c__ctr], 0, sizeof($CHECK));}" >> $g_CFILE
        echo "__b2c_record_${VAR##*.} = $TO;" >> $g_CFILE

    # Re-initialize strings if new area is bigger
    else
        if [[ $(Check_String_Type ${VAR}) -eq 1 ]]
        then
	    echo "if(${TO}>__b2c_array_${VAR##*.}) {for(__b2c__ctr=__b2c_array_${VAR##*.}; __b2c__ctr<${TO}; __b2c__ctr++) $VAR[__b2c__ctr+$g_OPTION_BASE] = (char*)calloc(1, sizeof(char));}" >> $g_CFILE
        fi
        echo "__b2c_array_${VAR##*.} = $TO;" >> $g_CFILE
    fi

}

#-----------------------------------------------------------

function Handle_Swap
{
    typeset VAR TO CHECK TYPE

    # Check if we have an argument at all
    if [[ "$1" = "SWAP" ]]
    then
	echo -e "\nSyntax error: empty SWAP at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the variable names without spaces
    VAR=`echo ${1%%,*} | tr -d "\040"`
    TO=`echo ${1##*,} | tr -d "\040"`

    # Perform universal swap
    if [[ $(Check_String_Type ${VAR}) -eq 1 && $(Check_String_Type ${TO}) -eq 0 ]]
    then
        echo "__b2c__assign = calloc(${g_MAX_DIGITS}+1, sizeof(char)); if (floor (${TO}) == ${TO}) { __b2c__ctr = snprintf(__b2c__assign, ${g_MAX_DIGITS}, \"%ld\", (long) ${TO}); }" >> $g_CFILE
        echo "else { __b2c__ctr = snprintf (__b2c__assign, ${g_MAX_DIGITS}, \"%g\", (double) ${TO}); } ${TO} = VAL(${VAR}); __b2c__STRFREE(${VAR}); ${VAR} = __b2c__assign;" >> $g_CFILE
    elif [[ $(Check_String_Type ${VAR}) -eq 0 && $(Check_String_Type ${TO}) -eq 1 ]]
    then
        echo "__b2c__assign = calloc(${g_MAX_DIGITS}+1, sizeof(char)); if (floor (${VAR}) == ${VAR}) { __b2c__ctr = snprintf(__b2c__assign, ${g_MAX_DIGITS}, \"%ld\", (long) ${VAR}); }" >> $g_CFILE
        echo "else { __b2c__ctr = snprintf (__b2c__assign, ${g_MAX_DIGITS}, \"%g\", (double) ${VAR}); } ${VAR} = VAL(${TO}); __b2c__STRFREE(${TO}); ${TO} = __b2c__assign;" >> $g_CFILE
    else
        # Determine type
        if [[ $(Check_String_Type ${VAR}) -eq 1 ]]
        then
            TYPE="char*"
        else
            CHECK=$(Get_Var ${VAR} ${g_FUNCNAME})
            if [[ -z $CHECK ]]
            then
	        echo -e "\nSyntax error: cannot determine type of variables in SWAP at line $g_COUNTER in file '$g_CURFILE'!"
	        exit 1
            fi
            # Leave one dimension out to exchange array variables
            TYPE=${CHECK%%\**}
        fi

        # Declare temp variable
        if [[ -n $g_FUNCNAME ]]
        then
            if [[ -z $(Get_Var __b2c__${VAR%%\[*}_swap ${g_FUNCNAME}) ]]
            then
	        g_STRINGARGS="$g_STRINGARGS ${TYPE} __b2c__${VAR%%\[*}_swap;"
                Save_Func_Var "__b2c__${VAR%%\[*}_swap" "${g_FUNCNAME}" "${TYPE}"
            fi
        else
            if [[ -z $(Get_Var __b2c__${VAR%%\[*}_swap) ]]
            then
                echo "${TYPE} __b2c__${VAR%%\[*}_swap;" >> $g_HFILE
                Save_Main_Var "__b2c__${VAR%%\[*}_swap" "${TYPE}"
            fi
        fi
        echo "__b2c__${VAR%%\[*}_swap = ${VAR}; ${VAR} = ${TO}; ${TO} = __b2c__${VAR%%\[*}_swap;" >> $g_CFILE
    fi
}

#-----------------------------------------------------------

function Handle_Setserial
{
    typeset DESC VALUE

    # Check if we have an argument at all
    if [[ "$1" = "SETSERIAL" ]]
    then
	echo -e "\nSyntax error: empty SETSERIAL at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if a mode is available
    if [[ "$1" != +(* IMODE *) && "$1" != +(* OMODE *) && "$1" != +(* CMODE *) && "$1" != +(* LMODE *) && "$1" != +(* OTHER *) && "$1" != +(* SPEED *) ]]
    then
	echo -e "\nSyntax error: no mode specified in SETSERIAL statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    DESC=${1%% *}

    # Get the setting
    if [[ ${1} = +(* OTHER *) ]]
    then
        VALUE=${1##* OTHER }
    elif [[ ${1} = +(* SPEED *) ]]
    then
        VALUE=${1##* SPEED }
    else
        VALUE=${1##*MODE }
    fi

    # Set the option for the file descriptor
    echo "memset (&__b2c__tty, 0, sizeof __b2c__tty); if (tcgetattr (${DESC}, &__b2c__tty) != 0)" >> $g_CFILE
    echo "{if(__b2c__trap){ERROR = 33; if(!__b2c__catch_set) RUNTIMEERROR(\"SETSERIAL\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE

    case $1 in
        +(*IMODE*) )
            if [[ $VALUE = +(*~*) ]]
            then
                echo "__b2c__tty.c_iflag &= ${VALUE};" >> $g_CFILE
            else
                echo "__b2c__tty.c_iflag |= ${VALUE};" >> $g_CFILE
            fi
            ;;
        +(*OMODE*) )
            if [[ $VALUE = +(*~*) ]]
            then
                echo "__b2c__tty.c_oflag &= ${VALUE};" >> $g_CFILE
            else
                echo "__b2c__tty.c_oflag |= ${VALUE};" >> $g_CFILE
            fi
            ;;
        +(*CMODE*) )
            if [[ $VALUE = +(*~*) ]]
            then
                echo "__b2c__tty.c_cflag &= ${VALUE};" >> $g_CFILE
            else
                echo "__b2c__tty.c_cflag |= ${VALUE};" >> $g_CFILE
            fi
            ;;
        +(*LMODE*) )
            if [[ $VALUE = +(*~*) ]]
            then
                echo "__b2c__tty.c_lflag &= ${VALUE};" >> $g_CFILE
            else
                echo "__b2c__tty.c_lflag |= ${VALUE};" >> $g_CFILE
            fi
            ;;
        +(*OTHER*) )
            echo "__b2c__tty.c_cc[${VALUE%=*}] = ${VALUE#*=};" >> $g_CFILE
            ;;
        +(*SPEED*) )
            echo "cfsetospeed (&__b2c__tty, ${VALUE}); cfsetispeed (&__b2c__tty, ${VALUE});" >> $g_CFILE
            ;;
    esac

    echo "if (tcsetattr (${DESC}, TCSANOW, &__b2c__tty) != 0)" >> $g_CFILE
    echo "{if(__b2c__trap){ERROR = 33; if(!__b2c__catch_set) RUNTIMEERROR(\"SETSERIAL\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
    then
        g_CATCH_USED=1
    fi
}

#-----------------------------------------------------------

function Handle_Call
{
    typeset CHECK STR VAR

    # Check if we have an argument at all
    if [[ "$1" = "CALL" ]]
    then
	echo -e "\nSyntax error: empty CALL at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Just call, no assignment
    if [[ "${1}" != +(* TO *) ]]
    then
	if [[ "${1}" = +(*\(*\)*) ]]
	then
	    echo "${1};" >> $g_CFILE
	else
	    echo "${1}();" >> $g_CFILE
	fi
    else
        VAR="${1##*TO }"
        # Check if string is declared
        if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "${VAR}" != +(*.*) ]]
        then
            if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	    then
                Register_String "${VAR}"
	    fi
        # Not a string?
        elif [[ "${VAR}" != +(*\[*\]*) && "${VAR}" != +(*.*) && "${VAR}" != +(*\(*\)*) && "${VAR}" != +(*-\>*) ]]
        then
            if [[ -z $(Get_Var ${VAR} ${g_FUNCNAME}) ]]
	    then
                Register_Numeric ${VAR}
	    fi
        fi

        # String variable?
	if [[ $(Check_String_Type ${VAR}) -eq 1 ]]
	then
            if [[ "${1%% TO*}" = +(*\(*\)*) ]]
            then
                echo "__b2c__assign=(char*)__b2c__strdup(${1%% TO*});" >> $g_CFILE
            else
                echo "__b2c__assign=(char*)__b2c__strdup(${1%% TO*}());" >> $g_CFILE
            fi
            echo "if(__b2c__assign==NULL) __b2c__assign = (char*)calloc(1, sizeof(char));" >> $g_CFILE
            # Now see if we have a assoc or a normal variable
	    if [[ "${VAR}" = +(*\(*\)) ]]
	    then
	        STR=${VAR#*\(}
	        echo "__b2c__${VAR%%\(*}_loc = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE
	        echo "__b2c__STRFREE(__b2c__${VAR%%\(*}_loc->value); __b2c__${VAR%%\(*}_loc->value = __b2c__assign;" >> $g_CFILE
	        # Check for relations
	        Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1"
	    else
                echo "__b2c__STRFREE(${VAR}); ${VAR} = __b2c__assign;" >> $g_CFILE
	    fi
        else
	    # Now see if we have an assoc or a normal variable
	    if [[ "${VAR}" = +(*\(*\)) ]]
	    then
	        STR=${VAR#*\(}
	        echo "__b2c__${VAR%%\(*}_loc = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE
	        if [[ "${1%% TO*}" = +(*\(*\)*) ]]
                then
                    echo "__b2c__${VAR%%\(*}_loc->value = ${1%% TO*};" >> $g_CFILE
                else
                    echo "__b2c__${VAR%%\(*}_loc->value = ${1%% TO*};" >> $g_CFILE
                fi
	        # Check for relations
	        Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1"
            else
	        if [[ "${1%% TO*}" = +(*\(*\)*) ]]
	        then
		    echo "${VAR} = ${1%% TO*};" >> $g_CFILE
	        else
		    echo "${VAR} = ${1%% TO*}();" >> $g_CFILE
                fi
	    fi
	fi
    fi
}

#-----------------------------------------------------------

function Handle_Run
{
    # Local variables
    typeset ARG CHAR TOKEN LINE
    typeset -i LEN ESCAPED IN_STRING

    # Check if we have an argument at all
    if [[ "$1" = "RUN" ]]
    then
	echo -e "\nSyntax error: empty RUN at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Start miniparser to find separate arguments
    let ESCAPED=0
    let IN_STRING=0

    # Skip first doublequote
    let LEN=${#1}-1
    # Replace spaces
    LINE=$(echo ${1// /${g_PARSEVAR}})
    # Line start on character after doublequote
    LINE="${LINE: -$LEN}"

    ARG="\""

    # Get the characters
    until [[ $LEN -eq 1 ]]
    do
	CHAR="${LINE:0:1}"
	case $CHAR in
	    "\\")
		if [[ $ESCAPED -eq 1 ]]
		then
		    ESCAPED=0
                else
		    ESCAPED=1
		    CHAR=
                fi;;
	    "\"")
		if [[ $ESCAPED -eq 1 ]]
		then
		    if [[ $IN_STRING -eq 0 ]]
		    then
			IN_STRING=1
		    else
			IN_STRING=0
		    fi
		    CHAR=
		fi
		ESCAPED=0;;
	    ${g_PARSEVAR})
		if [[ $IN_STRING -eq 0 ]]
		then
		    ARG="$ARG\",\""
		    CHAR=
		fi
		ESCAPED=0;;
	    *)
		ESCAPED=0;;
	esac
	# Convert back to space
	if [[ "${CHAR}" = "${g_PARSEVAR}" ]]
	then
	    ARG="${ARG} "
	else
	    ARG="${ARG}${CHAR}"
	fi
	let LEN=${#LINE}-1
	LINE="${LINE: -$LEN}"
    done

    ARG="${ARG}\""

    # Get first token
    TOKEN=$(Mini_Parser "${ARG}")

    echo "execlp($TOKEN,$ARG, NULL); fflush(stdout);" >> $g_CFILE
}

#-----------------------------------------------------------

function Handle_Save
{
    typeset SYM EXP SIZE TOKEN ARG

    ARG=${@}
    ARG=${ARG#* }

    # Check if we have an argument at all
    if [[ $# -lt 2 ]]
    then
	echo -e "\nSyntax error: empty SAVE/BSAVE/APPEND/BAPPEND at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    elif [[ "${ARG}" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: SAVE/BSAVE/APPEND/BAPPEND without TO at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    else
        SYM="${ARG% TO *}"
        EXP="${ARG##* TO }"
	if [[ ${EXP} = +(* SIZE *) ]]
	then
	    SIZE=${EXP##* SIZE }
	    EXP=${EXP% SIZE *}
	else
	    SIZE=0
	fi
	# How to open the file
	case $1 in
	    SAVE|BSAVE)
		echo "__b2c__outFile = fopen((const char*)${EXP}, \"w\");" >> $g_CFILE;;
	    APPEND|BAPPEND)
		echo "__b2c__outFile = fopen((const char*)${EXP}, \"a\");" >> $g_CFILE;;
	esac
        echo "if(__b2c__outFile == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"SAVE/BSAVE/APPEND/BAPPEND\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
	# Determine length
	case $1 in
	    SAVE|APPEND)
                # Start miniparser to see if we need to save comma separated list
                while [[ -n ${SYM} ]]
                do
                    TOKEN=$(Mini_Parser "${SYM}")
                    Print_Element "${TOKEN}" "__b2c__outFile"
                    SYM="${SYM:${#TOKEN}+1}"
                done
                ;;
	    BSAVE|BAPPEND)
		echo "__b2c__assign = (char*)$SYM; __b2c__ctr = ${SIZE};" >> $g_CFILE
	        echo "if(fwrite(__b2c__assign, 1, __b2c__ctr, __b2c__outFile) != __b2c__ctr){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set)" >> $g_CFILE
                echo "RUNTIMEERROR(\"BSAVE/BAPPEND\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                ;;
	esac
        echo "fclose(__b2c__outFile);" >> $g_CFILE
        if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
        then
            g_CATCH_USED=1
        fi
    fi
}

#-----------------------------------------------------------

function Handle_Map
{
    typeset SOURCE REST BY TO SIZE TYPE STATIC i

    # Check if we have an argument at all
    if [[ "$1" = "MAP" ]]
    then
	echo -e "\nSyntax error: empty MAP at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi
    
    # Check if BY is available
    if [[ "$1" != +(* BY *) ]]
    then
	echo -e "\nSyntax error: missing BY in MAP statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if TO is available
    if [[ "$1" != +(* TO *) ]]
    then
	echo -e "\nSyntax error: missing TO in MAP statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Check if SIZE is available
    if [[ "$1" != +(* SIZE *) ]]
    then
	echo -e "\nSyntax error: missing SIZE in MAP statement at line $g_COUNTER in file '$g_CURFILE'!"
	exit 1
    fi

    # Get the source string
    SOURCE=$(echo ${1%% BY *})
    REST=$(echo ${1##* BY })

    BY=$(echo ${REST%% TO *})
    REST=$(echo ${REST##* TO })

    TO=$(echo ${REST%% SIZE *})
    SIZE=$(echo ${REST##* SIZE })

    if [[ $SIZE = +(* STATIC*) ]]
    then
        SIZE=${SIZE%% STATIC*}
        STATIC=1
    else
        STATIC=0
    fi

    # Remove doublequotes from BY
    BY=$(echo ${BY} | tr -d "\042")

    # Make sure to get the type right
    SOURCE=${SOURCE// /}
    TYPE="long"

    if [[ $(Check_String_Type ${BY}) -eq 1 ]]
    then
        TYPE="char*"
    else
        for i in ${SOURCE//,/ }
        do
	    if [[ $(Get_Var ${i} ${g_FUNCNAME}) = +(*double*|*FLOATING*) ]]
	    then
	        TYPE="double"
	        break
	    fi
        done
    fi

    # Declare target array
    if [[ -z $(Get_Var ${TO} ${g_FUNCNAME}) ]]
    then
        if [[ $g_OPTION_EXPLICIT = "1" || $g_OPTION_EXPLICIT = "TRUE" ]]
        then
	    echo -e "\nSyntax error: OPTION EXPLICIT forces explicit variable declaration at line $g_COUNTER in file '$g_CURFILE'!"
            exit 1
        fi
	if [[ -n $g_FUNCNAME ]]
	then
            echo "${TYPE}* $TO;" >> $g_CFILE
            Save_Func_Var "${TO}" "$g_FUNCNAME" "${TYPE}*"
	else
            echo "${TYPE}* $TO;" >> $g_HFILE
            Save_Main_Var "${TO}" "${TYPE}*"
	fi
        echo "$TO = (${TYPE}*)calloc((size_t)($SIZE+$g_OPTION_BASE), sizeof(${TYPE}));" >> $g_CFILE

        # Cleanup local array members
        if [[ ${TYPE} = "char*" ]]
        then
            g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr<$SIZE+$g_OPTION_BASE; __b2c__ctr++){__b2c__STRFREE($TO[__b2c__ctr]);}"
        fi

	# Not static, then cleanup
	if [[ $STATIC -eq 0 ]]
	then
	    g_LOCALSTRINGS="$g_LOCALSTRINGS $TO"
	fi
    fi

    # Create the C code
    echo "for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr<${SIZE}+$g_OPTION_BASE; __b2c__ctr++){" >> $g_CFILE
    if [[ ${TYPE} = "char*" ]]
    then
        echo "${TO}[__b2c__ctr] = __b2c_Copy_String(${TO}[__b2c__ctr], ${BY}(${SOURCE//,/[__b2c__ctr],}[__b2c__ctr])); }" >> $g_CFILE
    else
        echo "${TO}[__b2c__ctr] = ${BY}(${SOURCE//,/[__b2c__ctr],}[__b2c__ctr]); }" >> $g_CFILE
    fi
}

#-----------------------------------------------------------
#
# Simple parser to tokenize line.
#
# Each line should begin with a statement.
# The rest of the line may contain functions, these are
#   converted using C macros.
#
#-----------------------------------------------------------

function Parse_Line
{
    typeset FOUND SYM INC COPY_COUNTER COPY_CURFILE STATEMENT CHECK FLINES TXT
    typeset LEN SEQ TOTAL EXP LINE TO_PARSE NEWFEED TRC_BACKUP TOKEN

    if [[ -z ${1} ]]
    then
        return
    fi

    # Get statement without spaces
    if [[ ${1} != +(*\*/) ]]
    then
        STATEMENT=$(echo ${1%% *})
    else
        STATEMENT=$(echo ${1})
    fi

    # See if we need to pass C code
    if [[ $g_USE_C -eq 1 ]]
    then
	if [[ ${@} = +(ENDUSEC|END USEC) ]]
	then
	    let g_USE_C=0
	elif [[ ${@} = +(ENDENUM|END ENUM) ]]
	then
	    let g_USE_C=0
            echo "};" >> $g_CFILE
	else
	    echo "${1}" >> $g_CFILE
	fi
    elif [[ $g_USE_H -eq 1 ]]
    then
	if [[ ${@} = +(ENDUSEH|END USEH) ]]
	then
	    let g_USE_H=0
	elif [[ ${@} = +(ENDENUM|END ENUM) || ${@} = +(ENDCLASS|END CLASS) ]]
	then
	    let g_USE_H=0
            echo "};" >> $g_HFILE
	else
	    echo "${1}" >> $g_HFILE
	fi
    # This covers both 1 line and multiline comments with */
    elif [[ "$STATEMENT" = +(*\*/) ]]
    then
        g_COMMENT="false"
    elif [[ ${g_COMMENT} = "false" ]]
    then
	case "${STATEMENT}" in
	    "USEC")
		let g_USE_C=1;;
	    "USEH")
		let g_USE_H=1;;
	    "CLASS")
		let g_USE_H=1
                echo "class ${1#* } {" >> $g_HFILE;;
	    "PRINT")
		Handle_Print "${1#* }" "stdout";;
	    "EPRINT")
		Handle_Print "${1#* }" "stderr";;
	    "INPUT")
		Handle_Input "${1#* }";;
	    "FOR")
                ((g_LOOPCTR+=1))
		Handle_For "${1#* }";;
	    "NEXT")
		echo "}" >> $g_CFILE
                if [[ $g_LOOPCTR -gt 0 && $g_OPTION_BREAK = +(1*|TRUE*) ]]
                then
                    ((g_LOOPCTR-=1))
                    if [[ $g_LOOPCTR -gt 0 ]]
                    then
                        echo "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" >> $g_CFILE
                    fi
                fi;;
	    "IF")
		# Check if THEN is available
		if [[ "${1}" != +(* THEN*) ]]
		then
		    echo -e "\nSyntax error: missing THEN in IF statement at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    SYM="${1#* }"
		    # Translate function to C function
                    Parse_Equation "${SYM% THEN*}"
		    echo "if(${g_EQUATION}){" >> $g_CFILE
		    if [[ ${SYM##* THEN } != +(*THEN*) ]]
		    then
                        TRC_BACKUP=${g_TRACE}
                        g_TRACE=0
			Tokenize "${SYM##* THEN }"
                        g_TRACE=${TRC_BACKUP}
                        echo "}" >> $g_CFILE
		    fi
		fi;;
	    "ELIF")
		# Check if THEN is available
		if [[ "${1}" != +(* THEN*) ]]
		then
		    echo -e "\nSyntax error: missing THEN in ELIF statement at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    SYM="${1#* }"
		    # Translate function to C function
                    Parse_Equation "${SYM% THEN*}"
		    if [[ ${SYM##* THEN } != +(*THEN*) ]]
		    then
		        echo "else if(${g_EQUATION}){" >> $g_CFILE
                        g_TRACE_PREFIX="ELIF "
			Tokenize "${SYM##* THEN }"
                        echo "}" >> $g_CFILE
                    else
		        echo "} else if(${g_EQUATION}){" >> $g_CFILE
                        g_TRACE_PREFIX="ELIF "
		    fi
		fi;;
	    "ELSE")
		if [[ ${1##*ELSE } != +(*ELSE*) ]]
		then
		    echo "else {" >> $g_CFILE
                    g_TRACE_PREFIX="ELSE "
		    Tokenize "${1##*ELSE }"
                    echo "}" >> $g_CFILE
                else
		    echo "} else {" >> $g_CFILE
                    g_TRACE_PREFIX="ELSE "
		fi;;
	    "FI")
		echo "}" >> $g_CFILE;;
	    "DOTIMES")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty DOTIMES at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
                    if [[ -z $(Get_Var "_") ]]
                    then
                        Register_Numeric "_"
                    fi
		    echo "long __do_times_${g_DOTIMES};" >> $g_HFILE
		    echo "for(__do_times_${g_DOTIMES} = 0; __do_times_${g_DOTIMES} < ${1#* }; __do_times_${g_DOTIMES}++) { _ = __do_times_${g_DOTIMES}+1;" >> $g_CFILE
		    ((g_DOTIMES+=1))
		fi;;
	    "DO")
		echo "{" >> $g_CFILE;;
	    "DONE")
		echo "}" >> $g_CFILE;;
	    "WHILE")
                ((g_LOOPCTR+=1))
		Handle_While "${1#* }";;
	    "WEND")
		echo "}" >> $g_CFILE
                if [[ $g_LOOPCTR -gt 0 ]]
                then
                    ((g_LOOPCTR-=1))
                    if [[ $g_LOOPCTR -gt 0 && $g_OPTION_BREAK = +(1*|TRUE*) ]]
                    then
                        echo "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" >> $g_CFILE
                    fi
                fi;;
	    "BREAK")
                # Check argument
                if [[ $g_OPTION_BREAK = +(1*|TRUE*) ]]
                then
		    if [[ "${1%% *}" != "${1#* }" && ${1#* } != "0" ]]
		    then
                        echo "__b2c__break_ctr = ${1#* }-1; __b2c__break_flag = 1;" >> $g_CFILE
                    fi
		    echo "break;" >> $g_CFILE
                else
		    echo -e "\nSyntax error: use of BREAK at line $g_COUNTER in file '$g_CURFILE' was disabled!"
		    exit 1
                fi;;
            "CONTINUE")
                # Check argument
		if [[ "${1%% *}" != "${1#* }" && ${1#* } != "0" ]]
		then
                    echo "__b2c__break_ctr = ${1#* }-1; __b2c__break_flag = 2;" >> $g_CFILE
                fi
                if [[ ${1#* } -gt 1 ]]
                then
		    echo "break;" >> $g_CFILE
                else
		    echo "continue;" >> $g_CFILE
                fi;;
	    "REPEAT")
                ((g_LOOPCTR+=1))
		echo "do{" >> $g_CFILE;;
	    "UNTIL")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty UNTIL at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    # Convert to legal C code
                    Parse_Equation "${1#* }"
		    echo "} while(!(${g_EQUATION}));" >> $g_CFILE
                    if [[ $g_LOOPCTR -gt 0 && $g_OPTION_BREAK = +(1*|TRUE*) ]]
                    then
                        ((g_LOOPCTR-=1))
                        if [[ $g_LOOPCTR -gt 0 ]]
                        then
                            echo "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" >> $g_CFILE
                        fi
                    fi
		fi;;
	    "LET")
		Handle_Let "${1#* }";;
	    +(\'*) )
                ;;
            +(/\**) )
                g_COMMENT="true";;
	    "SYSTEM")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty SYSTEM at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    echo "SYSTEM (${1#* });" >> $g_CFILE
		fi;;
	    "SLEEP")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty SLEEP at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    echo "usleep(${1#* }*1000);" >> $g_CFILE
		fi;;
	    "OPEN")
		Handle_Open "${1#* }";;
	    "CLOSE")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty CLOSE at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
                    EXP=$(echo ${1#*CLOSE })
		    if [[ "$EXP" = +(FILE *) ]]
		    then
                        EXP=${EXP#* }
                        while [[ -n ${EXP} ]]
                        do
                            TOKEN=$(Mini_Parser "${EXP}")
			    echo "fclose(${TOKEN});" >> $g_CFILE
                            EXP="${EXP:${#TOKEN}+1}"
			    TOKEN=$(echo ${TOKEN})
			    g_SEMANTIC_OPENCLOSE="${g_SEMANTIC_OPENCLOSE//@\'${TOKEN}\'*${TOKEN}@/}"
                        done
		    elif [[ "$EXP" = +(DIRECTORY *) ]]
		    then
                        EXP=${EXP#* }
                        while [[ -n ${EXP} ]]
                        do
                            TOKEN=$(Mini_Parser "${EXP}")
			    echo "closedir(${TOKEN});" >> $g_CFILE
                            EXP="${EXP:${#TOKEN}+1}"
			    TOKEN=$(echo ${TOKEN})
			    g_SEMANTIC_OPENCLOSE="${g_SEMANTIC_OPENCLOSE//@\'${TOKEN}\'*${TOKEN}@/}"
                        done
		    elif [[ "$EXP" = +(MEMORY *) ]]
		    then
                        EXP=${EXP#* }
                        while [[ -n ${EXP} ]]
                        do
                            TOKEN=$(Mini_Parser "${EXP}")
			    echo "${TOKEN} = NULL;" >> $g_CFILE
                            EXP="${EXP:${#TOKEN}+1}"
			    TOKEN=$(echo ${TOKEN})
			    g_SEMANTIC_OPENCLOSE="${g_SEMANTIC_OPENCLOSE//@\'${TOKEN}\'*${TOKEN}@/}"
                        done
		    elif [[ "$EXP" = +(LIBRARY *) ]]
		    then
                        EXP=${EXP#* }
                        while [[ -n ${EXP} ]]
                        do
                            TOKEN=$(Mini_Parser "${EXP}")
			    echo "if(__b2c__dlopen__pointer_${TOKEN//[[:punct:]]/} != NULL) {dlclose(__b2c__dlopen__pointer_${TOKEN//[[:punct:]]/}); __b2c__dlopen__pointer_${TOKEN//[[:punct:]]/} = NULL;}" >> $g_CFILE
                            EXP="${EXP:${#TOKEN}+1}"
			    TOKEN=$(echo ${TOKEN})
                        done
		    elif [[ "$EXP" = +(NETWORK *) || "$EXP" = +(SERVER *) || "$EXP" = +(UDP *) || "${EXP}" = +(DEVICE *) ]]
		    then
                        EXP=${EXP#* }
                        while [[ -n ${EXP} ]]
                        do
                            TOKEN=$(Mini_Parser "${EXP}")
                            # Close SSL socket if option was set
                            if [[ ${g_OPTION_TLS} = +(1*|TRUE*) ]]
                            then
                                echo "SSL_shutdown((SSL*)__b2c_ssl_ptr[${TOKEN}]);" >> $g_CFILE
                                echo "SSL_free((SSL*)__b2c_ssl_ptr[${TOKEN}]);" >> $g_CFILE
                                echo "SSL_CTX_free((SSL_CTX*)__b2c_ctx_ptr[${TOKEN}]);" >> $g_CFILE
                            fi
                            echo "close(${TOKEN});" >> $g_CFILE
                            EXP="${EXP:${#TOKEN}+1}"
			    TOKEN=$(echo ${TOKEN})
			    g_SEMANTIC_OPENCLOSE="${g_SEMANTIC_OPENCLOSE//@\'${TOKEN}\'*${TOKEN}@/}"
                        done
		    else
			echo -e "\nSyntax error: erronuous CLOSE argument at line $g_COUNTER in file '$g_CURFILE'!"
			exit 1
		    fi
		fi;;
	    "REWIND")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty REWIND at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    echo "rewind(${1#* });" >> $g_CFILE
		fi;;
	    "MEMREWIND")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty MEMREWIND at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    echo "${1#* } = (char*)__b2c_mem_${1#* };" >> $g_CFILE
		fi;;
	    "SEEK")
		Handle_Seek "${1#* }";;
	    "READLN")
		Handle_Readln "${1#* }";;
	    "WRITELN")
		Handle_Writeln "${1#* }";;
	    "GETBYTE")
		Handle_Getbyte "${1#* }";;
	    "PUTBYTE")
		Handle_Putbyte "${1#* }";;
	    "GETFILE")
		Handle_Getfile "${1#* }";;
	    "GETLINE")
		Handle_Getline "${1#* }";;
	    "PUTLINE")
		Handle_Putline "${1#* }";;
	    "END"|"ENDIF"|"ENDSUB"|"ENDWITH"|"ENDFORK"|"ENDRECORD"|"ENDSELECT"|"ENDFUNCTION")
		EXP=${1#*END }
		if [[ "${EXP}" = +(*IF*) ]]
		then
		    echo "}" >> $g_CFILE
		elif [[ "${EXP}" = +(*RECORD*) ]]
		then
		    if [[ -n $g_FUNCNAME ]]
		    then
			echo "} $g_RECORDNAME;" >> $g_CFILE
			echo "typedef $g_RECORDNAME ${g_RECORDNAME%_*}_type;" >> $g_CFILE
			if [[ -n $g_RECORDARRAY ]]
			then
			    echo "$g_RECORDNAME *${g_RECORDVAR%%\[*} = ($g_RECORDNAME*)calloc(${g_RECORDARRAY}+${g_OPTION_BASE}, sizeof($g_RECORDNAME));" >> $g_CFILE
			    g_LOCALSTRINGS="$g_LOCALSTRINGS ${g_RECORDVAR%%\[*}"
			    g_RECORDEND_BODY="long __b2c_record_${g_RECORDNAME%_*} = ${g_RECORDARRAY}+${g_OPTION_BASE}; ${g_RECORDEND_BODY}"
			else
			    echo "$g_RECORDNAME ${g_RECORDVAR//]/+${g_OPTION_BASE}]} = { 0 } ;" >> $g_CFILE
			fi
		    else
			echo "} $g_RECORDNAME;" >> $g_HFILE
			echo "typedef $g_RECORDNAME ${g_RECORDNAME%_*}_type;" >> $g_HFILE
			if [[ -n $g_RECORDARRAY ]]
			then
			    echo "$g_RECORDNAME *${g_RECORDVAR%%\[*};" >> $g_HFILE
			    echo "${g_RECORDVAR%%\[*} = ($g_RECORDNAME*)calloc(${g_RECORDARRAY}+${g_OPTION_BASE}, sizeof($g_RECORDNAME));" >> $g_CFILE
			    echo "long __b2c_record_${g_RECORDNAME%_*};" >> $g_HFILE
			    g_RECORDEND_BODY="${g_RECORDEND_BODY} __b2c_record_${g_RECORDNAME%_*} = ${g_RECORDARRAY}+${g_OPTION_BASE};"
			else
			    echo "$g_RECORDNAME ${g_RECORDVAR//]/+${g_OPTION_BASE}]} = { 0 } ;" >> $g_HFILE
			fi
                        echo $g_RECORDEND_HEADER >> $g_HFILE
		    fi
		    echo $g_RECORDEND_BODY >> $g_CFILE
		    g_RECORDNAME=
		    g_RECORDVAR=
		    g_RECORDEND_BODY=
                    g_RECORDEND_HEADER=
		    g_RECORDARRAY=
		    # Restore function name if GLOBAL was used
		    if [[ -n $g_RECORDCACHE ]]
		    then
			g_FUNCNAME=$g_RECORDCACHE
			g_RECORDCACHE=
		    fi
		elif [[ "${EXP}" = +(*FUNCTION*) ]]
		then
		    Handle_Endfunction
		elif [[ "${EXP}" = +(*SUB*) ]]
		then
		    Handle_Endsub
		elif [[ "${EXP}" = +(*WITH*) ]]
		then
		    g_WITHVAR=
		elif [[ "${EXP}" = +(*SELECT*) ]]
		then
		    if [[ $g_SELECTVAR_CTR -eq 0 ]]
		    then
			echo -e "\nSyntax error: invalid END SELECT at line $g_COUNTER in file '$g_CURFILE'!"
			exit 1
		    else
			echo "}" >> $g_CFILE
			g_SELECTVAR[$g_SELECTVAR_CTR]=
			g_IN_CASE[$g_SELECTVAR_CTR]=
			g_CASE_FALL=
			g_CASE_CONT=
			((g_SELECTVAR_CTR-=1))
		    fi
		elif [[ "${EXP}" = +(*FORK*) ]]
		then
		    if [[ -n ${1##*FORK} ]]
		    then
			echo "_exit(${1##*FORK});" >> $g_CFILE
		    else
			echo "_exit(EXIT_SUCCESS);" >> $g_CFILE
		    fi
		elif [[ "${EXP}" != "END" ]]
		then
		    echo "exit(${1#* });" >> $g_CFILE
		else
		    echo "exit(EXIT_SUCCESS);" >> $g_CFILE
		fi;;
	    "SUB")
		Handle_SubFunc "${1#* }";;
	    "CALL")
		Handle_Call "${1#* }";;
	    "FUNCTION")
		Handle_SubFunc "${1#* }";;
	    "RETURN")
		Handle_Return "${1#* }";;
	    "IMPORT")
		Handle_Import "${1#* }";;
	    "DECLARE")
		Handle_Declare "${1#* }";;
	    "GLOBAL")
		Handle_Declare "${1#* }";;
	    "LOCAL")
		Handle_Local "${1#* }";;
	    "DATA")
		Handle_Data "${1#* }";;
	    "RESTORE")
                if [[ "${1%% *}" = "${1#* }" ]]
                then
		    echo "__b2c__floatarray_ptr = 0;" >> $g_CFILE
		    echo "__b2c__stringarray_ptr = 0;" >> $g_CFILE
                else
                    echo "__b2c__data_jump_flag = 1; if(!setjmp(__b2c__data_jump)) goto ${1#* };" >> $g_CFILE
		    echo "__b2c__floatarray_ptr = __b2c__label_floatarray_${1#* };" >> $g_CFILE
		    echo "__b2c__stringarray_ptr = __b2c__label_stringarray_${1#* };" >> $g_CFILE
                fi;;
	    "READ")
		Handle_Read "${1#* }";;
	    "PUSH")
		Handle_Push "${1#* }";;
	    "PULL")
		Handle_Pull "${1#* }";;
	    "SEED")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty SEED at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    echo "srandom((unsigned int)${1#* });" >> $g_CFILE
		fi;;
	    "DEF")
		Handle_Deffn "${1#* }";;
	    "CONST")
		Handle_Const "${1#* }";;
	    "INCLUDE")
		# Get rid of doublequotes if they are there
		INC=`echo ${1#* } | tr -d "\042"`
		# See if there are arguments - equation adapted for KSH93
		if [[ ${INC//,/} != ${INC} ]]
		then
                    EXP=$(echo ${INC#*,} | tr "," " " | tr -d "${g_STRINGSIGN}")
		    INC=${INC%%,*}
		    TO_PARSE=0
		else
		    TO_PARSE=2
		fi
                # Check file extension
                if [[ ${INC} != +(*.bac) ]]
                then
                    INC="${INC}.bac"
                fi
		# Check argument
		if [[ ! -f ${INC%%,*} || "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSystem error: missing file '${INC%%,*}' for INCLUDE at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    # Clear current terminal line
		    echo -e -n "\r\033[2K"
		    # Check if the C Preprocessor needs to run
		    if [[ $g_CPP -eq 1 ]]
		    then
			if [[ -n `which cpp 2>/dev/null` ]]
			then
                            echo -n "Preprocessing '${INC}'... "
                            # Change next line marker to overcome C preprocessor interpretation
                            while read -r LINE; do if [[ ${LINE} = +(\#*) ]]; then echo "${LINE}"; else echo "@${LINE}@"; fi; done < $INC > $INC.tmp
                            cpp -w -P $INC.tmp $INC.cpp
                            # Restore the next line marker
                            while read -r LINE; do LINE="${LINE:1}"; echo "${LINE%@*}"; done < $INC.cpp > $INC.bac
			    g_TMP_FILES="$g_TMP_FILES ${INC}.cpp ${INC}.tmp ${INC}.bac"
			    NEWFEED="${INC}.bac"
                            echo "done."
			else
			    echo "System error: the C Preprocessor 'cpp' not found on this system! Exiting..."
			    exit 1
			fi
		    else
			NEWFEED=${INC}
		    fi
		    # Start walking through program
		    COPY_COUNTER=$g_COUNTER
		    g_COUNTER=1
		    # Assign new file
		    COPY_CURFILE=$g_CURFILE
		    # Set current filename
		    g_CURFILE=${NEWFEED}
                    # Detect if this is a Windows file
                    if [[ `head -1 ${NEWFEED}` = +(*${g_CRLF}) ]]
                    then
                        echo "System error: Windows file detected! Remove non-Unix CR line separators first. Exiting..."
                        exit 1
                    fi
		    while read -r LINE || [[ -n $LINE ]]
		    do
			# See if we need to enable flag
			for SYM in ${EXP}
			do
			    if [[ $TO_PARSE -eq 0 && "${LINE#* }" = +(${SYM%${g_STRINGSIGN}*}*) && "${LINE}" = +(*SUB*|*FUNCTION*) || "${LINE}" = +(*INCLUDE) ]]
			    then
				TO_PARSE=1
				break
			    fi
			done
			# Line is not empty?
			if [[ -n "$LINE" && $TO_PARSE -gt 0 ]]
			then
			    if [[ $g_QUIET -eq 0 ]]
			    then
				echo -e -n "\rConverting '${INC}'... ${g_COUNTER}\033[0K"
			    fi
			    if [[ "$LINE" = +(* \\) && "$LINE" != +(${g_SQUOTESIGN}*) ]]
			    then
				let LEN="${#LINE}"-2
				SEQ="${LINE:0:$LEN}"
				TOTAL=$TOTAL$SEQ
                            else
				TOTAL="${TOTAL}${LINE}"
				if [[ "${TOTAL}" != +(${g_SQUOTESIGN}*) ]]
				then
                                    echo "#undef __b2c_lineno" >> $g_CFILE
                                    echo "#define __b2c_lineno $g_COUNTER" >> $g_CFILE
                                    echo "#undef __b2c_lineno" >> $g_HFILE
                                    echo "#define __b2c_lineno $g_COUNTER" >> $g_HFILE
				    Tokenize "${TOTAL}"
				fi
				TOTAL=
			    fi
			fi
			# See if we need to stop parsing
			if [[ $TO_PARSE -eq 1 && "${LINE}" = +(*END*) && "${LINE}" = +(*SUB*|*FUNCTION*) ]]
			then
			    TO_PARSE=0
			fi
			# Increase line number
			((g_COUNTER+=1))
		    done < $NEWFEED
                    # Save total amount of lines
                    ((g_TOTAL_LINES+=$g_COUNTER-1))
		    # Restore original counter
		    g_COUNTER=$COPY_COUNTER
		    # Restore original file
		    g_CURFILE=$COPY_CURFILE
                    # Set DATA array indexes correctly
                    echo "__b2c__stringarray_ptr = ${g_CCTR};" >> $g_CFILE
                    echo "__b2c__floatarray_ptr = ${g_FCTR};" >> $g_CFILE
		fi;;
	    "POKE")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty POKE at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
                    EXP=${1#* }
                    if [[ ${EXP} = +(* SIZE *) ]]
                    then
		        SYM=${EXP##* SIZE }
                        EXP=${EXP% SIZE *}
                        TOKEN=$(Mini_Parser "${EXP}")
                        EXP="${EXP:${#TOKEN}+1}"
		        echo "if (__b2c__trap){if(__b2c__memory__check((char*)${TOKEN}, (${SYM})*sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"POKE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
		        echo "memset((void*)(__b2c__MEMTYPE*)(${TOKEN}), ${EXP}, (${SYM})*sizeof(__b2c__MEMTYPE));" >> $g_CFILE
                    else
                        TOKEN=$(Mini_Parser "${EXP}")
                        EXP="${EXP:${#TOKEN}+1}"
		        echo "if (__b2c__trap){if(__b2c__memory__check((char*)${TOKEN}, sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"POKE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
		        echo "*(__b2c__MEMTYPE*)(${TOKEN}) = (__b2c__MEMTYPE)(${EXP});" >> $g_CFILE
                    fi
                    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
                    then
                        g_CATCH_USED=1
                    fi
		fi;;
	    "RESIZE")
	    	# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty RESIZE at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    SYM=${1#* }
		    EXP=${SYM%% TO *}
                    CHECK=$(Get_Var ${EXP//./} ${g_FUNCNAME})
                    echo "if(__b2c__trap) {if(__b2c__memory__check((char*)${EXP}, sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"RESIZE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                    echo "${EXP} = (${CHECK})realloc((void*)${EXP}, sizeof(__b2c__MEMTYPE)*(${SYM##* TO }+1));" >> $g_CFILE
                    echo "if(__b2c__trap) {if((void*)${EXP} == NULL) {ERROR=6; if(!__b2c__catch_set) RUNTIMEERROR(\"RESIZE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
                    then
                        g_CATCH_USED=1
                    fi
		fi;;
	    "COPY")
		Handle_Copy "${1#* }";;
	    "DELETE")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty DELETE at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    # Translate to C function
		    if [[ "${1#* }" = +(*FILE*) ]]
		    then
			echo "if (unlink(${1#*FILE })==-1){if(__b2c__trap){ERROR = 7;if(!__b2c__catch_set) RUNTIMEERROR(\"DELETE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                        if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
                        then
                            g_CATCH_USED=1
                        fi
		    elif [[ "${1#* }" = +(*DIRECTORY*) ]]
		    then
		        echo "if (rmdir(${1#*DIRECTORY }) == -1){if(__b2c__trap){ERROR = 20;if(!__b2c__catch_set) RUNTIMEERROR(\"DELETE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                        if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
                        then
                            g_CATCH_USED=1
                        fi
		    elif [[ "${1#* }" = +(*RECURSIVE*) ]]
		    then
			 echo "__b2c__rmrecursive(__b2c_lineno, __b2c_filename, ${1#*RECURSIVE });" >> $g_CFILE
		    else
			echo "\nERROR: erronuous argument for DELETE at line $g_COUNTER in file '$g_CURFILE'!"
			exit 1
		    fi
		fi;;
	    "RENAME")
		Handle_Rename "${1#* }";;
	    "MAKEDIR")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty MAKEDIR at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    # Translate to C function
		    echo "if (__b2c__makedir(${1#* }) != 0){if(__b2c__trap){ERROR = 21;if(!__b2c__catch_set) RUNTIMEERROR(\"MAKEDIR\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
                    then
                        g_CATCH_USED=1
                    fi
		fi;;
	    "CHANGEDIR")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty CHANGEDIR at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    # Translate to C function
		    echo "if (chdir(${1#* }) == -1){if(__b2c__trap) {ERROR = 22;if(!__b2c__catch_set) RUNTIMEERROR(\"CHANGEDIR\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
                    then
                        g_CATCH_USED=1
                    fi
		fi;;
	    "FREE")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty FREE at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    # Associative record member
		    if [[ "${1}" = +(*[a-zA-Z]\(*\)) ]]
		    then
                        EXP=`echo ${1#* }`
                        # Start miniparser
                        while [[ -n ${EXP} ]]
                        do
                            TOKEN=`echo $(Mini_Parser "${EXP}")`
                            TXT=${TOKEN%?}
                            echo "__b2c__${TOKEN%%\(*}__del(${TXT#*\(}, NULL);" >> $g_CFILE
                            EXP="${EXP:${#TOKEN}+1}"
                        done
		    else
                        EXP=$(echo ${1#* })
                        IFS=","
	                for i in ${EXP// /}
                        do
                            if [[ -n $(Get_Var __b2c__${i}_type_)$(Get_Var __b2c__${i}_type_${g_FUNCNAME} ${g_FUNCNAME}) ]]
			    then
                                echo "__b2c__${i}_tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__${i}_tab); while(__b2c__hashtable_count(&__b2c__${i}_tab)) {" >> $g_CFILE
                                echo "__b2c__${i}_loc = (__b2c__${i}_typ*)__b2c__hashtable_find(&__b2c__${i}_tab, (HASHTABLE_U64)__b2c__${i}_tmp[0]);" >> $g_CFILE
                                echo "__b2c__${i}__del(__b2c__${i}_loc->key);} __b2c__hashtable_clear(&__b2c__${i}_tab);" >> $g_CFILE
			    else
				EXP=${i// /}
				echo "if(__b2c__trap){if(__b2c__memory__check((char *)${EXP}, sizeof(__b2c__MEMTYPE)))" >> $g_CFILE
				echo "{ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"FREE\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} } free((void*)${EXP});" >> $g_CFILE
				g_SEMANTIC_MEMFREE=${g_SEMANTIC_MEMFREE//@\'${EXP}\'*${EXP}@/}
			    fi
                        done
                        IFS="${g_ORGIFS}"
                        if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
                        then
                            g_CATCH_USED=1
                        fi
		    fi
		fi;;
	    "ON")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty ON at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		elif [[ "${1}" != +(* GOTO *) ]]
		then
		    echo -e "\nSyntax error: ON without GOTO at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    SYM=${1#* }
		    EXP=${1##* GOTO }
		    # Convert to C 'switch' statement
		    let SEQ=1
		    echo "switch(${SYM%GOTO *}){" >> $g_CFILE
                    while [[ -n ${EXP} ]]
                    do
                        TOKEN=$(Mini_Parser "${EXP}")
			echo "case ${SEQ}: goto ${TOKEN}; break;" >> $g_CFILE
                        EXP="${EXP:${#TOKEN}+1}"
			((SEQ+=1))
                    done
		    echo "}" >> $g_CFILE
		fi;;
	    "GOTO")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty GOTO at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    # Translate to C label
		    echo "goto ${1#* };" >> $g_CFILE
		fi;;
	    "GOSUB")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty GOSUB at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    # Translate to C label
		    echo "__b2c__gosub_buffer_ptr++; if (__b2c__gosub_buffer_ptr >= $g_MAX_RBUFFERS) {ERROR=31; if(!__b2c__catch_set) RUNTIMEERROR(\"GOSUB\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;}" >> $g_CFILE
		    echo "if(!setjmp(__b2c__gosub_buffer[__b2c__gosub_buffer_ptr])) goto ${1#* };" >> $g_CFILE
		    echo "__b2c__gosub_buffer_ptr--; if(__b2c__gosub_buffer_ptr < -1) __b2c__gosub_buffer_ptr = -1;" >> $g_CFILE
                    if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
                    then
                        g_CATCH_USED=1
                    fi
		fi;;
	    "LABEL")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty LABEL at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    # Translate to C label
		    echo "${1#* }:" >> $g_CFILE
		    echo ";" >> $g_CFILE
                    # Needed for RESTORE
                    if [[ -z $(Get_Var "__b2c__label_floatarray_${1#* }") ]]
	            then
                        echo "int __b2c__label_floatarray_${1#* };" >> $g_HFILE
                        echo "int __b2c__label_stringarray_${1#* };" >> $g_HFILE
                        Save_Main_Var "__b2c__label_floatarray_${1#* }" "int"
                        Save_Main_Var "__b2c__label_stringarray_${1#* }" "int"
                    fi
                    echo "__b2c__label_floatarray_${1#* } = $g_FCTR;" >> $g_CFILE
                    echo "__b2c__label_stringarray_${1#* } = $g_CCTR;" >> $g_CFILE
                    echo "if(__b2c__data_jump_flag){ __b2c__data_jump_flag=0; longjmp(__b2c__data_jump, 1);}" >> $g_CFILE
		fi;;
	    "TRAP")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty TRAP at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    if [[ "${1#* }" = "LOCAL" ]]
		    then
			echo "/* Error catching is enabled */" >> $g_CFILE
			echo "__b2c__trap = 1;" >> $g_CFILE
			echo "signal(SIGILL, __b2c__catch_signal);" >> $g_CFILE
			echo "signal(SIGABRT, __b2c__catch_signal);" >> $g_CFILE
			echo "signal(SIGFPE, __b2c__catch_signal);" >> $g_CFILE
			echo "signal(SIGSEGV, __b2c__catch_signal);" >> $g_CFILE
		    elif [[ "${1#* }" = "SYSTEM" ]]
		    then
			echo "/* Error catching is disabled */" >> $g_CFILE
			echo "__b2c__trap = 0;" >> $g_CFILE
			echo "signal(SIGILL, SIG_DFL);" >> $g_CFILE
			echo "signal(SIGABRT, SIG_DFL);" >> $g_CFILE
			echo "signal(SIGFPE, SIG_DFL);" >> $g_CFILE
			echo "signal(SIGSEGV, SIG_DFL);" >> $g_CFILE
		    else
			echo -e "\nSyntax error: invalid argument for TRAP at line $g_COUNTER in file '$g_CURFILE'!"
			exit 1
		    fi
		fi;;
	    "CATCH")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty CATCH at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		elif [[ "${1#* }" = +(*GOTO*) ]]
		then
		    echo "__b2c__catch_set = 1;" >> $g_CFILE
		    g_CATCHGOTO="${1##* GOTO }"
		elif [[ "${1#* }" = +(*ERROR*) ]]
		then
		    echo "__b2c__error_callback = &${1##* ERROR };" >> $g_CFILE
		elif [[ "${1#* }" = +(*RESET*) ]]
		then
		    echo "__b2c__catch_set = 0;" >> $g_CFILE
		    g_CATCHGOTO="__B2C__PROGRAM__EXIT"
		else
		    echo -e "\nSyntax error: CATCH without GOTO or RESET at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		fi;;
	    "RESUME")
		echo "longjmp(__b2c__jump, 1);" >> $g_CFILE;;
	    "CLEAR")
		echo "fprintf(stdout,\"\033[2J\"); fprintf(stdout,\"\033[0;0f\"); fflush(stdout);" >> $g_CFILE;;
	    "COLOR")
		Handle_Color "${1#* }";;
	    "GOTOXY")
		Handle_Gotoxy "${1#* }";;
	    "RECEIVE")
		Handle_Receive "${1#* }";;
	    "SEND")
		Handle_Send "${1#* }";;
	    "RECORD")
	    	# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty RECORD at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		elif [[ -n $g_RECORDNAME ]]
		then
		    echo -e "\nSyntax error: cannot define a record within a record!"
		    exit 1
		else
		    # Determine name
		    g_RECORDVAR=${1#* }
		    if [[ $g_RECORDVAR = +(* ARRAY *) ]]
		    then
			g_RECORDARRAY=${g_RECORDVAR#* ARRAY }
			g_RECORDVAR="${g_RECORDVAR%% ARRAY *}[$g_RECORDARRAY]"
		    fi
		    # Translate to C typedef struct
		    if [[ -n $g_FUNCNAME ]]
		    then
			g_RECORDNAME="${g_RECORDVAR%%\[*}_TYPE"
			echo "typedef struct {" >> $g_CFILE
                        Save_Func_Var "" "${g_FUNCNAME}" "$g_RECORDNAME"
		    else
			g_RECORDNAME="${g_RECORDVAR%%\[*}_TYPE"
			echo "typedef struct {" >> $g_HFILE
			Save_Main_Var "" "$g_RECORDNAME"
		    fi
		fi;;
	    "WITH")
	    	# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty WITH at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		elif [[ -n $g_RECORDNAME ]]
		then
		    echo -e "\nSyntax error: cannot define a WITH within a WITH!"
		    exit 1
		else
		    g_WITHVAR=${1#* }
		fi;;
	    "SPLIT")
		Handle_Split "${1#* }";;
	    "JOIN")
		Handle_Join "${1#* }";;
	    "SELECT")
	    	# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty SELECT at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    ((g_SELECTVAR_CTR+=1))
		    g_SELECTVAR[$g_SELECTVAR_CTR]=${1#* }
		    g_IN_CASE[$g_SELECTVAR_CTR]=
		    g_CASE_FALL=
		    g_CASE_CONT=
		fi;;
	    "CASE")
	    	# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo "\nSyntax error: empty CASE at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
                    # In processing of next CASE statements
		    if [[ ${g_IN_CASE[$g_SELECTVAR_CTR]} -eq 1 ]]
		    then
                        g_CASE_CONT="} else "
                    fi
                    # Create IF
		    if [[ $(Check_String_Type ${g_SELECTVAR[$g_SELECTVAR_CTR]}) -eq 1 ]]
		    then
			# Get expression without ;
			if [[ -z ${1##*;} ]]
			then
			    let LEN="${#1}"-1; EXP="${1:0:$LEN}"
			    g_CASE_FALL="${g_CASE_FALL} !__b2c__strcmp(${g_SELECTVAR[$g_SELECTVAR_CTR]}, ${EXP#* }) ||"
			else
                            EXP=${1#* }
	                    # Start miniparser
                            while [[ -n ${EXP} ]]
                            do
                                SYM=$(Mini_Parser "${EXP}")
		                g_CASE_FALL="${g_CASE_FALL} !__b2c__strcmp(${g_SELECTVAR[$g_SELECTVAR_CTR]}, ${SYM})"
                                EXP="${EXP:${#SYM}+1}"
                                if [[ -n ${EXP} ]]
                                then
                                    g_CASE_FALL="${g_CASE_FALL} ||"
                                fi
                            done
			    echo "${g_CASE_CONT} if (${g_CASE_FALL}){" >> $g_CFILE
			    g_IN_CASE[$g_SELECTVAR_CTR]=1
			    g_CASE_FALL=
			fi
		    else
			# Get expression without ;
			if [[ -z ${1##*;} ]]
			then
			    let LEN="${#1}"-1; EXP="${1:0:$LEN}"
                            g_CASE_FALL="${g_CASE_FALL} (${g_SELECTVAR[$g_SELECTVAR_CTR]}) == (${EXP#* }) ||"
			else
                            EXP=${1#* }
	                    # Start miniparser
                            while [[ -n ${EXP} ]]
                            do
                                SYM=$(Mini_Parser "${EXP}")
                                g_CASE_FALL="${g_CASE_FALL} (${g_SELECTVAR[$g_SELECTVAR_CTR]}) == (${SYM})"
                                EXP="${EXP:${#SYM}+1}"
                                if [[ -n ${EXP} ]]
                                then
                                    g_CASE_FALL="${g_CASE_FALL} ||"
                                fi
                            done
			    echo "${g_CASE_CONT} if (${g_CASE_FALL}){" >> $g_CFILE
			    g_IN_CASE[$g_SELECTVAR_CTR]=1
			    g_CASE_FALL=
			fi
		    fi
		fi;;
	    "DEFAULT")
		if [[ -n ${g_IN_CASE[$g_SELECTVAR_CTR]} ]]
		then
		    echo "} else {" >> $g_CFILE
		else
		    echo -e "\nSyntax error: cannot use DEFAULT without previous CASE at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		fi
		g_IN_CASE[$g_SELECTVAR_CTR]=
		g_CASE_FALL=;;
	    "SETENVIRON")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty SETENVIRON at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    # Resolve this with C macro
		    echo "SETENVIRON(${1#* });" >> $g_CFILE
		fi;;
	    "SORT")
		Handle_Sort "${1#* }";;
	    "STOP")
		# Check argument
		if [[ $(echo ${1%% *}) = $(echo ${1}) ]]
		then
		    echo "kill(getpid(), SIGSTOP);" >> $g_CFILE
                else
                    EXP=$(echo ${1#* } | tr -d "\042")
		    echo "kill(getpid(), ${EXP});" >> $g_CFILE
                fi
		;;
	    "TRACE")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty TRACE at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    if [[ "${1#* }" = +(*MONITOR*) ]]
                    then
			g_TRACE=1
	                echo "fprintf(stderr, \"File '${g_CURFILE}' line %d: TRACE ON - press <SPACE> to execute the program step by step, <ESC> to exit.\n\", $g_COUNTER);" >> $g_CFILE
                        g_MONITOR=
                        for SYM in `echo "${1#*MONITOR }" | tr -d '\054'`
                        do
                            if [[ -z $(Get_Var ${SYM} ${g_FUNCNAME}) ]]
                            then
		                echo -e "\nSyntax error: cannot monitor undeclared variable '${SYM}' at line $g_COUNTER in file '$g_CURFILE'!"
		                exit 1
                            fi
			    if [[ $(Check_String_Type ${SYM}) -eq 1 ]]
			    then
	                        g_MONITOR="${g_MONITOR} __b2c__assign = ${SYM}; if(__b2c__assign != NULL) fprintf(stderr, \"${SYM%%${g_STRINGSIGN}*}$ = %s\n\", __b2c__assign);"
                            else
                                if [[ "${SYM}" = +(*${g_LONGSIGN}*) ]]
                                then
	                            g_MONITOR="${g_MONITOR} fprintf(stderr, \"${SYM%%${g_LONGSIGN}*}%% = %s\n\", STR${g_STRINGSIGN}(${SYM}));"
                                elif [[ "${SYM}" = +(*${g_FLOATSIGN}*) ]]
                                then
	                            g_MONITOR="${g_MONITOR} fprintf(stderr, \"${SYM%%${g_FLOATSIGN}*}# = %s\n\", STR${g_STRINGSIGN}(${SYM}));"
                                else
	                            g_MONITOR="${g_MONITOR} fprintf(stderr, \"${SYM} = %s\n\", STR${g_STRINGSIGN}(${SYM}));"
                                fi
                            fi
                        done
		    elif [[ "${1#* }" = +(*ON*) ]]
		    then
			g_TRACE=1
	                echo "fprintf(stderr, \"File '${g_CURFILE}' line %d: TRACE ON - press <SPACE> to execute the program step by step, <ESC> to exit.\n\", $g_COUNTER);" >> $g_CFILE
		    elif [[ "${1#* }" = +(*OFF*) ]]
		    then
                        g_MONITOR=
			g_TRACE=0
		    fi
		fi;;
	    "OPTION")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty OPTION at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    if [[ "${1#* }" = +(*BASE*) ]]
		    then
			if [[ "${1##*BASE }" = +([0123456789]*) ]]
			then
			    g_OPTION_BASE=$(echo ${1##*BASE })
			else
			    echo -e "\nSyntax error: invalid argument to OPTION BASE at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
		    elif [[ "${1#* }" = +(*COMPARE*) ]]
		    then
			if [[ "${1##*COMPARE }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    echo "__b2c__option_compare = $(echo ${1##*COMPARE });" >> $g_CFILE
                            echo "#undef __b2c__STRCMP" >> $g_CFILE
                            if [[ "${1##*COMPARE }" = +(1*|TRUE*) ]]
                            then
                                echo "#define __b2c__STRCMP __b2c__strcasecmp" >> $g_CFILE
                            else
                                echo "#define __b2c__STRCMP __b2c__strcmp" >> $g_CFILE
                            fi
			else
			    echo -e "\nSyntax error: invalid argument to OPTION COMPARE at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
		    elif [[ "${1#* }" = +(*QUOTED*) ]]
		    then
			if [[ "${1##*QUOTED }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    echo "__b2c__option_quoted = $(echo ${1##*QUOTED });" >> $g_CFILE
			else
			    echo -e "\nSyntax error: invalid argument to OPTION QUOTED at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
		    elif [[ "${1#* }" = +(*UTF8*) ]]
		    then
			if [[ "${1##*UTF8 }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    echo "__b2c__option_utf8 = $(echo ${1##*UTF8 });" >> $g_CFILE
			else
			    echo -e "\nSyntax error: invalid argument to OPTION UTF8 at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
		    elif [[ "${1#* }" = +(*TLS*) ]]
		    then
			if [[ "${1##*TLS }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    g_OPTION_TLS=$(echo ${1##*TLS })
                            g_INC_TLS="#include <openssl/ssl.h>"
                            g_LIB_TLS="-lssl -lcrypto"
			else
			    echo -e "\nSyntax error: invalid argument to OPTION TLS at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
                    elif [[ "${1#* }" = +(*PROPER*) ]]
		    then
			if [[ "${1##*PROPER }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    echo "__b2c__option_proper = $(echo ${1##*PROPER });" >> $g_CFILE
			else
			    echo -e "\nSyntax error: invalid argument to OPTION PROPER at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
		    elif [[ "${1#* }" = +(*ERROR*) ]]
		    then
			if [[ "${1##*ERROR }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    echo "__b2c__option_error = $(echo ${1##*ERROR });" >> $g_CFILE
			else
			    echo -e "\nSyntax error: invalid argument to OPTION ERROR at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
		    elif [[ "${1#* }" = +(*DELIM*) ]]
		    then
                        echo "__b2c__option_delim = $(echo ${1##*DELIM});" >> $g_CFILE
		    elif [[ "${1#* }" = +(*INPUT*) ]]
		    then
                        g_OPTION_INPUT=$(echo ${1##*INPUT})
		    elif [[ "${1#* }" = +(*DQ*) ]]
		    then
                        echo "__b2c__option_dq = $(echo ${1##*DQ});" >> $g_CFILE
		    elif [[ "${1#* }" = +(*SOCKET*) ]]
		    then
			if [[ "${1##*SOCKET }" = +([0123456789]*) ]]
			then
			    g_OPTION_SOCKET=$(echo ${1##*SOCKET })
			else
			    echo -e "\nSyntax error: invalid argument to OPTION SOCKET at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
		    elif [[ "${1#* }" = +(*BREAK*) ]]
		    then
			if [[ "${1##*BREAK }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    g_OPTION_BREAK=$(echo ${1##*BREAK })
			else
			    echo -e "\nSyntax error: invalid argument to OPTION BREAK at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
                    elif [[ "${1#* }" = +(*MEMSTREAM*) ]]
		    then
			if [[ "${1##*MEMSTREAM }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    echo "__b2c__option_memstream = $(echo ${1##*MEMSTREAM });" >> $g_CFILE
			else
			    echo -e "\nSyntax error: invalid argument to OPTION MEMSTREAM at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
                    elif [[ "${1#* }" = +(*MEMTYPE*) ]]
		    then
                        echo "#undef __b2c__MEMTYPE" >> $g_CFILE
                        echo "#define __b2c__MEMTYPE $(echo ${1##*MEMTYPE })" >> $g_CFILE
                    elif [[ "${1#* }" = +(*COLLAPSE*) ]]
		    then
			if [[ "${1##*COLLAPSE }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    echo "__b2c__collapse = $(echo ${1##*COLLAPSE });" >> $g_CFILE
			else
			    echo -e "\nSyntax error: invalid argument to OPTION COLLAPSE at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
                    elif [[ "${1#* }" = +(*DEVICE*) ]]
		    then
			echo "__b2c__option_open = ($(echo ${1##*DEVICE }));" >> $g_CFILE
                    elif [[ "${1#* }" = +(*STARTPOINT*) ]]
		    then
			if [[ "${1##*STARTPOINT }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    echo "__b2c__option_startpoint = $(echo ${1##*STARTPOINT });" >> $g_CFILE
			else
			    echo -e "\nSyntax error: invalid argument to OPTION STARTPOINT at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
                    elif [[ "${1#* }" = +(*INTERNATIONAL*) ]]
		    then
			if [[ "${1##*INTERNATIONAL }" = +(1*|TRUE*) ]]
			then
			    echo "#include <libintl.h>" >> $g_HFILE
                            echo "setlocale(LC_ALL, \"\");" >> $g_CFILE
			    echo "if(bindtextdomain(\"${g_SOURCEFILE%.*}\",\"/usr/share/locale\")==NULL){if(__b2c__trap){ERROR = 6;if(!__b2c__catch_set) RUNTIMEERROR(\"OPTION INTERNATIONAL\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
			    echo "if(textdomain(\"${g_SOURCEFILE%.*}\")==NULL){if(__b2c__trap){ERROR = 6; if(!__b2c__catch_set) RUNTIMEERROR(\"OPTION INTERNATIONAL\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                            if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
                            then
                                g_CATCH_USED=1
                            fi
			else
			    echo -e "\nSyntax error: invalid argument to OPTION INTERNATIONAL at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
                    elif [[ "${1#* }" = +(*NETWORK*) ]]
		    then
                        case "${1##*NETWORK }" in
                            *TCP*)
                                g_NETWORKTYPE="TCP"
                                g_SOCKTYPE="SOCK_STREAM"
                                ;;
                            *UDP*)
                                g_NETWORKTYPE="UDP"
                                g_SOCKTYPE="SOCK_DGRAM"
                                ;;
                            *BROADCAST*)
                                g_NETWORKTYPE="BROADCAST"
                                g_SOCKTYPE="SOCK_DGRAM"
                                ;;
                            *MULTICAST*)
                                g_NETWORKTYPE="MULTICAST"
                                g_SOCKTYPE="SOCK_DGRAM"
				if [[ "${1##*MULTICAST }" = +([0123456789]) ]]
				then
				    g_MULTICAST_TTL="${1##*MULTICAST }"
				fi
                                ;;
                            *SCTP*)
			        echo "#include <netinet/sctp.h>" >> $g_HFILE
			        echo "struct sctp_initmsg __b2c__initmsg;" >> $g_HFILE
                                g_NETWORKTYPE="SCTP"
                                g_SOCKTYPE="SOCK_STREAM"
                                g_LDFLAGS="${g_LDFLAGS} -lsctp"
				if [[ "${1##*SCTP }" = +([0123456789]) ]]
				then
				    g_SCTP_STREAMS="${1##*SCTP }"
				fi
                                ;;
                            *)
			        echo -e "\nSyntax error: invalid argument to OPTION SOCKET at line $g_COUNTER in file '$g_CURFILE'!"
			        exit 1
                                ;;
			esac
                    elif [[ "${1#* }" = +(*PARSE*) ]]
		    then
			if [[ "${1##*PARSE }" = +([01]*|TRUE*|FALSE*) ]]
			then
                            g_IGNORE_PARSE=$(echo ${1##*PARSE })
			else
			    echo -e "\nSyntax error: invalid argument to OPTION PARSE at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
                        fi
                    elif [[ "${1#* }" = +(*EXPLICIT*) ]]
		    then
			if [[ "${1##*EXPLICIT }" = +([01]*|TRUE*|FALSE*) ]]
			then
			    g_OPTION_EXPLICIT=$(echo ${1##*EXPLICIT })
			else
			    echo -e "\nSyntax error: invalid argument to OPTION EXPLICIT at line $g_COUNTER in file '$g_CURFILE'!"
			    exit 1
			fi
                    elif [[ "${1#* }" = +(*VARTYPE*) ]]
		    then
                        g_VARTYPE=$(echo ${1##*VARTYPE })
		    else
			echo -e "\nSyntax error: argument to OPTION at line $g_COUNTER in file '$g_CURFILE' not recognized!"
			exit 1
		    fi
		fi;;
	    "PROTO")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty PROTO at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    SYM=`echo ${1#* } | tr -d "\042"`
		    # Check if ALIAS is there
		    if [[ $SYM = +(* ALIAS *) ]]
		    then
			echo "#define ${SYM##* ALIAS } ${SYM%% ALIAS *}" >> $g_HFILE
			g_IMPORTED="${SYM##* ALIAS } $g_IMPORTED"
			g_IMPORTED="${SYM%% ALIAS *} $g_IMPORTED"
		    elif [[ $SYM = +(* TYPE *) ]]
		    then
			echo "${SYM##* TYPE } ${SYM%% TYPE *};" >> $g_HFILE
		    else
			g_IMPORTED="${SYM//,/ } $g_IMPORTED"
		    fi
		fi;;
	    "INCR")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty INCR at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
                    # Get left side
                    TOKEN=$(Mini_Parser "${1}")
                    # Get right side
                    EXP="${1:${#TOKEN}+1}"
                    if [[ ${#EXP} -eq 0 ]]
                    then
                        EXP="1"
                    fi
                    TOKEN=${TOKEN#* }
		    # Check if there is associative array assignment
		    if [[ "${TOKEN}" = +(*[a-zA-Z]\(*\)) ]]
		    then
			INC=${TOKEN#*\(}
			echo "__b2c__${TOKEN%%\(*}_loc = __b2c__${TOKEN%%\(*}__add(${INC};" >> $g_CFILE
			echo "__b2c__${TOKEN%%\(*}_loc->value = ${TOKEN} + (${EXP});" >> $g_CFILE
			# Check for relations
			Relate_Recurse "${TOKEN%%\(*}" "${INC}" "${TOKEN}+(${EXP})" "-1"
		    else
                        # Regular number
                        if [[ ${EXP} = +(*[0-9].[0-9]*) && -z $(Get_Var ${TOKEN} ${g_FUNCNAME}) ]] 
                        then
                            if [[ $g_OPTION_EXPLICIT = "1" || $g_OPTION_EXPLICIT = "TRUE" ]]
                            then
	                        echo -e "\nSyntax error: OPTION EXPLICIT forces explicit variable declaration at line $g_COUNTER in file '$g_CURFILE'!"
                                exit 1
                            fi
	                    echo "double $TOKEN;" >> $g_HFILE
                            Save_Main_Var "${TOKEN}" "double"
                        elif [[ -z $(Get_Var ${TOKEN} ${g_FUNCNAME}) ]]
	                then
                            Register_Numeric ${TOKEN}
	                fi
			echo "${TOKEN} = ${TOKEN} + (${EXP});" >> $g_CFILE
		    fi
		fi;;
	    "DECR")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty DECR at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
                    # Get left side
                    TOKEN=$(Mini_Parser "${1}")
                    # Get right side
                    EXP="${1:${#TOKEN}+1}"
                    if [[ ${#EXP} -eq 0 ]]
                    then
                        EXP="1"
                    fi
                    TOKEN=${TOKEN#* }
		    # Check if there is associative array assignment
		    if [[ "${TOKEN}" = +(*[a-zA-Z]\(*\)) ]]
		    then
			INC=${TOKEN#*\(}
			echo "__b2c__${TOKEN%%\(*}_loc = __b2c__${TOKEN%%\(*}__add(${INC};" >> $g_CFILE
			echo "__b2c__${TOKEN%%\(*}_loc->value = ${TOKEN} - (${EXP});" >> $g_CFILE
			# Check for relations
			Relate_Recurse "${TOKEN%%\(*}" "${INC}" "${TOKEN}+(${EXP})" "-1"
		    else
                        # Regular number
                        if [[ ${EXP} = +(*[0-9].[0-9]*) && -z $(Get_Var ${TOKEN} ${g_FUNCNAME}) ]] 
                        then
                            if [[ $g_OPTION_EXPLICIT = "1" || $g_OPTION_EXPLICIT = "TRUE" ]]
                            then
	                        echo -e "\nSyntax error: OPTION EXPLICIT forces explicit variable declaration at line $g_COUNTER in file '$g_CURFILE'!"
                                exit 1
                            fi
	                    echo "double $TOKEN;" >> $g_HFILE
                            Save_Main_Var "${TOKEN}" "double"
                        elif [[ -z $(Get_Var ${TOKEN} ${g_FUNCNAME}) ]]
	                then
                            Register_Numeric ${TOKEN}
	                fi
			echo "${TOKEN} = ${TOKEN} - (${EXP});" >> $g_CFILE
		    fi
		fi;;
	    "ALARM")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty ALARM at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    EXP=${1#* }
		    if [[ $g_ALARM_FUNC != +(*__b2c__${EXP%,*}*) ]]
		    then
			g_ALARM_PROTO="$g_ALARM_PROTO void __b2c__${EXP%,*}(int signal){${EXP%,*}();} ;"
			g_ALARM_FUNC="$g_ALARM_FUNC __b2c__${EXP%,*}"
		    fi
		    echo "memset(&__b2c__psa, 0, sizeof(__b2c__psa)); __b2c__psa.sa_flags = SA_RESETHAND|SA_RESTART; __b2c__psa.sa_handler = __b2c__${EXP%,*}; sigaction(SIGALRM, &__b2c__psa, NULL);" >> $g_CFILE
                    echo "__b2c__alarm.it_value.tv_sec = (long)(${EXP#*,})/1000; __b2c__alarm.it_value.tv_usec = ((${EXP#*,})%1000)*1000;" >> $g_CFILE
                    echo "__b2c__alarm.it_interval.tv_sec = 0; __b2c__alarm.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &__b2c__alarm, NULL);" >> $g_CFILE
		fi;;
	    "SIGNAL")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty SIGNAL at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    EXP=${1#* }
		    if [[ ${EXP} = +(*,*) ]]
		    then
			if [[ ${EXP%,*} = +(*SIG_DFL*|*SIG_IGN*) ]]
			then
			    echo "memset(&__b2c__psa, 0, sizeof(__b2c__psa)); __b2c__psa.sa_handler = ${EXP%,*}; sigaction(${EXP#*,}, &__b2c__psa, NULL);" >> $g_CFILE
			else
			    if [[ $g_ALARM_FUNC != +(*__b2c__${EXP%,*}*) ]]
			    then
				echo "void __b2c__${EXP%,*}(int signal){${EXP%,*}();}" >> $g_HFILE
				g_ALARM_FUNC="$g_ALARM_FUNC __b2c__${EXP%,*}"
			    fi
			    echo "memset(&__b2c__psa, 0, sizeof(__b2c__psa)); __b2c__psa.sa_handler = __b2c__${EXP%,*}; sigaction(${EXP#*,}, &__b2c__psa, NULL);" >> $g_CFILE
			fi
		    else
			echo -e "\nSyntax error: missing argument in SIGNAL at line $g_COUNTER in file '$g_CURFILE'!"
			exit 1
		    fi
		fi;;
	    "CURSOR")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty CURSOR at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
                    EXP=1
		    if [[ "${1#* }" = +(*OFF*) ]]
		    then
			echo "fprintf(stdout,\"\033[?25l\"); fflush(stdout);" >> $g_CFILE
		    elif [[ "${1#* }" = +(*ON*) ]]
		    then
			echo "fprintf(stdout,\"\033[?25h\"); fflush(stdout);" >> $g_CFILE
            	    elif [[ "${1#* }" = +(*UP*) ]]
		    then
                        if [[ ${1##*UP } != +(*UP*) ]]
                        then
                            EXP=${1##*UP }
                        fi
			echo "fprintf(stdout,\"\033[%ldA\", (long)${EXP}); fflush(stdout);" >> $g_CFILE
		    elif [[ "${1#* }" = +(*DOWN*) ]]
		    then
                        if [[ ${1##*DOWN } != +(*DOWN*) ]]
                        then
                            EXP=${1##*DOWN }
                        fi
			echo "fprintf(stdout,\"\033[%ldB\", (long)${EXP}); fflush(stdout);" >> $g_CFILE
		    elif [[ "${1#* }" = +(*FORWARD*) ]]
		    then
                        if [[ ${1##*FORWARD } != +(*FORWARD*) ]]
                        then
                            EXP=${1##*FORWARD }
                        fi
			echo "fprintf(stdout,\"\033[%ldC\", (long)${EXP}); fflush(stdout);" >> $g_CFILE
		    elif [[ "${1#* }" = +(*BACK*) ]]
		    then
                        if [[ ${1##*BACK } != +(*BACK*) ]]
                        then
                            EXP=${1##*BACK }
                        fi
			echo "fprintf(stdout,\"\033[%ldD\", (long)${EXP}); fflush(stdout);" >> $g_CFILE
		    fi
		fi;;
            "SCROLL")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty SCROLL at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
                    EXP=1
		    if [[ "${1#* }" = +(*UP*) ]]
		    then
                        if [[ ${1##*UP } != +(*UP*) ]]
                        then
                            EXP=${1##*UP }
                        fi
			echo "fprintf(stdout,\"\033[%ldS\", (long)${EXP}); fflush(stdout);" >> $g_CFILE
		    elif [[ "${1#* }" = +(*DOWN*) ]]
		    then
                        if [[ ${1##*DOWN } != +(*DOWN*) ]]
                        then
                            EXP=${1##*DOWN }
                        fi
			echo "fprintf(stdout,\"\033[%ldT\", (long)${EXP}); fflush(stdout);" >> $g_CFILE
		    fi
		fi;;
	    "ALIAS")
		Handle_Alias "${1#* }";;
	    "LOOKUP")
		Handle_Lookup "${1#* }";;
	    "RELATE")
		Handle_Relate "${1#* }";;
	    "TEXTDOMAIN")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty TEXTDOMAIN at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    EXP=${1#* }
		    if [[ ${EXP} = +(*,*) ]]
		    then
			echo "if(bindtextdomain(${EXP})==NULL){if(__b2c__trap){ERROR = 6;if(!__b2c__catch_set) RUNTIMEERROR(\"TEXTDOMAIN\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
			echo "if(textdomain(${EXP%,*})==NULL){if(__b2c__trap){ERROR = 6; if(!__b2c__catch_set) RUNTIMEERROR(\"TEXTDOMAIN\", $g_COUNTER, \"$g_CURFILE\", ERROR); else if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE
                        if [[ ${g_CATCHGOTO} = "__B2C__PROGRAM__EXIT" ]]
                        then
                            g_CATCH_USED=1
                        fi
		    else
			echo -e "\nSyntax error: missing argument in TEXTDOMAIN at line $g_COUNTER in file '$g_CURFILE'!"
			exit 1
		    fi
		fi;;
	    "REDIM")
		Handle_Redim "${1#* }";;
            "EXIT")
		if [[ -z $g_FUNCNAME ]]
		then
		    echo -e "\nSyntax error: EXIT not in FUNCTION or SUB at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		fi
		# Free strings variables if there are any
		echo "${g_STRINGARRAYS}" >> $g_CFILE
		for EXP in $g_LOCALSTRINGS
		do
		    echo "__b2c__STRFREE($EXP);" >> $g_CFILE
		done
		echo "__b2c__catch_set = __b2c__catch_set_backup; __b2c__sbuffer = __b2c__sbuffer_backup; __b2c__sbuffer_ptr = __b2c__sbuffer_ptr_backup;" >> $g_CFILE
		# The actual exit
		if [[ "${g_FUNCNAME}" = +(*${g_STRINGSIGN}*) ]]
		then
		    echo "return(NULL);" >> $g_CFILE
		else
		    echo "return __b2c__exitval;" >> $g_CFILE
		fi;;
	    "PRAGMA")
		# Check argument
		if [[ "${1%% *}" = "${1#* }" ]]
		then
		    echo -e "\nSyntax error: empty PRAGMA at line $g_COUNTER in file '$g_CURFILE'!"
		    exit 1
		else
		    if [[ "${1#* }" = +(*OPTIONS*) ]]
		    then
                        g_CCFLAGS="$g_CCFLAGS ${1##*OPTIONS }"
		    elif [[ "${1#* }" = +(*COMPILER*) ]]
		    then
                        g_CCNAME="${1##*COMPILER }"
	            elif [[ "${1#* }" = +(*FRAMEWORK*) ]] 
                    then
			g_LDFLAGS="$g_LDFLAGS -framework ${1##*FRAMEWORK }"
                    elif [[ "${1#* }" = +(*RE*) ]]
		    then
                        g_PRAGMA_REGEX=$(echo ${1##*RE })
                        if [[ $g_PRAGMA_REGEX != +(* LDFLAGS *) ]]
                        then
                            EXP=${g_PRAGMA_REGEX%% *}
                            if [[ $EXP = +(*tre*) ]]
                            then
                                g_LDFLAGS="-ltre $g_LDFLAGS"
                            elif [[ $EXP = +(*pcre*) ]]
                            then
                                g_LDFLAGS="$g_LDFLAGS -lpcreposix"
                            elif [[ $EXP = +(*onig*) ]]
                            then
                                g_LDFLAGS="$g_LDFLAGS -lonig"
                            fi
                        else
                            EXP=${g_PRAGMA_REGEX##* LDFLAGS }
                            g_LDFLAGS="${EXP} $g_LDFLAGS"
                        fi
                    elif [[ "${1#* }" = +(*TLS*) ]]
		    then
                        g_LIB_TLS=$(echo ${1##*TLS })
                        if [[ $g_LIB_TLS != +(* LDFLAGS *) ]]
                        then
                            EXP=${g_LIB_TLS%% *}
                            if [[ $EXP = +(*openssl*) ]]
                            then
                                g_LIB_TLS="-lssl -lcrypto"
                                g_INC_TLS="#include <openssl/ssl.h>"
                            elif [[ $EXP = +(*gnutls*) ]]
                            then
                                g_LIB_TLS="-lgnutls -lgnutls-openssl"
                                g_INC_TLS="#include <gnutls/openssl.h>"
                            elif [[ $EXP = +(*wolfssl*) ]]
                            then
                                g_LIB_TLS="-lwolfssl"
                                g_INC_TLS="#include <wolfssl/options.h>\n#include <wolfssl/openssl/ssl.h>"
                            fi
                        else
                            g_INC_TLS="${g_LIB_TLS%% LDFLAGS *}"
                            g_LIB_TLS="${g_LIB_TLS##* LDFLAGS }"
                        fi
                        if [[ ${g_LIB_TLS} = +(*-lgnutls*) ]]
                        then
                            echo "#define SSL_set_tlsext_host_name(connection, name) gnutls_server_name_set(((SSL*)connection)->gnutls_state, GNUTLS_NAME_DNS, name, LEN(name))" >> $g_HFILE
                            echo "#undef VERIFY" >> $g_HFILE
                            echo "long VERIFY(int ssl, char* pem) { int result = 0; gnutls_certificate_credentials_t cred = NULL; if(__b2c_ssl_ptr[ssl] == NULL) return(-1);" >> $g_HFILE
                            echo "gnutls_certificate_allocate_credentials(&cred); gnutls_certificate_set_x509_trust_file(cred, pem, GNUTLS_X509_FMT_PEM);" >> $g_HFILE
                            echo "if(gnutls_credentials_set(((SSL*)__b2c_ssl_ptr[ssl])->gnutls_state, GNUTLS_CRD_CERTIFICATE, cred) != 0) return(-1); if(gnutls_certificate_verify_peers2(((SSL*)__b2c_ssl_ptr[ssl])->gnutls_state, &result) !=0) return(-1);" >> $g_HFILE
                            echo "gnutls_certificate_free_credentials(cred); return(result); }" >> $g_HFILE
                        fi
                    elif [[ "${1#* }" = +(*LDFLAGS*) ]]
		    then
                        if [[ ${1##*LDFLAGS } = +(*pkg-config*) ]]
                        then
                            g_LDFLAGS="$g_LDFLAGS ${1##*LDFLAGS }"
                        else
                            for EXP in ${1##*LDFLAGS }
                            do
                                if [[ ${EXP} = +(-*) || ${EXP} = +(*.a) ]]
                                then
                                    g_LDFLAGS="$g_LDFLAGS ${EXP}"
                                else
                                    g_LDFLAGS="$g_LDFLAGS -l${EXP}"
                                fi
                            done
                        fi
		    elif [[ "${1#* }" = +(*INCLUDE*) ]]
		    then
                        for EXP in ${1##*INCLUDE }
                        do
                            if [[ ${EXP:0:1} = "<" ]]
                            then
                                echo "#include ${EXP}" >> $g_HFILE
                            elif [[ ${EXP:0:1} = "/" ]]
                            then
                                echo "#include \"${EXP}\"" >> $g_HFILE
                            else
                                echo "#include \"`pwd`/${EXP}\"" >> $g_HFILE
                            fi
                        done
		    elif [[ "${1#* }" = +(*BACONLIB*) ]]
		    then
                        g_REBUILD_ARCHIVE="libbacon.a"
	                g_CCFLAGS="$g_CCFLAGS -fPIC"
		    else
                        echo "#pragma ${1##*PRAGMA }" >> $g_CFILE
		    fi
		fi;;
	    "SWAP")
		Handle_Swap "${1#* }";;
	    "SETSERIAL")
		Handle_Setserial "${1#* }";;
	    "ENUM")
                if [[ -z $g_FUNCNAME ]]
                then
                    echo "enum {" >> $g_HFILE
		    let g_USE_H=1
                else
                    echo "enum {" >> $g_CFILE
		    let g_USE_C=1
                fi;;
	    "RUN")
		Handle_Run "${1#* }";;
	    "SAVE")
		Handle_Save "SAVE" "${1#* }";;
	    "BSAVE")
		Handle_Save "BSAVE" "${1#* }";;
	    "APPEND")
		Handle_Save "APPEND" "${1#* }";;
	    "BAPPEND")
		Handle_Save "BAPPEND" "${1#* }";;
	    "MAP")
		Handle_Map "${1#* }";;
            "RESET")
                echo "fprintf(stdout,\"\033c\"); fflush(stdout);" >> $g_CFILE
                ;;
	    *)
		# Check on imported symbols first
		FOUND=0
		for SYM in $g_IMPORTED
		do
		    if [[ "$SYM" = "${1%%\(*}" || "$SYM" = "${1%% *}" ]]
		    then
			FOUND=1
                        # Check if there are () - KSH93 construction
                        if [[ ${1} = ${1##*\(} ]]
			then
			    echo "$SYM();" >> $g_CFILE
			else
			    echo "$SYM(${1#*\(};" >> $g_CFILE
			fi
                        break
		    fi
		done
		# Not an imported symbol? Check if assignment
		if [[ $FOUND -eq 0 ]]
		then
		    Handle_Let "$1"
		fi;;
	esac
    fi
}

#-----------------------------------------------------------

function Pre_Tokenize_Functions
{
    typeset DATA IS_ESCAPED IS_STRING TOKEN CHAR ARG SRC SOURCE TYPE VARS INTOKEN FIRST IS_LOOP
    typeset -i LEN NR

    # Initialize miniparser, convert spaces
    DATA="${1// /${g_PARSEVAR}}"

    # Check if one of these conversion time functions are there - the OR's are needed for KSH93
    if [[ ${DATA} = +(*TYPEOF\$*|*SOURCE\$*) || ${DATA} = +(*LOOP\$*|*COIL\$*|*INTL\$*) || ${DATA} = +(*NNTL\$*|*IIF\(*|*IIF\$\(*) || ${DATA} = +(*EVAL\(*|*VERIFY*|*REM*) ]]
    then
        IS_ESCAPED=0
        IS_STRING=0
        IS_LOOP=0
        TOKEN=
        NR=1
        LEN=${#DATA}
        until [[ $LEN -eq 0 ]]
        do
            CHAR="${DATA:0:7}"
	    if [[ "${CHAR}" = "TYPEOF$" ]]
            then
	        if [[ $IS_STRING -eq 0 ]]
	        then
                    ARG=${DATA%%\)*}
                    let LEN=${#DATA}-${#ARG}-1
		    TOKEN="${TOKEN}\"$(Get_Var ${ARG##*\(} ${g_FUNCNAME})\""
                    if [[ ${LEN} -eq 0 ]]
                    then
                        break
                    fi
	            DATA="${DATA: -$LEN}"
                fi
	    elif [[ "${CHAR}" = "SOURCE$" ]]
	    then
	        if [[ $IS_STRING -eq 0 ]]
	        then
		    if [[ ! -f $SRCARRAYFILE ]]
		    then 
			SRC=$(od -An -tu1 $g_SOURCEFILE)
			for i in ${SRC}
			do
			    SOURCE="$SOURCE${i},"
			done
			echo "unsigned char SOURCE${g_STRINGSIGN}[]={ ${SOURCE%?},0 };" > $SRCARRAYFILE
		    fi
		fi
	    fi
            CHAR="${DATA:0:6}"
            if [[ "${CHAR}" = "VERIFY" ]]
            then
                if [[ $IS_STRING -eq 0 ]]
	        then
                    ARG=${DATA#*\(}
                    INTOKEN=$(Mini_Parser "${ARG}")
                    let LEN=${#ARG}-${#INTOKEN}-1
	            INTOKEN="${DATA: -$LEN}"
                    ARG=${INTOKEN%%\)*}
                    echo "#undef __b2c__cacerts" >> $g_HFILE
                    echo "#define __b2c__cacerts ${ARG//${g_PARSEVAR}/ }" >> $g_HFILE
                    if [[ ${g_LIB_TLS} = +(*-lwolfssl*) ]]
                    then
                        echo "#undef __b2c__capeer" >> $g_HFILE
                        echo "#define __b2c__capeer SSL_VERIFY_PEER" >> $g_HFILE
                    fi
		    TOKEN="${TOKEN}VERIFY"
                    let LEN=${#DATA}-6
	            DATA="${DATA: -$LEN}"
                    if [[ ${LEN} -eq 0 ]]
                    then
                        break
                    fi
                fi
	    fi
            CHAR="${DATA:0:5}"
	    if [[ "${CHAR}" = "LOOP$" || "${CHAR}" = "COIL$" ]]
            then
	        if [[ $IS_STRING -eq 0 ]]
	        then
                    if [[ ${IS_LOOP} -eq 1 ]]
                    then
                        TOKEN="LOOP_ERROR"
		        break
                    fi
                    ARG=${DATA#*\(}
                    FIRST=$(Mini_Parser "${ARG}")
                    let LEN=${#DATA}-${#FIRST}-7
	            ARG="${ARG: -$LEN}"
                    SECOND=$(Mini_Parser "${ARG}")
                    let LEN=${#ARG}-${#SECOND}
	            ARG="${ARG: -$LEN}"
                    if [[ ${ARG:0:1} = "," ]]
                    then
                        ARG="${ARG:1}"
                        SRC=$(Mini_Parser "${ARG}")
                    else
                        SRC="${SECOND}"
                        SECOND="${FIRST}"
                        FIRST="_"
                    fi
                    if [[ "${CHAR}" = "LOOP$" ]]
                    then
                        TOKEN="IF setjmp(__b2c__loop2) THEN:FOR ${FIRST}=1 TO ${SECOND}:__b2c__loop_result${g_STRINGSIGN} = CONCAT\$(__b2c__loop_result${g_STRINGSIGN}, ${SRC}:NEXT:CALL longjmp(__b2c__loop1, 1):ENDIF:${TOKEN}"
                    else
                        TOKEN="IF setjmp(__b2c__loop2) THEN:FOR ${FIRST}=1 TO ${SECOND}:__b2c__loop_result${g_STRINGSIGN} = APPEND\$(__b2c__loop_result${g_STRINGSIGN}, 0, ${SRC}:NEXT:CALL longjmp(__b2c__loop1, 1):ENDIF:${TOKEN}"
                    fi
                    IS_LOOP=1
                fi
	    elif [[ "${CHAR}" = "INTL$" ]]
            then
	        if [[ $IS_STRING -eq 0 ]]
	        then
                    let LEN=${#DATA}-5
	            DATA="${DATA: -$LEN}"
		    TOKEN="${TOKEN}gettext"
                fi
	    elif [[ "${CHAR}" = "NNTL$" ]]
            then
	        if [[ $IS_STRING -eq 0 ]]
	        then
                    let LEN=${#DATA}-5
	            DATA="${DATA: -$LEN}"
		    TOKEN="${TOKEN}ngettext"
                fi
            elif [[ "${CHAR}" = "IIF\$(" ]]
            then
	        if [[ $IS_STRING -eq 0 ]]
	        then
                    ARG=${DATA#*\(}
                    INTOKEN=$(Mini_Parser "${ARG}")
                    if [[ $ARG = +(*${g_PARSEVAR}BETWEEN${g_PARSEVAR}*\;*) ]]
                    then
                        ARG="${ARG:${#INTOKEN}+1}"
                        INTOKEN="$INTOKEN;$(Mini_Parser ${ARG})"
                    fi
                    Parse_Equation "${INTOKEN}"
		    TOKEN="${TOKEN}IIF\$(${g_EQUATION}"
                    let LEN=${#DATA}-${#INTOKEN}-5
	            DATA="${DATA: -$LEN}"
                fi
            elif [[ "${CHAR}" = "EVAL(" ]]
            then
	        if [[ $IS_STRING -eq 0 ]]
                then
                    if [[ $NR -eq 1 ]]
	            then
                        VARS="__b2c_te_variable __b2c_evalvars_${g_FUNCNAME}${g_COUNTER}[] = {{EmptyString, 0}"
                        for i in ${!g_ALL_FUNC_VARS[@]}
                        do
                            if [[ "${i##*___}" = ${g_FUNCNAME} ]]
                            then
                                TYPE=$(Get_Var ${i%%___*} ${g_FUNCNAME})
                                if [[ ${TYPE} != +(*\**) && ${TYPE} = +(*double|*FLOATING) ]]
                                then
                                    SRC=${i%%___*}
                                    VARS="${VARS},{\"${SRC}\", &${SRC}}"
                                    ((NR+=1))
                                fi
                            fi
                        done
                        for i in ${!g_ALL_MAIN_VARS[@]}
                        do
                            TYPE=$(Get_Var $i)
                            if [[ ${TYPE} != +(*\**) && ${TYPE} = +(*double|*FLOATING) ]]
                            then
                                VARS="${VARS},{\"${i}\", &${i}}"
                                ((NR+=1))
                            fi
                        done
                        echo "${VARS}};" >> $g_CFILE
                    fi
		    TOKEN="${TOKEN}EVAL(__b2c_evalvars_${g_FUNCNAME}${g_COUNTER},${NR},"
                    let LEN=${#DATA}-5
	            DATA="${DATA: -$LEN}"
                fi
            fi
            CHAR="${DATA:0:4}"
	    if [[ "${CHAR}" = "IIF(" ]]
            then
	        if [[ $IS_STRING -eq 0 ]]
	        then
                    ARG=${DATA#*\(}
                    INTOKEN=$(Mini_Parser "${ARG}")
                    if [[ $ARG = +(*${g_PARSEVAR}BETWEEN${g_PARSEVAR}*\;*) ]]
                    then
                        ARG="${ARG:${#INTOKEN}+1}"
                        INTOKEN="$INTOKEN;$(Mini_Parser ${ARG})"
                    fi
                    Parse_Equation "${INTOKEN}"
		    TOKEN="${TOKEN}IIF(${g_EQUATION}"
                    let LEN=${#DATA}-${#INTOKEN}-4
	            DATA="${DATA: -$LEN}"
                fi
	    elif [[ "${CHAR}" = +(REM[[:space:]]|REM${g_PARSEVAR}) || ${DATA} = "REM" ]]
            then
	        if [[ $IS_STRING -eq 0 ]]
	        then
                    let LEN=0
                    break
                fi
            fi
	    CHAR="${DATA:0:1}"
	    case $CHAR in
	        \\)
		    if [[ $IS_ESCAPED -eq 0 ]]
		    then
		        IS_ESCAPED=1
		    else
		        IS_ESCAPED=0
		    fi;;
	        \")
		    if [[ $IS_ESCAPED -eq 0 ]]
		    then
		        if [[ $IS_STRING -eq 0 ]]
		        then
			    IS_STRING=1
		        else
			    IS_STRING=0
		        fi
		    fi
		    IS_ESCAPED=0;;
            esac
	    TOKEN="${TOKEN}${CHAR}"
	    let LEN=${#DATA}-1
	    DATA="${DATA: -$LEN}"
        done
        echo "${TOKEN}"
    else
        echo "${DATA}"
    fi
}

#-----------------------------------------------------------

function Tokenize
{
    typeset CHAR IS_STATEMENT TOKEN DATA LEN LINE INLEN INCHAR INTOKEN ITEM1 ITEM2 RESULT ARG ELEM EXP SEP STR
    typeset -i DIRECT INSPAC BRACKET ISQUOTE IS_STRING INSTR IS_ESCAPED INESCAPED SFUNC SFTOT IN_FUNC

    # Verify if there is a class definition
    if [[ ${1} = +(CLASS*) ]]
    then
        Parse_Line "${1}"
        return
    fi

    # In TRACE MODE show linenr and code
    if [[ $g_TRACE -eq 1 ]]
    then
        if [[ ${1} != +(FUNCTION*) && ${1} != +(SUB*) && ${1} != +(ELIF*) && ${1} != +(ELSE*) ]]
        then
	    echo "if(__b2c__getch() == 27) {fprintf(stderr, \"TRACE OFF - exiting trace mode.\n\"); exit(EXIT_SUCCESS);}" >> $g_CFILE
	    LINE=`echo "${1}" | tr "\042" "\047"`
	    LINE="${LINE//\\/\\\\}"
	    echo "fprintf(stderr, \"File '${g_CURFILE}' line %d: ${g_TRACE_PREFIX}${LINE//%/%%}\n\", $g_COUNTER);" >> $g_CFILE
            if [[ -n $g_MONITOR ]]
            then
                echo ${g_MONITOR} >> $g_CFILE
            fi
            g_TRACE_PREFIX=
        fi
    fi

    # Initialize miniparser, convert spaces
    DATA=$(Pre_Tokenize_Functions "${1}")

    # Check on nested loops
    if [[ ${DATA} = "LOOP_ERROR" ]]
    then
        echo -e "\nSyntax error: nested LOOP$/COIL$ at line $g_COUNTER in file '$g_CURFILE'!"
        exit 1
    fi

    SFTOT=0
    SFUNC=0
    IN_FUNC=0

    while true
    do
        IS_ESCAPED=0
        IS_STRING=0
        IS_STATEMENT=""
        TOKEN=
        LEN=${#DATA}

        until [[ $LEN -eq 0 ]]
        do
	    CHAR="${DATA:0:1}"
	    case $CHAR in
	        :)
                    if [[ $IS_STRING -eq 0 && "${DATA:1:1}" = ":" ]]
                    then
	                let LEN=${#DATA}-1
	                DATA="${DATA: -$LEN}"
	                TOKEN="${TOKEN}:"
		    elif [[ $IS_STRING -eq 0 && $g_USE_C -eq 0 && $g_USE_H -eq 0 && $IN_FUNC -eq 0 ]]
		    then
                        # If we are in a string function increase line counter
                        if [[ ${g_FUNCNAME} = +(*${g_STRINGSIGN}*) && $SFTOT -gt 0 ]]
                        then
                            ((g_STRING_LINE+=1))
                        fi
                        # Determine amount of string funcs
                        if [[ $SFTOT -gt $g_STRING_FUNC ]]
                        then
                            g_STRING_FUNC=$SFTOT
                        fi
		        Parse_Line "${TOKEN//${g_PARSEVAR}/ }"
		        CHAR=
		        TOKEN=
		        IS_STATEMENT=""
                        SFUNC=0
                        SFTOT=0
		    fi;;
	        ${g_TAB})
		    if [[ $IS_STRING -eq 0 ]]
		    then
		        TOKEN="${TOKEN} "
                    else
		        TOKEN="${TOKEN}${g_TAB}"
                    fi
		    CHAR=
		    IS_ESCAPED=0
		    ;;
	        $)
		    if [[ $IS_STRING -eq 0 || ${1} = +(*IMPORT*FROM*TYPE*) ]]
		    then
		        TOKEN="${TOKEN}${g_STRINGSIGN}"
		        CHAR=
		        IS_ESCAPED=0
                        let SFUNC=1
		    fi;;
                \()
                    if [[ ${IS_STRING} -eq 0 && $g_USE_C -eq 0 && $g_USE_H -eq 0 ]]
                    then
                        ((IN_FUNC+=1))
                        if [[ ${SFUNC} -gt 0 ]]
                        then
                            let SFUNC=0
                            ((SFTOT+=1))
                        fi
                    fi;;
                \))
                    if [[ ${IS_STRING} -eq 0 && $g_USE_C -eq 0 && $g_USE_H -eq 0 ]]
                    then
                        ((IN_FUNC-=1))
                    fi;;
                \?)
                    if [[ ${IS_STRING} -eq 0 && $g_USE_C -eq 0 && $g_USE_H -eq 0 && $IN_FUNC -eq 0 ]]
                    then
                        CHAR="PRINT "
                    fi;;
                \[)
                    if [[ ${IS_STRING} -eq 0 && "${DATA:0:2}" != "[]" && "${DATA:0:11}" != "[(uint64_t)" ]]
                    then
                        CHAR="[(uint64_t)"
                    fi;;
	        %)
		    if [[ $IS_STRING -eq 0 && ${TOKEN: -1} = +([a-zA-Z0-9_]) ]]
		    then
		        TOKEN="${TOKEN}${g_LONGSIGN}"
		        CHAR=
		        IS_ESCAPED=0
		    fi;;
	        \#)
		    if [[ $IS_STRING -eq 0 && ${TOKEN: -1} = +([a-zA-Z0-9_]) && ${#TOKEN} -gt 0 ]]
		    then
		        TOKEN="${TOKEN}${g_FLOATSIGN}"
		        CHAR=
		        IS_ESCAPED=0
		    fi;;
	        \\)
		    if [[ $IS_ESCAPED -eq 0 ]]
		    then
		        IS_ESCAPED=1
		    else
		        IS_ESCAPED=0
		    fi;;
	        \")
		    if [[ $IS_ESCAPED -eq 0 ]]
		    then
		        if [[ $IS_STRING -eq 0 ]]
		        then
			    IS_STRING=1
		        else
			    IS_STRING=0
		        fi
		    fi
		    IS_ESCAPED=0;;
                \&)
		    if [[ $IS_STRING -eq 0 && $g_USE_C -eq 0 && $g_USE_H -eq 0 ]]
		    then
                        # ITEMIZER1: Get item on the left side
                        INTOKEN=$(echo ${TOKEN// /${g_PARSEVAR}})
                        INLEN=${#INTOKEN}
                        ITEM1=""
                        BRACKET=0
                        INSPAC=0
                        INSTR=0
                        DIRECT=0
                        ISQUOTE=0
                        until [[ $INLEN -eq 0 ]]
                        do
                            INCHAR="${INTOKEN: -1}"
                            case ${INCHAR} in
                                \)|\])
                                    ISQUOTE=0
                                    DIRECT=1
                                    if [[ ${INSTR} -eq 0 ]]
                                    then
                                        ((BRACKET+=1))
                                    fi;;
                                \(|\[)
                                    ISQUOTE=0
                                    DIRECT=1
                                    if [[ ${INSTR} -eq 0 ]]
                                    then
                                        ((BRACKET-=1))
                                        if [[ ${BRACKET} -lt 0 ]]
                                        then
                                            break
                                        fi
                                    fi;;
                                =|\>)
                                    ISQUOTE=0
                                    if [[ ${INSTR} -eq 0 ]]
                                    then
                                        break
                                    fi;;
                                ,)
                                    ISQUOTE=0
                                    if [[ ${INSTR} -eq 0 && ${BRACKET} -eq 0 ]]
                                    then
                                        break
                                    fi;;
                    	        \\)
		                    if [[ $ISQUOTE -eq 1 ]]
		                    then
		                        INSTR=1
		                    fi
                                    ISQUOTE=0;;
	                        \")
                                    ISQUOTE=1
                                    DIRECT=1
		                    if [[ $INSTR -eq 0 ]]
		                    then
			                INSTR=1
		                    else
			                INSTR=0
		                    fi;;
                                [A-Za-z])
                                    ISQUOTE=0
                                    DIRECT=1
                                    if [[ ${INSTR} -eq 0 && ${BRACKET} -eq 0 ]]
                                    then
                                        if [[ $INSPAC -gt 0 ]]
                                        then
                                            break
                                        fi
                                    fi;;
                                ${g_PARSEVAR})
                                    ISQUOTE=0
                                    if [[ ${INSTR} -eq 0 && ${BRACKET} -eq 0 ]]
                                    then
                                        if [[ ${DIRECT} -gt 0 ]]
                                        then
                                            INSPAC=1
                                        fi
                                    fi;;
                                :)
                                    if [[ ${BRACKET} -eq 0 ]]
                                    then
                                        ISQUOTE=0
                                        if [[ ${INSTR} -eq 0 ]]
                                        then
                                            break
                                        fi
                                    fi;;
                            esac
	                    if [[ "${INCHAR}" = "${g_PARSEVAR}" ]]
	                    then
	                        ITEM1=" ${ITEM1}"
                            else
	                        ITEM1="${INCHAR}${ITEM1}"
                            fi
                            let INLEN=${#INTOKEN}-1
                            INTOKEN="${INTOKEN:0:$INLEN}"
                        done
                        # If ITEM is a string element continue
			if [[ $(Check_String_Type ${ITEM1}) -eq 1 ]]
			then
		            CHAR=""
                            TOKEN=$(echo ${INTOKEN// /${g_PARSEVAR}})
                            # ITEMIZER2: Get item on the right side
                            ((LEN-=1))
                            INTOKEN="${DATA: -$LEN}"
                            INLEN=${#INTOKEN}
                            ITEM2=""
                            BRACKET=0
                            INSTR=0
                            INESCAPED=0
			    INSPAC=0
			    DIRECT=0
                            SFUNC=0
                            until [[ $INLEN -eq 0 ]]
                            do
                                INCHAR="${INTOKEN:0:1}"
                                case $INCHAR in
                                    \()
					DIRECT=1
                                        if [[ ${INSTR} -eq 0 ]]
                                        then
                                            ((BRACKET+=1))
                                        fi
                                        if [[ ${SFUNC} -gt 0 ]]
                                        then
                                            let SFUNC=0
                                            ((SFTOT+=1))
                                        fi;;
                                    \))
					DIRECT=1
                                        if [[ ${INSTR} -eq 0 ]]
                                        then
                                            ((BRACKET-=1))
                                            if [[ ${BRACKET} -lt 0 ]]
                                            then
                                                break
                                            fi
                                        fi;;
                                    ,|\=|\<|\!)
                                        if [[ ${INSTR} -eq 0 && ${BRACKET} -eq 0 ]]
                                        then
                                            break
                                        fi;;
                                    \&)
                                        if [[ ${INSTR} -eq 0 && ${BRACKET} -eq 0 ]]
                                        then
			                    INSPAC=0
			                    DIRECT=0
                                            INCHAR=","
                                        fi;;
            	                    \\)
		                        if [[ $INESCAPED -eq 0 ]]
		                        then
		                            INESCAPED=1
		                        else
		                            INESCAPED=0
		                        fi;;
	                            \")
					DIRECT=1
		                        if [[ $INESCAPED -eq 0 ]]
		                        then
		                            if [[ $INSTR -eq 0 ]]
		                            then
			                        INSTR=1
		                            else
			                        INSTR=0
		                            fi
                                        fi
                                        INESCAPED=0;;
				    [A-Za-z])
					DIRECT=1
					if [[ ${INSTR} -eq 0 && ${BRACKET} -eq 0 ]]
					then
					    if [[ $INSPAC -gt 0 ]]
					    then
						break
					    fi
					fi;;
				    ${g_PARSEVAR})
					if [[ ${INSTR} -eq 0 && ${BRACKET} -eq 0 ]]
					then
					    if [[ ${DIRECT} -gt 0 ]]
					    then
						INSPAC=1
					    fi
					fi;;
                                    :|\;)
                                        if [[ ${INSTR} -eq 0 && ${BRACKET} -eq 0 ]]
                                        then
                                            break
                                        fi;;
                                esac
	                        if [[ "${INCHAR}" = "${g_PARSEVAR}" ]]
	                        then
	                            ITEM2="${ITEM2} "
                                elif [[ "${INCHAR}" = "$" ]]
                                then
		                    if [[ $INSTR -eq 0 || ${1} = +(*IMPORT*FROM*TYPE*) ]]
		                    then
	                                ITEM2="${ITEM2}${g_STRINGSIGN}"
                                        let SFUNC=1
                                    else
	                                ITEM2="${ITEM2}$"
                                    fi
                                else
	                            ITEM2="${ITEM2}${INCHAR}"
                                fi
                                let INLEN=${#INTOKEN}-1
                                INTOKEN="${INTOKEN: -$INLEN}"
                            done
                            ((INLEN+=1))
		            DATA="${DATA: -$INLEN}"
                            # Make sure concatenation of literals is done by C - delete comma
                            EXP="${ITEM1},${ITEM2}"
                            STR=""
                            # Start miniparser
                            while [[ -n ${EXP} ]]
                            do
                                ELEM=$(Mini_Parser "${EXP}")
                                if [[ -z $STR ]]
                                then
                                    STR="${ELEM}"
                                else
                                    STR="${STR},${ELEM}"
                                fi
                                EXP="${EXP:${#ELEM}+1}"
                            done
                            # Construct concatenation
                            TOKEN="${TOKEN} CONCAT${g_STRINGSIGN}(${STR}) "
                            ((SFTOT+=1))
                        fi
                    fi
		    IS_ESCAPED=0;;
                [A-Za-z=])
		    if [[ $IS_STRING -eq 0 ]]
		    then
		        IS_STATEMENT=" "
		    fi
		    IS_ESCAPED=0;;
	        *)
		    IS_ESCAPED=0;;
	    esac
	    # Convert back to space
	    if [[ "${CHAR}" = "${g_PARSEVAR}" ]]
	    then
	        TOKEN="${TOKEN}${IS_STATEMENT}"
            elif [[ -n ${CHAR} ]]
            then
	        TOKEN="${TOKEN}${CHAR}"
	    fi
	    let LEN=${#DATA}-1
	    DATA="${DATA: -$LEN}"
        done

        # Check if all nested '&' have been parsed
        if [[ "${TOKEN}" = "${RESULT}" ]]
        then
            break
        fi
        RESULT=${TOKEN}
        DATA=$(echo ${TOKEN// /${g_PARSEVAR}})
    done
    # If we are in a string function increase line counter
    if [[ ${g_FUNCNAME} = +(*${g_STRINGSIGN}*) && $SFTOT -gt 0 ]]
    then
        ((g_STRING_LINE+=1))
    fi
    # Determine amount of string funcs
    if [[ $SFTOT -gt $g_STRING_FUNC ]]
    then
        g_STRING_FUNC=$SFTOT
    fi
    Parse_Line "${TOKEN//${g_PARSEVAR}/ }"
}

#-----------------------------------------------------------

function Parse_Chunk
{
    typeset CHAR IS_ESCAPED IS_STRING IS_POINTER TOKEN DATA LEN TERM EQ IS_EQUATION CHECK LAST V1 V2

    IS_ESCAPED=0
    IS_POINTER=0
    IS_STRING=0
    IS_EQUATION=0
    CHECK=0
    TOKEN=

    # Initialize miniparser, convert spaces
    DATA=$(echo ${1// /${g_PARSEVAR}})
    LEN=${#DATA}

    # Check if this is a string
    if [[ $(Check_String_Type "${1}") -eq 1 ]]
    then
        CHECK=1
    fi

    until [[ $LEN -eq 0 ]]
    do
        CHAR="${DATA:0:7}"
        if [[ $CHAR = "BETWEEN" && ${#DATA} -gt 8 ]]
        then
            TERM="${DATA##*BETWEEN}"
            V1=$(Mini_Parser "${TERM}" "AND")
            TERM="${TERM:${#V1}}"
            if [[ ${TERM} = +(AND*) ]]
            then
                V2="${TERM:3}"
            else
                V2="${TERM:1}"
            fi
            if [[ $CHECK -eq 1 ]]
            then
                if [[ $V2 = +(*${g_PARSEVAR}EXCL) ]]
                then
                    TOKEN="(__b2c__STRCMP($TOKEN, __b2c__min_str($V1,${V2%EXCL*})) > 0 && __b2c__STRCMP($TOKEN, __b2c__max_str($V1,${V2%EXCL*})) < 0 ? 1 : 0)"
                else
                    TOKEN="(__b2c__STRCMP($TOKEN, __b2c__min_str($V1,$V2)) >= 0 && __b2c__STRCMP($TOKEN, __b2c__max_str($V1,$V2)) <= 0 ? 1 : 0)"
                fi
                CHECK=0
            else
                if [[ $V2 = +(*${g_PARSEVAR}EXCL) ]]
                then
                    TOKEN="($TOKEN > fmin($V1,${V2%EXCL*}) && $TOKEN < fmax($V1,${V2%EXCL*}) ? 1 : 0)"
                else
                    TOKEN="($TOKEN >= fmin($V1,$V2) && $TOKEN <= fmax($V1,$V2) ? 1 : 0)"
                fi
            fi
            TOKEN=$(echo ${TOKEN//${g_PARSEVAR}/ })
            break
        fi
        CHAR="${DATA:0:2}"
	case $CHAR in
            "==")
                if [[ $IS_STRING -eq 0 ]]
                then
	            DATA="= ${DATA:2}"
                fi;;
            "<>")
                if [[ $IS_STRING -eq 0 ]]
                then
	            DATA="!=${DATA:2}"
                fi;;
        esac
	CHAR="${DATA:0:1}"
	case $CHAR in
	    =)
		if [[ $IS_STRING -eq 0 ]]
		then
                    if [[ $CHECK -eq 1 || $(Get_Var "${TOKEN}" ${g_FUNCNAME}) = +(*char\**) ]]
                    then
			if [[ -n $EQ ]]
			then
			    EQ="${EQ}="
			else
			    TERM="${TOKEN}"
			    TOKEN=
			    CHECK=1
			    EQ="=="
			fi
                    elif [[ $IS_EQUATION -eq 0 ]]
                    then
		        TOKEN="(${TOKEN})=="
                    else
		        TOKEN="${TOKEN}="
                        IS_EQUATION=0
                    fi
		    IS_ESCAPED=0
                else
		    TOKEN="${TOKEN}="
		fi;;
	    !)
		if [[ $IS_STRING -eq 0 ]]
		then
                    if [[ $CHECK -eq 1 || $(Get_Var "${TOKEN}" ${g_FUNCNAME}) = +(*char\**) ]]
                    then
                        TERM="${TOKEN}"
                        TOKEN=
                        CHECK=1
                        EQ="!"
                    elif [[ $IS_EQUATION -eq 0 ]]
                    then
                        TOKEN="(${TOKEN})!="
		        IS_ESCAPED=0
                        let LEN=${#DATA}-1
                        DATA="${DATA: -$LEN}"
                    else
                        TOKEN="${TOKEN}!"
                        IS_EQUATION=0
                    fi
                else
                    TOKEN="${TOKEN}!"
		fi;;
            \<)
		if [[ $IS_STRING -eq 0 ]]
		then
                    if [[ $CHECK -eq 1 || $(Get_Var "${TOKEN}" ${g_FUNCNAME}) = +(*char\**) ]]
                    then
                        TERM="${TOKEN}"
                        TOKEN=
                        CHECK=1
			EQ="<"
		    else
			if [[ $IS_EQUATION -eq 1 ]]
			then
			    IS_EQUATION=0
			else
			    IS_EQUATION=1
			fi
			TOKEN="${TOKEN}<"
		    fi
		else
		    TOKEN="${TOKEN}<"
		fi;;
            \>)
		if [[ $IS_STRING -eq 0 && $IS_POINTER -eq 0 ]]
		then
                    if [[ $CHECK -eq 1 || $(Get_Var "${TOKEN}" ${g_FUNCNAME}) = +(*char\**) ]]
                    then
                        TERM="${TOKEN}"
                        TOKEN=
                        CHECK=1
			EQ=">"
		    else
			if [[ $IS_EQUATION -eq 1 ]]
			then
			    IS_EQUATION=0
			else
			    IS_EQUATION=1
			fi
			TOKEN="${TOKEN}>"
		    fi
		else
                    TOKEN="${TOKEN}>"
		    IS_POINTER=0
		fi;;
	    \\)
		if [[ $IS_ESCAPED -eq 0 ]]
		then
		    IS_ESCAPED=1
		else
		    IS_ESCAPED=0
		fi
                TOKEN="${TOKEN}\\";;
            -)
		if [[ $IS_STRING -eq 0 && $IS_POINTER -eq 0 ]]
                then
		    IS_POINTER=1
                fi
		TOKEN="${TOKEN}-";;
	    \")
		if [[ $IS_ESCAPED -eq 0 ]]
		then
		    if [[ $IS_STRING -eq 0 ]]
		    then
			IS_STRING=1
		    else
			IS_STRING=0
		    fi
		fi
		IS_ESCAPED=0
                TOKEN="${TOKEN}\"";;
	    *)
		# Handle normal char after '<' or '>' symbol
		if [[ $IS_EQUATION -eq 1 ]]
		then
		    IS_EQUATION=0
		    LAST=$(echo "${TOKEN: -1}")
		    TOKEN="(${TOKEN%?})${LAST}"
		fi
		    
                # Convert back to space
	        if [[ "${CHAR}" = "${g_PARSEVAR}" ]]
	        then
	            TOKEN="${TOKEN} "
                else
	            TOKEN="${TOKEN}${CHAR}"
	        fi
		IS_POINTER=0
		IS_ESCAPED=0;;
	esac
	let LEN=${#DATA}-1
	DATA="${DATA: -$LEN}"
    done

    if [[ $CHECK -eq 1 ]]
    then
        TOKEN="__b2c__STRCMP(${TERM}, $TOKEN) $EQ 0"
    fi

    g_EQUATION="${g_EQUATION} ${TOKEN} ${2}"
}

#-----------------------------------------------------------

function Parse_Equation
{
    typeset CHAR IS_ESCAPED IS_STRING TOKEN DATA LEN FLAG
    typeset AND OR BETWEEN

    g_EQUATION=
    IS_ESCAPED=0
    IS_STRING=0
    FLAG=0
    TOKEN=

    AND="${g_PARSEVAR}AND${g_PARSEVAR}"
    OR="${g_PARSEVAR}OR${g_PARSEVAR}"
    BETWEEN="${g_PARSEVAR}BETWEEN${g_PARSEVAR}"

    # Initialize miniparser, convert spaces
    DATA=$(echo ${1// /${g_PARSEVAR}})
    LEN=${#DATA}

    until [[ $LEN -eq 0 ]]
    do
        CHAR="${DATA:0:9}"
	if [[ "${CHAR}" = "${BETWEEN}" ]]
        then
	    if [[ $IS_STRING -eq 0 ]]
	    then
                FLAG=1
            fi
        fi
        CHAR="${DATA:0:5}"
	if [[ "${CHAR}" = "${AND}" ]]
        then
            if [[ ${FLAG} -eq 0 ]]
            then
	        if [[ $IS_STRING -eq 0 ]]
	        then
		    Parse_Chunk "${TOKEN}" " AND "
                    let LEN=${#DATA}-4
	            DATA="${DATA: -$LEN}"
		    CHAR=
		    TOKEN=
                fi
            else
                FLAG=0
            fi
        fi
        CHAR="${DATA:0:4}"
	if [[ "${CHAR}" = "${OR}" ]]
        then
	    if [[ $IS_STRING -eq 0 ]]
	    then
		Parse_Chunk "${TOKEN}" " OR "
                let LEN=${#DATA}-3
	        DATA="${DATA: -$LEN}"
		CHAR=
		TOKEN=
            fi
        fi
	CHAR="${DATA:0:1}"
	case $CHAR in
	    \\)
		if [[ $IS_ESCAPED -eq 0 ]]
		then
		    IS_ESCAPED=1
		else
		    IS_ESCAPED=0
		fi;;
	    \")
		if [[ $IS_ESCAPED -eq 0 ]]
		then
		    if [[ $IS_STRING -eq 0 ]]
		    then
			IS_STRING=1
		    else
			IS_STRING=0
		    fi
		fi
		IS_ESCAPED=0;;
	    *)
		IS_ESCAPED=0;;
	esac
	# Convert back to space
	if [[ "${CHAR}" = "${g_PARSEVAR}" ]]
	then
	    TOKEN="${TOKEN} "
        else
	    TOKEN="${TOKEN}${CHAR}"
	fi
	let LEN=${#DATA}-1
	DATA="${DATA: -$LEN}"
    done
    Parse_Chunk "${TOKEN}"
}

#-----------------------------------------------------------
#
# Main program
#
#-----------------------------------------------------------

# Default BACON settings
let g_MAX_DIGITS=32

# This is the size for static buffers like fgets, read etc.
let g_BUFFER_SIZE=512

# Maximum RETURN buffers
let g_MAX_RBUFFERS=32

# Maximum SSL file descriptors
let g_MAX_SSL_FDS=256

# Defaults for parameters
g_CCNAME=
g_TEMPDIR=
g_INCFILES=
g_CCFLAGS=
g_BINEXT=
g_REBUILD_ARCHIVE=
g_ARNAME="ar -r"
g_RANLIB=

g_CCNAME_TMP=
g_TEMPDIR_TMP=
g_INCFILES_TMP=
g_LDFLAGS_TMP=
g_CCFLAGS_TMP=

let g_NO_COMPILE=0
let g_TMP_PRESERVE=0
let g_QUIET=0
let g_SEMANTIC=0
let g_NO_QUESTION=0
let g_CPP=0
let g_XGETTEXT=0
let g_SAVE_CONFIG=0
let g_DEBUG=0

let g_USE_C=0
let g_USE_H=0
let g_MAX_BACKLOG=5

g_INCLUDE_FILES=
g_PRAGMA_REGEX=
let g_TRACE=0
let g_OPTION_BASE=0
let g_OPTION_SOCKET=5
g_OPTION_TLS=
g_INC_TLS=
g_LIB_TLS=
let g_OPTION_BREAK=1

# Some global declarations
g_CURFILE=
g_FUNCNAME=
g_FUNCTYPE=
g_PROTOTYPE=
g_TMP_FILES=
g_LOCALSTRINGS=
g_STRINGARRAYS=
g_STRINGARGS=
g_DYNAMICARRAYS=
g_STATICARRAYS=
g_RECORDCACHE=
let g_LOOPCTR=0
g_ERRORTXT=
g_EQUATION=
g_COMMENT="false"
g_TRACE_PREFIX=
g_IGNORE_PARSE="1"
g_OPTION_EXPLICIT="0"
g_OPTION_INPUT="\"\n\""
g_VARTYPE="long"
g_OBJ_FILES=
g_MAKE_LINE=
g_MONITOR=
let g_STRING_FUNC=1
let g_STRING_LINE=0
g_ALARM_FUNC=
g_ALARM_PROTO=
g_DOTIMES=0
g_LOCAL_SBUFFER=

# Always create a final label
g_CATCHGOTO="__B2C__PROGRAM__EXIT"
g_CATCH_USED=0

# Records
g_RECORDNAME=
g_RECORDVAR=
g_RECORDARRAY=
g_WITHVAR=
g_RECORDEND_BODY=
g_RECORDEND_HEADER=

# Socket defaults
g_SOCKTYPE="SOCK_STREAM"
g_NETWORKTYPE="TCP"
g_MULTICAST_TTL=1
g_SCTP_STREAMS=1

# Select/Case
typeset -a g_SELECTVAR
typeset -a g_IN_CASE
g_SELECTVAR_CTR=0

# Relate
typeset -a g_RELATE
g_RELATE_CTR=0

g_FCTR=0
g_CCTR=0

RETURN_CODE=0

# Timer related
ttime=0

# Read any configfile values
if [[ ! -d $HOME/.bacon ]]
then
    mkdir $HOME/.bacon
fi

if [[ -f $HOME/.bacon/bacon.cfg ]]
then
    while read -r LINE
    do
	case ${LINE%% *} in
	    ccname) g_CCNAME_TMP=${LINE#ccname}; g_CCNAME_TMP=${g_CCNAME_TMP##*( )};;
	    tempdir) g_TEMPDIR_TMP=${LINE#tempdir}; g_TEMPDIR_TMP=${g_TEMPDIR_TMP##*( )};;
	    incfiles) g_INCFILES_TMP=${LINE#incfiles};;
	    ldflags) g_LDFLAGS_TMP=${LINE#ldflags};;
	    ccflags) g_CCFLAGS_TMP=${LINE#ccflags};;
	    lowercase) g_LOWERCASE_TMP=${LINE#lowercase};;
	esac
    done < $HOME/.bacon/bacon.cfg
fi

# Get arguments
while getopts ":c:d:i:l:o:b:r:axnjfpqsvwyz@" OPT
do
    case $OPT in
	c) g_CCNAME=$OPTARG;;
	d) if [[ ! -d $OPTARG ]]
	   then
		mkdir -p $OPTARG
	   fi
	   g_TEMPDIR=$OPTARG;;
	i) if [[ ! -f $OPTARG && ! -f "/usr/include/$OPTARG" && ! -f "/usr/local/include/$OPTARG" ]]
	   then
		echo -e "System error: included C header file from -i option not found!"
		exit 1
	   fi
	   if [[ ! -f "/usr/include/$OPTARG" && ! -f "/usr/local/include/$OPTARG" ]]
	   then
		if [[ ${OPTARG:0:1} != "/" ]]
                then
		    g_INCFILES="$g_INCFILES `pwd`/${OPTARG}"
                else
		    g_INCFILES="$g_INCFILES ${OPTARG}"
		fi
	   else
		g_INCFILES="$g_INCFILES <${OPTARG}>"
	   fi;;
	l) if [[ $OPTARG = +(* *) || $OPTARG = +(-*) ]]
           then
               g_LDFLAGS="$g_LDFLAGS $OPTARG"
           else
	       g_LDFLAGS="$g_LDFLAGS -l$OPTARG"
           fi;;
	o) g_CCFLAGS="$g_CCFLAGS $OPTARG";;
	n) g_NO_COMPILE=1;;
	a) g_CCFLAGS="$g_CCFLAGS -fPIC"
           g_REBUILD_ARCHIVE="libbacon.a";;
        b) g_ARNAME="$OPTARG";;
        r) g_RANLIB="$OPTARG";;
	j) g_CPP=1;;
	f) g_LDFLAGS="$g_LDFLAGS -shared -rdynamic"
	   g_CCFLAGS="$g_CCFLAGS -fPIC"
	   g_BINEXT=".so";; 
	p) g_TMP_PRESERVE=1;;
	q) g_QUIET=1;;
	s) g_SEMANTIC=1;;
	x) g_XGETTEXT=1;;
	y) g_NO_QUESTION=1;;
	v) echo
	   echo "BaCon version $g_VERSION on $(uname -s -m) - Shell - (c) Peter van Eerten - MIT License."
	   echo
	   exit 0;; 
	w) g_SAVE_CONFIG=1;;
	z) g_LOWERCASE=1;;
	@) g_DEBUG=1;;
	\?|h) echo 
	    echo "USAGE: bacon [options] program[.bac]"
	    echo 
	    echo "OPTIONS:"
	    echo 
	    echo -e " -c <compiler>\tCompiler to use (default: cc)"
	    echo -e " -l <ldflags>\tPass libraries to linker"
	    echo -e " -o <options>\tPass compiler options"
	    echo -e " -i <include>\tAdd include file to C code"
	    echo -e " -d <tmpdir>\tTemporary directory (default: .)"
	    echo -e " -b <archiver>\tDefine archiver"
	    echo -e " -r <ranlib>\tDefine ranlib"
	    echo -e " -y \t\tAutomatically delete temporary files"
	    echo -e " -a \t\tRebuild BaCon archive"
	    echo -e " -x \t\tExtract gettext strings"
	    echo -e " -z \t\tAllow lowercase keywords"
	    echo -e " -f \t\tCreate Shared Object"
	    echo -e " -n \t\tDo not compile, only convert"
	    echo -e " -j \t\tInvoke C Preprocessor"
	    echo -e " -p \t\tPreserve temporary files"
	    echo -e " -q \t\tShow summary after conversion only"
	    echo -e " -s \t\tSuppress semantic error warnings"
	    echo -e " -w \t\tSave options to BaCon configfile"
	    echo -e " -v \t\tShow version"
	    echo -e " -h \t\tShow help"
	    echo 
	    exit 0;;
    esac
done

shift $(($OPTIND-1))

# See if configfile must be written
if [[ $g_SAVE_CONFIG -eq 1 ]]
then
    echo -e "ccname $g_CCNAME" > $HOME/.bacon/bacon.cfg
    echo -e "tempdir $g_TEMPDIR" >> $HOME/.bacon/bacon.cfg
    echo -e "incfiles $g_INCFILES" >> $HOME/.bacon/bacon.cfg
    echo -e "ldflags ${g_LDFLAGS##*\-lm}" >> $HOME/.bacon/bacon.cfg
    echo -e "ccflags $g_CCFLAGS" >> $HOME/.bacon/bacon.cfg
    echo -e "lowercase $g_LOWERCASE" >> $HOME/.bacon/bacon.cfg
    g_CCNAME_TMP=$g_CCNAME
    g_TEMPDIR_TMP=$g_TEMPDIR
    g_INCFILES_TMP=$g_INCFILES
    g_LDFLAGS_TMP=$g_LDFLAGS
    g_CCFLAGS_TMP=$g_CCFLAGS
    g_LOWERCASE_TMP=$g_LOWERCASE
fi

# Use the commandline or configfile settings?
if [[ -z $g_CCNAME ]]
then
    g_CCNAME="${g_CCNAME_TMP}"
    if [[ -z $g_CCNAME ]]
    then
        g_CCNAME=cc
    fi
fi
if [[ -z $g_TEMPDIR ]]
then
    g_TEMPDIR="${g_TEMPDIR_TMP}"
    if [[ -z $g_TEMPDIR ]]
    then
        g_TEMPDIR="."
    fi
fi
if [[ -z $g_INCFILES ]]
then
    g_INCFILES="${g_INCFILES_TMP}"
fi
g_LDFLAGS="${g_LDFLAGS} ${g_LDFLAGS_TMP}"
if [[ -z $g_CCFLAGS ]]
then
    g_CCFLAGS="${g_CCFLAGS_TMP}"
fi
if [[ -z $g_LOWERCASE || $g_LOWERCASE -eq 0 ]]
then
    g_LOWERCASE="${g_LOWERCASE_TMP}"
fi

# Check if a filename was entered, if so get it
if [[ $# -eq 0 ]]
then
    if [[ $g_SAVE_CONFIG -eq 0 ]]
    then
        echo -e "System error: no filename? Run with '-h' to see usage."
        exit 1
    fi
elif [[ "$@" = +(http://*) ]]
then
    if [[ -z `which telnet 2>/dev/null` ]]
    then
	echo "System error: No telnet client found! Cannot retrieve file."
	exit 1
    fi
    echo -n "Fetching file... "

    # Remove http part
    g_SOURCEFILE="${@#*http://}"

    # Get header to see if file exists, and if so, get length
    HEAD=`(echo "set crlf on"; echo "open ${g_SOURCEFILE%%/*} 80"; sleep 1;
    echo "HEAD /${g_SOURCEFILE#*/} HTTP/1.1"; echo "Host: ${g_SOURCEFILE%%/*}"; echo;
    sleep 1; echo "quit";) | telnet 2>/dev/null`

    LEN=`echo ${HEAD#*Content-Length: }`

    # No file found on server
    if [[ "${LEN%% *}" = "telnet>" || "${HEAD}" != +(*Content-Length*) ]]
    then
        echo "System error: file not found! Check URL and try again."
        exit 1
    fi

    # Get the actual contents of the file
    DOWNLOAD=`(echo "set crlf on"; echo "open ${g_SOURCEFILE%%/*} 80"; sleep 2;
    echo "GET /${g_SOURCEFILE#*/} HTTP/1.1"; echo "Host: ${g_SOURCEFILE%%/*}"; echo;
    sleep 2; echo "quit";) | telnet 2>/dev/null`

    # Set the final filename and save
    g_SOURCEFILE="${1##*/}"
    let START=${#DOWNLOAD}-${LEN%% *}
    echo "${DOWNLOAD:${START}:${#DOWNLOAD}}" > $g_SOURCEFILE

    # Check resulting filesize with HTTP header
    FILELEN=`wc -c $g_SOURCEFILE`
    let FILELEN=${FILELEN%% *}-1
    if [[ ${FILELEN} -ne ${LEN%% *} ]]
    then
        echo "System error: file could not be downloaded probably due to a timeout. Try again later."
        exit 1
    fi
    echo "done."
elif [[ "$@" != +(*.bac) ]]
then
    g_SOURCEFILE="$@.bac"
else
    g_SOURCEFILE="$@"
fi

# Check if file exists
if [[ ! -f $g_SOURCEFILE ]]
then
    echo -e "System error: file '$g_SOURCEFILE' not found!"
    exit 1
fi

# Change the working directory
if [[ -d ${g_SOURCEFILE%/*} && ${g_SOURCEFILE} = +(/*) ]]
then
    cd ${g_SOURCEFILE%/*}
fi

# Now create the global filenames where to write to
g_CFILE=$g_TEMPDIR/${g_SOURCEFILE##*/}.c
g_HFILE=$g_TEMPDIR/${g_SOURCEFILE##*/}.h
g_GENERIC=$g_TEMPDIR/${g_SOURCEFILE##*/}.generic.h
STRINGARRAYFILE=$g_TEMPDIR/${g_SOURCEFILE##*/}.string.h
FLOATARRAYFILE=$g_TEMPDIR/${g_SOURCEFILE##*/}.float.h
SRCARRAYFILE=$g_TEMPDIR/${g_SOURCEFILE##*/}.src.h

# Add to total file list
g_TMP_FILES="$g_CFILE $g_HFILE $g_GENERIC $STRINGARRAYFILE $FLOATARRAYFILE"

# Check if previous temporary files exist
LEN=`ls $g_TEMPDIR/${g_SOURCEFILE%.bac}.*.* 2>/dev/null | wc -l`
if [[ ${g_NO_QUESTION} -eq 1 ]]
then
    rm -f $g_TEMPDIR/${g_SOURCEFILE%.bac}.*.*
else
    if [[ ${LEN} -gt 0 ]]
    then
        if [[ -n $BASH ]]
        then
            read -p "WARNING: ${LEN} temporary files found! Do you want to delete them (y/n)? " ANSWER
        else
            read ANSWER?"WARNING: ${LEN} temporary files found! Do you want to delete them (y/n)? "
        fi
        if [[ ${ANSWER} = "y" ]]
        then
            rm -f $g_TEMPDIR/${g_SOURCEFILE%.bac}.*.*
            echo "Temporary files were deleted."
        else
            echo "Exiting..."
            exit 1
        fi
    fi
fi

# Keep start time
ttime=$SECONDS

# Create C file
echo "/* Created with Shell BaCon $g_VERSION - (c) Peter van Eerten - MIT License */" > $g_CFILE
echo "#include \"${g_SOURCEFILE##*/}.h\"" >> $g_CFILE
echo "#include \"${g_SOURCEFILE##*/}.string.h\"" >> $g_CFILE
echo "#include \"${g_SOURCEFILE##*/}.float.h\"" >> $g_CFILE
echo "#undef __b2c_filename" >> $g_CFILE
echo "#define __b2c_filename \"${g_SOURCEFILE##*/}\"" >> $g_CFILE
echo "int __b2c__trap = 1;" >> $g_CFILE
echo "int __b2c__catch_set_backup = 0, __b2c__catch_set = 0;" >> $g_CFILE
echo "void (*__b2c__error_callback)(char*, char*, long) = NULL;" >> $g_CFILE
echo "int __b2c__option_compare = 0;" >> $g_CFILE
echo "int __b2c__option_quoted = 1;" >> $g_CFILE
echo "int __b2c__option_dq = 34;" >> $g_CFILE
echo "int __b2c__option_utf8 = 0;" >> $g_CFILE
echo "int __b2c__option_proper = 0;" >> $g_CFILE
echo "int __b2c__option_error = 1;" >> $g_CFILE
echo "char *__b2c__option_delim = \" \";" >> $g_CFILE
echo "int __b2c__option_memstream = 0;" >> $g_CFILE
echo "int __b2c__option_startpoint = 0;" >> $g_CFILE
echo "int __b2c__option_open = O_RDWR|O_NOCTTY|O_SYNC;" >> $g_CFILE
echo "int __b2c__collapse = 0;" >> $g_CFILE
echo "int __b2c__break_ctr = 0;" >> $g_CFILE
echo "int __b2c__break_flag = 0;" >> $g_CFILE
echo "char __b2c__chop_default[] = \"\r\n\t \";" >> $g_CFILE
echo "int __b2c__stringarray_ptr = 0;" >> $g_CFILE
echo "int __b2c__floatarray_ptr = 0;" >> $g_CFILE
echo "char EmptyString[1] = { 0 };" >> $g_CFILE
echo "char* __b2c__sbuffer_main[__b2c_STRING_FUNC] = { NULL };" >> $g_CFILE
echo "int __b2c__sbuffer_size = __b2c_STRING_FUNC;" >> $g_CFILE
echo "int __b2c__sbuffer_ptr = -1;" >> $g_CFILE
echo "char** __b2c__sbuffer = __b2c__sbuffer_main;" >> $g_CFILE
echo "char* __b2c__rbuffer[$g_MAX_RBUFFERS] = { NULL };" >> $g_CFILE
echo "size_t __b2c__rbuffer_length[$g_MAX_RBUFFERS] = { 0 };" >> $g_CFILE
echo "void* __b2c_ctx_ptr[${g_MAX_SSL_FDS}] = { 0 };" >> $g_CFILE
echo "void* __b2c_ssl_ptr[${g_MAX_SSL_FDS}] = { 0 };" >> $g_CFILE
echo "int __b2c__rbuffer_ptr = 0;" >> $g_CFILE
echo "jmp_buf __b2c__gosub_buffer[$g_MAX_RBUFFERS];" >> $g_CFILE
echo "int __b2c__gosub_buffer_ptr = -1;" >> $g_CFILE
echo "char* __b2c__loop_result${g_STRINGSIGN} = NULL;" >> $g_CFILE
echo "jmp_buf __b2c__data_jump, __b2c__loop1, __b2c__loop2;" >> $g_CFILE
echo "int __b2c__data_jump_flag = 0;" >> $g_CFILE
echo "char **__b2c__deltree = { NULL }; int __b2c__del_ctr = 0;" >> $g_CFILE
echo "char *__b2c__assign = NULL;" >> $g_CFILE
echo "int __b2c__yes = 1; char __b2c__ttl = 1;" >> $g_CFILE
echo "char __b2c__data_client[$g_BUFFER_SIZE] = { 0 }; char __b2c__data_server[$g_BUFFER_SIZE] = { 0 };" >> $g_CFILE
echo "int __b2c__arglen = 0;" >> $g_CFILE
echo "char **__b2c__stringstack = NULL; double *__b2c__doublestack = NULL;" >> $g_CFILE
echo "long *__b2c__longstack = NULL; int *__b2c__typestack = NULL; int __b2c__stackptr = 0;" >> $g_CFILE
echo "/* Set some BaCon reserved variables to their default value */" >> $g_CFILE
echo "int ERROR = 0;" >> $g_CFILE
echo "int RETVAL = 0;" >> $g_CFILE
echo "int REGLEN = 0;" >> $g_CFILE
echo "char VERSION${g_STRINGSIGN}[] = \"$g_VERSION\";" >> $g_CFILE
echo "/* We need to put the global definitions here because of TCC */" >> $g_CFILE
echo "jmp_buf __b2c__jump;" >> $g_CFILE
echo "struct timeval __b2c__tm; time_t __b2c__elapsed_secs; int __b2c__elapsed_usecs;" >> $g_CFILE
echo "struct itimerval __b2c__alarm;" >> $g_CFILE
echo "long __b2c__ctr, __b2c__length, __b2c__start;" >> $g_CFILE
echo "char __b2c__input__buffer[$g_BUFFER_SIZE];" >> $g_CFILE
echo "FILE *__b2c__inFile; FILE *__b2c__outFile; size_t __b2c__Byte; struct dirent *__b2c__dir;" >> $g_CFILE
echo "struct termios __b2c__tty;" >> $g_CFILE
echo "struct timeval __b2c__to; struct hostent *__b2c__he; char *__b2c__host; char *__b2c__port; struct sockaddr_in *__b2c__addr, *__b2c__from; struct ip_mreq __b2c__imreq;" >> $g_CFILE
echo "int __b2c__result; int __b2c__handle;" >> $g_CFILE
echo "int __b2c__counter;" >> $g_CFILE
echo "int __b2c__is_escaped, __b2c__in_string;" >> $g_CFILE
echo "char __b2c__warn[$g_BUFFER_SIZE];" >> $g_CFILE
echo "unsigned long __b2c__ptrlow = ULONG_MAX;" >> $g_CFILE
echo "unsigned long __b2c__ptrhgh = 0;" >> $g_CFILE
echo "struct sigaction __b2c__psa;" >> $g_CFILE
echo "char *ARGUMENT${g_STRINGSIGN};" >> $g_CFILE
echo "char *__b2c__me_var${g_STRINGSIGN} = NULL;" >> $g_CFILE

# Create H file
echo "/* Created with Shell BaCon $g_VERSION - (c) Peter van Eerten - MIT License */" > $g_HFILE
echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" >> $g_HFILE
echo "#undef __b2c_filename" >> $g_HFILE
echo "#define __b2c_filename \"${g_SOURCEFILE##*/}\"" >> $g_HFILE

echo "#undef __b2c_filename" > $STRINGARRAYFILE
echo "#define __b2c_filename \"${STRINGARRAYFILE}\"" >> $STRINGARRAYFILE
echo "char *__b2c__stringarray[] = {" >> $STRINGARRAYFILE

echo "#undef __b2c_filename" > $FLOATARRAYFILE
echo "#define __b2c_filename \"${FLOATARRAYFILE}\"" >> $FLOATARRAYFILE
echo "double __b2c__floatarray[] = {" >> $FLOATARRAYFILE

if [[ ${g_LDFLAGS} = +(*shared*) ]]
then
    echo "/************************************/" >> $g_CFILE
    echo "/* Init function for shared objects */" >> $g_CFILE
    echo "/************************************/" >> $g_CFILE
    echo "#ifdef __GNUC__" >> $g_CFILE
    echo "static int BaCon_init() __attribute__((constructor));" >> $g_CFILE
    echo "#endif" >> $g_CFILE
    echo "int BaCon_init(void){int argc=0; char *argv[2] = { NULL };" >> $g_CFILE
else
    echo "/****************************/" >> $g_CFILE
    echo "/* Main program starts here */" >> $g_CFILE
    echo "/****************************/" >> $g_CFILE
    echo "int main(int argc, char **argv){" >> $g_CFILE
fi

# Check version
echo "__b2c__version(\"$g_VERSION\");" >> $g_CFILE
echo "if(argc>0) { __b2c__me_var${g_STRINGSIGN} = strdup(argv[0]); }" >> $g_CFILE

# See if we have the detector
echo "if(argc==2 && !strcmp(argv[1], \"-bacon\")){fprintf(stderr, \"Converted by %s.\n\", COMPILED_BY_WHICH_BACON${g_STRINGSIGN}); exit(EXIT_FAILURE);}" >> $g_CFILE

# Put arguments into reserved variable ARGUMENT
echo "/* Setup the reserved variable 'ARGUMENT' */" >> $g_CFILE
echo "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" >> $g_CFILE
echo "{if(strstr(argv[__b2c__counter], \" \")||strstr(argv[__b2c__counter], \"\011\")) __b2c__arglen += strlen(argv[__b2c__counter]) + 3;" >> $g_CFILE
echo "else __b2c__arglen += strlen(argv[__b2c__counter]) + 1;} __b2c__arglen++; ARGUMENT${g_STRINGSIGN} = (char*)calloc(__b2c__arglen, sizeof(char));" >> $g_CFILE
echo "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++){if(strstr(argv[__b2c__counter], \" \")||strstr(argv[__b2c__counter], \"\011\")){" >> $g_CFILE
echo "strcat(ARGUMENT${g_STRINGSIGN}, \"\042\"); strcat(ARGUMENT${g_STRINGSIGN}, argv[__b2c__counter]); strcat(ARGUMENT${g_STRINGSIGN}, \"\042\");}" >> $g_CFILE
echo "else strcat(ARGUMENT${g_STRINGSIGN}, argv[__b2c__counter]); if(__b2c__counter != argc - 1) strcat(ARGUMENT${g_STRINGSIGN}, \" \");}" >> $g_CFILE
echo "/* By default seed random generator */" >> $g_CFILE
echo "srandom((unsigned int)time(NULL));" >> $g_CFILE
echo "/* Initialize internal stackpointer */" >> $g_CFILE
echo "__b2c__typestack = (int*)calloc(1, sizeof(int));" >> $g_CFILE
echo "__b2c__stringstack = (char**)realloc(__b2c__stringstack, sizeof(char*)); __b2c__stringstack[0] = (char*)calloc(1, sizeof(char));" >> $g_CFILE
echo "/* Determine current moment and keep it for TIMER function */" >> $g_CFILE
echo "gettimeofday(&__b2c__tm, NULL); __b2c__elapsed_usecs = __b2c__tm.tv_usec; __b2c__elapsed_secs = __b2c__tm.tv_sec;" >> $g_CFILE
echo "/* Setup error signal handling */" >> $g_CFILE
echo "signal(SIGILL, __b2c__catch_signal);" >> $g_CFILE
echo "signal(SIGABRT, __b2c__catch_signal);" >> $g_CFILE
echo "signal(SIGFPE, __b2c__catch_signal);" >> $g_CFILE
echo "signal(SIGSEGV, __b2c__catch_signal);" >> $g_CFILE
echo "/* Rest of the program */" >> $g_CFILE

# There are no imported symbols yet
g_IMPORTED=

# Check MEMORY/OPEN declarations
g_SEMANTIC_MEMFREE=
g_SEMANTIC_OPENCLOSE=

# List all BaCon functions
DATA_1="ABS ACOS ADDRESS AND ASC ASIN ATN CEIL CMDLINE COLUMNS COS COUNT DAY DEC DEG ENDFILE EQUAL ERROR EVEN EXP FILEEXISTS FILELEN FILETIME FILETYPE FLOOR FP GETKEY GETX GETY UNFLATTEN DEL$ ULEN SUM SUMF CLASS LOOP$"
DATA_2="HOUR IIF INSTR INSTRREV ISFALSE ISKEY ISTRUE LEN LOG MAXNUM MEMCHECK MEMORY MEMTELL MINUTE MOD MONTH NOT NOW ODD OR PEEK POW RAD RANDOM REGEX RND ROUND ROWS SEARCH LIBRARY MAP APPEND$ UTF8$ EXPLODE$ ENDCLASS"
DATA_3="SECOND SGN SIN SIZEOF SQR TAN TELL TIMER TIMEVALUE VAL WAIT WEEK YEAR ALARM ALIAS APPENDING ARRAY AS ASSOC BACONLIB BACK BASE BG BLACK BLUE BREAK BROADCAST BY CALL CASE CHANGE$ TAIL$ ALIGN$ BETWEEN PROPER HASDELIM"
DATA_4="CATCH CHANGEDIR CHUNK CLEAR CLOSE CMODE COLLAPSE COLOR CONST COMPARE COMPILER CONTINUE COPY CURRENT CURSOR CYAN DATA DECLARE DECR DEFAULT DEF DELETE DEVICE DIRECTORY DO EXCHANGE$ HEAD$ ENDRECORD NRKEYS CA$ WALK$"
DATA_5="DOWN DOWNTO ELIF ELSE ENDFUNCTION ENDIF END ENDSELECT ENDSUB ENDENUM ENDUSEC ENDUSEH ENDWITH ENUM EPRINT EQ EXIT FG FI FILE FN FOR FORMAT FORWARD FRAMEWORK FREE FROM DOTIMES AMOUNT DELIM$ UCS RE OBTAIN$ VERIFY"
DATA_6="FUNCTION GE GETBYTE GETFILE GETLINE GLOBAL GOSUB GOTO GOTOXY GREEN GT IF IMODE IMPORT IN INCLUDE INCR INPUT INTENSE INTERNATIONAL INVERSE IS ISNOT JOIN LABEL LDFLAGS DONE INSERT$ REV$ SORT$ ISASCII HASH ISUTF8"
DATA_7="LE LET LMODE LOCAL LOOKUP LT MAGENTA MAKEDIR MEMREWIND MEMSTREAM MEMTYPE MONITOR MULTICAST NE NETWORK NEXT NORMAL OFF OFFSET OMODE ON OPEN OPTION OPTIONS OTHER PARSE ROR ROL FLATTEN UNIQ BYTELEN DQ TLS CIPHER$"
DATA_8="POKE PRAGMA PRINT PROTO PULL PUSH PUTBYTE PUTLINE READING READ READLN READWRITE RECEIVE RECORD RECURSIVE RED REDIM RELATE REM RENAME REPEAT RESET RESIZE RESTORE RESUME BIT SAVE BSAVE ISTOKEN ME$ EXPLICIT TOASCII$"
DATA_9="RETURN REWIND SCROLL SCTP SEED SEEK SELECT SEND SERVER SETENVIRON SETSERIAL SIZE SLEEP SOCKET SORT SPEED SPLIT START STARTPOINT STEP STOP SUB SWAP SYSTEM TCP SIGNAL ENDFORK APPEND BAPPEND PROPER$ EVAL CN$ COIL$"
DATA_10="TEXTDOMAIN THEN TO TRACE TRAP TYPE UDP UNTIL UP USEC USEH VAR VARTYPE WEND WHENCE WHILE WHITE WITH WRITELN WRITING YELLOW NUMBER STRING FLOATING MYPID FORK REAP LINENO TOKEN$ TALLY QUOTED ROTATE$ B64ENC$"
DATA_11="CHOP$ CHR$ CONCAT$ CURDIR$ ERR$ EXEC$ EXTRACT$ FILL$ GETENVIRON$ GETPEER$ HOSTNAME$ HEX$ HOST$ IIF$ INTL$ LCASE$ LEFT$ MID$ MONTH$ NNTL$ OS$ REPLACE$ REVERSE$ RIGHT$ INBETWEEN$ OUTBETWEEN$ LAST$ B64DEC$ RIP$"
DATA_12="SPC$ STR$ TAB$ TYPEOF$ UCASE$ WEEKDAY$ REALPATH$ BASENAME$ DIRNAME$ MAXRANDOM NL$ CR$ EL$ CL$ PI REGLEN RETVAL VERSION$ ARGUMENT$ TRUE FALSE MIN MAX MIN$ MAX$ RUN RUN$ SOURCE$ BLOAD LOAD$ CUT$ FIRST$ MERGE$"

# Allow lowercase statements and functions
if [[ $g_LOWERCASE -eq 1 ]]
then
    echo -n "Creating lowercase definitions... "
    for i in ${DATA_1} ${DATA_2} ${DATA_3} ${DATA_4} ${DATA_5} ${DATA_6} ${DATA_7} ${DATA_8} ${DATA_9} ${DATA_10} ${DATA_11} ${DATA_12}
    do
        MAPPING="$MAPPING -D`echo ${i}|tr [:upper:] [:lower:]`=${i}"
    done
    echo "done."
    g_CPP=1
fi

# Prevent filename expansion
set -f

# Check if the C Preprocessor needs to run
if [[ $g_CPP -eq 1 ]]
then
    if [[ -n `which cpp 2>/dev/null` ]]
    then
        echo -n "Preprocessing '${g_SOURCEFILE}'... "
        # Change next line marker to overcome C preprocessor interpretation
        while read -r LINE; do if [[ ${LINE} = +(\#*) ]]; then echo "${LINE}"; else echo "@${LINE}@"; fi; done < $g_SOURCEFILE > $g_SOURCEFILE.tmp
        cpp -w -P $MAPPING $g_SOURCEFILE.tmp $g_SOURCEFILE.cpp
        # Restore next line marker
        while read -r LINE; do LINE="${LINE:1}"; echo "${LINE%@*}"; done < $g_SOURCEFILE.cpp > $g_SOURCEFILE.bac
	g_TMP_FILES="$g_TMP_FILES ${g_SOURCEFILE}.cpp ${g_SOURCEFILE}.tmp ${g_SOURCEFILE}.bac"
        g_FEED="${g_SOURCEFILE}.bac"
        echo "done."
    else
        if [[ $g_LOWERCASE -eq 1 ]]
        then
	    echo -e "System error: the C Preprocessor 'cpp' not found, cannot parse lowercase! Exiting..."
        else
	    echo -e "System error: the C Preprocessor 'cpp' not found on this system! Exiting..."
        fi
	exit 1
    fi
else
    g_FEED=${g_SOURCEFILE}
fi
# Set current filename
g_CURFILE="${g_SOURCEFILE}"

# Initialize
LEN=
TOTAL=
SEQ=
g_COUNTER=0
g_TOTAL_LINES=0

# Register result buffer for LOOP$ function
Save_Main_Var "__b2c__loop_result${g_STRINGSIGN}" "char*"

# Detect if this is a Windows file
if [[ `head -1 ${g_FEED}` = +(*${g_CRLF}) ]]
then
    echo "System error: Windows file detected! Remove non-Unix CR line separators first. Exiting..."
    exit 1
fi

# Start walking through program
echo -e -n "\rConverting '${g_SOURCEFILE}'... "

while read -r LINE
do
    ((g_COUNTER+=1))
    if [[ $g_QUIET -eq 0 ]]
    then
	echo -e -n "\rConverting '${g_SOURCEFILE}'... ${g_COUNTER}\033[0K"
    fi
    # Line is not empty?
    if [[ -n "$LINE" ]]
    then
	if [[ "$LINE" = +(* \\) && "$LINE" != +(${g_SQUOTESIGN}*) ]]
	then
	    let LEN="${#LINE}"-2
	    SEQ="${LINE:0:$LEN}"
	    TOTAL="${TOTAL}${SEQ}"
        else
	    TOTAL="${TOTAL}${LINE}"
	    if [[ "${TOTAL}" != +(${g_SQUOTESIGN}*) ]]
	    then
                echo "#undef __b2c_lineno" >> $g_CFILE
                echo "#define __b2c_lineno $g_COUNTER" >> $g_CFILE
                echo "#undef __b2c_lineno" >> $g_HFILE
                echo "#define __b2c_lineno $g_COUNTER" >> $g_HFILE
		Tokenize "${TOTAL}"
	    fi
	    TOTAL=
	fi
    fi
done < ${g_FEED}

# Debug variables
if [[ ${g_DEBUG} -eq 1 ]]
then
    Debug_Vars
fi

# Restore filename expansion
set +f

# Finalize main C-file
if [[ $g_CATCH_USED -eq 1 ]]
then
    echo "__B2C__PROGRAM__EXIT:" >> $g_CFILE
fi
echo "return 0;" >> $g_CFILE
echo "}" >> $g_CFILE

# Finalize STRING ARRAY file for DATA
echo " \"\" };" >> $STRINGARRAYFILE

# Finalize FLOAT ARRAY file for DATA
echo " 0.0};" >> $FLOATARRAYFILE

# Create generic headerfile, functions are converted using macros
echo "/* Created with Shell BaCon $g_VERSION - (c) Peter van Eerten - MIT License */" > $g_GENERIC
echo "#include <stdio.h>" >> $g_GENERIC
echo "#include <stdlib.h>" >> $g_GENERIC
echo "#include <stdarg.h>" >> $g_GENERIC
echo "#include <stdint.h>" >> $g_GENERIC
echo "#include <libgen.h>" >> $g_GENERIC
echo "#include <limits.h>" >> $g_GENERIC
echo "#include <float.h>" >> $g_GENERIC
echo "#include <sys/time.h>" >> $g_GENERIC
echo "#include <sys/stat.h>" >> $g_GENERIC
echo "#include <sys/types.h>" >> $g_GENERIC
echo "#include <sys/wait.h>" >> $g_GENERIC
echo "#include <sys/socket.h>" >> $g_GENERIC
echo "#include <sys/utsname.h>" >> $g_GENERIC
echo "#include <sys/ioctl.h>" >> $g_GENERIC
echo "#include <dirent.h>" >> $g_GENERIC
echo "#include <setjmp.h>" >> $g_GENERIC
echo "#include <netdb.h>" >> $g_GENERIC
if [[ `uname` = +(*BSD*) ]]
then
    echo "#include <netinet/in.h>" >> $g_GENERIC
    echo "#define strcat(x, y) __b2c_strlcat(x, y)" >> $g_GENERIC
    echo "#define strcpy(x, y) __b2c_strlcpy(x, y)" >> $g_GENERIC
fi
echo "#include <arpa/inet.h>" >> $g_GENERIC
echo "#include <signal.h>" >> $g_GENERIC
# REGEX header
if [[ -n $g_PRAGMA_REGEX ]]
then
    if [[ $g_PRAGMA_REGEX != +(* INCLUDE *) ]]
    then
        SUBSTR=${g_PRAGMA_REGEX%% *}
        if [[ $SUBSTR = +(*tre*) ]]
        then
            echo "#include <tre/regex.h>" >> $g_GENERIC
        elif [[ $SUBSTR = +(*pcre*) ]]
        then
            echo "#include <pcreposix.h>" >> $g_GENERIC
        elif [[ $SUBSTR = +(*onig*) ]]
        then
            echo "#include <onigposix.h>" >> $g_GENERIC
        fi
    else
        SUBSTR=${g_PRAGMA_REGEX##* INCLUDE }
        echo "#include ${SUBSTR%% *}" >> $g_GENERIC
    fi
else
    echo "#include <regex.h>" >> $g_GENERIC
fi
# TLS header
if [[ -n ${g_INC_TLS} ]]
then
    if [[ ${g_INC_TLS} = +(* INCLUDE *) ]]
    then
        for i in ${g_INC_TLS##* INCLUDE }
        do
            echo "#include ${i}" >> $g_GENERIC
        done
    else
        echo -e "${g_INC_TLS}" >> $g_GENERIC
    fi
fi
echo "#include <fcntl.h>" >> $g_GENERIC
echo "#include <math.h>" >> $g_GENERIC
echo "#include <unistd.h>" >> $g_GENERIC
echo "#include <string.h>" >> $g_GENERIC
echo "#include <ctype.h>" >> $g_GENERIC
echo "#include <wctype.h>" >> $g_GENERIC
echo "#include <locale.h>" >> $g_GENERIC
echo "#include <dlfcn.h>" >> $g_GENERIC
echo "#include <errno.h>" >> $g_GENERIC
echo "#include <termios.h>" >> $g_GENERIC
echo "#include <time.h>" >> $g_GENERIC
# Add user include files
for i in $g_INCFILES
do
    if [[ "$i" = +(*\<*) ]]
    then
	echo "#include $i" >> $g_GENERIC
    else
	echo "#include \"$i\"" >> $g_GENERIC
    fi
done
echo "/* Undefine all symbols which happen to be BaCon keywords */" >> $g_GENERIC
for i in ${DATA_1} ${DATA_2} ${DATA_3} ${DATA_4} ${DATA_5} ${DATA_6} ${DATA_7} ${DATA_8} ${DATA_9} ${DATA_10} ${DATA_11} ${DATA_12}
do
    if [[ ${i} != +(*\$) ]]
    then
        echo "#undef ${i}" >> $g_GENERIC
    fi
done

echo "/* Declarations for internal variables */" >> $g_GENERIC
echo "extern jmp_buf __b2c__jump;" >> $g_GENERIC
echo "extern int __b2c__trap;" >> $g_GENERIC
echo "extern int __b2c__catch_set_backup, __b2c__catch_set;" >> $g_GENERIC
echo "extern void (*__b2c__error_callback)(char*, char*, long);" >> $g_GENERIC
echo "extern int __b2c__option_compare;" >> $g_GENERIC
echo "extern int __b2c__option_quoted;" >> $g_GENERIC
echo "extern int __b2c__option_dq;" >> $g_GENERIC
echo "extern int __b2c__option_utf8;" >> $g_GENERIC
echo "extern int __b2c__option_proper;" >> $g_GENERIC
echo "extern int __b2c__option_error;" >> $g_GENERIC
echo "extern char *__b2c__option_delim;" >> $g_GENERIC
echo "extern int __b2c__option_memstream;" >> $g_GENERIC
echo "extern int __b2c__option_startpoint;" >> $g_GENERIC
echo "extern int __b2c__option_open;" >> $g_GENERIC
echo "extern int __b2c__collapse;" >> $g_GENERIC
echo "extern int __b2c__break_ctr;" >> $g_GENERIC
echo "extern int __b2c__break_flag;" >> $g_GENERIC
echo "extern struct timeval __b2c__tm; extern time_t __b2c__elapsed_secs; extern int __b2c__elapsed_usecs;" >> $g_GENERIC
echo "extern struct itimerval __b2c__alarm;" >> $g_GENERIC
echo "extern char __b2c__chop_default[];" >> $g_GENERIC
echo "extern int __b2c__stringarray_ptr;" >> $g_GENERIC
echo "extern int __b2c__floatarray_ptr;" >> $g_GENERIC
echo "extern long __b2c__ctr, __b2c__length, __b2c__start;" >> $g_GENERIC
echo "extern char __b2c__input__buffer[$g_BUFFER_SIZE];" >> $g_GENERIC
echo "extern char EmptyString[1];" >> $g_GENERIC
# Save the max amount of parallel string buffers
echo "#define __b2c_STRING_FUNC ($g_STRING_FUNC+$g_STRING_LINE)" >> $g_GENERIC
echo "extern char* __b2c__sbuffer_main[__b2c_STRING_FUNC];" >> $g_GENERIC
echo "extern int __b2c__sbuffer_size;" >> $g_GENERIC
echo "extern int __b2c__sbuffer_ptr;" >> $g_GENERIC
echo "extern char** __b2c__sbuffer;" >> $g_GENERIC
echo "extern char* __b2c__rbuffer[$g_MAX_RBUFFERS];" >> $g_GENERIC
echo "extern size_t __b2c__rbuffer_length[$g_MAX_RBUFFERS];" >> $g_GENERIC
echo "extern void* __b2c_ctx_ptr[${g_MAX_SSL_FDS}];" >> $g_GENERIC
echo "extern void* __b2c_ssl_ptr[${g_MAX_SSL_FDS}];" >> $g_GENERIC
echo "extern int __b2c__rbuffer_ptr;" >> $g_GENERIC
echo "extern jmp_buf __b2c__gosub_buffer[$g_MAX_RBUFFERS];" >> $g_GENERIC
echo "extern int __b2c__gosub_buffer_ptr;" >> $g_GENERIC
echo "extern char* __b2c__loop_result${g_STRINGSIGN};" >> $g_GENERIC
echo "extern jmp_buf __b2c__data_jump, __b2c__loop1, __b2c__loop2;" >> $g_GENERIC
echo "extern int __b2c__data_jump_flag;" >> $g_GENERIC
echo "extern char **__b2c__deltree; extern int __b2c__del_ctr;" >> $g_GENERIC
echo "extern char *__b2c__assign;" >> $g_GENERIC
echo "extern FILE *__b2c__inFile; extern FILE *__b2c__outFile; extern size_t __b2c__Byte; extern struct dirent *__b2c__dir;" >> $g_GENERIC
echo "extern struct termios __b2c__tty;" >> $g_GENERIC
echo "extern struct timeval __b2c__to; extern struct hostent *__b2c__he; extern char *__b2c__host; extern char *__b2c__port; extern struct sockaddr_in *__b2c__addr, *__b2c__from; extern struct ip_mreq __b2c__imreq;" >> $g_GENERIC
echo "extern int __b2c__yes; extern char __b2c__ttl;" >> $g_GENERIC
echo "extern int __b2c__result; extern int __b2c__handle;" >> $g_GENERIC
echo "extern char __b2c__data_client[$g_BUFFER_SIZE]; extern char __b2c__data_server[$g_BUFFER_SIZE];" >> $g_GENERIC
echo "extern int __b2c__counter;" >> $g_GENERIC
echo "extern int __b2c__is_escaped, __b2c__in_string;" >> $g_GENERIC
echo "extern int __b2c__arglen;" >> $g_GENERIC
echo "extern char **__b2c__stringstack; extern double *__b2c__doublestack;" >> $g_GENERIC
echo "extern long *__b2c__longstack; extern int *__b2c__typestack; extern int __b2c__stackptr;" >> $g_GENERIC
echo "extern char __b2c__warn[$g_BUFFER_SIZE];" >> $g_GENERIC
echo "extern char *__b2c__stringarray[];" >> $g_GENERIC
echo "extern double __b2c__floatarray[];" >> $g_GENERIC
echo "extern unsigned long __b2c__ptrlow;" >> $g_GENERIC
echo "extern unsigned long __b2c__ptrhgh;" >> $g_GENERIC
echo "extern struct sigaction __b2c__psa;" >> $g_GENERIC
echo "extern char *__b2c__me_var${g_STRINGSIGN};" >> $g_GENERIC
echo "/* Declarations for BaCon variables */" >> $g_GENERIC
echo "extern char *ARGUMENT${g_STRINGSIGN};" >> $g_GENERIC
echo "extern int ERROR;" >> $g_GENERIC
echo "extern int RETVAL;" >> $g_GENERIC
echo "extern int REGLEN;" >> $g_GENERIC
echo "extern char VERSION${g_STRINGSIGN}[];" >> $g_GENERIC
# Prototypes for functions
echo "/* Prototypes for internal functions */" >> $g_GENERIC
echo "extern long int lrint(double __b2c__x);" >> $g_GENERIC
echo "extern double round(double __b2c__x);" >> $g_GENERIC
echo "void *__rbuf_realloc(void*, size_t);" >> $g_GENERIC
echo "void *__sbuf_realloc(void*, size_t);" >> $g_GENERIC
echo "long __sbuf_malloc_handle(size_t);" >> $g_GENERIC
echo "void __sbuf_need_realloc(long, size_t);" >> $g_GENERIC
echo "int __b2c__sortnrd(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnrd_down(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnrf(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnrf_down(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnrl(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnrl_down(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnri(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnri_down(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnrs(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnrs_down(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnrc(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortnrc_down(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortstr(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__sortstr_down(const void*, const void*);" >> $g_GENERIC
echo "int __b2c__strcasecmp(const char*, const char*);" >> $g_GENERIC
echo "int __b2c__strcmp(const char*, const char*);" >> $g_GENERIC
echo "char *__b2c__strdup(const char*);" >> $g_GENERIC
echo "char *__b2c__strndup(const char*, size_t);" >> $g_GENERIC
echo "void* __b2c_str_realloc(char*, size_t);" >> $g_GENERIC
if [[ `uname` = +(*BSD*) ]]
then
    echo "char *__b2c_strlcat(char*, const char*);" >> $g_GENERIC
    echo "char *__b2c_strlcpy(char*, const char*);" >> $g_GENERIC
fi
echo "/* Prototypes for BaCon functions */" >> $g_GENERIC
echo "char *ERR${g_STRINGSIGN}(int);" >> $g_GENERIC
echo "char *__b2c__align(int, char*, char*, unsigned long, int, ...);" >> $g_GENERIC
echo "long __b2c__amount(char*, char*);" >> $g_GENERIC
echo "char *__b2c__append(char*, long, char*, char*);" >> $g_GENERIC
echo "char* __b2c__asc2char(int);" >> $g_GENERIC
echo "char* __b2c__asc2utf8(int);" >> $g_GENERIC
echo "int __b2c_utf8_conv(int,char*);" >> $g_GENERIC
echo "unsigned char __b2c__isascii(const char*);" >> $g_GENERIC
echo "unsigned char __b2c__isutf8(const char*);" >> $g_GENERIC
echo "char *__b2c__toascii(char*);" >> $g_GENERIC
echo "char *__b2c__b64enc(char*, ...);" >> $g_GENERIC
echo "char *__b2c__b64dec(char*);" >> $g_GENERIC
echo "char *__b2c__bin(int, long);" >> $g_GENERIC
echo "unsigned long __b2c__bit(long);" >> $g_GENERIC
echo "void __b2c__catch_signal(int);" >> $g_GENERIC
echo "char * __b2c__change(char*,int,char*,...);" >> $g_GENERIC
echo "char* __b2c__chop(char*, char*, int);" >> $g_GENERIC
echo "char * __b2c__concat(char*, ...);" >> $g_GENERIC
echo "long __b2c__count(int, char*, char*, unsigned int);" >> $g_GENERIC
echo "char *__b2c__curdir(void);" >> $g_GENERIC
echo "char *__b2c__cut(char*, long, long , ...);" >> $g_GENERIC
echo "char *__b2c__datename(time_t, int);" >> $g_GENERIC
echo "char *__b2c__dec2hex(int);" >> $g_GENERIC
echo "char *__b2c__del(char*, long, ...);" >> $g_GENERIC
echo "char *__b2c__delim(char*, char*, char*);" >> $g_GENERIC
echo "long __b2c__delim_engine(int, long*, char*, char*, long);" >> $g_GENERIC
echo "char *__b2c__dirname(int, char*, int, char*, ...);" >> $g_GENERIC
echo "unsigned long __b2c__epoch(int, int, int, int, int, int);" >> $g_GENERIC
echo "char* __b2c__exchange(char*,int,int,...);" >> $g_GENERIC
echo "char *__b2c__exec(int, int, char*, char*, ...);" >> $g_GENERIC
echo "char *__b2c__explode(int,char*,char*, int, ...);" >> $g_GENERIC
echo "char *__b2c__extract(int, char*, char*, char*, int);" >> $g_GENERIC
echo "long __b2c__filelen(int, char*, const char*);" >> $g_GENERIC
echo "long __b2c__filetime(int, char*, const char*, int);" >> $g_GENERIC
echo "long __b2c__filetype(int, char *, const char*);" >> $g_GENERIC
echo "char* __b2c__fill(unsigned long, unsigned int);" >> $g_GENERIC
echo "char *__b2c__first(char*, int, char*);" >> $g_GENERIC
echo "char *__b2c__flatten(char *src, ...);" >> $g_GENERIC
echo "long __b2c__getch(void);" >> $g_GENERIC
echo "char *__b2c__getenv(char*);" >> $g_GENERIC
echo "int __b2c__getopt(int, char**, char*);" >> $g_GENERIC
echo "char* __b2c__getpeer(int, char*, int);" >> $g_GENERIC
echo "long __b2c__getxy(int);" >> $g_GENERIC
echo "int __b2c__hasdelim(char*, char*);" >> $g_GENERIC
echo "char *__b2c__head(char*, long, char*);" >> $g_GENERIC
echo "long __b2c__hex2dec(int, char*, char*, ...);" >> $g_GENERIC
echo "char* __b2c__hostname(int, char*);" >> $g_GENERIC
echo "char* __b2c__inbetween(int, char*, char*, char*, int);" >> $g_GENERIC
echo "char *__b2c__insert(int,char*,char*, int, char*);" >> $g_GENERIC
echo "long __b2c__instr(int, char*, char*, char*, int);" >> $g_GENERIC
echo "long __b2c__instrrev(int,char*,char*, char*, int);" >> $g_GENERIC
echo "long __b2c__istoken(char*,char*, ...);" >> $g_GENERIC
echo "char *__b2c__last(char*, int, char*);" >> $g_GENERIC
echo "char* __b2c__lcase(int,char*,char*);" >> $g_GENERIC
echo "char* __b2c__left(int, char*, char*, unsigned long);" >> $g_GENERIC
echo "char *__b2c__load(int, int, char*, char*);" >> $g_GENERIC
echo "int __b2c__makedir(char*);" >> $g_GENERIC
echo "char *__b2c__me(char*);" >> $g_GENERIC
echo "int __b2c__memory__check(volatile char*, int);" >> $g_GENERIC
echo "char *__b2c__merge(char*, ...);" >> $g_GENERIC
echo "char* __b2c__mid(int, char*, char*, long, long); " >> $g_GENERIC
echo "char* __b2c__min_str(char*,char*);" >> $g_GENERIC
echo "char* __b2c__max_str(char*,char*);" >> $g_GENERIC
echo "char* __b2c__nethost(int, char*, char*);" >> $g_GENERIC
echo "long __b2c__netpeek(int, char*, int, int);" >> $g_GENERIC
echo "char* __b2c__os(int, char*);" >> $g_GENERIC
echo "int __b2c__peek_check(int, char*, char*, int);" >> $g_GENERIC
echo "char *__b2c__proper(int,char*,char*, ...);" >> $g_GENERIC
echo "long __b2c__regex(int, char*, char*,char*);" >> $g_GENERIC
echo "char * __b2c__replace(int, char*, char*, char*, char*, int);" >> $g_GENERIC
echo "char *__b2c__rev(char*, ...);" >> $g_GENERIC
echo "char* __b2c__reverse(int, char*, char*);" >> $g_GENERIC
echo "char* __b2c__right(int, char*, char*, unsigned long);" >> $g_GENERIC
echo "char *__b2c__rip(int, char*, char*, ...);" >> $g_GENERIC
echo "int __b2c__rmrecursive(int, char*, char*);" >> $g_GENERIC
echo "unsigned long __b2c__rol(int,long);" >> $g_GENERIC
echo "unsigned long __b2c__ror(int,long);" >> $g_GENERIC
echo "char *__b2c__rotate(char*, int, ...);" >> $g_GENERIC
echo "long __b2c__screen(int);" >> $g_GENERIC
echo "long __b2c__search(int, char*, FILE*, ...);" >> $g_GENERIC
echo "void __b2c__segv(int);" >> $g_GENERIC
echo "char *__b2c__sort(char*, ...);" >> $g_GENERIC
echo "char* __b2c__spc(int);" >> $g_GENERIC
echo "char* __b2c__str(double);" >> $g_GENERIC
echo "long __b2c__sum(int, long*, long, ...);" >> $g_GENERIC
echo "double __b2c__sumf(int, double*, double, ...);" >> $g_GENERIC
echo "char* __b2c__tab(int);" >> $g_GENERIC
echo "char *__b2c__tail(char*, long, char*);" >> $g_GENERIC
echo "long __b2c__tally(char*, ...);" >> $g_GENERIC
echo "long __b2c__time(time_t, int);" >> $g_GENERIC
echo "unsigned long __b2c__timer(void);" >> $g_GENERIC
echo "char *__b2c__token(char*, long, char*);" >> $g_GENERIC
echo "char* __b2c__ucase(int,char*,char*);" >> $g_GENERIC
echo "char *__b2c__unflatten(char *src, ...);" >> $g_GENERIC
echo "char *__b2c__uniq(char*, ...);" >> $g_GENERIC
echo "unsigned int __b2c__utf8toasc(char*);" >> $g_GENERIC
echo "void __b2c__version(char*);" >> $g_GENERIC
echo "char* __b2c__walk(int, char*, char*, int, char*, int, ...);" >> $g_GENERIC
echo "char* __b2c_Copy_String(char*,char*);" >> $g_GENERIC
echo "char* __b2c_Assign_String (char**,char*);" >> $g_GENERIC
echo "char* __b2c__topstring(char*);" >> $g_GENERIC
echo "unsigned long __b2c__len(const char*);" >> $g_GENERIC
echo "unsigned long __b2c__ulen(int,char*,char*,...);" >> $g_GENERIC
echo "unsigned long __b2c__blen(int,char*,char*,char*,long,...);" >> $g_GENERIC
echo "unsigned long __b2c__ucs2_clen(int,char*,char*,char*,int);" >> $g_GENERIC
echo "unsigned long __b2c__buf(const char*);" >> $g_GENERIC
echo "char *__b2c__loop_helper(jmp_buf);" >> $g_GENERIC
echo "/* Internal macro definitions */" >> $g_GENERIC
echo "#define __b2c__MEMTYPE char" >> $g_GENERIC
echo "#define __b2c__STRCMP __b2c__strcmp" >> $g_GENERIC
echo "#define __b2c__BUFOFFSET 9" >> $g_GENERIC
echo "#define __b2c__INRANGE(x) ((unsigned long)x > __b2c__ptrlow && (unsigned long)x < __b2c__ptrhgh ? 1 : 0)" >> $g_GENERIC
echo "#define __b2c__SETRANGE(x) if((unsigned long)x < __b2c__ptrlow) __b2c__ptrlow = (unsigned long)x-1; if((unsigned long)x > __b2c__ptrhgh) __b2c__ptrhgh = (unsigned long)x+__b2c__BUFOFFSET+1;" >> $g_GENERIC
echo "#define __b2c__STRFREE(x) ( x!=NULL && (long)x&1 ? free(x-__b2c__BUFOFFSET) : free(x) )" >> $g_GENERIC
echo "#define __b2c__SETLEN(x,y) *(uint32_t*)(x-__b2c__BUFOFFSET) = y;" >> $g_GENERIC
echo "#define __b2c__SETBIT(x) *(uint8_t*)(x-1) |= 1" >> $g_GENERIC
echo "#define __b2c__IS_SBUF(x) *(uint8_t*)(x-1) & 1" >> $g_GENERIC
echo "#define __b2c__UNSETBIT(x) *(uint8_t*)(x-1) &= 254" >> $g_GENERIC
echo "#define __b2c__INVALIDATE(x) if((long)x & 1) { *(uint8_t*)(x-1) |= 128; }" >> $g_GENERIC
echo "#define __b2c__VALID(x) (*(uint8_t*)(x-1) < 128)" >> $g_GENERIC
echo "#define __b2c_INDIRECT2(x, y) x ## y" >> $g_GENERIC
echo "#define __b2c_INDIRECT(x, y) __b2c_INDIRECT2(x, y)" >> $g_GENERIC
echo "#define __b2c__FUNCSELECT2(_1, _2, x, ...) x" >> $g_GENERIC
echo "#define __b2c__FUNCSELECT3(_1, _2, _3, x, ...) x" >> $g_GENERIC
echo "#define __b2c__FUNCSELECT4(_1, _2, _3, _4, x, ...) x" >> $g_GENERIC
if [[ -n $BASH ]]
then
    echo "#define COMPILED_BY_WHICH_BACON${g_STRINGSIGN} \"Shell Script BaCon $g_VERSION in BASH $BASH_VERSION\"" >> $g_GENERIC
elif [[ -n $ZSH_NAME ]]
then
    echo "#define COMPILED_BY_WHICH_BACON${g_STRINGSIGN} \"Shell Script BaCon $g_VERSION in ZSH $ZSH_VERSION\"" >> $g_GENERIC
else
    echo "#define COMPILED_BY_WHICH_BACON${g_STRINGSIGN} \"Shell Script BaCon $g_VERSION in KSH $KSH_VERSION\"" >> $g_GENERIC
fi
echo "#define RUNTIMEERROR(a, x, y, z) do { if(__b2c__option_error) { fprintf(stderr, \"Runtime error: statement '%s' at line %d in '%s': %s\n\", a, x, y, ERR${g_STRINGSIGN}(z)); exit(z); } if(__b2c__error_callback){(*__b2c__error_callback)(a,y,x);} } while(0)" >> $g_GENERIC
echo "#define RUNTIMEFERR(a, x, y, z) do { if(__b2c__option_error) { fprintf(stderr, \"Runtime error: function '%s' at line %d in '%s': %s\n\", a, z, y, ERR${g_STRINGSIGN}(x)); exit(x); } if(__b2c__error_callback){(*__b2c__error_callback)(a,y,z);} return(0); } while(0)" >> $g_GENERIC
echo "/* BaCon functions */" >> $g_GENERIC
echo "#define ABS(x) (((x) < 0) ? -(x) : (x))" >> $g_GENERIC
echo "#define ACOS(x) acos((double)x)" >> $g_GENERIC
echo "#define ADDRESS(x) (long)(&x)" >> $g_GENERIC
echo "#define ALIGN${g_STRINGSIGN}(...) __b2c__align(__b2c_lineno, __b2c_filename, __VA_ARGS__, 0)" >> $g_GENERIC
echo "#define __b2c__AMOUNT1(x) __b2c__amount(x, NULL)" >> $g_GENERIC
echo "#define __b2c__AMOUNT2(x, y) __b2c__amount(x, y)" >> $g_GENERIC
echo "#define AMOUNT(...) __b2c__FUNCSELECT2(__VA_ARGS__, __b2c__AMOUNT2, __b2c__AMOUNT1)(__VA_ARGS__)" >> $g_GENERIC
echo "#define AND &&" >> $g_GENERIC
echo "#define __b2c__APPEND3(x, y, z) __b2c__append(x, y, z, NULL)" >> $g_GENERIC
echo "#define __b2c__APPEND4(x, y, z, f) __b2c__append(x, y, z, f)" >> $g_GENERIC
echo "#define APPEND${g_STRINGSIGN}(...) __b2c__FUNCSELECT4(__VA_ARGS__, __b2c__APPEND4, __b2c__APPEND3)(__VA_ARGS__)" >> $g_GENERIC
echo "#define ASC(x) (unsigned char)*x" >> $g_GENERIC
echo "#define ASIN(x) asin((double)x)" >> $g_GENERIC
echo "#define ATN(x) atan((double)x)" >> $g_GENERIC
echo "#define ATN2(x,y) atan2((double)x,(double)y)" >> $g_GENERIC
echo "#define B64DEC${g_STRINGSIGN}(x) __b2c__b64dec(x)" >> $g_GENERIC
echo "#define B64ENC${g_STRINGSIGN}(...) __b2c__b64enc(__VA_ARGS__, 0)" >> $g_GENERIC
echo "#define BASENAME${g_STRINGSIGN}(...) __b2c__dirname(__b2c_lineno, __b2c_filename, 1, __VA_ARGS__, 0)" >> $g_GENERIC
echo "#define BIN${g_STRINGSIGN}(x) __b2c__bin(sizeof(__b2c__MEMTYPE), x)" >> $g_GENERIC
echo "#define BIT(x) __b2c__bit(x)" >> $g_GENERIC
echo "#define BLOAD(x) (void*)__b2c__load(1, __b2c_lineno, __b2c_filename, x)" >> $g_GENERIC
echo "#define BYTELEN(x, ...) __b2c__blen(__b2c_lineno, __b2c_filename, \"BYTELEN\", x, __VA_ARGS__, 0)" >> $g_GENERIC
echo "#define CEIL(x) (double)ceil(x)" >> $g_GENERIC
echo "#define CA${g_STRINGSIGN}(x) (__b2c_ssl_ptr[x] == NULL ? \"Connection '\" #x \"' has no TLS!\" : (char*)X509_NAME_oneline(X509_get_issuer_name(SSL_get_peer_certificate((SSL*)__b2c_ssl_ptr[x])), __b2c__input__buffer, $g_BUFFER_SIZE))" >> $g_GENERIC
echo "#define CN${g_STRINGSIGN}(x) (__b2c_ssl_ptr[x] == NULL ? \"Connection '\" #x \"' has no TLS!\" : (char*)X509_NAME_oneline(X509_get_subject_name(SSL_get_peer_certificate((SSL*)__b2c_ssl_ptr[x])), __b2c__input__buffer, $g_BUFFER_SIZE))" >> $g_GENERIC
echo "#define CIPHER${g_STRINGSIGN}(x) (__b2c_ssl_ptr[x] == NULL ? \"Connection '\" #x \"' has no TLS!\" : (char*)SSL_CIPHER_description(SSL_get_current_cipher((SSL*)__b2c_ssl_ptr[x]), __b2c__input__buffer, $g_BUFFER_SIZE))" >> $g_GENERIC
echo "#define VERIFY(x, y) (__b2c_ssl_ptr[x] == NULL ? -1 : (long)SSL_get_verify_result((SSL*)__b2c_ssl_ptr[x]) )" >> $g_GENERIC
echo "#define CHANGE${g_STRINGSIGN}(...) __b2c__change(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define __b2c__CHOP1(x) __b2c__chop(x, NULL, 0)" >> $g_GENERIC
echo "#define __b2c__CHOP2(x, y) __b2c__chop(x, y, 0)" >> $g_GENERIC
echo "#define __b2c__CHOP3(x, y, z) __b2c__chop(x, y, z)" >> $g_GENERIC
echo "#define CHOP${g_STRINGSIGN}(...) __b2c__FUNCSELECT3(__VA_ARGS__, __b2c__CHOP3, __b2c__CHOP2, __b2c__CHOP1)(__VA_ARGS__)" >> $g_GENERIC
echo "#define CHR${g_STRINGSIGN}(x) __b2c__asc2char(x)" >> $g_GENERIC
echo "#define UTF8${g_STRINGSIGN}(x) __b2c__asc2utf8(x)" >> $g_GENERIC
echo "#define CL${g_STRINGSIGN} \"\033[2K\"" >> $g_GENERIC
echo "#define CMDLINE(x) __b2c__getopt(argc, argv, x)" >> $g_GENERIC
echo "#define COIL${g_STRINGSIGN}(...) ( !setjmp(__b2c__loop1) ? __b2c__loop_helper(__b2c__loop2) : __b2c__loop_result${g_STRINGSIGN} )" >> $g_GENERIC
echo "#define COLUMNS __b2c__screen(0)" >> $g_GENERIC
echo "#define CONCAT${g_STRINGSIGN}(...) __b2c__concat(__VA_ARGS__, (char*)NULL)" >> $g_GENERIC
echo "#define COS(x) cos((double)x)" >> $g_GENERIC
echo "#define COUNT(x, y) ((x) != NULL ? __b2c__count(__b2c_lineno, __b2c_filename, x, y) : 0)" >> $g_GENERIC
echo "#define CR${g_STRINGSIGN} \"\r\"" >> $g_GENERIC
echo "#define CURDIR${g_STRINGSIGN} __b2c__curdir()" >> $g_GENERIC
echo "#define CUT${g_STRINGSIGN}(...) __b2c__cut(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define DAY(x) __b2c__time(x, 1)" >> $g_GENERIC
echo "#define DEC(...) __b2c__hex2dec(__b2c_lineno, __b2c_filename, __VA_ARGS__, 0)" >> $g_GENERIC
echo "#define DEG(x) (x*180/PI)" >> $g_GENERIC
echo "#define DEL${g_STRINGSIGN}(...) __b2c__del(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define DELIM${g_STRINGSIGN}(x, y, z) __b2c__delim(x, y, z)" >> $g_GENERIC
echo "#define DIRNAME${g_STRINGSIGN}(...) __b2c__dirname(__b2c_lineno, __b2c_filename, 2, __VA_ARGS__, 0)" >> $g_GENERIC
echo "#define EL${g_STRINGSIGN} \"\033[0K\"" >> $g_GENERIC
echo "#define ENDFILE(x) feof(x)" >> $g_GENERIC
echo "#define EQ ==" >> $g_GENERIC
echo "#define EQUAL(x, y) ((x) != NULL && (y) != NULL ? !__b2c__STRCMP(x, y) : 0)" >> $g_GENERIC
echo "#define EVAL(x, y, z) __b2c__eval(__b2c_lineno, __b2c_filename, x, y, z)" >> $g_GENERIC
echo "#define EVEN(x) (((long)(x) % 2 == 0) ? 1 : 0)" >> $g_GENERIC
echo "#define EXCHANGE${g_STRINGSIGN}(...) __b2c__exchange(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define EXEC${g_STRINGSIGN}(...) __b2c__exec(0, __b2c_lineno, __b2c_filename, __VA_ARGS__, 0, 0)" >> $g_GENERIC
echo "#define EXP(x) exp((double)x)" >> $g_GENERIC
echo "#define EXPLODE${g_STRINGSIGN}(...) __b2c__explode(__b2c_lineno, __b2c_filename, __VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define __b2c__EXTRACT2(x, y) __b2c__extract(__b2c_lineno, __b2c_filename, x, y, 0)" >> $g_GENERIC
echo "#define __b2c__EXTRACT3(x, y, z) __b2c__extract(__b2c_lineno, __b2c_filename, x, y, z)" >> $g_GENERIC
echo "#define EXTRACT${g_STRINGSIGN}(...) __b2c__FUNCSELECT3(__VA_ARGS__, __b2c__EXTRACT3, __b2c__EXTRACT2)(__VA_ARGS__)" >> $g_GENERIC
echo "#define FALSE 0" >> $g_GENERIC
echo "#define FILEEXISTS(x) (x != NULL ? !access(x, F_OK) : 0)" >> $g_GENERIC
echo "#define FILELEN(x) __b2c__filelen(__b2c_lineno, __b2c_filename, x)" >> $g_GENERIC
echo "#define FILETIME(x, y) __b2c__filetime(__b2c_lineno, __b2c_filename, x, y)" >> $g_GENERIC
echo "#define FILETYPE(x) __b2c__filetype(__b2c_lineno, __b2c_filename, x)" >> $g_GENERIC
echo "#define FILL${g_STRINGSIGN}(x, y) ((y) >= 0 && (y) <= 0x10FFFF ? __b2c__fill(x, y) : EmptyString)" >> $g_GENERIC
echo "#define __b2c__FIRST2(x, y) __b2c__first(x, y, NULL)" >> $g_GENERIC
echo "#define __b2c__FIRST3(x, y, z) __b2c__first(x, y, z)" >> $g_GENERIC
echo "#define FIRST${g_STRINGSIGN}(...) __b2c__FUNCSELECT3(__VA_ARGS__, __b2c__FIRST3, __b2c__FIRST2)(__VA_ARGS__)" >> $g_GENERIC
echo "#define FLATTEN${g_STRINGSIGN}(...) __b2c__flatten(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define FLOATING double" >> $g_GENERIC
echo "#define FLOOR(x) (long)floor(x)" >> $g_GENERIC
echo "#define FORK fork()" >> $g_GENERIC
echo "#define FP(x) (void*)(&x)" >> $g_GENERIC
echo "#define GE >=" >> $g_GENERIC
echo "#define GETENVIRON${g_STRINGSIGN}(x) ((x) != NULL ? __b2c__getenv(x) : (char*)\"null\")" >> $g_GENERIC
echo "#define GETKEY __b2c__getch()" >> $g_GENERIC
echo "#define GETPEER${g_STRINGSIGN}(x) __b2c__getpeer(__b2c_lineno, __b2c_filename, x)" >> $g_GENERIC
echo "#define GETX __b2c__getxy(0)" >> $g_GENERIC
echo "#define GETY __b2c__getxy(1)" >> $g_GENERIC
echo "#define GT >" >> $g_GENERIC
echo "#define __b2c__HASDELIM1(x) __b2c__hasdelim(x, NULL)" >> $g_GENERIC
echo "#define __b2c__HASDELIM2(x, y) __b2c__hasdelim(x, y)" >> $g_GENERIC
echo "#define HASDELIM(...) __b2c__FUNCSELECT2(__VA_ARGS__, __b2c__HASDELIM2, __b2c__HASDELIM1)(__VA_ARGS__)" >> $g_GENERIC
echo "#define HASH(x) __b2c__HashFNV1a((char*)x)" >> $g_GENERIC
echo "#define __b2c__HEAD2(x, y) __b2c__head(x, y, NULL)" >> $g_GENERIC
echo "#define __b2c__HEAD3(x, y, z) __b2c__head(x, y, z)" >> $g_GENERIC
echo "#define HEAD${g_STRINGSIGN}(...) __b2c__FUNCSELECT3(__VA_ARGS__, __b2c__HEAD3, __b2c__HEAD2)(__VA_ARGS__)" >> $g_GENERIC
echo "#define HEX${g_STRINGSIGN}(x) __b2c__dec2hex(x)" >> $g_GENERIC
echo "#define HOST${g_STRINGSIGN}(x) __b2c__nethost(__b2c_lineno, __b2c_filename, x)" >> $g_GENERIC
echo "#define HOSTNAME${g_STRINGSIGN} __b2c__hostname(__b2c_lineno, __b2c_filename)" >> $g_GENERIC
echo "#define HOUR(x) __b2c__time(x, 4)" >> $g_GENERIC
echo "#define IIF(x, y, z) (x ? y : z)" >> $g_GENERIC
echo "#define IIF${g_STRINGSIGN}(x, y, z) (char*)(x ? y : z)" >> $g_GENERIC
echo "#define __b2c__INBETWEEN3(x, y, z) __b2c__inbetween(0, x, y, z, 0)" >> $g_GENERIC
echo "#define __b2c__INBETWEEN4(x, y, z, f) __b2c__inbetween(0, x, y, z, f)" >> $g_GENERIC
echo "#define INBETWEEN${g_STRINGSIGN}(...) __b2c__FUNCSELECT4(__VA_ARGS__, __b2c__INBETWEEN4, __b2c__INBETWEEN3)(__VA_ARGS__)" >> $g_GENERIC
echo "#define INSERT${g_STRINGSIGN}(x, y, z) __b2c__insert(__b2c_lineno, __b2c_filename, x, y, z)" >> $g_GENERIC
echo "#define __b2c__INSTR2(x, y) __b2c__instr(__b2c_lineno, __b2c_filename, x, y, -1)" >> $g_GENERIC
echo "#define __b2c__INSTR3(x, y, z) __b2c__instr(__b2c_lineno, __b2c_filename, x, y, z)" >> $g_GENERIC
echo "#define INSTR(...) __b2c__FUNCSELECT3(__VA_ARGS__, __b2c__INSTR3, __b2c__INSTR2)(__VA_ARGS__)" >> $g_GENERIC
echo "#define __b2c__INSTRREV2(x, y) __b2c__instrrev(__b2c_lineno, __b2c_filename, x, y, -1)" >> $g_GENERIC
echo "#define __b2c__INSTRREV3(x, y, z) __b2c__instrrev(__b2c_lineno, __b2c_filename, x, y, z)" >> $g_GENERIC
echo "#define INSTRREV(...) __b2c__FUNCSELECT3(__VA_ARGS__, __b2c__INSTRREV3, __b2c__INSTRREV2)(__VA_ARGS__)" >> $g_GENERIC
echo "#define INT(x) lrint((double)x)" >> $g_GENERIC
echo "#define IS ==" >> $g_GENERIC
echo "#define ISASCII(x) __b2c__isascii(x)" >> $g_GENERIC
echo "#define ISFALSE(x) ((x) == 0)" >> $g_GENERIC
echo "#define ISKEY(x, ...) ( (__b2c_INDIRECT(__b2c__ ## x ## __add_secure_, __b2c_assoc_ ## x)(0, __VA_ARGS__, NULL) == NULL) ? 0 : 1)" >> $g_GENERIC
echo "#define ISNOT !=" >> $g_GENERIC
echo "#define ISTOKEN(...) __b2c__istoken(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define ISTRUE(x) ((x) != 0)" >> $g_GENERIC
echo "#define ISUTF8(x) __b2c__isutf8(x)" >> $g_GENERIC
echo "#define LCASE${g_STRINGSIGN}(x) __b2c__lcase(__b2c_lineno, __b2c_filename, x)" >> $g_GENERIC
echo "#define LE <=" >> $g_GENERIC
echo "#define LEFT${g_STRINGSIGN}(x, y) __b2c__left(__b2c_lineno, __b2c_filename, x, y)" >> $g_GENERIC
echo "#define LEN(x) (__b2c__option_utf8 ? __b2c__ulen(__b2c_lineno, __b2c_filename, \"LEN\", x, -1) : __b2c__len(x))" >> $g_GENERIC
echo "#define ULEN(...) __b2c__ulen(__b2c_lineno, __b2c_filename, \"ULEN\", __VA_ARGS__, -1)" >> $g_GENERIC
echo "#define __b2c__LAST2(x, y) __b2c__last(x, y, NULL)" >> $g_GENERIC
echo "#define __b2c__LAST3(x, y, z) __b2c__last(x, y, z)" >> $g_GENERIC
echo "#define LAST${g_STRINGSIGN}(...) __b2c__FUNCSELECT3(__VA_ARGS__, __b2c__LAST3, __b2c__LAST2)(__VA_ARGS__)" >> $g_GENERIC
echo "#define LINENO __b2c_lineno" >> $g_GENERIC
echo "#define LOAD${g_STRINGSIGN}(x) __b2c__load(0, __b2c_lineno, __b2c_filename, x)" >> $g_GENERIC
echo "#define LOG(x) log((double)x)" >> $g_GENERIC
echo "#define LOOP${g_STRINGSIGN}(...) ( !setjmp(__b2c__loop1) ? __b2c__loop_helper(__b2c__loop2) : __b2c__loop_result${g_STRINGSIGN} )" >> $g_GENERIC
echo "#define LT <" >> $g_GENERIC
echo "#define MAX(x, y) fmax(x, y)" >> $g_GENERIC
echo "#define MAX${g_STRINGSIGN}(x, y) __b2c__max_str(x, y)" >> $g_GENERIC
echo "#define MAXNUM(x) (x)POW(2, SIZEOF(x)*8)" >> $g_GENERIC
if [[ `uname` = +(*SunOS*|*OSF1*) ]]
then
    echo "#define MAXRANDOM 2147483647" >> $g_GENERIC
else
    echo "#define MAXRANDOM RAND_MAX" >> $g_GENERIC
fi
echo "#define ME${g_STRINGSIGN} __b2c__me_var${g_STRINGSIGN}" >> $g_GENERIC
echo "#define MEMCHECK(x) !(__b2c__memory__check((char*)x, sizeof(__b2c__MEMTYPE)))" >> $g_GENERIC
echo "#define MEMORY(x) (calloc(x+__b2c__option_memstream, sizeof(__b2c__MEMTYPE)))" >> $g_GENERIC
echo "#define MEMTELL(x) (long)x" >> $g_GENERIC
echo "#define MERGE${g_STRINGSIGN}(...) __b2c__merge(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define __b2c__MID2(x, y) __b2c__mid(__b2c_lineno, __b2c_filename, x, y, -1)" >> $g_GENERIC
echo "#define __b2c__MID3(x, y, z) __b2c__mid(__b2c_lineno, __b2c_filename, x, y, z)" >> $g_GENERIC
echo "#define MID${g_STRINGSIGN}(...) __b2c__FUNCSELECT3(__VA_ARGS__, __b2c__MID3, __b2c__MID2)(__VA_ARGS__)" >> $g_GENERIC
echo "#define MIN(x, y) fmin(x, y)" >> $g_GENERIC
echo "#define MIN${g_STRINGSIGN}(x, y) __b2c__min_str(x, y)" >> $g_GENERIC
echo "#define MINUTE(x) __b2c__time(x, 5)" >> $g_GENERIC
echo "#define MOD(x, y) ((long)(x) % (long)(y))" >> $g_GENERIC
echo "#define MONTH(x) __b2c__time(x, 2)" >> $g_GENERIC
echo "#define MONTH${g_STRINGSIGN}(x) __b2c__datename(x, 2)" >> $g_GENERIC
echo "#define MYPID getpid()" >> $g_GENERIC
echo "#define NE !=" >> $g_GENERIC
echo "#define NL${g_STRINGSIGN} \"\n\"" >> $g_GENERIC
echo "#define NOT(x) (!(x))" >> $g_GENERIC
echo "#define NOW (long)time(NULL)" >> $g_GENERIC
echo "#define NRKEYS(x) __b2c__hashtable_count(__b2c_INDIRECT(&__b2c__ ## x ## _table_, __b2c_assoc_ ## x))" >> $g_GENERIC
echo "#define NUMBER long" >> $g_GENERIC
echo "#define __b2c__OBTAIN1(x) __b2c_INDIRECT(__b2c__ ## x ## _obtain_, __b2c_assoc_ ## x)(NULL)" >> $g_GENERIC
echo "#define __b2c__OBTAIN2(x, y) __b2c_INDIRECT(__b2c__ ## x ## _obtain_, __b2c_assoc_ ## x)(y)" >> $g_GENERIC
echo "#define OBTAIN${g_STRINGSIGN}(...) __b2c__FUNCSELECT2(__VA_ARGS__, __b2c__OBTAIN2, __b2c__OBTAIN1)(__VA_ARGS__)" >> $g_GENERIC
echo "#define ODD(x) (((long)(x) % 2 != 0) ? 1 : 0)" >> $g_GENERIC
echo "#define OR ||" >> $g_GENERIC
echo "#define OS${g_STRINGSIGN} __b2c__os(__b2c_lineno, __b2c_filename)" >> $g_GENERIC
echo "#define __b2c__OUTBETWEEN3(x, y, z) __b2c__inbetween(1, x, y, z, 0)" >> $g_GENERIC
echo "#define __b2c__OUTBETWEEN4(x, y, z, f) __b2c__inbetween(1, x, y, z, f)" >> $g_GENERIC
echo "#define OUTBETWEEN${g_STRINGSIGN}(...) __b2c__FUNCSELECT4(__VA_ARGS__, __b2c__OUTBETWEEN4, __b2c__OUTBETWEEN3)(__VA_ARGS__)" >> $g_GENERIC
echo "#define PEEK(x) (__b2c__peek_check(__b2c_lineno, __b2c_filename, (char*)x, sizeof(__b2c__MEMTYPE)) == 0 ? *(__b2c__MEMTYPE *)(x) : 0)" >> $g_GENERIC
echo "#define PI 3.14159265358979323846" >> $g_GENERIC
echo "#define POW(x, y) pow((double)x, (double)y)" >> $g_GENERIC
echo "#define PROPER${g_STRINGSIGN}(...) __b2c__proper(__b2c_lineno, __b2c_filename, __VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define RAD(x) (x*PI/180)" >> $g_GENERIC
echo "#define RANDOM(x) ((x) != 0 ? random()/(MAXRANDOM/(x)) : 0)" >> $g_GENERIC
echo "#define REALPATH${g_STRINGSIGN}(...) __b2c__dirname(__b2c_lineno, __b2c_filename, 0, __VA_ARGS__, 0)" >> $g_GENERIC
echo "#define REAP(x) waitpid(x, NULL, WNOHANG)" >> $g_GENERIC
echo "#define REGEX(x, y) __b2c__regex(__b2c_lineno, __b2c_filename, x, y)" >> $g_GENERIC
echo "#define __b2c__REPLACE3(x, y, z) __b2c__replace(__b2c_lineno, __b2c_filename, x, y, z, 0)" >> $g_GENERIC
echo "#define __b2c__REPLACE4(x, y, z, f) __b2c__replace(__b2c_lineno, __b2c_filename, x, y, z, f)" >> $g_GENERIC
echo "#define REPLACE${g_STRINGSIGN}(...) __b2c__FUNCSELECT4(__VA_ARGS__, __b2c__REPLACE4, __b2c__REPLACE3)(__VA_ARGS__)" >> $g_GENERIC
echo "#define REV${g_STRINGSIGN}(...) __b2c__rev(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define REVERSE${g_STRINGSIGN}(x) __b2c__reverse(__b2c_lineno, __b2c_filename, x)" >> $g_GENERIC
echo "#define RIGHT${g_STRINGSIGN}(x, y) __b2c__right(__b2c_lineno, __b2c_filename, x, y)" >> $g_GENERIC
echo "#define RIP${g_STRINGSIGN}(x, ...) __b2c__rip(__b2c_lineno, __b2c_filename, x, __VA_ARGS__, -1)" >> $g_GENERIC
echo "#define RND random()" >> $g_GENERIC
echo "#define ROL(x) __b2c__rol(sizeof(__b2c__MEMTYPE), x)" >> $g_GENERIC
echo "#define ROR(x) __b2c__ror(sizeof(__b2c__MEMTYPE), x)" >> $g_GENERIC
echo "#define ROTATE${g_STRINGSIGN}(x, ...) __b2c__rotate(x, __VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define ROUND(x) lrint((double)x)" >> $g_GENERIC
echo "#define ROWS __b2c__screen(1)" >> $g_GENERIC
echo "#define RUN${g_STRINGSIGN}(...) __b2c__exec(1, __b2c_lineno, __b2c_filename, __VA_ARGS__, 0, 0)" >> $g_GENERIC
echo "#define SEARCH(...) __b2c__search(__b2c_lineno, __b2c_filename, __VA_ARGS__, -1)" >> $g_GENERIC
echo "#define SECOND(x) __b2c__time(x, 6)" >> $g_GENERIC
echo "#define SETENVIRON(x, y) if((x) != NULL && (y) != NULL) setenv(x, y, 1)" >> $g_GENERIC
echo "#define SGN(x) ((x) == 0 ? 0 : ((x) < 0 ? -1 : 1))" >> $g_GENERIC
echo "#define SIN(x) sin((double)x)" >> $g_GENERIC
echo "#define SIZEOF(x) sizeof(x)" >> $g_GENERIC
echo "#define SORT${g_STRINGSIGN}(...) __b2c__sort(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define SPC${g_STRINGSIGN}(x) ((x) >= 0 ? __b2c__spc(x) : EmptyString)" >> $g_GENERIC
echo "#define SQR(x) sqrt((double)(x))" >> $g_GENERIC
echo "#define STR${g_STRINGSIGN}(x) __b2c__str(x)" >> $g_GENERIC
echo "#define STRING char*" >> $g_GENERIC
echo "#define SUM(x,...) __b2c__sum($g_OPTION_BASE, x, __VA_ARGS__, LONG_MAX)" >> $g_GENERIC
echo "#define SUMF(x,...) __b2c__sumf($g_OPTION_BASE, x, __VA_ARGS__, DBL_MAX)" >> $g_GENERIC
echo "#define SYSTEM(x) do {if (x != NULL) {RETVAL = system(x); if(WIFEXITED(RETVAL)) RETVAL = WEXITSTATUS(RETVAL);} else RETVAL=0;} while(0)" >> $g_GENERIC
echo "#define TAB${g_STRINGSIGN}(x) ((x) >= 0 ? __b2c__tab(x) : EmptyString)" >> $g_GENERIC
echo "#define __b2c__TAIL2(x, y) __b2c__tail(x, y, NULL)" >> $g_GENERIC
echo "#define __b2c__TAIL3(x, y, z) __b2c__tail(x, y, z)" >> $g_GENERIC
echo "#define TAIL${g_STRINGSIGN}(...) __b2c__FUNCSELECT3(__VA_ARGS__, __b2c__TAIL3, __b2c__TAIL2)(__VA_ARGS__)" >> $g_GENERIC
echo "#define TALLY(...) __b2c__tally(__VA_ARGS__, -1)" >> $g_GENERIC
echo "#define TAN(x) tan((double)x)" >> $g_GENERIC
echo "#define TELL(x) ftell(x)" >> $g_GENERIC
echo "#define TIMER __b2c__timer()" >> $g_GENERIC
echo "#define TIMEVALUE(x,y,z,a,b,c) __b2c__epoch(x,y,z,a,b,c)" >> $g_GENERIC
echo "#define TOASCII${g_STRINGSIGN}(x) __b2c__toascii(x)" >> $g_GENERIC
echo "#define __b2c__TOKEN2(x, y) __b2c__token(x, y, NULL)" >> $g_GENERIC
echo "#define __b2c__TOKEN3(x, y, z) __b2c__token(x, y, z)" >> $g_GENERIC
echo "#define TOKEN${g_STRINGSIGN}(...) __b2c__FUNCSELECT3(__VA_ARGS__, __b2c__TOKEN3, __b2c__TOKEN2)(__VA_ARGS__)" >> $g_GENERIC
echo "#define TRUE 1" >> $g_GENERIC
echo "#define UCASE${g_STRINGSIGN}(x) __b2c__ucase(__b2c_lineno, __b2c_filename, x)" >> $g_GENERIC
echo "#define UCS(x) (unsigned int)__b2c__utf8toasc(x)" >> $g_GENERIC
echo "#define UNFLATTEN${g_STRINGSIGN}(...) __b2c__unflatten(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define UNIQ${g_STRINGSIGN}(...) __b2c__uniq(__VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define VAL(x) ((x) != NULL ? atof(x) : 0)" >> $g_GENERIC
echo "#define WAIT(x, y) __b2c__netpeek(__b2c_lineno, __b2c_filename, x, y)" >> $g_GENERIC
echo "#define WALK${g_STRINGSIGN}(...) __b2c__walk(__b2c_lineno, __b2c_filename, __VA_ARGS__, NULL)" >> $g_GENERIC
echo "#define WEEK(x) __b2c__time(x, 7)" >> $g_GENERIC
echo "#define WEEKDAY${g_STRINGSIGN}(x) __b2c__datename(x, 1)" >> $g_GENERIC
echo "#define YEAR(x) __b2c__time(x, 3)" >> $g_GENERIC
echo -e "#ifndef HASHTABLE_U32\n#define HASHTABLE_U32 uint32_t\n#endif" >> $g_GENERIC
echo -e "#ifndef HASHTABLE_U64\n#define HASHTABLE_U64 uint64_t\n#endif" >> $g_GENERIC
echo -e "#ifndef HASHTABLE_SIZE_T\n#undef _CRT_NONSTDC_NO_DEPRECATE\n#define _CRT_NONSTDC_NO_DEPRECATE\n#undef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n#include <stddef.h>\n#define HASHTABLE_SIZE_T size_t\n#endif" >> $g_GENERIC
echo -e "#ifndef HASHTABLE_ASSERT\n#undef _CRT_NONSTDC_NO_DEPRECATE\n#define _CRT_NONSTDC_NO_DEPRECATE\n#undef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n#include <assert.h>\n#define HASHTABLE_ASSERT( x ) assert( x )\n#endif" >> $g_GENERIC
echo -e "#ifndef HASHTABLE_MEMSET\n#undef _CRT_NONSTDC_NO_DEPRECATE\n#define _CRT_NONSTDC_NO_DEPRECATE\n#undef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n#include <string.h>\n#define HASHTABLE_MEMSET( ptr, val, cnt ) ( memset( ptr, val, cnt ) )\n#endif" >> $g_GENERIC
echo -e "#ifndef HASHTABLE_MEMCPY\n#undef _CRT_NONSTDC_NO_DEPRECATE\n#define _CRT_NONSTDC_NO_DEPRECATE\n#undef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n#include <string.h>\n#define HASHTABLE_MEMCPY( dst, src, cnt ) ( memcpy( dst, src, cnt ) )\n#endif" >> $g_GENERIC
echo -e "#ifndef HASHTABLE_MALLOC\n#undef _CRT_NONSTDC_NO_DEPRECATE\n#define _CRT_NONSTDC_NO_DEPRECATE\n#undef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n#include <stdlib.h>\n#define HASHTABLE_MALLOC( ctx, size ) ( malloc( size ) )\n #define HASHTABLE_FREE( ctx, ptr ) ( free( ptr ) )\n#endif" >> $g_GENERIC
echo "struct __b2c__hashtable_internal_slot_t { HASHTABLE_U32 key_hash; int item_index; int base_count; };" >> $g_GENERIC
echo "typedef struct __b2c__hashtable_t { void* memctx; int count; int item_size; struct __b2c__hashtable_internal_slot_t* slots; int slot_capacity; HASHTABLE_U64* items_key; int* items_slot; void* items_data; int item_capacity; void* swap_temp; } __b2c__hashtable_t;" >> $g_GENERIC
echo "HASHTABLE_U64 __b2c__HashFNV1a(const char*);" >> $g_GENERIC
echo "void __b2c__hashtable_init( __b2c__hashtable_t* table, int item_size, int initial_capacity, void* memctx );" >> $g_GENERIC
echo "void __b2c__hashtable_term( __b2c__hashtable_t* table );" >> $g_GENERIC
echo "void* __b2c__hashtable_insert( __b2c__hashtable_t* table, HASHTABLE_U64 key, void const* item );" >> $g_GENERIC
echo "void __b2c__hashtable_remove( __b2c__hashtable_t* table, HASHTABLE_U64 key );" >> $g_GENERIC
echo "void __b2c__hashtable_clear( __b2c__hashtable_t* table );" >> $g_GENERIC
echo "void* __b2c__hashtable_find( __b2c__hashtable_t const* table, HASHTABLE_U64 key );" >> $g_GENERIC
echo "int __b2c__hashtable_count( __b2c__hashtable_t const* table );" >> $g_GENERIC
echo "void* __b2c__hashtable_items( __b2c__hashtable_t const* table );" >> $g_GENERIC
echo "HASHTABLE_U64 const* __b2c__hashtable_keys( __b2c__hashtable_t const* table );" >> $g_GENERIC
echo "void __b2c__hashtable_swap( __b2c__hashtable_t* table, int index_a, int index_b );" >> $g_GENERIC
echo "typedef struct __b2c_te_expr { int type; union {double value; const double *bound; const void *function;}; void *parameters[1]; } __b2c_te_expr;" >> $g_GENERIC
echo "typedef struct __b2c_te_variable { const char *name; const void *address; int type; void *context; } __b2c_te_variable;" >> $g_GENERIC
echo "double __b2c_te_interp(const char *expression, int *error); __b2c_te_expr *te_compile(const char *expression, const __b2c_te_variable *variables, int var_count, int *error);" >> $g_GENERIC
echo "double __b2c_te_eval(const __b2c_te_expr *n); void __b2c_te_print(const __b2c_te_expr *n); void __b2c_te_free(__b2c_te_expr *n);" >> $g_GENERIC
echo "double __b2c__eval(int, char*, __b2c_te_variable*, int, char*);" >> $g_GENERIC
echo "#define __b2c__cacerts NULL" >> $g_GENERIC
echo "#define __b2c__capeer SSL_VERIFY_NONE" >> $g_GENERIC

# Generate functions
if [[ -n ${g_REBUILD_ARCHIVE} ]]
then
    g_CTEMP="$g_TEMPDIR/bacon.base64.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "/* Portions of this code based on Bob Trower's C implementation at http://base64.sourceforge.net - MIT licensed */ static const char cd64[]=\"|\$\$\$}rstuvwxyz{\$\$\$\$\$\$\$>?@ABCDEFGHIJKLMNOPQRSTUVW\$\$\$\$\$\$XYZ[\\\\]^_\`abcdefghijklmnopq\";" >> $g_CTEMP
    echo "static const char cb64[]=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"; static void encodeblock(unsigned char *in, unsigned char *out, int len)" >> $g_CTEMP
    echo "{ out[0] = (unsigned char) cb64[ (int)(in[0] >> 2) ]; out[1] = (unsigned char) cb64[ (int)(((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)) ];" >> $g_CTEMP
    echo "out[2] = (unsigned char) (len > 1 ? cb64[ (int)(((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)) ] : '='); out[3] = (unsigned char) (len > 2 ? cb64[ (int)(in[2] & 0x3f) ] : '='); }" >> $g_CTEMP
    echo "char * __b2c__b64enc (char* src, ...) { long idx; va_list ap; unsigned char in[4], out[4]; int i, j, len, cur = 0, posit = 0; if (src == NULL) { return (EmptyString); } va_start (ap, src);" >> $g_CTEMP
    echo "len = va_arg (ap, int); if (len == 0) { len = __b2c__len (src); } va_end (ap); if (len == 0) { return (EmptyString); } idx = __sbuf_malloc_handle(((len + 2) / 3) * 4 + 1);" >> $g_CTEMP
    echo "while(cur < len){ for( i = 0; i < 3 && (cur + i < len); i++ ){ in[i] = (unsigned char) src[cur+i]; } in[i] = 0; cur += i; if( i > 0 ) { encodeblock( in, out, i );" >> $g_CTEMP
    echo "for( j = 0; j < 4; j++ ) { __b2c__sbuffer[idx][posit+j] = out[j]; } posit += 4; } } __b2c__sbuffer[idx][posit] = '\0'; __b2c__SETLEN(__b2c__sbuffer[idx], posit);" >> $g_CTEMP
    echo "return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "static void decodeblock(unsigned char in[4], unsigned char out[3]) { out[0] = (unsigned char ) (in[0] << 2 | in[1] >> 4); out[1] = (unsigned char)(in[1] << 4 | in[2] >> 2);" >> $g_CTEMP
    echo "out[2] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]); }" >> $g_CTEMP
    echo "char *__b2c__b64dec (char *src) { long idx; unsigned char in[4], out[3], v; int i, stlen, len, cur = 0, posit = 0; if(src == NULL){ return (EmptyString); }" >> $g_CTEMP
    echo "stlen = __b2c__len (src); if (stlen == 0) { return (EmptyString); } idx = __sbuf_malloc_handle (((stlen + 3) / 4) * 3 + 1);" >> $g_CTEMP
    echo "while(cur < stlen){ for (len = 0, i = 0; i < 4 && (cur < stlen); i++) { v = 0; while (cur < stlen && v == 0){ v = (unsigned char) src[cur]; cur++; v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);" >> $g_CTEMP
    echo "if (v) {v = (unsigned char) ((v == '$') ? 0 : v - 61);} } if(cur <= stlen){ len++; if (v) { in[i] = (unsigned char)(v - 1); } else { in[i] = 0; } } } if(len){ decodeblock(in, out);" >> $g_CTEMP
    echo "for(i = 0; i < len - 1; i++) { __b2c__sbuffer[idx][posit + i] = out[i]; } __b2c__sbuffer[idx][posit + i] = '\0'; } posit += len - 1; } __b2c__SETLEN(__b2c__sbuffer[idx], posit);" >> $g_CTEMP
    echo "return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.base64.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.base64.o: bacon.base64.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.base64.c"

    g_CTEMP="$g_TEMPDIR/bacon.binary.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "unsigned long __b2c__bit(long x) { return(x ? 2<<(x-1) : 1); } unsigned long __b2c__rol(int type, long x)" >> $g_CTEMP
    echo "{ return((x)&lrint(pow(2, type*8-1)) ? (((x)<<1)|1)&lrint(pow(2, type*8)-1) : ((x)<<1)&lrint(pow(2, type*8)-1)); }" >> $g_CTEMP
    echo "unsigned long __b2c__ror(int type, long x) { return((x)&1 ? (((x)>>1)&lrint(pow(2, type*8)-1))|lrint(pow(2, type*8-1)) : ((x)>>1)&lrint(pow(2, type*8)-1)); }" >> $g_CTEMP
    echo "char *__b2c__bin(int type, long x) { long idx, i; idx = __sbuf_malloc_handle (type*8+1); for(i = 0; i<type*8; i++)" >> $g_CTEMP
    echo "{ if(x&1) { __b2c__sbuffer[idx][type*8-1-i] = 49; } else { __b2c__sbuffer[idx][type*8-1-i] = 48; } x = x>>1; }" >> $g_CTEMP
    echo " __b2c__sbuffer[idx][type*8] = '\0'; __b2c__SETLEN (__b2c__sbuffer[idx], type*8); return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.binary.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.binary.o: bacon.binary.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.binary.c"

    g_CTEMP="$g_TEMPDIR/bacon.chop.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char *__b2c__chop(char *source, char *string, int location) { char *tmp; long i, length, idx; if (source == NULL || __b2c__len (source) == 0) { return (source); } if (string == NULL) { string = (char *) __b2c__chop_default; }" >> $g_CTEMP
    echo "length = __b2c__len (string); if (location == 0 || location == 1) { while (*source != '\0') { for (i = 0; i < length; i++) { if (*source == *(string + i)) { source++; break; } } if (i == length) { break; } } if (*source == '\0') return(EmptyString); }" >> $g_CTEMP
    echo "tmp = source + strlen (source) - 1; if (location == 0 || location == 2) { while (tmp >= source && *tmp != '\0') { for (i = 0; i < length; i++) { if (*tmp == *(string + i)) { tmp--; break; } } if (i == length) { break; } } } tmp++;" >> $g_CTEMP
    echo "idx = __sbuf_malloc_handle (tmp - source + 1); memmove (__b2c__sbuffer[idx], source, tmp - source); __b2c__SETLEN (__b2c__sbuffer[idx], tmp - source); __b2c__sbuffer[idx][tmp - source] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.chop.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.chop.o: bacon.chop.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.chop.c"

    g_CTEMP="$g_TEMPDIR/bacon.chr.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__asc2char (int i) { long idx; int len; idx = __sbuf_malloc_handle(2); len = snprintf (__b2c__sbuffer[idx], 2, \"%c\", i);" >> $g_CTEMP
    echo "__b2c__SETLEN(__b2c__sbuffer[idx], len); return(char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char * __b2c__asc2utf8 (int i) { long idx; int len; char buf[5]; len = __b2c_utf8_conv(i, buf); idx = __sbuf_malloc_handle (len+1); memcpy (__b2c__sbuffer[idx], buf, len);" >> $g_CTEMP
    echo "__b2c__SETLEN (__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "unsigned int __b2c__utf8toasc(char* ptr) { unsigned int result = 0; if((*ptr&0xF0)==0xF0) { result = (*ptr&0x07)<<2; ptr++; result = result | ((*ptr&0x30)>>4); result = result << 8; result = result | ((*ptr&0x0F)<<4);" >> $g_CTEMP
    echo "ptr++; result = result | ((*ptr&0x3C)>>2); result = result << 8; result = result | ((*ptr&0x03)<<6); ptr++; result = result | (*ptr&0x3F); } else if((*ptr&0xE0)==0xE0) { result = (*ptr&0x0F)<<4; ptr++;" >> $g_CTEMP
    echo "result = result | ((*ptr&0x3C)>>2); result = result << 8; result = result | ((*ptr&0x03)<<6); ptr++; result = result | (*ptr&0x3F); } else if((*ptr&0xC0)==0xC0) { result = (*ptr&0x1C)>>2; result = result << 8;" >> $g_CTEMP
    echo "result = result | ((*ptr&0x03)<<6); ptr++; result = result | (*ptr&0x3F); } else if((*ptr&0x80) == 0) { result = (*ptr&0x7F); } return (result); }" >> $g_CTEMP
    echo "unsigned char __b2c__isascii(const char *ptr) { long x; for(x=0; *(ptr+x); x++) { if(*(ptr+x)&128) return(0); } return(1); }" >> $g_CTEMP
    echo "unsigned char __b2c__isutf8(const char *ptr) { int result = 1; if (ptr == NULL) { return (0); } while (*ptr) { if ((*ptr & 0xF0) == 0xF0)" >> $g_CTEMP
    echo "{ if ((*(ptr + 1) & 0xC0) != 0x80 || (*(ptr + 2) & 0xc0) != 0x80 || (*(ptr + 3) & 0xc0) != 0x80 ) { result = 0; break; } ptr += 4; } else if ((*ptr & 0xE0) == 0xE0)" >> $g_CTEMP
    echo "{ if ((*(ptr + 1) & 0xc0) != 0x80 || (*(ptr + 2) & 0xc0) != 0x80 ) { result = 0; break; } ptr += 3; } else if ((*ptr & 0xC0) == 0xC0) { if ((*(ptr + 1) & 0xc0) != 0x80 )" >> $g_CTEMP
    echo "{ result = 0; break; } ptr += 2; } else if ((*ptr & 0x80) == 0) { ptr++; } else { result = 0; break; } } return (result); }" >> $g_CTEMP
    echo "char* __b2c__toascii(char *ptr) { int len, x; len = __b2c__len(ptr); for(x=0; x < len; x++) { *(ptr+x) = *(ptr+x)&0x7f; } return (ptr); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.chr.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.chr.o: bacon.chr.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.chr.c" >> $g_CTEMP

    g_CTEMP="$g_TEMPDIR/bacon.cmdline.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "int __b2c__getopt(int argc, char **argv, char* str){int opt; opterr = 0; opt = getopt(argc, argv, str); __b2c__STRFREE(ARGUMENT${g_STRINGSIGN});" >> $g_CTEMP
    echo "if(opt != -1) ARGUMENT${g_STRINGSIGN} = __b2c__strdup(optarg); else ARGUMENT${g_STRINGSIGN} = argv[optind]; return(opt);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.cmdline.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.cmdline.o: bacon.cmdline.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.cmdline.c"

    g_CTEMP="$g_TEMPDIR/bacon.concat.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__concat (char *first, ...) { long length = 0, cnew, idx; char *next; va_list ap; if(first != NULL && (length = __b2c__len(first)) > 0)" >> $g_CTEMP
    echo "{ idx = __sbuf_malloc_handle (length + 1); memmove (__b2c__sbuffer[idx], first, length + 1); }" >> $g_CTEMP
    echo "else { idx = __sbuf_malloc_handle(sizeof (char)); __b2c__sbuffer[idx][0] = '\0'; } va_start (ap, first);" >> $g_CTEMP
    echo "while ((next = va_arg (ap, char *)) != NULL) { cnew = __b2c__len(next); __sbuf_need_realloc (idx, length + cnew + 1);" >> $g_CTEMP
    echo "memmove(__b2c__sbuffer[idx] + length, next, cnew); length += cnew; } va_end (ap);" >> $g_CTEMP 
    echo "__b2c__SETLEN(__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.concat.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.concat.o: bacon.concat.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.concat.c"

    g_CTEMP="$g_TEMPDIR/bacon.count.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__count (int l, char *k, char *x, unsigned int y) { long i, z = 0; if (__b2c__option_utf8) { while (*x) { if (__b2c__utf8toasc (x) == y) { z++; } if ((*x & 0xF0) == 0xF0) { x += 4; }" >> $g_CTEMP
    echo "else if ((*x & 0xE0) == 0xE0) { x += 3; } else if ((*x & 0xC0) == 0xC0) { x += 2; } else if ((*x & 0x80) == 0) { x++; } else { ERROR = 38; RUNTIMEFERR (\"COUNT\", ERROR, k, l); } } } else " >> $g_CTEMP
    echo "{ for (i = 0; x[i] != '\0'; i++) { if (x[i] == y) { z++; } } } return z; }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.count.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.count.o: bacon.count.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.count.c"

    g_CTEMP="$g_TEMPDIR/bacon.curdir.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__curdir (void) { long idx; idx = __sbuf_malloc_handle (${g_BUFFER_SIZE}); __b2c__sbuffer[idx] = getcwd(__b2c__sbuffer[idx], ${g_BUFFER_SIZE});" >> $g_CTEMP
    echo "__b2c__SETLEN(__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); __b2c__sbuffer[idx][${g_BUFFER_SIZE}-1] = '\0'; return(char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.curdir.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.curdir.o: bacon.curdir.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.curdir.c"

    g_CTEMP="$g_TEMPDIR/bacon.datename.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char* __b2c__datename (time_t now, int which) { struct tm *ts; long idx; int len = 0; idx = __sbuf_malloc_handle (${g_MAX_DIGITS}); ts = localtime (&now);" >> $g_CTEMP
    echo "switch (which) { case 1: len = strftime (__b2c__sbuffer[idx], ${g_MAX_DIGITS}, \"%A\", ts); break; case 2: len = strftime (__b2c__sbuffer[idx], ${g_MAX_DIGITS}, \"%B\", ts); break; }" >> $g_CTEMP
    echo "__b2c__SETLEN(__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.datename.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.datename.o: bacon.datename.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.datename.c"

    g_CTEMP="$g_TEMPDIR/bacon.dec.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__hex2dec (int l, char *k, char *h, ...) { unsigned int i = 0; unsigned long j=0; long flag, len, x; va_list ap; va_start (ap, h); flag = va_arg (ap, int); va_end (ap);" >> $g_CTEMP
    echo "if(flag == 0) { if (sscanf (h, \"%X\", &i) == EOF && __b2c__trap) { ERROR = 5; RUNTIMEFERR (\"DEC\", ERROR, k, l); } j = i;} else { len = __b2c__len(h)-1;" >> $g_CTEMP
    echo "for(x=len; x>= 0; x--) { if(h[len-x] == 49){ j+=pow(2, x); } else if(h[len-x] != 48) { ERROR = 5; RUNTIMEFERR (\"DEC\", ERROR, k, l); } } } return(long)(j);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.dec.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.dec.o: bacon.dec.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.dec.c"

    g_CTEMP="$g_TEMPDIR/bacon.dirname.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "#ifndef PATH_MAX" >> $g_CTEMP
    echo "#define PATH_MAX 4096" >> $g_CTEMP
    echo "#endif" >> $g_CTEMP
    echo "char *__b2c__dirname(int l, char *k, int x, char *y, ...) {long idx, arg = 0, i; char *dup; va_list ap; if(y == NULL || __b2c__len(y) == 0){ return(EmptyString); } idx = __sbuf_malloc_handle (PATH_MAX * sizeof (char)); dup = strdup(y); switch(x) {case 0: if ((realpath(y, __b2c__sbuffer[idx])) == NULL)" >> $g_CTEMP
    echo "{ if (__b2c__trap) { ERROR = 26; RUNTIMEFERR(\"REALPATH$\", ERROR, k, l);} else strncpy (__b2c__sbuffer[idx], \"Error getting real path\", ${g_BUFFER_SIZE}); } break; case 1: va_start (ap, y); arg = va_arg (ap, int);" >> $g_CTEMP
    echo "va_end(ap); if(strncpy(__b2c__sbuffer[idx], basename(dup), PATH_MAX) == NULL) {if (__b2c__trap) { ERROR = 26; RUNTIMEFERR(\"BASENAME$\", ERROR, k, l); } else strncpy (__b2c__sbuffer[idx], \"Error getting basename\", ${g_BUFFER_SIZE});}" >> $g_CTEMP
    echo "break; case 2: if (strncpy(__b2c__sbuffer[idx], dirname(dup), PATH_MAX) == NULL) {if(__b2c__trap) { ERROR = 26; RUNTIMEFERR(\"DIRNAME$\", ERROR, k, l); } else strncpy (__b2c__sbuffer[idx], \"Error getting dirname\", ${g_BUFFER_SIZE}); " >> $g_CTEMP
    echo "} break;} free(dup); __b2c__SETLEN(__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); __b2c__sbuffer[idx][PATH_MAX - 1] = '\0'; if(arg && x==1){ for(i=__b2c__len(__b2c__sbuffer[idx]); i>=0; i--) { if(__b2c__sbuffer[idx][i]==46) break; }" >> $g_CTEMP
    echo "if(i >= 0){ if(arg == 1) {__b2c__sbuffer[idx][i] = '\0'; __b2c__SETLEN(__b2c__sbuffer[idx], i);} if(arg == 2){ i++; memmove(__b2c__sbuffer[idx], __b2c__sbuffer[idx]+i, __b2c__len(__b2c__sbuffer[idx])-i+1);" >> $g_CTEMP
    echo "__b2c__SETLEN(__b2c__sbuffer[idx], __b2c__len(__b2c__sbuffer[idx])-i);} } else if(arg == 2) {__b2c__sbuffer[idx][0] = '\0'; __b2c__SETLEN(__b2c__sbuffer[idx], 0);} } return (char *) (__b2c__sbuffer[idx]);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.dirname.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.dirname.o: bacon.dirname.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.dirname.c"

    g_CTEMP="$g_TEMPDIR/bacon.epoch.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "unsigned long __b2c__epoch(int year, int month, int day, int hour, int minute, int second){struct tm tm; time_t t; tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day;" >> $g_CTEMP
    echo "tm.tm_hour = hour; tm.tm_min = minute; tm.tm_sec = second; tm.tm_isdst = -1; t = mktime(&tm); if (t == -1) return (0); return(long) t; }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.epoch.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.epoch.o: bacon.epoch.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.epoch.c"

    g_CTEMP="$g_TEMPDIR/bacon.error.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char *ERR${g_STRINGSIGN}(int nr){" >> $g_CTEMP
    echo "switch(nr){" >> $g_CTEMP
    echo "case 0: strcpy(__b2c__warn, \"Success\"); break;" >> $g_CTEMP
    echo "case 1: strcpy(__b2c__warn, \"Trying to access illegal memory: \"); strncat(__b2c__warn,strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 2: strcpy(__b2c__warn, \"Error opening file: \"); strncat(__b2c__warn,strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 3: strcpy(__b2c__warn, \"Could not open library.\"); break;" >> $g_CTEMP
    echo "case 4: strcpy(__b2c__warn, \"Symbol not found in library.\"); break;" >> $g_CTEMP
    echo "case 5: strcpy(__b2c__warn, \"Wrong value: \"); strncat(__b2c__warn, strerror(errno), $g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 6: strcpy(__b2c__warn, \"Unable to claim memory.\"); break;" >> $g_CTEMP
    echo "case 7: strcpy(__b2c__warn, \"Unable to delete file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 8: strcpy(__b2c__warn, \"Could not open directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 9: strcpy(__b2c__warn, \"Unable to rename file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 10: strcpy(__b2c__warn, \"NETWORK argument should contain colon with port number\"); break;" >> $g_CTEMP
    echo "case 11: strcpy(__b2c__warn, \"Could not resolve hostname!\"); break;" >> $g_CTEMP
    echo "case 12: strcpy(__b2c__warn, \"Socket error: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 13: strcpy(__b2c__warn, \"Unable to open address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 14: strcpy(__b2c__warn, \"Error reading from socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 15: strcpy(__b2c__warn, \"Error sending to socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 16: strcpy(__b2c__warn, \"Error checking socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 17: strcpy(__b2c__warn, \"Unable to bind the specified socket address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 18: strcpy(__b2c__warn, \"Unable to listen to socket address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 19: strcpy(__b2c__warn, \"Cannot accept incoming connection: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 20: strcpy(__b2c__warn, \"Unable to remove directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 21: strcpy(__b2c__warn, \"Unable to create directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 22: strcpy(__b2c__warn, \"Unable to change to directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 23: strcpy(__b2c__warn, \"GETENVIRON argument does not exist as environment variable\"); break;" >> $g_CTEMP
    echo "case 24: strcpy(__b2c__warn, \"Unable to stat file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 25: strcpy(__b2c__warn, \"Search contains illegal string\"); break;" >> $g_CTEMP
    echo "case 26: strcpy(__b2c__warn, \"Cannot return name: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 27: strcpy(__b2c__warn, \"Illegal regex expression\"); break;" >> $g_CTEMP
    echo "case 28: strcpy(__b2c__warn, \"Unable to create bidirectional pipes: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 29: strcpy(__b2c__warn, \"Unable to fork process: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 30: strcpy(__b2c__warn, \"Cannot read from pipe: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 31: strcpy(__b2c__warn, \"Gosub nesting too deep!\"); break;" >> $g_CTEMP
    echo "case 32: strcpy(__b2c__warn, \"Could not open device: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 33: strcpy(__b2c__warn, \"Error configuring serial port: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 34: strcpy(__b2c__warn, \"Error accessing device: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 35: strcpy(__b2c__warn, \"Error in INPUT: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_CTEMP
    echo "case 36: strcpy(__b2c__warn, \"Illegal value in SORT dimension!\"); break;" >> $g_CTEMP
    echo "case 37: strcpy(__b2c__warn, \"Illegal option for SEARCH!\"); break;" >> $g_CTEMP
    echo "case 38: strcpy(__b2c__warn, \"Invalid UTF8 string!\"); break;" >> $g_CTEMP
    echo "case 39: strcpy(__b2c__warn, \"Illegal EVAL expression!\"); break;" >> $g_CTEMP
    echo "case 40: strcpy(__b2c__warn, \"SSL file descriptor error!\"); break;" >> $g_CTEMP
    echo "case 41: strcpy(__b2c__warn, \"SSL file descriptor pool exhausted!\"); break;" >> $g_CTEMP
    echo "}; ERROR = 0; return(__b2c__warn);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.error.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.error.o: bacon.error.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.error.c"

    g_CTEMP="$g_TEMPDIR/bacon.eval.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "/* TINYEXPR - Tiny recursive descent parser and evaluation engine in C - Copyright (c) 2015-2018 Lewis Van Winkle - ZLIB license - https://github.com/codeplea/tinyexpr */" >> $g_CTEMP
    echo "/* Code logic was not touched. Some cosmetic changes: (1) removed comments and whitespaces (2) added additional casting to allow compilation with g++ (PvE) */" >> $g_CTEMP
    echo -e "#ifndef NAN\n#define NAN (0.0/0.0)\n#endif\n#ifndef INFINITY\n#define INFINITY (1.0/0.0)\n#endif" >> $g_CTEMP
    echo "enum { TE_VARIABLE = 0, TE_FUNCTION0 = 8, TE_FUNCTION1, TE_FUNCTION2, TE_FUNCTION3, TE_FUNCTION4, TE_FUNCTION5, TE_FUNCTION6, TE_FUNCTION7," >> $g_CTEMP
    echo "TE_CLOSURE0 = 16, TE_CLOSURE1, TE_CLOSURE2, TE_CLOSURE3, TE_CLOSURE4, TE_CLOSURE5, TE_CLOSURE6, TE_CLOSURE7, TE_FLAG_PURE = 32 };" >> $g_CTEMP
    echo "typedef double (*te_fun2)(double, double); enum { TOK_NULL = TE_CLOSURE7+1, TOK_ERROR, TOK_END, TOK_SEP, TOK_OPEN, TOK_CLOSE, TOK_NUMBER, TOK_VARIABLE, TOK_INFIX };" >> $g_CTEMP
    echo "enum {TE_CONSTANT = 1}; typedef struct state { const char *start; const char *next; int type; union {double value; const double *bound; const void *function;}; void *context;" >> $g_CTEMP
    echo -e "const __b2c_te_variable *lookup; int lookup_len; } state;\n#define TYPE_MASK(TYPE) ((TYPE)&0x0000001F)\n#define IS_PURE(TYPE) (((TYPE) & TE_FLAG_PURE) != 0)" >> $g_CTEMP
    echo -e "#define IS_FUNCTION(TYPE) (((TYPE) & TE_FUNCTION0) != 0)\n#define IS_CLOSURE(TYPE) (((TYPE) & TE_CLOSURE0) != 0)" >> $g_CTEMP
    echo -e "#define ARITY(TYPE) ( ((TYPE) & (TE_FUNCTION0 | TE_CLOSURE0)) ? ((TYPE) & 0x00000007) : 0)\n#define NEW_EXPR(type, ...) new_expr((type), (const __b2c_te_expr**)(const __b2c_te_expr*[]){__VA_ARGS__})" >> $g_CTEMP
    echo "static __b2c_te_expr *new_expr(const int type, const __b2c_te_expr *parameters[]) { const int arity = ARITY(type); const int psize = sizeof(void*) * arity;" >> $g_CTEMP
    echo "const int size = (sizeof(__b2c_te_expr) - sizeof(void*)) + psize + (IS_CLOSURE(type) ? sizeof(void*) : 0); __b2c_te_expr *ret = (__b2c_te_expr*)malloc(size); memset(ret, 0, size); if (arity && parameters)" >> $g_CTEMP
    echo "{ memcpy(ret->parameters, parameters, psize); } ret->type = type; ret->bound = 0; return ret; }" >> $g_CTEMP
    echo "void __b2c_te_free_parameters(__b2c_te_expr *n) { if (!n) return; switch (TYPE_MASK(n->type)) { case TE_FUNCTION7: case TE_CLOSURE7: __b2c_te_free((__b2c_te_expr*)n->parameters[6]);" >> $g_CTEMP
    echo "case TE_FUNCTION6: case TE_CLOSURE6: __b2c_te_free((__b2c_te_expr*)n->parameters[5]); case TE_FUNCTION5: case TE_CLOSURE5: __b2c_te_free((__b2c_te_expr*)n->parameters[4]);" >> $g_CTEMP
    echo "case TE_FUNCTION4: case TE_CLOSURE4: __b2c_te_free((__b2c_te_expr*)n->parameters[3]); case TE_FUNCTION3: case TE_CLOSURE3: __b2c_te_free((__b2c_te_expr*)n->parameters[2]);" >> $g_CTEMP
    echo "case TE_FUNCTION2: case TE_CLOSURE2: __b2c_te_free((__b2c_te_expr*)n->parameters[1]); case TE_FUNCTION1: case TE_CLOSURE1: __b2c_te_free((__b2c_te_expr*)n->parameters[0]); } }" >> $g_CTEMP
    echo "void __b2c_te_free(__b2c_te_expr *n) { if (!n) return; __b2c_te_free_parameters(n); free(n); } static double pi(void) {return 3.14159265358979323846;}" >> $g_CTEMP
    echo "static double e(void) {return 2.71828182845904523536;} static double fac(double a) { if (a < 0.0) return NAN; if (a > UINT_MAX) return INFINITY;" >> $g_CTEMP
    echo "unsigned int ua = (unsigned int)(a); unsigned long int result = 1, i; for (i = 1; i <= ua; i++) { if (i > ULONG_MAX / result) return INFINITY; result *= i; } return (double)result; }" >> $g_CTEMP
    echo "static double ncr(double n, double r) { if (n < 0.0 || r < 0.0 || n < r) return NAN; if (n > UINT_MAX || r > UINT_MAX) return INFINITY; unsigned long int un = (unsigned int)(n), ur = (unsigned int)(r), i;" >> $g_CTEMP
    echo "unsigned long int result = 1; if (ur > un / 2) ur = un - ur; for (i = 1; i <= ur; i++) { if (result > ULONG_MAX / (un - ur + i)) return INFINITY; result *= un - ur + i; result /= i; } return result; }" >> $g_CTEMP
    echo "static double npr(double n, double r) {return ncr(n, r) * fac(r);} static const __b2c_te_variable functions[] = { {\"abs\", (const void*)(double(*)(double))fabs, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {\"acos\", (const void*)(double(*)(double))acos, TE_FUNCTION1 | TE_FLAG_PURE, 0}," >> $g_CTEMP
    echo "{\"asin\", (const void*)(double(*)(double))asin, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {\"atan\", (const void*)(double(*)(double))atan, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {\"atan2\", (const void*)(double(*)(double,double))atan2, TE_FUNCTION2 | TE_FLAG_PURE, 0}, {\"ceil\", (const void*)(double(*)(double))ceil, TE_FUNCTION1 | TE_FLAG_PURE, 0}," >> $g_CTEMP
    echo "{\"cos\", (const void*)(double(*)(double))cos, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {\"cosh\", (const void*)(double(*)(double))cosh, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {\"e\", (const void*)e, TE_FUNCTION0 | TE_FLAG_PURE, 0}, {\"exp\", (const void*)(double(*)(double))exp, TE_FUNCTION1 | TE_FLAG_PURE, 0}," >> $g_CTEMP
    echo -e "{\"fac\", (const void*)fac, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {\"floor\", (const void*)(double(*)(double))floor, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {\"ln\", (const void*)(double(*)(double))log, TE_FUNCTION1 | TE_FLAG_PURE, 0},\n#ifdef TE_NAT_LOG" >> $g_CTEMP
    echo -e "{\"log\", (const void*)(double(*)(double))log, TE_FUNCTION1 | TE_FLAG_PURE, 0},\n#else\n{\"log\", (const void*)(double(*)(double))log10, TE_FUNCTION1 | TE_FLAG_PURE, 0},\n#endif\n {\"log10\", (const void*)(double(*)(double))log10,  TE_FUNCTION1 | TE_FLAG_PURE, 0}," >> $g_CTEMP
    echo "{\"ncr\", (const void*)ncr, TE_FUNCTION2 | TE_FLAG_PURE, 0}, {\"npr\", (const void*)npr, TE_FUNCTION2 | TE_FLAG_PURE, 0}, {\"pi\", (const void*)pi, TE_FUNCTION0 | TE_FLAG_PURE, 0}, {\"pow\", (const void*)(double(*)(double,double))pow, TE_FUNCTION2 | TE_FLAG_PURE, 0}," >> $g_CTEMP
    echo "{\"sin\", (const void*)(double(*)(double))sin, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {\"sinh\", (const void*)(double(*)(double))sinh, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {\"sqrt\", (const void*)(double(*)(double))sqrt, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {\"tan\", (const void*)(double(*)(double))tan, TE_FUNCTION1 | TE_FLAG_PURE, 0}," >> $g_CTEMP
    echo "{\"tanh\", (const void*)(double(*)(double))tanh, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {0, 0, 0, 0} }; static const __b2c_te_variable *find_builtin(const char *name, int len) { int imin = 0; int imax = sizeof(functions) / sizeof(__b2c_te_variable) - 2;" >> $g_CTEMP
    echo "while (imax >= imin) { const int i = (imin + ((imax-imin)/2)); int c = strncmp(name, functions[i].name, len); if (!c) c = '\0' - functions[i].name[len]; if (c == 0) { return functions + i; } else if (c > 0)" >> $g_CTEMP
    echo "{ imin = i + 1; } else { imax = i - 1; } } return 0; } static const __b2c_te_variable *find_lookup(const state *s, const char *name, int len) { int iters; const __b2c_te_variable *var; if (!s->lookup) return 0;" >> $g_CTEMP
    echo "for (var = s->lookup, iters = s->lookup_len; iters; ++var, --iters) { if (strncmp(name, var->name, len) == 0 && var->name[len] == '\0') { return var; } } return 0; }" >> $g_CTEMP
    echo "static double add(double a, double b) {return a + b;} static double sub(double a, double b) {return a - b;} static double mul(double a, double b) {return a * b;}" >> $g_CTEMP
    echo "static double divide(double a, double b) {return a / b;} static double negate(double a) {return -a;} static double comma(double a, double b) {(void)a; return b;}" >> $g_CTEMP
    echo "void next_token(state *s) { s->type = TOK_NULL; do { if (!*s->next){ s->type = TOK_END; return; } if ((s->next[0] >= '0' && s->next[0] <= '9') || s->next[0] == '.') { s->value = strtod(s->next, (char**)&s->next);" >> $g_CTEMP
    echo "s->type = TOK_NUMBER; } else { if (s->next[0] >= 'a' && s->next[0] <= 'z') { const char *start; start = s->next;" >> $g_CTEMP
    echo "while ((s->next[0] >= 'a' && s->next[0] <= 'z') || (s->next[0] >= '0' && s->next[0] <= '9') || (s->next[0] == '_')) s->next++; const __b2c_te_variable *var = find_lookup(s, start, s->next - start); if (!var) var = find_builtin(start, s->next - start);" >> $g_CTEMP
    echo "if (!var) { s->type = TOK_ERROR; } else { switch(TYPE_MASK(var->type)) { case TE_VARIABLE: s->type = TOK_VARIABLE; s->bound = (const double*)var->address; break;" >> $g_CTEMP
    echo "case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3: case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: s->context = var->context;" >> $g_CTEMP
    echo "case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3: case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: s->type = var->type; s->function = var->address; break; } } }" >> $g_CTEMP
    echo "else { switch (s->next++[0]) { case '+': s->type = TOK_INFIX; s->function = (const void*)add; break; case '-': s->type = TOK_INFIX; s->function = (const void*)sub; break;" >> $g_CTEMP
    echo "case '*': s->type = TOK_INFIX; s->function = (const void*)mul; break; case '/': s->type = TOK_INFIX; s->function = (const void*)divide; break; case '^': s->type = TOK_INFIX; s->function = (const void*)(double(*)(double,double))pow; break; case '%': s->type = TOK_INFIX; s->function = (const void*)(double(*)(double,double))fmod; break;" >> $g_CTEMP
    echo "case '(': s->type = TOK_OPEN; break; case ')': s->type = TOK_CLOSE; break; case ',': s->type = TOK_SEP; break; case ' ': case '\t': case '\n': case '\r': break; default: s->type = TOK_ERROR; break; } } } } while (s->type == TOK_NULL); }" >> $g_CTEMP
    echo "static __b2c_te_expr *list(state *s); static __b2c_te_expr *expr(state *s); static __b2c_te_expr *power(state *s); static __b2c_te_expr *base(state *s) { __b2c_te_expr *ret; int arity;" >> $g_CTEMP
    echo "switch (TYPE_MASK(s->type)) { case TOK_NUMBER: ret = new_expr(TE_CONSTANT, 0); ret->value = s->value; next_token(s); break; case TOK_VARIABLE: ret = new_expr(TE_VARIABLE, 0); ret->bound = s->bound; next_token(s); break;" >> $g_CTEMP
    echo "case TE_FUNCTION0: case TE_CLOSURE0: ret = new_expr(s->type, 0); ret->function = s->function; if (IS_CLOSURE(s->type)) ret->parameters[0] = s->context; next_token(s); if (s->type == TOK_OPEN) { next_token(s);" >> $g_CTEMP
    echo "if (s->type != TOK_CLOSE) { s->type = TOK_ERROR; } else { next_token(s); } } break; case TE_FUNCTION1: case TE_CLOSURE1: ret = new_expr(s->type, 0); ret->function = s->function; if (IS_CLOSURE(s->type)) ret->parameters[1] = s->context;" >> $g_CTEMP
    echo "next_token(s); ret->parameters[0] = power(s); break; case TE_FUNCTION2: case TE_FUNCTION3: case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: case TE_CLOSURE2: case TE_CLOSURE3: case TE_CLOSURE4:" >> $g_CTEMP
    echo "case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: arity = ARITY(s->type); ret = new_expr(s->type, 0); ret->function = s->function; if (IS_CLOSURE(s->type)) ret->parameters[arity] = s->context; next_token(s);" >> $g_CTEMP
    echo "if (s->type != TOK_OPEN) { s->type = TOK_ERROR; } else { int i; for(i = 0; i < arity; i++) { next_token(s); ret->parameters[i] = expr(s); if(s->type != TOK_SEP) { break; } }" >> $g_CTEMP
    echo "if(s->type != TOK_CLOSE || i != arity - 1) { s->type = TOK_ERROR; } else { next_token(s); } } break; case TOK_OPEN: next_token(s); ret = list(s); if (s->type != TOK_CLOSE) { s->type = TOK_ERROR; } else { next_token(s); } break;" >> $g_CTEMP
    echo "default: ret = new_expr(0, 0); s->type = TOK_ERROR; ret->value = NAN; break; } return ret; } static __b2c_te_expr *power(state *s) { int sign = 1; while (s->type == TOK_INFIX && (s->function == add || s->function == sub))" >> $g_CTEMP
    echo "{ if (s->function == sub) sign = -sign; next_token(s); } __b2c_te_expr *ret; if (sign == 1) { ret = base(s); } else { ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, (const __b2c_te_expr*)base(s)); ret->function = (const void*)negate; } return ret; }" >> $g_CTEMP
    echo -e "\n#ifdef TE_POW_FROM_RIGHT\n static __b2c_te_expr *factor(state *s) { __b2c_te_expr *ret = power(s); int neg = 0; __b2c_te_expr *insertion = 0; if (ret->type == (TE_FUNCTION1 | TE_FLAG_PURE) && ret->function == negate)" >> $g_CTEMP
    echo "{ __b2c_te_expr *se = ret->parameters[0]; free(ret); ret = se; neg = 1; } while (s->type == TOK_INFIX && (s->function == pow)) { te_fun2 t = (te_fun2)s->function; next_token(s); if (insertion)" >> $g_CTEMP
    echo "{ __b2c_te_expr *insert = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, insertion->parameters[1], power(s)); insert->function = t; insertion->parameters[1] = insert; insertion = insert; } else " >> $g_CTEMP
    echo "{ ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s)); ret->function = t; insertion = ret; } } if (neg) { ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, ret); ret->function = negate; } return ret; }" >> $g_CTEMP
    echo -e "\n#else\n static __b2c_te_expr *factor(state *s) { __b2c_te_expr *ret = power(s); while (s->type == TOK_INFIX && (s->function == (double(*)(double,double))pow)) { te_fun2 t = (te_fun2)s->function; next_token(s); ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s)); ret->function = (const void*)t; } return ret; }\n#endif\n" >> $g_CTEMP
    echo "static __b2c_te_expr *term(state *s) { __b2c_te_expr *ret = factor(s); while (s->type == TOK_INFIX && (s->function == mul || s->function == divide || s->function == (double(*)(double,double))fmod)) { te_fun2 t = (te_fun2)s->function; next_token(s);" >> $g_CTEMP
    echo "ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, factor(s)); ret->function = (const void*)t; } return ret; } static __b2c_te_expr *expr(state *s) { __b2c_te_expr *ret = term(s); while (s->type == TOK_INFIX && (s->function == add || s->function == sub))" >> $g_CTEMP
    echo "{ te_fun2 t = (te_fun2)s->function; next_token(s); ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, term(s)); ret->function = (const void*)t; } return ret; } static __b2c_te_expr *list(state *s) { __b2c_te_expr *ret = expr(s);" >> $g_CTEMP
    echo "while (s->type == TOK_SEP) { next_token(s); ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, expr(s)); ret->function = (const void*)comma; } return ret; }" >> $g_CTEMP
    echo -e "\n#define TE_FUN(...) ((double(*)(__VA_ARGS__))n->function)\n#define M(e) __b2c_te_eval((const __b2c_te_expr*)n->parameters[e])\n" >> $g_CTEMP
    echo "double __b2c_te_eval(const __b2c_te_expr *n) { if (!n) return NAN; switch(TYPE_MASK(n->type)) { case TE_CONSTANT: return n->value; case TE_VARIABLE: return *n->bound; case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3:" >> $g_CTEMP
    echo "case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: switch(ARITY(n->type)) { case 0: return TE_FUN(void)(); case 1: return TE_FUN(double)(M(0)); case 2: return TE_FUN(double, double)(M(0), M(1));" >> $g_CTEMP
    echo "case 3: return TE_FUN(double, double, double)(M(0), M(1), M(2)); case 4: return TE_FUN(double, double, double, double)(M(0), M(1), M(2), M(3)); case 5: return TE_FUN(double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4));" >> $g_CTEMP
    echo "case 6: return TE_FUN(double, double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4), M(5)); case 7: return TE_FUN(double, double, double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4), M(5), M(6)); default: return NAN; }" >> $g_CTEMP
    echo "case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3: case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: switch(ARITY(n->type)) { case 0: return TE_FUN(void*)(n->parameters[0]);" >> $g_CTEMP
    echo "case 1: return TE_FUN(void*, double)(n->parameters[1], M(0)); case 2: return TE_FUN(void*, double, double)(n->parameters[2], M(0), M(1)); case 3: return TE_FUN(void*, double, double, double)(n->parameters[3], M(0), M(1), M(2));" >> $g_CTEMP
    echo "case 4: return TE_FUN(void*, double, double, double, double)(n->parameters[4], M(0), M(1), M(2), M(3)); case 5: return TE_FUN(void*, double, double, double, double, double)(n->parameters[5], M(0), M(1), M(2), M(3), M(4));" >> $g_CTEMP
    echo "case 6: return TE_FUN(void*, double, double, double, double, double, double)(n->parameters[6], M(0), M(1), M(2), M(3), M(4), M(5)); case 7: return TE_FUN(void*, double, double, double, double, double, double, double)(n->parameters[7], M(0), M(1), M(2), M(3), M(4), M(5), M(6));" >> $g_CTEMP
    echo -e "default: return NAN; } default: return NAN; } }\n#undef TE_FUN\n#undef M\n" >> $g_CTEMP
    echo "static void optimize(__b2c_te_expr *n) { if (n->type == TE_CONSTANT) return; if (n->type == TE_VARIABLE) return; if (IS_PURE(n->type)) { const int arity = ARITY(n->type); int known = 1; int i; for (i = 0; i < arity; ++i) { optimize((__b2c_te_expr*)n->parameters[i]);" >> $g_CTEMP
    echo "if (((__b2c_te_expr*)(n->parameters[i]))->type != TE_CONSTANT) { known = 0; } } if (known) { const double value = __b2c_te_eval(n); __b2c_te_free_parameters(n); n->type = TE_CONSTANT; n->value = value; } } }" >> $g_CTEMP
    echo "__b2c_te_expr *te_compile(const char *expression, const __b2c_te_variable *variables, int var_count, int *error) { state s; s.start = s.next = expression; s.lookup = variables; s.lookup_len = var_count; next_token(&s); __b2c_te_expr *root = list(&s);" >> $g_CTEMP
    echo "if (s.type != TOK_END) { __b2c_te_free(root); if (error) { *error = (s.next - s.start); if (*error == 0) *error = 1; } return 0; } else { optimize(root); if (error) *error = 0; return root; } }" >> $g_CTEMP
    echo "double __b2c_te_interp(const char *expression, int *error) { __b2c_te_expr *n = te_compile(expression, 0, 0, error); double ret; if (n) { ret = __b2c_te_eval(n); __b2c_te_free(n); } else { ret = NAN; } return ret; }" >> $g_CTEMP
    echo "static void pn (const __b2c_te_expr *n, int depth) { int i, arity; printf(\"%*s\", depth, \"\"); switch(TYPE_MASK(n->type)) { case TE_CONSTANT: printf(\"%f\n\", n->value); break; case TE_VARIABLE: printf(\"bound %p\n\", n->bound); break;" >> $g_CTEMP
    echo "case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3: case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3:" >> $g_CTEMP
    echo "case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: arity = ARITY(n->type); printf(\"f%d\", arity); for(i = 0; i < arity; i++) { printf(\" %p\", n->parameters[i]); } printf(\"\n\"); for(i = 0; i < arity; i++)" >> $g_CTEMP
    echo "{ pn((const __b2c_te_expr*)n->parameters[i], depth + 1); } break; } } void __b2c_te_print(const __b2c_te_expr *n) { pn(n, 0); }" >> $g_CTEMP
    echo "double __b2c__eval(int l, char *k, __b2c_te_variable *x, int y, char *z) { int err; __b2c_te_expr *expr; double result = 0; if (z == NULL) return (0); expr = te_compile(z, x, y, &err);" >> $g_CTEMP
    echo "if (expr) { result = __b2c_te_eval(expr); __b2c_te_free(expr); } else if (__b2c__trap) { ERROR = 39; fprintf (stderr, \"Position %d in EVAL argument %s\n\", err, z); RUNTIMEFERR(\"EVAL\", ERROR, k, l); } return(result); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.eval.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.eval.o: bacon.eval.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.eval.c"

    g_CTEMP="$g_TEMPDIR/bacon.exec.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "static char ** Get_Args (char *line) { char **ptr = NULL; char *arg; int in_string = 0, x = 0; arg = line; while (*line != '\0') { switch (*line) { case 34: in_string = 1 - in_string; line++; break;" >> $g_CTEMP
    echo "case 32: if (!in_string) { ptr = (char **) realloc (ptr, (x + 1) * sizeof (char *)); if(*arg == 34) arg++; if(*(line-1) == 34) line--; ptr[x] = __b2c__strndup(arg, line-arg); while (isspace (*line) && *line != '\0'){ line++; } arg = line; x++; }" >> $g_CTEMP
    echo "else {line++;} break; default: line++; } } ptr = (char **) realloc (ptr, (x + 2) * sizeof (char *)); if(*arg == 34) arg++; if(*(line-1) == 34) line--; ptr[x] = __b2c__strndup(arg, line - arg); ptr[x+1] = NULL; return (ptr); }" >> $g_CTEMP
    echo "char * __b2c__exec(int t, int l, char *k, char *cmd, ...) { int forking, length, dnull, out = 0; ssize_t result = 0; int wpipe[2], rpipe[2]; char **args; char *str, *ans = NULL; long idx; va_list ap; va_start (ap, cmd); str = va_arg (ap, char*); out = va_arg (ap, int); va_end (ap);" >> $g_CTEMP
    echo "idx = __sbuf_malloc_handle (sizeof (char)); if (pipe (rpipe) < 0 || pipe (wpipe) < 0) { if (__b2c__trap) { ERROR = 29; RUNTIMEFERR(\"EXEC$\", ERROR, k, l); } } if ((forking = fork ()) < 0) { if (__b2c__trap) { ERROR = 29; RUNTIMEFERR(\"EXEC$\", ERROR, k, l); } }" >> $g_CTEMP
    echo "else if (forking == 0) { fflush(stdout); close (wpipe[1]); close (rpipe[0]); dup2 (wpipe[0], STDIN_FILENO); close (wpipe[0]);	dnull = open(\"/dev/null\", O_RDWR); if(out == 1) { dup2 (rpipe[1], STDOUT_FILENO); dup2(dnull, STDERR_FILENO); } else if (out == 2) { dup2(dnull, STDOUT_FILENO);" >> $g_CTEMP
    echo "dup2(rpipe[1], STDERR_FILENO); } else { dup2(rpipe[1], STDOUT_FILENO); dup2(rpipe[1], STDERR_FILENO); } close (rpipe[1]); if(t == 0) { forking = system (cmd); if (WIFEXITED (forking)) result = WEXITSTATUS (forking); }" >> $g_CTEMP
    echo "else { args = Get_Args(cmd); if(execvp(args[0], args) < 0 ) { if (__b2c__trap) { ERROR = 29; RUNTIMEFERR (\"EXEC$\", ERROR, k, l); } } } close(dnull); _exit(result); } else { close (wpipe[0]); close (rpipe[1]); ans = (char*)malloc(${g_BUFFER_SIZE});" >> $g_CTEMP
    echo "length = 0; if (str != NULL) result = write (wpipe[1], str, __b2c__len(str)); close (wpipe[1]); do { result = read (rpipe[0], ans, ${g_BUFFER_SIZE}); if (result == -1 && __b2c__trap) { ERROR = 30; RUNTIMEFERR(\"EXEC$\", ERROR, k, l);}" >> $g_CTEMP
    echo "if (result == 0) break; __sbuf_need_realloc(idx, length + result + 1); if (__b2c__sbuffer[idx] == NULL && __b2c__trap) { ERROR = 6; RUNTIMEFERR(\"EXEC$\", ERROR, k, l); }" >> $g_CTEMP
    echo "memcpy(__b2c__sbuffer[idx] + length, ans, (size_t)abs(result)); length += result; } while (result > 0); __b2c__SETLEN(__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\0';" >> $g_CTEMP
    echo "close (rpipe[0]); free (ans); wait (&RETVAL); RETVAL = WEXITSTATUS (RETVAL); } return (char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.exec.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.exec.o: bacon.exec.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.exec.c"

    g_CTEMP="$g_TEMPDIR/bacon.filelen.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__filelen(int l, char *k, const char *x) {struct stat buf; if(stat(x, &buf) < 0 && __b2c__trap){ERROR = 24; RUNTIMEFERR(\"FILELEN\", ERROR, k, l);}" >> $g_CTEMP
    echo "if(x == NULL || stat(x, &buf) < 0) return -1; else return(long)(buf.st_size);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.filelen.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.filelen.o: bacon.filelen.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.filelen.c"

    g_CTEMP="$g_TEMPDIR/bacon.filetime.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__filetime(int l, char *k, const char *x, int y) {struct stat buf; if(stat(x, &buf) < 0 && __b2c__trap){ERROR = 24; RUNTIMEFERR(\"FILETIME\", ERROR, k, l);}" >> $g_CTEMP
    echo "if(x == NULL || stat(x, &buf) < 0 || y < 0 || y > 2) return -1; switch(y) {case 0: return(long)(buf.st_atime); break;" >> $g_CTEMP
    echo "case 1: return(long)(buf.st_mtime); break;} return(long)(buf.st_ctime);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.filetime.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.filetime.o: bacon.filetime.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.filetime.c"

    g_CTEMP="$g_TEMPDIR/bacon.filetype.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__filetype(int l, char *k, const char *x) {long fs = 0; struct stat buf; if(x == NULL) return 0; if(lstat(x, &buf) < 0 && __b2c__trap)" >> $g_CTEMP
    echo "{ERROR = 24; RUNTIMEFERR(\"FILETYPE\", ERROR, k, l);} if (S_ISREG(buf.st_mode)) fs = 1; if (S_ISDIR(buf.st_mode)) fs = 2;" >> $g_CTEMP
    echo "if (S_ISCHR(buf.st_mode)) fs = 3; if (S_ISBLK(buf.st_mode)) fs = 4; if (S_ISFIFO(buf.st_mode)) fs = 5;" >> $g_CTEMP
    echo "if (S_ISLNK(buf.st_mode)) fs = 6; if (S_ISSOCK(buf.st_mode)) fs = 7; return(fs);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.filetype.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.filetype.o: bacon.filetype.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.filetype.c"

    g_CTEMP="$g_TEMPDIR/bacon.fill.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__fill (unsigned long amount, unsigned int txt) { long idx; char buf[5]; int x, len; if (__b2c__option_utf8) { len = __b2c_utf8_conv (txt, buf); idx = __sbuf_malloc_handle (amount * len + 1);" >> $g_CTEMP
    echo "for (x = 0; x < (amount * len); x += len) { memcpy (__b2c__sbuffer[idx] + x, buf, len); } __b2c__SETLEN (__b2c__sbuffer[idx], amount * len); __b2c__sbuffer[idx][amount * len] = '\\0'; } else" >> $g_CTEMP
    echo "{ idx = __sbuf_malloc_handle (amount + 1); memset (__b2c__sbuffer[idx], txt, amount); __b2c__SETLEN (__b2c__sbuffer[idx], amount); __b2c__sbuffer[idx][amount] = '\\0'; } return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.fill.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.fill.o: bacon.fill.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.fill.c"

    g_CTEMP="$g_TEMPDIR/bacon.flatten.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char *__b2c__flatten(char *src, ...) { char quote[] = { 34, 0 }; long len, x, pos=0, escaped=0, idx; char *meta; va_list ap; if(src == NULL) return(src);" >> $g_CTEMP
    echo "va_start (ap, src); meta = va_arg (ap, char *); va_end (ap); if (meta == NULL) { meta = quote; } len = __b2c__len(src); idx = __sbuf_malloc_handle(len + 1);" >> $g_CTEMP
    echo "memmove(__b2c__sbuffer[idx], src, len); __b2c__sbuffer[idx][len] = '\0'; for(x = 0; src[x] != 0; x++) { if(src[x] == meta[0]) { if(!escaped) { memmove(__b2c__sbuffer[idx]+pos, src+x+1, len-x-1); }" >> $g_CTEMP
    echo "else { pos++; escaped = 0; } } else { switch(src[x]) { case 92: if(!escaped) { memmove(__b2c__sbuffer[idx]+pos, src+x+1, len-x-1); escaped = 1; } else {pos++;} break;" >> $g_CTEMP
    echo "default: pos++; escaped = 0; } } } __b2c__SETLEN (__b2c__sbuffer[idx], pos); __b2c__sbuffer[idx][pos] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char * __b2c__unflatten (char *src, ...) { char quote[] = { 34, 0 }; long x, pos = 1, idx; char *meta; va_list ap; if (src == NULL) return (src); va_start (ap, src);" >> $g_CTEMP
    echo "meta = va_arg (ap, char *); va_end (ap); if (meta == NULL) { meta = quote; } idx = __sbuf_malloc_handle (2*__b2c__len (src) + 1); __b2c__sbuffer[idx][0] = meta[0];" >> $g_CTEMP
    echo "for (x = 0; src[x] != 0; x++) { if (src[x] == meta[0]) { __b2c__sbuffer[idx][pos++] = 92; __b2c__sbuffer[idx][pos++] = src[x]; }" >> $g_CTEMP
    echo "else {__b2c__sbuffer[idx][pos++] = src[x];} } __b2c__sbuffer[idx][pos++] = meta[0]; __b2c__SETLEN (__b2c__sbuffer[idx], pos);" >> $g_CTEMP
    echo "__b2c__sbuffer[idx][pos] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.flatten.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.flatten.o: bacon.flatten.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.flatten.c"

    g_CTEMP="$g_TEMPDIR/bacon.getenviron.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__getenv (char *env) {char *tmp; long idx; idx = __sbuf_malloc_handle (${g_BUFFER_SIZE} * sizeof (char)); tmp = getenv(env); if (tmp == NULL) { return (EmptyString); }" >> $g_CTEMP
    echo "else { strncpy (__b2c__sbuffer[idx], tmp, ${g_BUFFER_SIZE}); } __b2c__SETLEN (__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); __b2c__sbuffer[idx][$g_BUFFER_SIZE - 1] = '\0'; return (char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.getenviron.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.getenviron.o: bacon.getenviron.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.getenviron.c"

    g_CTEMP="$g_TEMPDIR/bacon.getkey.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__getch(){long ch; struct termios oldt, newt; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); newt.c_cc[VMIN]=1;" >> $g_CTEMP
    echo "newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &newt); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); return(ch);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.getkey.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.getkey.o: bacon.getkey.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.getkey.c"

    if [[ `uname` = "OSF1" ]]
    then
        LEN="int"
    else
        LEN="unsigned int"
    fi
    g_CTEMP="$g_TEMPDIR/bacon.getpeer.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__getpeer(int l, char *k, int remote) { struct sockaddr_in *peer; ${LEN} length = sizeof (peer); char port[6]; long idx; idx = __sbuf_malloc_handle (${g_BUFFER_SIZE} * sizeof (char)); peer = (struct sockaddr_in*)calloc (1, sizeof (*peer));" >> $g_CTEMP
    echo "if (getpeername (remote, (struct sockaddr *) peer, &length) < 0) { if (__b2c__trap) { ERROR = 16; RUNTIMEFERR(\"GETPEER$\", ERROR, k, l); } else strncpy (__b2c__sbuffer[idx], \"Peer not found\", ${g_BUFFER_SIZE}); }" >> $g_CTEMP
    echo "else { strncpy (__b2c__sbuffer[idx], inet_ntoa (peer->sin_addr),  ${g_BUFFER_SIZE} - 7); strcat (__b2c__sbuffer[idx], \":\"); snprintf (port, 6, \"%d\", ntohs (peer->sin_port)); strcat (__b2c__sbuffer[idx], port); }" >> $g_CTEMP
    echo "free (peer); __b2c__SETLEN (__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); __b2c__sbuffer[idx][ ${g_BUFFER_SIZE} - 1] = '\0'; return (char*)(__b2c__sbuffer[idx]);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.getpeer.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.getpeer.o: bacon.getpeer.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.getpeer.c"

    g_CTEMP="$g_TEMPDIR/bacon.getxy.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__getxy(int type){char asw[$g_BUFFER_SIZE]; struct termios old, cnew; int len, x = 0, y = 0; tcgetattr(STDIN_FILENO, &old); cnew = old; cnew.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &cnew);" >> $g_CTEMP
    echo "if(write(STDOUT_FILENO, \"\033[6n\", 4)>=0){len = read(STDIN_FILENO, asw, $g_BUFFER_SIZE); asw[len] = '\0'; tcsetattr(STDIN_FILENO, TCSANOW, &old); sscanf(asw, \"\033[%d;%dR\", &y, &x);} if (!type) return(long)x; return(long)y;}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.getxy.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.getxy.o: bacon.getxy.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.getxy.c"

    g_CTEMP="$g_TEMPDIR/bacon.hash.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "/* Using the MIT licensed HASH table implementation from Mattias Gustavsson at https://github.com/mattiasgustavsson/libs. Slightly modified so it allows a key check in case of collisions (linear probing). PvE. */" >> $g_CTEMP
    echo "HASHTABLE_U64 __b2c__HashFNV1a(const char *key){ uint64_t hash = 14695981039346656037UL; if(key==NULL) { return(0); } while(*key) {hash = 1099511628211 * (hash ^ *key); key++; } return(hash); }" >> $g_CTEMP
    echo "static HASHTABLE_U32 hashtable_internal_pow2ceil( HASHTABLE_U32 v ) { --v; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; ++v; v += ( v == 0 ); return v; }" >> $g_CTEMP
    echo "void __b2c__hashtable_init( __b2c__hashtable_t* table, int item_size, int initial_capacity, void* memctx ) { initial_capacity = (int)hashtable_internal_pow2ceil( initial_capacity >=0 ? (HASHTABLE_U32) initial_capacity : 32U ); table->memctx = memctx; table->count = 0;" >> $g_CTEMP
    echo "table->item_size = item_size; table->slot_capacity = (int) hashtable_internal_pow2ceil( (HASHTABLE_U32) ( initial_capacity + initial_capacity / 2 ) ); int slots_size = (int)( table->slot_capacity * sizeof( *table->slots ) );" >> $g_CTEMP
    echo "table->slots = (struct __b2c__hashtable_internal_slot_t*) HASHTABLE_MALLOC( table->memctx, (HASHTABLE_SIZE_T) slots_size ); HASHTABLE_ASSERT( table->slots ); HASHTABLE_MEMSET( table->slots, 0, (HASHTABLE_SIZE_T) slots_size ); table->item_capacity = (int) hashtable_internal_pow2ceil( (HASHTABLE_U32) initial_capacity );" >> $g_CTEMP
    echo "table->items_key = (HASHTABLE_U64*) HASHTABLE_MALLOC( table->memctx, table->item_capacity * ( sizeof( *table->items_key ) + sizeof( *table->items_slot ) + table->item_size ) + table->item_size ); HASHTABLE_ASSERT( table->items_key );" >> $g_CTEMP
    echo "table->items_slot = (int*)( table->items_key + table->item_capacity ); table->items_data = (void*)( table->items_slot + table->item_capacity ); table->swap_temp = (void*)( ( (uintptr_t) table->items_data ) + table->item_size * table->item_capacity ); }" >> $g_CTEMP
    echo "void __b2c__hashtable_term( __b2c__hashtable_t* table ) { HASHTABLE_FREE( table->memctx, table->items_key ); HASHTABLE_FREE( table->memctx, table->slots ); }" >> $g_CTEMP
    echo "/* from https://gist.github.com/badboy/6267743 */ static HASHTABLE_U32 hashtable_internal_calculate_hash( HASHTABLE_U64 key ) { key = ( ~key ) + ( key << 18 ); key = key ^ ( key >> 31 ); key = key * 21; key = key ^ ( key >> 11 );" >> $g_CTEMP
    echo "key = key + ( key << 6 ); key = key ^ ( key >> 22 );  HASHTABLE_ASSERT( key ); return (HASHTABLE_U32) key; }" >> $g_CTEMP
    echo "static int hashtable_internal_find_slot( __b2c__hashtable_t const* table, HASHTABLE_U64 key) { int const slot_mask = table->slot_capacity - 1; HASHTABLE_U32 const hash = hashtable_internal_calculate_hash(__b2c__HashFNV1a((char*)(uintptr_t)key)); int const base_slot = (int)( hash & (HASHTABLE_U32)slot_mask );" >> $g_CTEMP
    echo "int base_count = table->slots[ base_slot ].base_count; int slot = base_slot; while( base_count > 0 ) { HASHTABLE_U32 slot_hash = table->slots[ slot ].key_hash; if( slot_hash ) { int slot_base = (int)( slot_hash & (HASHTABLE_U32)slot_mask ); if( slot_base == base_slot )" >> $g_CTEMP
    echo "{ HASHTABLE_ASSERT( base_count > 0 ); --base_count; if( slot_hash == hash && !__b2c__strcmp((char*)(uintptr_t)table->items_key[ table->slots[ slot ].item_index ], (char*)(uintptr_t)key )) return slot; } } slot = ( slot + 1 ) & slot_mask; }   return -1; }" >> $g_CTEMP
    echo "static void hashtable_internal_expand_slots( __b2c__hashtable_t* table ) { int i; int const old_capacity = table->slot_capacity; struct __b2c__hashtable_internal_slot_t* old_slots = table->slots; table->slot_capacity *= 2; int const slot_mask = table->slot_capacity - 1;" >> $g_CTEMP
    echo "int const size = (int)( table->slot_capacity * sizeof( *table->slots ) ); table->slots = (struct __b2c__hashtable_internal_slot_t*) HASHTABLE_MALLOC( table->memctx, (HASHTABLE_SIZE_T) size ); HASHTABLE_ASSERT( table->slots ); HASHTABLE_MEMSET( table->slots, 0, (HASHTABLE_SIZE_T) size );" >> $g_CTEMP
    echo "for( i = 0; i < old_capacity; ++i ) { HASHTABLE_U32 const hash = old_slots[ i ].key_hash; if( hash ) { int const base_slot = (int)( hash & (HASHTABLE_U32)slot_mask ); int slot = base_slot; while( table->slots[ slot ].key_hash ) slot = ( slot + 1 ) & slot_mask;" >> $g_CTEMP
    echo "table->slots[ slot ].key_hash = hash; int item_index = old_slots[ i ].item_index; table->slots[ slot ].item_index = item_index; table->items_slot[ item_index ] = slot; ++table->slots[ base_slot ].base_count; } } HASHTABLE_FREE( table->memctx, old_slots ); }" >> $g_CTEMP
    echo "static void hashtable_internal_expand_items( __b2c__hashtable_t* table ) { table->item_capacity *= 2; HASHTABLE_U64* const new_items_key = (HASHTABLE_U64*) HASHTABLE_MALLOC( table->memctx, table->item_capacity * ( sizeof( *table->items_key ) + sizeof( *table->items_slot ) + table->item_size ) + table->item_size);" >> $g_CTEMP
    echo "HASHTABLE_ASSERT( new_items_key ); int* const new_items_slot = (int*)( new_items_key + table->item_capacity ); void* const new_items_data = (void*)( new_items_slot + table->item_capacity ); void* const new_swap_temp = (void*)( ( (uintptr_t) new_items_data ) + table->item_size * table->item_capacity );" >> $g_CTEMP
    echo "HASHTABLE_MEMCPY( new_items_key, table->items_key, table->count * sizeof( *table->items_key ) ); HASHTABLE_MEMCPY( new_items_slot, table->items_slot, table->count * sizeof( *table->items_key ) ); HASHTABLE_MEMCPY( new_items_data, table->items_data, (HASHTABLE_SIZE_T) table->count * table->item_size );" >> $g_CTEMP
    echo "HASHTABLE_FREE( table->memctx, table->items_key ); table->items_key = new_items_key; table->items_slot = new_items_slot; table->items_data = new_items_data; table->swap_temp = new_swap_temp; }" >> $g_CTEMP
    echo "void* __b2c__hashtable_insert( __b2c__hashtable_t* table, HASHTABLE_U64 key, void const* item ) { HASHTABLE_ASSERT( hashtable_internal_find_slot( table, key) < 0 ); if( table->count >= ( table->slot_capacity - table->slot_capacity / 3 ) ) hashtable_internal_expand_slots( table );" >> $g_CTEMP
    echo "int const slot_mask = table->slot_capacity - 1; HASHTABLE_U32 const hash = hashtable_internal_calculate_hash(__b2c__HashFNV1a((char*)(uintptr_t)key)); int const base_slot = (int)( hash & (HASHTABLE_U32)slot_mask ); int base_count = table->slots[ base_slot ].base_count; int slot = base_slot; int first_free = slot;" >> $g_CTEMP
    echo "while( base_count ) { HASHTABLE_U32 const slot_hash = table->slots[ slot ].key_hash; if( slot_hash == 0 && table->slots[ first_free ].key_hash != 0 ) first_free = slot; int slot_base = (int)( slot_hash & (HASHTABLE_U32)slot_mask ); if( slot_base == base_slot ) --base_count; slot = ( slot + 1 ) & slot_mask; }" >> $g_CTEMP
    echo "slot = first_free; while( table->slots[ slot ].key_hash ) slot = ( slot + 1 ) & slot_mask; if( table->count >= table->item_capacity ) hashtable_internal_expand_items( table ); HASHTABLE_ASSERT( !table->slots[ slot ].key_hash && ( hash & (HASHTABLE_U32) slot_mask ) == (HASHTABLE_U32) base_slot );" >> $g_CTEMP
    echo "HASHTABLE_ASSERT( hash ); table->slots[ slot ].key_hash = hash; table->slots[ slot ].item_index = table->count; ++table->slots[ base_slot ].base_count; void* dest_item = (void*)( ( (uintptr_t) table->items_data ) + table->count * table->item_size ); memcpy( dest_item, item, (HASHTABLE_SIZE_T) table->item_size );" >> $g_CTEMP
    echo "table->items_key[ table->count ] = key; table->items_slot[ table->count ] = slot; ++table->count; return(dest_item); }" >> $g_CTEMP 
    echo "void __b2c__hashtable_remove( __b2c__hashtable_t* table, HASHTABLE_U64 key ) { int const slot = hashtable_internal_find_slot( table, key); HASHTABLE_ASSERT( slot >= 0 ); int const slot_mask = table->slot_capacity - 1; HASHTABLE_U32 const hash = table->slots[ slot ].key_hash;" >> $g_CTEMP
    echo "int const base_slot = (int)( hash & (HASHTABLE_U32) slot_mask ); HASHTABLE_ASSERT( hash ); --table->slots[ base_slot ].base_count; table->slots[ slot ].key_hash = 0; int index = table->slots[ slot ].item_index; int last_index = table->count - 1; free((char*)(uintptr_t)table->items_key[index]); if( index != last_index )" >> $g_CTEMP
    echo "{ table->items_key[ index ] = table->items_key[ last_index ]; table->items_slot[ index ] = table->items_slot[ last_index ]; void* dst_item = (void*)( ( (uintptr_t) table->items_data ) + index * table->item_size ); void* src_item = (void*)( ( (uintptr_t) table->items_data ) + last_index * table->item_size );" >> $g_CTEMP
    echo "HASHTABLE_MEMCPY( dst_item, src_item, (HASHTABLE_SIZE_T) table->item_size ); table->slots[ table->items_slot[ last_index ] ].item_index = index; } --table->count; }" >> $g_CTEMP 
    echo "void __b2c__hashtable_clear( __b2c__hashtable_t* table ) { table->count = 0; HASHTABLE_MEMSET( table->slots, 0, table->slot_capacity * sizeof( *table->slots ) ); }" >> $g_CTEMP
    echo "void* __b2c__hashtable_find( __b2c__hashtable_t const* table, HASHTABLE_U64 key ) { int const slot = hashtable_internal_find_slot( table, key); if( slot < 0 ) return 0; int const index = table->slots[ slot ].item_index; void* const item = (void*)( ( (uintptr_t) table->items_data ) + index * table->item_size ); return item; }" >> $g_CTEMP
    echo "int __b2c__hashtable_count( __b2c__hashtable_t const* table ) { return table->count; }" >> $g_CTEMP
    echo "void* __b2c__hashtable_items( __b2c__hashtable_t const* table ) { return table->items_data; }" >> $g_CTEMP
    echo "HASHTABLE_U64 const* __b2c__hashtable_keys( __b2c__hashtable_t const* table ) { return table->items_key; }" >> $g_CTEMP
    echo "void __b2c__hashtable_swap( __b2c__hashtable_t* table, int index_a, int index_b ) { if( index_a < 0 || index_a >= table->count || index_b < 0 || index_b >= table->count ) return; int slot_a = table->items_slot[ index_a ]; int slot_b = table->items_slot[ index_b ];" >> $g_CTEMP
    echo "table->items_slot[ index_a ] = slot_b; table->items_slot[ index_b ] = slot_a; HASHTABLE_U64 temp_key = table->items_key[ index_a ]; table->items_key[ index_a ] = table->items_key[ index_b ]; table->items_key[ index_b ] = temp_key;" >> $g_CTEMP
    echo " void* item_a = (void*)( ( (uintptr_t) table->items_data ) + index_a * table->item_size ); void* item_b = (void*)( ( (uintptr_t) table->items_data ) + index_b * table->item_size ); HASHTABLE_MEMCPY( table->swap_temp, item_a, table->item_size );" >> $g_CTEMP
    echo "HASHTABLE_MEMCPY( item_a, item_b, table->item_size ); HASHTABLE_MEMCPY( item_b, table->swap_temp, table->item_size ); table->slots[ slot_a ].item_index = index_b; table->slots[ slot_b ].item_index = index_a; }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.hash.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.hash.o: bacon.hash.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.hash.c"

    g_CTEMP="$g_TEMPDIR/bacon.hex.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__dec2hex (int nr) { long idx; int len; idx = __sbuf_malloc_handle (${g_MAX_DIGITS}); len = snprintf (__b2c__sbuffer[idx], ${g_MAX_DIGITS}, \"%X\", nr);" >> $g_CTEMP
    echo "__b2c__SETLEN (__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\0'; return (char *) (__b2c__sbuffer[idx]);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.hex.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.hex.o: bacon.hex.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.hex.c"

    g_CTEMP="$g_TEMPDIR/bacon.host.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__nethost(int l, char *k, char *host) {int y, flag = 0; struct in_addr address; struct sockaddr_in *addrin; struct hostent *he = NULL; long idx; idx = __sbuf_malloc_handle (${g_BUFFER_SIZE});" >> $g_CTEMP
    echo "for(y = 0; host[y] != '\0'; y++) { if(isalpha (*(host + y))) { flag = 1; break; } } if(flag) he = gethostbyname (host); else { if(inet_aton (host, &address)) he = gethostbyaddr ((void *)&address, sizeof(struct in_addr), AF_INET); }" >> $g_CTEMP
    echo "if(he == NULL || he->h_addr == NULL || he->h_name == NULL) { if(__b2c__trap) { ERROR = 11; RUNTIMEFERR(\"HOST$\", ERROR, k, l); } else strncpy(__b2c__sbuffer[idx], \"Host not found\", ${g_BUFFER_SIZE}); } else { if (flag)" >> $g_CTEMP
    echo "{ addrin = (struct sockaddr_in*)calloc (1, sizeof (*addrin)); addrin->sin_addr = *((struct in_addr *) he->h_addr); strncpy(__b2c__sbuffer[idx], inet_ntoa (addrin->sin_addr), ${g_BUFFER_SIZE}); free (addrin); } else strncpy(__b2c__sbuffer[idx], he->h_name, ${g_BUFFER_SIZE}); }" >> $g_CTEMP
    echo "__b2c__SETLEN(__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); __b2c__sbuffer[idx][${g_BUFFER_SIZE} - 1] = '\0'; return (char*)(__b2c__sbuffer[idx]);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.host.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.host.o: bacon.host.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.host.c"

    g_CTEMP="$g_TEMPDIR/bacon.hostname.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__hostname (int l, char *k) { long idx; idx = __sbuf_malloc_handle (${g_BUFFER_SIZE} * sizeof (char)); if(gethostname(__b2c__sbuffer[idx], ${g_BUFFER_SIZE}))" >> $g_CTEMP
    echo "{ if (__b2c__trap) { ERROR = 26; RUNTIMEFERR(\"HOSTNAME$\", ERROR, k, l); } else strncpy (__b2c__sbuffer[idx], \"Error getting hostname\", ${g_BUFFER_SIZE}); }" >> $g_CTEMP
    echo "__b2c__SETLEN(__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); __b2c__sbuffer[idx][${g_BUFFER_SIZE}-1] = '\0'; return (char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.hostname.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.hostname.o: bacon.hostname.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.hostname.c"

    g_CTEMP="$g_TEMPDIR/bacon.insert.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char *__b2c__insert(int l, char *k, char *src, int pos, char *str) { long len, tot, idx, blen; if (src == NULL || str == NULL) { return (src); } len = __b2c__len (src); tot = __b2c__len (str);" >> $g_CTEMP
    echo "idx = __sbuf_malloc_handle (len + tot + 1); pos--; if (pos <= 0) { memmove (__b2c__sbuffer[idx], str, tot); memmove (__b2c__sbuffer[idx] + tot, src, len); } else if (pos > len) { memmove (__b2c__sbuffer[idx], src, len);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx] + len, str, tot); } else { if (__b2c__option_utf8) { blen = __b2c__blen (l, k, \"INSERT$\", src, pos, 0); memmove (__b2c__sbuffer[idx], src, blen); memmove (__b2c__sbuffer[idx] + blen, str, tot);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx] + blen + tot, src + blen, len - blen); } else { memmove (__b2c__sbuffer[idx], src, pos); memmove (__b2c__sbuffer[idx] + pos, str, tot); memmove (__b2c__sbuffer[idx] + pos + tot, src + pos, len - pos); } }" >> $g_CTEMP
    echo "__b2c__SETLEN (__b2c__sbuffer[idx], len + tot); __b2c__sbuffer[idx][len + tot] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.insert.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.insert.o: bacon.insert.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.insert.c"

    g_CTEMP="$g_TEMPDIR/bacon.instr.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__instr(int l, char *k, char *first, char *tmp, int pos) { char *result; if (first == NULL) { return (0); } if (tmp == NULL || __b2c__len (tmp) == 0) { return (0); } if (pos <= 0) {  pos = 1; }" >> $g_CTEMP
    echo "result = strstr (first + pos - 1, tmp); if(result == NULL) {  return (0); } if (__b2c__option_utf8) { return (long) __b2c__ucs2_clen (l, k, \"INSTR\", first, result - first + 1); } return (long) (result - first + 1); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.instr.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.instr.o: bacon.instr.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.instr.c"

    g_CTEMP="$g_TEMPDIR/bacon.instrrev.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__instrrev(int m, char *k, char *first, char *tmp, int pos) { char *result, *found; long l; if (first == NULL){ return (0);} if (tmp == NULL || __b2c__len (tmp) == 0) { return (0); } if (pos < 0) { pos = 0; }" >> $g_CTEMP
    echo "l = __b2c__len (first); found = first; do { result = strstr (found, tmp); if (result != NULL && result <= first + l - pos) { found = result + 1; continue; } if (result > first + l - pos) result = NULL; } while (result != NULL);" >> $g_CTEMP
    echo "if (__b2c__option_startpoint) { if (l - (found - first) + 1 > l) { return 0; } if (__b2c__option_utf8) { return (long) (__b2c__ulen (l, k, \"INSTRREV\", first, -1) - __b2c__ucs2_clen (l, k, \"INSTRREV\", first, found - first) + 1); }" >> $g_CTEMP
    echo "return (long) (l - (found - first) + 1); } if (__b2c__option_utf8) { return (long) __b2c__ucs2_clen (m, k, \"INSTRREV\", first, found - first); } return (long) (found - first); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.instrrev.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.instrrev.o: bacon.instrrev.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.instrrev.c"

    g_CTEMP="$g_TEMPDIR/bacon.lcase.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__lcase (int l, char *k, char *src) { long idx, len, i; size_t mbslen; wchar_t *wcs, *wp; char *local; if (src == NULL) { return (NULL); } len = __b2c__len (src); idx = __sbuf_malloc_handle (len + 1); if (__b2c__option_utf8)" >> $g_CTEMP
    echo "{ local = setlocale (LC_ALL, \"\"); if ((mbslen = mbstowcs (NULL, src, 0)) == (size_t) - 1) { ERROR = 38; RUNTIMEFERR (\"LCASE$\", ERROR, k, l); } wcs = (wchar_t*)calloc (mbslen + 1, sizeof (wchar_t)); if (mbstowcs (wcs, src, mbslen + 1) == (size_t) - 1)" >> $g_CTEMP
    echo "{ ERROR = 38; RUNTIMEFERR (\"LCASE$\", ERROR, k, l); } for (wp = wcs; *wp != 0; wp++) { *wp = towlower (*wp); } if (wcstombs (__b2c__sbuffer[idx], wcs, len) == (size_t) - 1) { ERROR = 38; RUNTIMEFERR (\"LCASE$\", ERROR, k, l); } free (wcs);" >> $g_CTEMP
    echo "setlocale (LC_ALL, local); } else { for (i = 0; i < len; i++) { __b2c__sbuffer[idx][i] = tolower (src[i]); } } __b2c__SETLEN (__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.lcase.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.lcase.o: bacon.lcase.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.lcase.c"

    g_CTEMP="$g_TEMPDIR/bacon.left.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__left (int l, char *k, char *src, unsigned long n) { unsigned long length, idx; if (src == NULL) { return (NULL); } length = __b2c__len (src); if (n > (__b2c__option_utf8 ? __b2c__ucs2_clen (l, k, \"LEFT$\", src, length) : length))" >> $g_CTEMP
    echo "{ idx = __sbuf_malloc_handle (length + 1); memmove (__b2c__sbuffer[idx], src, length); __b2c__SETLEN (__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\0'; } else { if (__b2c__option_utf8) { n = __b2c__blen (l, k, \"LEFT$\", src, n, 0); }" >> $g_CTEMP
    echo "idx = __sbuf_malloc_handle (n + 1); memmove (__b2c__sbuffer[idx], src, n); __b2c__SETLEN (__b2c__sbuffer[idx], n); __b2c__sbuffer[idx][n] = '\0'; } return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.left.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.left.o: bacon.left.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.left.c"

    g_CTEMP="$g_TEMPDIR/bacon.load.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char* __b2c__load (int flag, int l, char *k, char *file) { FILE *handle; struct stat buf; long idx; void* mem; handle = fopen ((const char*)file, \"r\"); if(handle == NULL && __b2c__trap)" >> $g_CTEMP
    echo "{ ERROR = 2; RUNTIMEFERR (\"LOAD$/BLOAD\", ERROR, k, l); } if(stat(file, &buf) < 0 && __b2c__trap) { ERROR = 24; RUNTIMEFERR (\"LOAD$/BLOAD\", ERROR, k, l); } if(flag) { mem = malloc(buf.st_size);" >> $g_CTEMP
    echo "if(fread (mem, sizeof (char), buf.st_size, handle) != buf.st_size && __b2c__trap) { ERROR = 2; RUNTIMEFERR(\"BLOAD\", ERROR, k, l); } fclose(handle); return(char*)(mem); } else" >> $g_CTEMP
    echo "{ idx = __sbuf_malloc_handle (buf.st_size + 1); if(fread (__b2c__sbuffer[idx], sizeof (char), buf.st_size, handle) != buf.st_size && __b2c__trap) { ERROR = 2;" >> $g_CTEMP
    echo "RUNTIMEFERR (\"LOAD$\", ERROR, k, l); } __b2c__SETLEN(__b2c__sbuffer[idx], buf.st_size); __b2c__sbuffer[idx][buf.st_size] = '\0'; fclose(handle); return(char*)(__b2c__sbuffer[idx]); } }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.load.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.load.o: bacon.load.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.load.c"

    g_CTEMP="$g_TEMPDIR/bacon.makedir.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "int __b2c__makedir (char *in) { char *i, *dir; if (in == NULL || __b2c__len (in) == 0) { return 0; } if (*in != '/') { dir = (char*)calloc(__b2c__len(in) + 3, sizeof (char)); strcpy (dir, \"./\"); strcat (dir, in); }" >> $g_CTEMP
    echo "else { dir = strdup (in); } i = dir; do { i++; while (*i != '/' && *i != '\0') i++; if (*i == '/') { *i = '\0'; mkdir (dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); *i = '/'; } else if (*i == '\0')" >> $g_CTEMP
    echo "{ mkdir (dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); } if (errno != EEXIST && errno != 0) { free (dir); return errno; } } while (*i != '\0'); free (dir); return 0; }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.makedir.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.makedir.o: bacon.makedir.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.makedir.c"

    g_CTEMP="$g_TEMPDIR/bacon.malloc.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "void *__rbuf_realloc(void *__b2c__ptr, size_t __b2c__size){if(__b2c__rbuffer_length[__b2c__rbuffer_ptr] < __b2c__size)" >> $g_CTEMP
    echo "{__b2c__rbuffer_length[__b2c__rbuffer_ptr] = (size_t)__b2c__size*4; return(realloc(__b2c__ptr, __b2c__rbuffer_length[__b2c__rbuffer_ptr]));} return(__b2c__ptr);}" >> $g_CTEMP
    echo "void __sbuf_need_realloc (long idx, size_t size) { if (__b2c__sbuffer[idx] == NULL) { __b2c__sbuffer[idx] = (char*)calloc(__b2c__BUFOFFSET + size*2 + 1, sizeof(char));" >> $g_CTEMP
    echo "*(uint32_t *) (__b2c__sbuffer[idx] + 4) = size * 2 + 1; *(uint8_t*)(__b2c__sbuffer[idx] + 8) = 1; __b2c__SETRANGE(__b2c__sbuffer[idx]); __b2c__sbuffer[idx]+=__b2c__BUFOFFSET; }" >> $g_CTEMP
    echo "else if (__b2c__buf (__b2c__sbuffer[idx]) <= size) { __b2c__sbuffer[idx] = (char*)realloc (__b2c__sbuffer[idx] - __b2c__BUFOFFSET, __b2c__BUFOFFSET + size * 2 + 1);" >> $g_CTEMP
    echo "*(uint32_t *) (__b2c__sbuffer[idx] + 4) = size * 2 + 1; *(uint8_t*)(__b2c__sbuffer[idx] + 8) = 1; __b2c__SETRANGE(__b2c__sbuffer[idx]); __b2c__sbuffer[idx]+=__b2c__BUFOFFSET; } }" >> $g_CTEMP
    echo "long __sbuf_malloc_handle (size_t size) {__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr>=__b2c__sbuffer_size) __b2c__sbuffer_ptr=0; __sbuf_need_realloc (__b2c__sbuffer_ptr, size);" >> $g_CTEMP
    echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, size); __b2c__SETLEN(__b2c__sbuffer[__b2c__sbuffer_ptr], 0); return(__b2c__sbuffer_ptr); }" >> $g_CTEMP
    echo "char *__b2c__strdup (const char *s) { if (s == NULL) { return (NULL); } return (strdup (s)); }" >> $g_CTEMP
    echo "char *__b2c__strndup (const char *s, size_t n) { char *cnew; if (s == NULL) { return (NULL); } cnew = (char*)malloc(n + 1); if(cnew == NULL) return(NULL); cnew[n] = '\0'; return (char*)strncpy(cnew, s, n); }" >> $g_CTEMP
    echo "int __b2c__strcmp(const char *__b2c__s1, const char *__b2c__s2){if(__b2c__s1 == NULL && __b2c__s2 == NULL) return 0;" >> $g_CTEMP
    echo "if(__b2c__s1 == NULL) { __b2c__s1 = EmptyString; } if(__b2c__s2 == NULL) { __b2c__s2 = EmptyString; } return(strcmp(__b2c__s1, __b2c__s2));}" >> $g_CTEMP
    echo "int __b2c__strcasecmp(const char *__b2c__s1, const char *__b2c__s2){if(__b2c__s1 == NULL && __b2c__s2 == NULL) { return 0; }" >> $g_CTEMP
    echo "if(__b2c__s1 == NULL) { return(-1); } if(__b2c__s2 == NULL) { return(1); } return(strcasecmp(__b2c__s1, __b2c__s2));}" >> $g_CTEMP
    echo "void *__b2c_str_realloc(char *ptr, size_t size) { if (ptr == NULL || __b2c__buf((char*)ptr) <= size) { if ((long) ptr & 1)" >> $g_CTEMP
    echo "{ ptr = (char*)realloc(ptr - __b2c__BUFOFFSET, __b2c__BUFOFFSET + size * 2 + 1); } else { ptr = (char*)realloc(ptr, __b2c__BUFOFFSET + size * 2 + 1); }" >> $g_CTEMP
    echo "*(uint32_t *) ((char*)ptr + 4) = size * 2 + 1; *(uint8_t *) ((char*)ptr + 8) = 0; __b2c__SETRANGE (ptr); ptr += __b2c__BUFOFFSET; } return(ptr); }" >> $g_CTEMP
    echo "char *__b2c_Copy_String (char *x, char *y) { long ylen; if (y == NULL) { __b2c__STRFREE (x); return (NULL); } else" >> $g_CTEMP
    echo "{ ylen = __b2c__len (y); } x = (char*)__b2c_str_realloc(x, ylen); memmove (x, y, ylen); if ((uintptr_t) x & 1) { __b2c__SETLEN (x, ylen); } x[ylen] = '\0'; return (x); }" >> $g_CTEMP
    echo "char *__b2c_Assign_String (char **x, char *y) { char *tmp; if (*x != NULL && y != NULL && ((uintptr_t)y&1) && __b2c__INRANGE(y)) { if(__b2c__IS_SBUF(y)) {" >> $g_CTEMP
    echo "tmp = *x; *x = y; __b2c__UNSETBIT(*x); __b2c__sbuffer[__b2c__sbuffer_ptr] = __b2c__topstring(tmp); __b2c__SETBIT(__b2c__sbuffer[__b2c__sbuffer_ptr]);" >> $g_CTEMP
    echo "return (*x); } } return (__b2c_Copy_String (*x, y)); }" >> $g_CTEMP
    echo "char *__b2c__topstring (char *ptr) { unsigned int len; if((long)ptr&1) { return ptr; } len = (ptr == NULL ? 0 : strlen (ptr)); ptr = (char*)realloc(ptr, __b2c__BUFOFFSET + len + 1);" >> $g_CTEMP
    echo "memset(ptr + len, 0, __b2c__BUFOFFSET+1); memmove(ptr + __b2c__BUFOFFSET, ptr, len + 1); *(uint32_t *) (ptr) = len; *(uint32_t *) (ptr + 4) = len + 1; __b2c__SETRANGE(ptr); return(ptr + __b2c__BUFOFFSET); }" >> $g_CTEMP
    echo "unsigned long __b2c__len (const char *ptr) { if (ptr == NULL) { return (0); } if (((uintptr_t)ptr&1) && __b2c__INRANGE(ptr) && __b2c__VALID(ptr)) { return (*(uint32_t *) (ptr - __b2c__BUFOFFSET)); } return ((unsigned long) strlen (ptr)); }" >> $g_CTEMP
    echo "unsigned long __b2c__buf (const char *ptr) { if (ptr == NULL) { return (0); } if (((uintptr_t)ptr&1) && __b2c__INRANGE(ptr)) { return (*(uint32_t *) (ptr - __b2c__BUFOFFSET + 4)); } return ((unsigned long) strlen (ptr)+1); }" >> $g_CTEMP
    echo "char *__b2c__loop_helper(jmp_buf buf) { if(__b2c__loop_result${g_STRINGSIGN} != NULL) { __b2c__SETLEN (__b2c__loop_result${g_STRINGSIGN}, 0); __b2c__loop_result${g_STRINGSIGN} = __b2c_Assign_String(&__b2c__loop_result${g_STRINGSIGN}, EmptyString); } longjmp(buf, 1); return(NULL); }" >> $g_CTEMP
    if [[ `uname` = +(*BSD*) ]]
    then
        echo "char *__b2c_strlcat(char *dest, const char *src) { strlcat(dest, src, __b2c__len(dest)+__b2c__len(src)+1); return(dest); }" >> $g_CTEMP
        echo "char *__b2c_strlcpy(char *dest, const char *src) { strlcpy(dest, src, __b2c__len(src)+1); return(dest); }" >> $g_CTEMP
    fi
    g_OBJ_FILES="$g_OBJ_FILES bacon.malloc.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.malloc.o: bacon.malloc.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.malloc.c"

    g_CTEMP="$g_TEMPDIR/bacon.memcheck.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "void __b2c__catch_signal(int sig){" >> $g_CTEMP
    echo "switch (sig) {case SIGABRT: fprintf(stderr, \"ERROR: signal ABORT received - internal error. Try to compile the program with TRAP LOCAL to find the cause.\n\"); break;" >> $g_CTEMP
    echo "case SIGFPE: fprintf(stderr, \"ERROR: signal for FPE received - division by zero? Examine the calculations in the program.\n\"); break;" >> $g_CTEMP
    echo "case SIGSEGV: fprintf(stderr, \"ERROR: signal for SEGMENTATION FAULT received - memory invalid or array out of bounds? Try to compile the program with TRAP LOCAL to find the cause.\n\"); break;" >> $g_CTEMP
    echo "case SIGILL: fprintf(stderr, \"ERROR: signal for ILLEGAL INSTRUCTION received - executing the program on other hardware? Try to recompile the program from scratch.\n\"); break;} exit(sig);}" >> $g_CTEMP
    echo "void __b2c__segv(int sig){longjmp(__b2c__jump, 1);}" >> $g_CTEMP
    echo "int __b2c__memory__check(volatile char* x, int size){int i, illegal = 0; void(*handler)(int); handler = signal(SIGSEGV, __b2c__segv);" >> $g_CTEMP
    echo "if(!setjmp(__b2c__jump)) {for(i = 0; i < size; i++) if(*(x+i)) continue;} else illegal = 1;" >> $g_CTEMP
    echo "if(__b2c__trap) signal(SIGSEGV, __b2c__catch_signal); else signal(SIGSEGV, handler); return(illegal);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.memcheck.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.memcheck.o: bacon.memcheck.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.memcheck.c"

    g_CTEMP="$g_TEMPDIR/bacon.mid.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char *__b2c__mid (int l, char *k, char *src, long pos, long length) { long idx, src_len; if (src == NULL) { return (EmptyString); } src_len = __b2c__len (src); pos -= 1; if (pos < 0)" >> $g_CTEMP
    echo "{ pos = (__b2c__option_utf8 ? __b2c__ucs2_clen (l, k, \"MID$\", src, src_len) : src_len) + 1 + pos; } if (__b2c__option_utf8) { pos = __b2c__blen (l, k, \"MID$\", src, pos, 0); }" >> $g_CTEMP
    echo "if (pos > src_len) { return (EmptyString); } if (__b2c__option_utf8 && length >= 0) { length = __b2c__blen (l, k, \"MID$\", src + pos, length, 0); } if (length < 0 || pos + length > src_len)" >> $g_CTEMP
    echo "{ length = src_len - pos; } idx = __sbuf_malloc_handle (length + 1); memmove (__b2c__sbuffer[idx], src + pos, length); __b2c__SETLEN (__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.mid.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.mid.o: bacon.mid.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.mid.c"

    g_CTEMP="$g_TEMPDIR/bacon.minmax.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char* __b2c__min_str(char* x, char* y) {if(strcmp(x, y) < 0) { return(x); } return(y);}" >> $g_CTEMP
    echo "char* __b2c__max_str(char* x, char* y) {if(strcmp(x, y) > 0) { return(x); } return(y);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.minmax.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.minmax.o: bacon.minmax.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.minmax.c"

    g_CTEMP="$g_TEMPDIR/bacon.os.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__os(int l, char *k) { struct utsname buf; long idx; idx = __sbuf_malloc_handle (${g_BUFFER_SIZE}*sizeof (char));" >> $g_CTEMP
    echo "if (uname (&buf) < 0 && __b2c__trap) { ERROR = 26; RUNTIMEFERR(\"OS$\", ERROR, k, l); } strcpy (__b2c__sbuffer[idx], buf.sysname);" >> $g_CTEMP
    echo "strcat (__b2c__sbuffer[idx], \" \"); strcat (__b2c__sbuffer[idx], buf.machine); __b2c__SETLEN (__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); return (char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.os.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.os.o: bacon.os.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.os.c"

    g_CTEMP="$g_TEMPDIR/bacon.peek.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "int __b2c__peek_check(int l, char *k, char* x, int size) {if(__b2c__trap) {if(__b2c__memory__check((char*)x, size)) {ERROR=1; RUNTIMEFERR(\"PEEK\", ERROR, k, l);} } return(0); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.peek.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.peek.o: bacon.peek.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.peek.c"

    g_CTEMP="$g_TEMPDIR/bacon.remove.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "int __b2c__rmrecursive(int l, char *k, char *dir){DIR *mydir; char *path, *item = NULL; struct stat buf = { 0 }; struct dirent *next = { NULL }; mydir = opendir(dir); if(mydir == NULL) {if(__b2c__trap) {ERROR = 8; RUNTIMEFERR(\"DELETE RECURSIVE\", ERROR, k, l);} }" >> $g_CTEMP
    echo "while (1) { if (item != NULL) free(item); next = readdir(mydir); if(next != NULL) { item = (char*)calloc((strlen (next->d_name) + 1), sizeof(char));" >> $g_CTEMP
    echo "strcpy(item, next->d_name); } else { break; } if (!strcmp (item, \".\") || !strcmp(item, \"..\") ) continue; path = (char*)calloc(strlen(dir)+strlen(item)+2, sizeof(char));" >> $g_CTEMP
    echo "strcpy(path, dir); strcat(path, \"/\"); strcat(path, item); lstat(path, &buf); if(S_ISDIR (buf.st_mode)) { __b2c__rmrecursive(l, k, path); } else { if(remove(path) < 0)" >> $g_CTEMP
    echo "{ if(__b2c__trap) { ERROR = 7; RUNTIMEFERR(\"DELETE RECURSIVE\", ERROR, k, l); } } } if(path != NULL) free(path); } closedir(mydir); if(remove(dir) < 0)" >> $g_CTEMP
    echo "{ if(__b2c__trap) { ERROR = 7; RUNTIMEFERR(\"DELETE RECURSIVE\", ERROR, k, l); } } return(0);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.remove.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.remove.o: bacon.remove.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.remove.c"

    g_CTEMP="$g_TEMPDIR/bacon.reverse.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__reverse(int l, char *k, char *src) { long i, length, len, idx, blen; if (src == NULL) { return (EmptyString); } length = __b2c__len (src); idx = __sbuf_malloc_handle (length + 1);" >> $g_CTEMP
    echo "if(__b2c__option_utf8) { len = length; while (len > 0) { blen = __b2c__blen (l, k, \"REVERSE$\", src, 1, 0); memcpy (__b2c__sbuffer[idx] + len - blen, src, blen); src += blen; len -= blen; } } else" >> $g_CTEMP
    echo "{ for (i = 0; i < length; i++) { __b2c__sbuffer[idx][i] = src[length - i - 1]; } } __b2c__SETLEN (__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.reverse.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.reverse.o: bacon.reverse.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.reverse.c"

    g_CTEMP="$g_TEMPDIR/bacon.right.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__right (int l, char *k, char *src, unsigned long n) { unsigned long length, idx; if (src == NULL) { return (NULL); } length = __b2c__len (src); if (n > (__b2c__option_utf8 ? __b2c__ucs2_clen (l, k, \"RIGHT$\", src, length) : length))" >> $g_CTEMP
    echo "{ idx = __sbuf_malloc_handle (length + 1); memmove (__b2c__sbuffer[idx], src, length); __b2c__SETLEN (__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\0'; } else { if (__b2c__option_utf8) { n = __b2c__blen (l, k, \"RIGHT$\", src, n, 1); }" >> $g_CTEMP
    echo "idx = __sbuf_malloc_handle (n + 1); memmove (__b2c__sbuffer[idx], src + length - n, n); __b2c__SETLEN (__b2c__sbuffer[idx], n); __b2c__sbuffer[idx][n] = '\0'; } return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.right.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.right.o: bacon.right.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.right.c"

    g_CTEMP="$g_TEMPDIR/bacon.rip.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char *__b2c__rip(int l, char *k, char *src, ...) { long idx, src_len, pos, length; va_list ap; if (src == NULL) { return (EmptyString); } src_len = __b2c__len (src); va_start (ap, src); pos = va_arg (ap, int) - 1;" >> $g_CTEMP
    echo "if (pos < 0) { pos = (__b2c__option_utf8 ? __b2c__ucs2_clen (l, k, \"RIP$\", src, src_len) : src_len) + 1 + pos; } if (__b2c__option_utf8) { pos = __b2c__blen (l, k, \"RIP$\", src, pos, 0); } if (pos > src_len)" >> $g_CTEMP
    echo "{ return (EmptyString); } length = va_arg (ap, int); va_end (ap); if (__b2c__option_utf8 && length >= 0) { length = __b2c__blen (l, k, \"RIP$\", src + pos, length, 0); } if (length < 0 || pos + length > src_len)" >> $g_CTEMP
    echo "{ length = src_len - pos; } idx = __sbuf_malloc_handle (src_len); memmove (__b2c__sbuffer[idx], src, pos); memmove (__b2c__sbuffer[idx]+pos, src + pos + length,  src_len-pos-length); __b2c__SETLEN (__b2c__sbuffer[idx], src_len-length);" >> $g_CTEMP
    echo "__b2c__sbuffer[idx][src_len-length] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.rip.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.rip.o: bacon.rip.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.rip.c"

    g_CTEMP="$g_TEMPDIR/bacon.screen.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__screen(int type){long x; struct winsize tmp; ioctl(STDOUT_FILENO, TIOCGWINSZ, &tmp); if(type) { x = tmp.ws_row; } else { x = tmp.ws_col; } return(x); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.screen.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.screen.o: bacon.screen.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.screen.c"

    g_CTEMP="$g_TEMPDIR/bacon.search.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__search (int l, char *k, FILE * x, ...) { long off, pos=0, org_pos; int whence, flag = 0; char *ptr, *y; va_list ap; va_start (ap, x); y = va_arg (ap, char*); whence = va_arg (ap, int); va_end (ap); if (x == NULL && __b2c__trap)" >> $g_CTEMP
    echo "{ ERROR = 2; RUNTIMEFERR (\"SEARCH\", ERROR, k, l); } if (y == NULL && __b2c__trap) { ERROR = 25; RUNTIMEFERR (\"SEARCH\", ERROR, k, l); } org_pos = ftell (x); ptr = (char *) malloc (__b2c__len (y) + 1);" >> $g_CTEMP
    echo "switch(whence) { case -1: case 0: off = 1; break; case 1: off = 1; break; case 2: off = -1; break; case 3: off = -1; break; default: ERROR = 37; RUNTIMEFERR (\"SEARCH\", ERROR, k, l); } do { switch(whence) { case -1: case 0: fseek (x, pos, SEEK_SET);" >> $g_CTEMP
    echo "break; case 1: fseek (x, org_pos+pos, SEEK_SET);break; case 2: flag = fseek (x, org_pos- __b2c__len (y)+pos, SEEK_SET); break; case 3: fseek (x, pos-__b2c__len (y), SEEK_END); break; }" >> $g_CTEMP
    echo "if (fread (ptr, sizeof (char), __b2c__len (y), x) <= 0) { if (__b2c__trap) { ERROR = 2; RUNTIMEFERR (\"SEARCH\", ERROR, k, l); } } pos += off; } while (!feof (x) && !flag && memcmp (ptr, y, __b2c__len (y)));" >> $g_CTEMP
    echo "if (memcmp (ptr, y, __b2c__len (y))) { pos = -1; } else {pos = ftell(x)-__b2c__len (y); } fseek (x, org_pos, SEEK_SET); free (ptr); return(pos); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.search.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.search.o: bacon.search.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.search.c"

    g_CTEMP="$g_TEMPDIR/bacon.sort.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "int __b2c__sortnrd(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return -1; else return 1;}" >> $g_CTEMP
    echo "int __b2c__sortnrd_down(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return 1; else return -1;}" >> $g_CTEMP
    echo "int __b2c__sortnrf(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return -1; else return 1;}" >> $g_CTEMP
    echo "int __b2c__sortnrf_down(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return 1; else return -1;}" >> $g_CTEMP
    echo "int __b2c__sortnrl(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return -1; else return 1;}" >> $g_CTEMP
    echo "int __b2c__sortnrl_down(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return 1; else return -1;}" >> $g_CTEMP
    echo "int __b2c__sortnri(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return -1; else return 1;}" >> $g_CTEMP
    echo "int __b2c__sortnri_down(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return 1; else return -1;}" >> $g_CTEMP
    echo "int __b2c__sortnrs(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(short*)__b2c__a==*(short*)__b2c__b) return 0; else if (*(short*)__b2c__a < *(short*)__b2c__b) return -1; else return 1;}" >> $g_CTEMP
    echo "int __b2c__sortnrs_down(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(short*)__b2c__a==*(short*)__b2c__b) return 0; else if (*(short*)__b2c__a < *(short*)__b2c__b) return 1; else return -1;}" >> $g_CTEMP
    echo "int __b2c__sortnrc(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(char*)__b2c__a==*(char*)__b2c__b) return 0; else if (*(char*)__b2c__a < *(char*)__b2c__b) return -1; else return 1;}" >> $g_CTEMP
    echo "int __b2c__sortnrc_down(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if (*(char*)__b2c__a==*(char*)__b2c__b) return 0; else if (*(char*)__b2c__a < *(char*)__b2c__b) return 1; else return -1;}" >> $g_CTEMP
    echo "int __b2c__sortstr(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if(*(char **)__b2c__a == NULL) return -1; if(*(char **)__b2c__b == NULL) return 1; return strcmp(*(char **)__b2c__a, *(char **)__b2c__b);}" >> $g_CTEMP
    echo "int __b2c__sortstr_down(const void *__b2c__a, const void *__b2c__b)" >> $g_CTEMP
    echo "{if(*(char **)__b2c__a == NULL) return -1; if(*(char **)__b2c__b == NULL) return 1; return strcmp(*(char **)__b2c__b, *(char **)__b2c__a);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.sort.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.sort.o: bacon.sort.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.sort.c"

    g_CTEMP="$g_TEMPDIR/bacon.spc.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__spc(int amount) { long idx; idx = __sbuf_malloc_handle (amount + 1); memset(__b2c__sbuffer[idx], 32, amount);" >> $g_CTEMP
    echo "__b2c__SETLEN (__b2c__sbuffer[idx], amount); __b2c__sbuffer[idx][amount] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.spc.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.spc.o: bacon.spc.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.spc.c"

    g_CTEMP="$g_TEMPDIR/bacon.str.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__str(double nr) {long idx; int len; idx = __sbuf_malloc_handle(${g_MAX_DIGITS}); if (floor (nr) == nr) { len = snprintf(__b2c__sbuffer[idx], ${g_MAX_DIGITS}, \"%ld\", (long) nr); }" >> $g_CTEMP
    echo "else { len = snprintf (__b2c__sbuffer[idx], ${g_MAX_DIGITS}, \"%g\", (double) nr); } __b2c__SETLEN (__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\0'; return(char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.str.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.str.o: bacon.str.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.str.c"

    g_CTEMP="$g_TEMPDIR/bacon.sum.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__sum(int base, long *array, long nr, ...) { va_list ap; long limit = 0, total = 0; int x; va_start (ap, nr); limit = va_arg (ap, long); va_end (ap);" >> $g_CTEMP
    echo "for(x = base; x < nr+base; x++) { if(limit == LONG_MAX){ total += array[x]; } else { if(array[x]>limit) { total += array[x]; } } } return(total); }" >> $g_CTEMP
    echo "double __b2c__sumf(int base, double *array, double nr, ...) { va_list ap; double limit = 0, total = 0; int x; va_start (ap, nr); limit = va_arg (ap, double); va_end (ap);" >> $g_CTEMP
    echo "for(x = base; x < nr+base; x++) { if(limit == DBL_MAX){ total += array[x]; } else { if(array[x]>limit) { total += array[x]; } } } return(total); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.sum.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.sum.o: bacon.sum.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.sum.c"

    g_CTEMP="$g_TEMPDIR/bacon.tab.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char *__b2c__tab(int amount) { long idx; idx = __sbuf_malloc_handle (amount + 1); memset(__b2c__sbuffer[idx], 9, amount);" >> $g_CTEMP
    echo "__b2c__SETLEN (__b2c__sbuffer[idx], amount); __b2c__sbuffer[idx][amount] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.tab.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.tab.o: bacon.tab.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.tab.c"

    g_CTEMP="$g_TEMPDIR/bacon.tally.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__tally(char *haystack, ...) { char *needle, *res; int pos; long total = 0; va_list ap; if (haystack == NULL) return (0);" >> $g_CTEMP
    echo "va_start (ap, haystack); needle = va_arg (ap, char *); if (needle == NULL || __b2c__len(needle) == 0) return (0); pos = va_arg (ap, int); if (pos <= 0) pos = 1; va_end (ap);" >> $g_CTEMP
    echo "haystack+=pos-1; while((res = strstr(haystack, needle)) != NULL) { haystack = res+1; total++; } return (long) (total); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.tally.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.tally.o: bacon.tally.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.tally.c"

    g_CTEMP="$g_TEMPDIR/bacon.time.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__time (time_t now, int which){ long result; char *buffer; struct tm *ts; buffer = (char*)calloc(${g_MAX_DIGITS}, sizeof (char)); ts = localtime (&now); switch (which) {" >> $g_CTEMP
    echo "case 1: strftime (buffer, ${g_MAX_DIGITS}, \"%d\", ts); break; case 2: strftime (buffer, ${g_MAX_DIGITS}, \"%m\", ts); break; case 3: strftime (buffer, ${g_MAX_DIGITS}, \"%Y\", ts); break;" >> $g_CTEMP
    echo "case 4: strftime (buffer, ${g_MAX_DIGITS}, \"%H\", ts); break; case 5: strftime (buffer, ${g_MAX_DIGITS}, \"%M\", ts); break; case 6: strftime (buffer, ${g_MAX_DIGITS}, \"%S\", ts); break;" >> $g_CTEMP
    echo "case 7: strftime (buffer, ${g_MAX_DIGITS}, \"%W\", ts); break; } result = atol(buffer); free(buffer); return(result); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.time.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.time.o: bacon.time.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.time.c"

    g_CTEMP="$g_TEMPDIR/bacon.timer.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "unsigned long __b2c__timer(){struct timeval time; gettimeofday(&time, NULL); if(difftime(time.tv_sec, __b2c__elapsed_secs) < 1) return(unsigned long)((time.tv_usec-__b2c__elapsed_usecs)/1000);" >> $g_CTEMP
    echo "else return(unsigned long)((difftime(time.tv_sec, __b2c__elapsed_secs)-1)*1000+((1000000-__b2c__elapsed_usecs)+time.tv_usec)/1000);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.timer.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.timer.o: bacon.timer.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.timer.c"

    g_CTEMP="$g_TEMPDIR/bacon.token.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__delim_engine(int type, long *returned_value, char* string, char* delim, long nr) { long x, len, cnt = 0, start = 0; int in_string = 0, is_escaped = 0;" >> $g_CTEMP
    echo "if (delim == NULL) { delim = __b2c__option_delim; } len = __b2c__len(delim); for (x = 0; string[x] != 0; x++) { if(!in_string) { if(string[x] == delim[0]) { if(!strncmp(string+x, delim, len))" >> $g_CTEMP
    echo "{ if (__b2c__collapse == 0) { cnt++; } else if (x + len - start > len) { cnt++; } if (nr && nr == cnt) { break; } else { start = x + len; } } } } if(string[x] == 92) {if (!is_escaped) { is_escaped = 1; } else" >> $g_CTEMP
    echo "{ is_escaped = 0; } } else if(string[x] == __b2c__option_dq) {if (!is_escaped && __b2c__option_quoted) { in_string = 1 - in_string; } is_escaped = 0; } else { is_escaped = 0; } } switch(type)" >> $g_CTEMP
    echo "{ case 1: if(nr-cnt > 1) { *returned_value = 0; } else { *returned_value = x-start; } break; case 2: if(x==0) { *returned_value=0; } else { if(__b2c__collapse==0) { cnt++; } else if(x+len-start>len){ cnt++; } *returned_value = cnt; } break; default: *returned_value = 0; } return(start); }" >> $g_CTEMP
    echo "char *__b2c__token(char *string, long nr, char *delim) { long start, idx; long length[1] = { 0 }; if (string == NULL || nr < 1) { return (EmptyString); }" >> $g_CTEMP
    echo "start = __b2c__delim_engine(1, length, string, delim, nr); if(length[0] == 0) { return(EmptyString); }" >> $g_CTEMP
    echo "idx = __sbuf_malloc_handle (length[0] + 1); memmove (__b2c__sbuffer[idx], string + start, length[0]); __b2c__SETLEN (__b2c__sbuffer[idx], length[0]); __b2c__sbuffer[idx][length[0]] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "long __b2c__amount(char *string, char *delim) { long amount[1] = { 0 }; if (string == NULL) { return (0); } __b2c__delim_engine(2, amount, string, delim, 0); return (amount[0]); }" >> $g_CTEMP
    echo "int __b2c__hasdelim (char *string, char *delim) { long length[1] = { 0 }; long start = 0; if (string == NULL) { return (0); }" >> $g_CTEMP
    echo "start = __b2c__delim_engine (2, length, string, delim, 2); if(start == 0) { return (0); } if (delim == NULL) { delim = __b2c__option_delim; } return (start-__b2c__len (delim)+1); }" >> $g_CTEMP
    echo "char *__b2c__exchange (char *string, int index1, int index2, ...) { char *delim; long tmp, idx, tlen, len1, len2, start1 = 0, start2 = 0; long length[1] = { 0 }; va_list ap;" >> $g_CTEMP
    echo "if (string == NULL || index1 <= 0 || index2 <= 0) { return (string); } va_start (ap, index2); delim = va_arg (ap, char*); va_end (ap); start1 = __b2c__delim_engine(1, length, string, delim, index1);" >> $g_CTEMP
    echo "len1 = length[0]; length[0] = 0; start2 = __b2c__delim_engine(1, length, string, delim, index2); len2 = length[0]; if (start1 == start2)" >> $g_CTEMP
    echo "{ return (string); } else if (start2 < start1) { tmp = start2; start2 = start1; start1 = tmp; tmp = len2; len2 = len1; len1 = tmp; }" >> $g_CTEMP
    echo "tlen = __b2c__len (string); idx = __sbuf_malloc_handle (tlen + 1); memmove (__b2c__sbuffer[idx], string, start1); memmove (__b2c__sbuffer[idx] + start1, string + start2, len2);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx] + start1 + len2, string + start1 + len1, start2 - (start1 + len1)); memmove (__b2c__sbuffer[idx] + start1 + len2 + start2 - (start1 + len1), string + start1, len1);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx] + start1 + len2 + start2 - (start1 + len1) + len1, string + start2 + len2, tlen - (start2 + len2)); __b2c__SETLEN (__b2c__sbuffer[idx], tlen);" >> $g_CTEMP
    echo "__b2c__sbuffer[idx][tlen] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__change (char *string, int index, char *cnew, ...) { char *delim; long idx, tlen, start, len, nlen; long length[1] = { 0 }; va_list ap; if (string == NULL || index <= 0)" >> $g_CTEMP
    echo "{ return (string); } va_start (ap, cnew); delim = va_arg (ap, char *); va_end (ap); start = __b2c__delim_engine(1, length, string, delim, index);" >> $g_CTEMP
    echo "len = length[0]; tlen = __b2c__len(string); nlen = __b2c__len(cnew); idx = __sbuf_malloc_handle (tlen - len + nlen + 1); memmove (__b2c__sbuffer[idx], string, start);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx] + start, cnew, nlen); memmove (__b2c__sbuffer[idx] + start + nlen, string + start + len, tlen - (start + len)); __b2c__SETLEN (__b2c__sbuffer[idx], tlen - len + nlen);" >> $g_CTEMP
    echo "__b2c__sbuffer[idx][tlen - len + nlen] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "long __b2c__istoken(char *string, char *token, ...) { char *delim; long len, x=0, start, result = 0; long length[1] = { 0 }; va_list ap; if (string == NULL || token == NULL) { return (0); }" >> $g_CTEMP
    echo "va_start (ap, token); delim = va_arg (ap, char *); va_end (ap); len = __b2c__len (token); while(1) { x++; start = __b2c__delim_engine (1, length, string, delim, x); if(length[0] == 0) { break; }" >> $g_CTEMP
    echo "if (len != length[0]) { continue; } if (memcmp (token, string + start, len) == 0) { result = x; break; } } return (result); }" >> $g_CTEMP
    echo "char *__b2c__uniq (char *string, ...) { char *delim; long x, y, len, dlen, total = 0, start1, start2, found, idx; long amount[1] = { 0 }; long length[1] = { 0 };" >> $g_CTEMP
    echo "va_list ap; if (string == NULL) { return (string); } va_start (ap, string); delim = va_arg (ap, char *); va_end (ap); if (delim == NULL) { delim = __b2c__option_delim; } dlen = __b2c__len (delim);" >> $g_CTEMP
    echo "idx = __sbuf_malloc_handle (__b2c__len (string) + 1); start1 = __b2c__delim_engine (2, amount, string, delim, 0); if (amount[0] <= 1) { return (string); } for (x = 1; x <= amount[0]; x++)" >> $g_CTEMP
    echo "{ start1 = __b2c__delim_engine (1, length, string, delim, x); len = length[0]; found = 0; for (y = x + 1; y <= amount[0]; y++) { start2 = __b2c__delim_engine (1, length, string, delim, y);" >> $g_CTEMP
    echo "if (len != length[0]) { continue; } if (memcmp (string + start1, string + start2, len) == 0) { found = 1; break; } } if(!found) { memmove (__b2c__sbuffer[idx] + total, string + start1, len);" >> $g_CTEMP
    echo "total += len; if (x < amount[0]) { memmove (__b2c__sbuffer[idx] + total, delim, dlen); total += dlen; } } } __b2c__SETLEN (__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\0';" >> $g_CTEMP
    echo "return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__sort(char *string, ...) { char **array; char *delim, *buffer; long start, total = 0, x, len, dlen, idx; long amount[1] = { 0 }; long length[1] = { 0 };" >> $g_CTEMP
    echo "va_list ap; if (string == NULL) { return (string); } va_start (ap, string); delim = va_arg (ap, char *); va_end (ap); if (delim == NULL) { delim = __b2c__option_delim; } dlen = __b2c__len (delim);" >> $g_CTEMP
    echo "buffer = __b2c__strdup (string); start = __b2c__delim_engine (2, amount, buffer, delim, 0); array = (char **) calloc (amount[0], sizeof (char *)); for (x = 1; x <= amount[0]; x++)" >> $g_CTEMP
    echo "{ start = __b2c__delim_engine (1, length, string, delim, x); buffer[start + length[0]] = '\0'; if(buffer[start] == 34 && buffer[start+length[0]-1] == 34) { buffer[start + length[0]-1] = '\0';" >> $g_CTEMP
    echo "array[x-1] = buffer + start + 1; } else { array[x-1] = buffer + start; } } qsort (&array[0], amount[0], sizeof (char *), __b2c__sortstr); idx = __sbuf_malloc_handle (__b2c__len (string) + amount[0]*2 + 1);" >> $g_CTEMP
    echo "for (x = 0; x < amount[0]; x++) { len = strlen (array[x]); if(strstr(array[x], delim)) { __b2c__sbuffer[idx][total] = 34; memmove (__b2c__sbuffer[idx] + total+1, array[x], len);" >> $g_CTEMP
    echo "__b2c__sbuffer[idx][total+len+1] = 34; total += len+2;} else { memmove (__b2c__sbuffer[idx] + total, array[x], len); total += len; } if (x < amount[0] - 1) { memmove (__b2c__sbuffer[idx] + total, delim, dlen);" >> $g_CTEMP
    echo "total += dlen; } } free (buffer); free (array); __b2c__SETLEN (__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__rev(char *string, ...) { char *delim; long start, total = 0, x, dlen, idx; long amount[1] = { 0 }; long length[1] = { 0 }; va_list ap;" >> $g_CTEMP
    echo "if (string == NULL) { return (string); } va_start (ap, string); delim = va_arg (ap, char *); va_end (ap); if (delim == NULL) { delim = __b2c__option_delim; } dlen = __b2c__len (delim);" >> $g_CTEMP
    echo "start = __b2c__delim_engine (2, amount, string, delim, 0); idx = __sbuf_malloc_handle (__b2c__len (string) + 1); for (x = amount[0]; x > 0; x--) { start = __b2c__delim_engine (1, length, string, delim, x);" >> $g_CTEMP
    echo "memmove(__b2c__sbuffer[idx] + total, string+start, length[0]); total+=length[0]; if (x > 1) { memmove (__b2c__sbuffer[idx] + total, delim, dlen); total += dlen; } }" >> $g_CTEMP
    echo "__b2c__SETLEN (__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__delim(char *string, char *from, char *to) { long start, total = 0, x, tlen, idx; long amount[1] = { 0 }; long length[1] = { 0 }; if (string == NULL || from == NULL || to == NULL)" >> $g_CTEMP
    echo "{ return (string); } tlen = __b2c__len(to); start = __b2c__delim_engine (2, amount, string, from, 0); idx = __sbuf_malloc_handle (__b2c__len (string) + amount[0]*tlen + 1);" >> $g_CTEMP
    echo "for (x = 1; x <= amount[0]; x++) { start = __b2c__delim_engine (1, length, string, from, x); memmove (__b2c__sbuffer[idx] + total, string + start, length[0]); total += length[0]; if (x < amount[0])" >> $g_CTEMP
    echo "{ memmove (__b2c__sbuffer[idx] + total, to, tlen); total += tlen; } } __b2c__SETLEN(__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\0'; return (char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__head (char *string, long pos, char *delim) { long start, idx; long amount[1] = { 0 }; long length[1] = { 0 }; if (string == NULL)" >> $g_CTEMP
    echo "{ return (string); } if (delim == NULL) { delim = __b2c__option_delim; } start = __b2c__delim_engine (2, amount, string, delim, 0);" >> $g_CTEMP
    echo "if (amount[0] < 1 || pos < 1) { return (EmptyString); } if (pos > amount[0]) { pos = amount[0]; } idx = __sbuf_malloc_handle (__b2c__len (string) + 1); start = __b2c__delim_engine (1, length, string, delim, pos);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx], string, start + length[0]); __b2c__SETLEN (__b2c__sbuffer[idx], start + length[0]); __b2c__sbuffer[idx][start + length[0]] = '\0'; return (char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__tail (char *string, long pos, char *delim) { long start, slen, idx; long amount[1] = { 0 }; long length[1] = { 0 }; if (string == NULL)" >> $g_CTEMP
    echo "{ return (string); } if (delim == NULL) { delim = __b2c__option_delim; } start = __b2c__delim_engine (2, amount, string, delim, 0);" >> $g_CTEMP
    echo "if (amount[0] < 1 || pos < 1) { return (EmptyString); } if (amount[0] - pos + 1 < 1) { pos = 1; } else { pos = amount[0] - pos + 1; } slen = __b2c__len (string); idx = __sbuf_malloc_handle(slen + 1);" >> $g_CTEMP
    echo "start = __b2c__delim_engine (1, length, string, delim, pos); memmove (__b2c__sbuffer[idx], string + start, slen-start); __b2c__SETLEN (__b2c__sbuffer[idx], slen-start); __b2c__sbuffer[idx][slen-start] = '\0';" >> $g_CTEMP
    echo "return(char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__append(char *string, long pos, char *cnew, char *delim) { long start, dlen, slen, nlen, idx, total = 0; long amount[1] = { 0 }; long length[1] = { 0 };" >> $g_CTEMP
    echo "if (cnew == NULL || pos < 0) { return (string); } if(string == NULL){ string = EmptyString; delim = EmptyString; } else if(delim == NULL){ delim = __b2c__option_delim; } start = __b2c__delim_engine (2, amount, string, delim, 0);" >> $g_CTEMP
    echo "if (amount[0] < 1) { return (cnew); } if (pos == 0) { pos = amount[0]+1; } dlen = __b2c__len (delim); nlen = __b2c__len (cnew); slen = __b2c__len (string); idx = __sbuf_malloc_handle (slen + nlen + dlen + 1); if (pos > amount[0])" >> $g_CTEMP
    echo "{ memmove(__b2c__sbuffer[idx], string, slen); memmove(__b2c__sbuffer[idx]+slen, delim, dlen); memmove(__b2c__sbuffer[idx]+slen+dlen, cnew, nlen); total = slen+dlen+nlen; } else { start = __b2c__delim_engine (1, length, string, delim, pos);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx], string, start); total += start; memmove (__b2c__sbuffer[idx] + total, cnew, nlen); total += nlen; memmove (__b2c__sbuffer[idx] + total, delim, dlen); total += dlen;" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx] + total, string + start, slen - start); total += (slen - start); } __b2c__SETLEN (__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__del(char *string, long pos, ...) { char *delim; long start, slen, dlen, idx, total = 0; long amount[1] = { 0 }; long length[1] = { 0 }; va_list ap; if (string == NULL)" >> $g_CTEMP
    echo "{ return (string); } va_start (ap, pos); delim = va_arg (ap, char *); va_end (ap); if (delim == NULL) { delim = __b2c__option_delim; } start = __b2c__delim_engine (2, amount, string, delim, 0); if (pos < 1 || pos > amount[0])" >> $g_CTEMP
    echo "{ return(string); } dlen = __b2c__len (delim); slen = __b2c__len (string); idx = __sbuf_malloc_handle (slen + 1); start = __b2c__delim_engine (1, length, string, delim, pos); memmove (__b2c__sbuffer[idx], string, start);" >> $g_CTEMP
    echo "total += start; if (pos < amount[0]) { memmove (__b2c__sbuffer[idx] + total, string + start + length[0] + dlen, slen-(start + length[0] + dlen)); total += slen-(start + length[0] + dlen); }" >> $g_CTEMP
    echo "else if(total >= dlen) { total -= dlen; } __b2c__SETLEN (__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__cut(char *string, long pos1, long pos2, ...) { char *delim; long start1, start2, idx, tmp, total = 0; long amount[1] = { 0 }; long length[1] = { 0 }; va_list ap; if (string == NULL)" >> $g_CTEMP
    echo "{ return (string); } va_start (ap, pos2); delim = va_arg (ap, char *); va_end (ap); if (delim == NULL) { delim = __b2c__option_delim; } if (pos1 > pos2) { tmp = pos1; pos1 = pos2; pos2 = tmp; } __b2c__delim_engine (2, amount, string, delim, 0);" >> $g_CTEMP
    echo "if(pos1 < 1) { pos1 = 1; } if(pos2 > amount[0]) { pos2 = amount[0]; } idx = __sbuf_malloc_handle (__b2c__len (string) + 1); start1 = __b2c__delim_engine (1, length, string, delim, pos1);" >> $g_CTEMP
    echo "start2 = __b2c__delim_engine (1, length, string, delim, pos2); memmove (__b2c__sbuffer[idx], string + start1, start2-start1+length[0]); total += (start2-start1+length[0]); __b2c__SETLEN (__b2c__sbuffer[idx], total);" >> $g_CTEMP
    echo "__b2c__sbuffer[idx][total] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char * __b2c__align (int l, char *k, char *str, unsigned long width, int mode, ...) { long start, x, y, left, idx, line_start = 0, last_write_pos, write_pos = 0, characters, last_read_pos, read_pos = 0, wtotal = 0, ctotal = 0, found = 0, tab, pos, cursor;" >> $g_CTEMP
    echo "int quoted, collapse, indent; long amount[1] = { 0 }; long total[1] = { 0 }; long length[1] = { 0 }; long lw[1] = { 0 }; char *string, *concat, *wrap, *line; va_list ap; if (str == NULL) { return (str); } if (width < 1) { return (EmptyString); }" >> $g_CTEMP
    echo "va_start (ap, mode); indent = va_arg (ap, int); va_end (ap); quoted = __b2c__option_quoted; __b2c__option_quoted = 0; string = __b2c__strdup(str); for (x = 0; string[x]; x++) { if (string[x] == 10 && string[x + 1] == 10) x++; else if (string[x] == 10) string[x] = 32; } x--;" >> $g_CTEMP
    echo "while (x >= 0 && string[x] == 32) { string[x] = 0; x--; } start = __b2c__delim_engine (2, amount, string, NULL, 0); concat = (char *) calloc (x + amount[0] + 1, sizeof (char)); for (x = 1; x <= amount[0]; x++) { start = __b2c__delim_engine (1, length, string, NULL, x);" >> $g_CTEMP
    echo "memmove (concat + ctotal, string + start, length[0]); ctotal += length[0]; if (x < amount[0]) { memset (concat + ctotal, 32, 1); ctotal += 1; } } wrap = (char *) calloc (ctotal + ctotal / width + 1, sizeof (char)); while (read_pos < ctotal)" >> $g_CTEMP
    echo "{ if (*(concat + read_pos) == 32) { if (write_pos == 0) { read_pos++; continue; } else { last_write_pos = wtotal; last_read_pos = read_pos; found = 1; } } memmove (wrap + wtotal, concat + read_pos, 1); write_pos++; wtotal++; if (*(concat + read_pos) == 10)" >> $g_CTEMP
    echo "{ write_pos = 0; line_start = wtotal; } else if ( (__b2c__option_utf8 ? __b2c__ucs2_clen (l, k, \"ALIGN$\", wrap + line_start, write_pos) : write_pos) >= width) { if (found) { memset (wrap + last_write_pos, 10, 1); wtotal = last_write_pos + 1; read_pos = last_read_pos; if (*(concat + read_pos + 1) == 10)" >> $g_CTEMP
    echo "{ read_pos++; } } else { memset (wrap + wtotal, 10, 1); wtotal += 1; } found = 0; write_pos = 0; line_start = wtotal; } read_pos++; } collapse = __b2c__collapse; __b2c__collapse = 0; start = __b2c__delim_engine (2, amount, wrap, \"\n\", 0); __b2c__collapse = collapse;" >> $g_CTEMP
    echo "line_start = 0; idx = __sbuf_malloc_handle (amount[0] * indent + amount[0] * width * 4 + 1); line = (char *) calloc (width * 4, sizeof (char)); for (x = 1; x <= amount[0]; x++) { collapse = __b2c__collapse; __b2c__collapse = 0; start = __b2c__delim_engine (1, length, wrap, \"\n\", x);" >> $g_CTEMP
    echo "while (*(wrap + start + length[0] - 1) == 32) { length[0]--; } characters = (__b2c__option_utf8 ? __b2c__ucs2_clen (l, k, \"ALIGN$\", wrap + start, length[0]) : length[0]); __b2c__collapse = collapse; switch (mode) { case 0: memset (__b2c__sbuffer[idx] + line_start, 32, indent); line_start += indent;" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx] + line_start, wrap + start, length[0]); line_start += length[0]; memset (__b2c__sbuffer[idx] + line_start, 32, width - characters); line_start += (width - characters); if (x < amount[0]) { memset (__b2c__sbuffer[idx] + line_start, '\n', 1);" >> $g_CTEMP
    echo "line_start++; } break; case 1: memset (__b2c__sbuffer[idx] + line_start, 32, indent); line_start += indent; memset (__b2c__sbuffer[idx] + line_start, 32, width - characters); line_start += (width - characters); memmove (__b2c__sbuffer[idx] + line_start, wrap + start, length[0]);" >> $g_CTEMP
    echo "line_start += length[0]; if (x < amount[0]) { memset (__b2c__sbuffer[idx] + line_start, '\n', 1); line_start++; } break; case 2: tab = (width - characters) / 2; memset (__b2c__sbuffer[idx] + line_start, 32, indent + tab); line_start += (indent + tab);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx] + line_start, wrap + start, length[0]); line_start += length[0]; memset (__b2c__sbuffer[idx] + line_start, 32, tab + (width - characters) % 2); line_start += (tab + (width - characters) % 2); if (x < amount[0])" >> $g_CTEMP
    echo "{ memset (__b2c__sbuffer[idx] + line_start, '\n', 1); line_start++; } break; case 3: memset (__b2c__sbuffer[idx] + line_start, 32, indent); line_start += indent; memset (line, 0, width * 4); memmove (line, wrap + start, length[0]); pos = __b2c__delim_engine (2, total, line, NULL, 0);" >> $g_CTEMP
    echo "if (total[0] == 0) { total[0] = 1; } cursor = 0; left = width - characters; for (y = 1; y <= total[0]; y++) { pos = __b2c__delim_engine (1, lw, line, NULL, y); memmove (__b2c__sbuffer[idx] + line_start + cursor, line + pos, lw[0]); cursor += lw[0]; if (left >= width / 2)" >> $g_CTEMP
    echo "{ if (y < total[0]) { tab = 1; } else { tab = left; } } else if (total[0] > 1) { tab = 1 + left / (total[0] - 1); if (left % (total[0] - 1)) { tab++; left--; } } else { tab = left; } if ((__b2c__option_utf8 ? __b2c__ucs2_clen (l, k, \"ALIGN$\", __b2c__sbuffer[idx] + line_start, cursor) : cursor) < width)" >> $g_CTEMP
    echo "{ memset (__b2c__sbuffer[idx] + line_start + cursor, 32, tab); cursor += tab; } } line_start += cursor; if (x < amount[0]) { memset (__b2c__sbuffer[idx] + line_start, '\n', 1); line_start++; } break; } } free (wrap); free (concat); free (line); free(string);" >> $g_CTEMP
    echo "__b2c__option_quoted = quoted; __b2c__SETLEN (__b2c__sbuffer[idx], line_start); __b2c__sbuffer[idx][line_start] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char * __b2c__proper (int l, char *k, char *string, ...) { char *delim, *local; long start, total = 0, x, y, dlen, blen, idx; long amount[1] = { 0 }; long length[1] = { 0 }; wchar_t wcs[8] = { 0 }; va_list ap; if (string == NULL) { return (string); }" >> $g_CTEMP
    echo "va_start (ap, string); delim = va_arg (ap, char *); va_end (ap); if (delim == NULL) { delim = __b2c__option_delim; } dlen = __b2c__len (delim); start = __b2c__delim_engine (2, amount, string, delim, 0); idx = __sbuf_malloc_handle (__b2c__len (string) + 1); if (__b2c__option_utf8)" >> $g_CTEMP
    echo "{ local = setlocale (LC_ALL, \"\"); for (x = 1; x <= amount[0]; x++) { start = __b2c__delim_engine (1, length, string, delim, x); blen = __b2c__blen (l, k, \"PROPER$\", string + start, 1, 0); if (mbtowc (wcs, string + start, blen) == (int) - 1) { ERROR = 38; RUNTIMEFERR (\"PROPER$\", ERROR, k, l); }" >> $g_CTEMP
    echo "*wcs = towupper (*wcs); if (wctomb (__b2c__sbuffer[idx] + total, *wcs) == (int) - 1) { ERROR = 38; RUNTIMEFERR (\"PROPER$\", ERROR, k, l); } for (y = blen; y < length[0]; y += blen) { blen = __b2c__blen (l, k, \"PROPER$\", string + start + y, 1, 0); if (mbtowc (wcs, string + start + y, blen) == (int) - 1)" >> $g_CTEMP
    echo "{ ERROR = 38; RUNTIMEFERR (\"PROPER$\", ERROR, k, l); } if(__b2c__option_proper == 0) { *wcs = towlower (*wcs); } if (wctomb (__b2c__sbuffer[idx] + total + y, *wcs) == (int) - 1) { ERROR = 38; RUNTIMEFERR (\"PROPER$\", ERROR, k, l); } } total += length[0]; if (x < amount[0]) { memmove (__b2c__sbuffer[idx] + total, delim, dlen);" >> $g_CTEMP
    echo "total += dlen; } } setlocale (LC_ALL, local); } else { for (x = 1; x <= amount[0]; x++) { start = __b2c__delim_engine (1, length, string, delim, x); *(__b2c__sbuffer[idx] + total) = toupper(*(string+start)); for (y = 1; y < length[0]; y ++) { *(__b2c__sbuffer[idx]+start+y) = (__b2c__option_proper == 0 ? tolower(*(string+start+y)) : *(string+start+y)); }" >> $g_CTEMP
    echo "total += length[0]; if (x < amount[0]) { memmove (__b2c__sbuffer[idx] + total, delim, dlen); total += dlen; } } } __b2c__SETLEN (__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__rotate(char *string, int pos, ...) { char *delim; long start, total = 0, x, dlen, idx; long amount[1] = { 0 }; long length[1] = { 0 }; va_list ap; if (string == NULL) { return (string); } va_start (ap, pos); delim = va_arg (ap, char *); va_end (ap);" >> $g_CTEMP
    echo "if (delim == NULL) { delim = __b2c__option_delim; } dlen = __b2c__len (delim); start = __b2c__delim_engine (2, amount, string, delim, 0); if(amount[0] <= 1) { return(string); } if(abs(pos) >= amount[0]) { pos = pos%amount[0]; } if (pos == 0) { return (string); } if(pos<0) { pos = amount[0]+pos; }" >> $g_CTEMP
    echo "idx = __sbuf_malloc_handle (__b2c__len (string) + 1); for (x = amount[0]-pos+1; x <= amount[0]; x++) { start = __b2c__delim_engine (1, length, string, delim, x); memmove (__b2c__sbuffer[idx] + total, string + start, length[0]); total += length[0]; memmove (__b2c__sbuffer[idx] + total, delim, dlen);" >> $g_CTEMP
    echo "total += dlen; } for (x = 1; x <= amount[0]-pos; x++) { start = __b2c__delim_engine (1, length, string, delim, x); memmove (__b2c__sbuffer[idx] + total, string + start, length[0]); total += length[0]; if (x < amount[0]-pos) { memmove (__b2c__sbuffer[idx] + total, delim, dlen); total += dlen; } }" >> $g_CTEMP
    echo "__b2c__SETLEN (__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__last (char *string, int pos, char *delim) { long start, slen, idx; long amount[1] = { 0 }; long length[1] = { 0 }; if (string == NULL) { return (string); } if (delim == NULL) { delim = __b2c__option_delim; }" >> $g_CTEMP
    echo "start = __b2c__delim_engine (2, amount, string, delim, 0); if (amount[0] <= 1 || pos <= 0) { return (string); } if (pos >= amount[0]) { return (EmptyString); } slen = __b2c__len (string); idx = __sbuf_malloc_handle (slen + 1); start = __b2c__delim_engine (1, length, string, delim, pos+1);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx], string + start, slen-start); __b2c__SETLEN (__b2c__sbuffer[idx], slen-start); __b2c__sbuffer[idx][slen-start] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char * __b2c__first (char *string, int pos, char *delim) { long dlen, end, idx; long amount[1] = { 0 }; long length[1] = { 0 }; if (string == NULL) { return (string); } if (delim == NULL) { delim = __b2c__option_delim; }" >> $g_CTEMP
    echo "end = __b2c__delim_engine (2, amount, string, delim, 0); if (amount[0] <= 1 || pos <= 0) { return (string); } if (pos >= amount[0]) { return (EmptyString); } idx = __sbuf_malloc_handle (__b2c__len (string) + 1); end = __b2c__delim_engine (1, length, string, delim, amount[0]-pos+1);" >> $g_CTEMP
    echo "dlen = __b2c__len (delim); memmove (__b2c__sbuffer[idx], string, end-dlen); __b2c__SETLEN (__b2c__sbuffer[idx], end-dlen); __b2c__sbuffer[idx][end-dlen] = '\0'; return(char*)(__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__explode (int l, char *k, char *string, int pos, ...) { char *delim; long x, dlen, len, blen, idx, ctr=0, where = 0, escaped = 0, in_string = 0; va_list ap; if (string == NULL || pos <= 0 || pos >= (len = __b2c__len (string)) ) { return (string); } va_start (ap, pos); delim = va_arg (ap, char *); va_end (ap); if (delim == NULL) { delim = __b2c__option_delim; }" >> $g_CTEMP
    echo "dlen = __b2c__len (delim); blen = pos; idx = __sbuf_malloc_handle (len + (len - 1) * dlen + 1); for (x = 0; x < len; x += blen) { if (__b2c__option_utf8) { blen = __b2c__blen(l, k, \"EXPLODE$\", string + x, pos, 0); } switch(*(string+x)) { case 92: escaped = 1 - escaped; break; case 34: if(!escaped && __b2c__option_quoted) { in_string = 1 - in_string; } escaped = 0; break;" >> $g_CTEMP
    echo "default: escaped = 0; } memmove (__b2c__sbuffer[idx] + where, string + x, blen); where+=blen; if (x < (len - blen) && !in_string) { memmove (__b2c__sbuffer[idx] + where, delim, dlen); where+=dlen; ctr+=dlen; } } __b2c__SETLEN (__b2c__sbuffer[idx], len+ctr); __b2c__sbuffer[idx][len+ctr] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__merge(char *string, ...) { char *delim; long start, total = 0, x, idx; long amount[1] = { 0 }; long length[1] = { 0 }; va_list ap; if (string == NULL) { return (string); } va_start (ap, string); delim = va_arg (ap, char *); va_end (ap);" >> $g_CTEMP
    echo "if (delim == NULL) { delim = __b2c__option_delim; } start = __b2c__delim_engine (2, amount, string, delim, 0); idx = __sbuf_malloc_handle (__b2c__len (string) + 1); for (x = 1; x <= amount[0]; x++) { start = __b2c__delim_engine (1, length, string, delim, x);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx] + total, string + start, length[0]); total += length[0]; } __b2c__SETLEN (__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    echo "char *__b2c__inbetween(int flag, char *haystack, char *lm, char *rm, int greedy) { char *l, *pos; int collapse; long idx, len, start, end=0, in, w1, w2; long length[1] = { 0 };" >> $g_CTEMP
    echo "if (haystack == NULL || lm == NULL || rm == NULL) { return (EmptyString); } collapse = __b2c__collapse; __b2c__collapse = 0; start = __b2c__delim_engine (2, length, haystack, lm, 2);" >> $g_CTEMP
    echo "if (start == 0) { __b2c__collapse = collapse; return (EmptyString); } if (greedy == 0) { in = __b2c__delim_engine (2, length, haystack+start+end, rm, 2); if (in == 0) { __b2c__collapse = collapse; return (EmptyString); }" >> $g_CTEMP
    echo "l = haystack+start-__b2c__len(lm); pos = haystack+start+in-__b2c__len(rm); } else if (greedy == 1) { while (1) { in = __b2c__delim_engine (2, length, haystack+start+end, rm, 2); if(in) { end += in; } else { break; } }" >> $g_CTEMP
    echo "if (end == 0) { __b2c__collapse = collapse; return (EmptyString); } l = haystack+start-__b2c__len(lm); pos = haystack+start+end-__b2c__len(rm); } else { w1 = start; w2 = start;" >> $g_CTEMP
    echo "while (1) { end = __b2c__delim_engine (2, length, haystack + w1, rm, 2); if (end == 0) { __b2c__collapse = collapse; return (EmptyString); } in = __b2c__delim_engine (2, length, haystack + w2, lm, 2); if (in && ((w2 + in) < (w1 + end)))" >> $g_CTEMP
    echo "{ w1 = w1 + end; w2 = w2 + in; } else { break; } } l = haystack + start - __b2c__len (lm); pos = haystack + w1 + end - __b2c__len (rm); } if (flag) { pos += strlen (rm); len = strlen (pos); idx = __sbuf_malloc_handle ((l - haystack) + len + 1);" >> $g_CTEMP
    echo "memmove (__b2c__sbuffer[idx], haystack, l - haystack); memmove (__b2c__sbuffer[idx] + (l - haystack), pos, len); __b2c__SETLEN (__b2c__sbuffer[idx], (l - haystack) + len); __b2c__sbuffer[idx][(l - haystack) + len] = '\0'; } else" >> $g_CTEMP
    echo "{ l += strlen (lm); idx = __sbuf_malloc_handle (pos - l + 1); memmove (__b2c__sbuffer[idx], l, pos - l); __b2c__SETLEN (__b2c__sbuffer[idx], pos - l); __b2c__sbuffer[idx][pos - l] = '\0'; } return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
     g_OBJ_FILES="$g_OBJ_FILES bacon.token.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.token.o: bacon.token.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.token.c"

    g_CTEMP="$g_TEMPDIR/bacon.ucase.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char * __b2c__ucase (int l, char *k, char *src) { long idx, len, i; size_t mbslen; wchar_t *wcs, *wp; char *local; if (src == NULL) { return (NULL); } len = __b2c__len (src); idx = __sbuf_malloc_handle (len + 1); if (__b2c__option_utf8)" >> $g_CTEMP
    echo "{ local = setlocale (LC_ALL, \"\"); if ((mbslen = mbstowcs (NULL, src, 0)) == (size_t) - 1) { ERROR = 38; RUNTIMEFERR (\"UCASE$\", ERROR, k, l); } wcs = (wchar_t*)calloc (mbslen + 1, sizeof (wchar_t)); if (mbstowcs (wcs, src, mbslen + 1) == (size_t) - 1)" >> $g_CTEMP
    echo "{ ERROR = 38; RUNTIMEFERR (\"UCASE$\", ERROR, k, l); } for (wp = wcs; *wp != 0; wp++) { *wp = towupper (*wp); } if (wcstombs (__b2c__sbuffer[idx], wcs, len) == (size_t) - 1) { ERROR = 38; RUNTIMEFERR (\"UCASE$\", ERROR, k, l); } free (wcs);" >> $g_CTEMP
    echo "setlocale (LC_ALL, local); } else { for (i = 0; i < len; i++) { __b2c__sbuffer[idx][i] = toupper (src[i]); } } __b2c__SETLEN (__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.ucase.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.ucase.o: bacon.ucase.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.ucase.c"

    g_CTEMP="$g_TEMPDIR/bacon.utf8.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "int __b2c_utf8_conv(int txt, char* utf8) { unsigned char b1, b2, b3; int len; if (txt > 0xFFFF) { b1 = txt & 0x0000FF; b2 = (txt & 0x00FF00) >> 8; b3 = (txt & 0xFF0000) >> 16;" >> $g_CTEMP
    echo "len = snprintf (utf8, 5, \"%c%c%c%c\", 0xF0 | (b3 >> 2), 0x80 | ((b3 & 0x03) << 4) | ((b2 & 0xF0) >> 4), 0x80 | ((b2 & 0x0F) << 2) | ((b1 & 0xC0) >> 6)," >> $g_CTEMP
    echo "0x80 | (b1 & 0x3F)); } else if (txt > 0x07FF) { b1 = txt & 0x00FF; b2 = (txt & 0xFF00) >> 8; len = snprintf (utf8, 4, \"%c%c%c\", 0xE0 | ((b2 & 0xF0) >> 4)," >> $g_CTEMP
    echo "0x80 | ((b2 & 0x0F) << 2) | ((b1 & 0xC0) >> 6), 0x80 | (b1 & 0x3F)); } else if (txt > 0x007F) { b1 = txt & 0x00FF; b2 = (txt & 0xFF00) >> 8; len = snprintf (utf8, 3, \"%c%c\"," >> $g_CTEMP
    echo "0xC0 | (b2 << 2) | ((b1 & 0xC0) >> 6), 0x80 | (b1 & 0x3F)); } else { len = snprintf (utf8, 2, \"%c\", txt & 0x7F); } return(len); }" >> $g_CTEMP
    echo "unsigned long __b2c__ulen (int l, char *k, char *func, ...) { int pos; long len = 0; char *ptr; va_list ap; va_start (ap, func); ptr = va_arg (ap, char*); pos = va_arg (ap, int); va_end (ap); if (ptr == NULL) { return(0); } if(pos < 0) { while(*ptr){ if((*ptr&0xF0) == 0xF0) { len++; ptr += 4; } else if((*ptr&0xE0) == 0xE0) { len++; ptr += 3; }" >> $g_CTEMP
    echo "else if((*ptr&0xC0) == 0xC0) { len++; ptr += 2; } else if((*ptr&0x80) == 0) { len++; ptr++; } else { ERROR = 38; RUNTIMEFERR(func, ERROR, k, l); } } } else { len = __b2c__ucs2_clen(l, k, \"ULEN\", ptr, pos); } return(len); }" >> $g_CTEMP
    echo "unsigned long __b2c__blen (int l, char *k, char *func, char *ptr, long c, ...) { va_list ap; char *org = ptr; int flag; if (ptr == NULL){ return (0); } va_start (ap, c); flag = va_arg(ap, int); va_end (ap);" >> $g_CTEMP
    echo "if(flag) { c = __b2c__ulen (l, k, \"BYTELEN\", org, -1)-c; } while (*ptr && c > 0) { if ((*ptr & 0xF0) == 0xF0) { ptr += 4; } else if ((*ptr & 0xE0) == 0xE0) { ptr += 3; } else if ((*ptr & 0xC0) == 0xC0) { ptr += 2; } else if ((*ptr & 0x80) == 0)" >> $g_CTEMP
    echo "{ ptr++; } else { ERROR = 38; fprintf (stderr, \"Cannot decode UTF-8 string: '%s'\n\", org); RUNTIMEFERR (func, ERROR, k, l); } c--; } if(flag) { return (__b2c__len(org) - (ptr - org)); } else { return (ptr - org); } }" >> $g_CTEMP
    echo "unsigned long __b2c__ucs2_clen (int l, char* k, char *func, char *ptr, int c) { int len = 0; char *org; if (ptr == NULL) return (0); org = ptr; while (*ptr && c > 0) { if ((*ptr & 0xF0) == 0xF0) { ptr += 4; c -= 4; } else if ((*ptr & 0xE0) == 0xE0)" >> $g_CTEMP
    echo "{ ptr += 3; c -= 3; } else if ((*ptr & 0xC0) == 0xC0) { ptr += 2; c -= 2; } else if ((*ptr & 0x80) == 0) { ptr++; c--; } else { ERROR = 38; fprintf(stderr, \"Cannot decode UTF-8 string: '%s'\n\", org); RUNTIMEFERR (func, ERROR, k, l); } len++; } return (len); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.utf8.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.utf8.o: bacon.utf8.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.utf8.c"

    g_CTEMP="$g_TEMPDIR/bacon.version.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "void __b2c__version(char* in){if(strcmp(\"${g_VERSION}\", in)) {printf(\"System error: this BaCon binary was compiled with a previous BaCon archive and therefore may not function correctly.\n\");" >> $g_CTEMP
    echo "printf(\"Recompile your program using the '-a' flag.\n\"); exit(EXIT_FAILURE);} }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.version.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.version.o: bacon.version.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.version.c"

    g_CTEMP="$g_TEMPDIR/bacon.wait.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__netpeek(int l, char *k, int fd, int usec){fd_set rfds; struct timeval tv; long retval; struct termios oldt = { 0}, newt = { 0 }; if(fd == STDIN_FILENO){tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO);" >> $g_CTEMP
    echo "newt.c_cc[VMIN]=1; newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &newt);} FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_usec = (usec%1000)*1000; tv.tv_sec = usec/1000; retval = select(fd + 1, &rfds, NULL, NULL, &tv);" >> $g_CTEMP
    echo "if (retval == -1 && __b2c__trap) {ERROR = 16; RUNTIMEFERR(\"WAIT\", ERROR, k, l);} if(fd == STDIN_FILENO){if(retval) if(read(fd, &retval, 1)==0) retval=0; tcsetattr(STDIN_FILENO, TCSANOW, &oldt);} return(retval);}" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.wait.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.wait.o: bacon.wait.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.wait.c"
fi

# Always link with '-lbacon', should be defined before regex linking definition
if [[ $g_LDFLAGS != +(*-lbacon++*) ]]
then
    g_LDFLAGS="-lbacon ${g_LDFLAGS}"
fi

if [[ -n ${g_REBUILD_ARCHIVE} || -n ${g_PRAGMA_REGEX} ]]
then
    g_CTEMP="$g_TEMPDIR/bacon.extract.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char *__b2c__extract(int l, char *k, char *src, char *needle, int flag) { int reti, len, pos = 0; char *tmp; regex_t regex; char __b2c__buf[100]; regmatch_t where[1]; long idx;" >> $g_CTEMP
    echo "if (src == NULL || needle == NULL) { return (src); } if (__b2c__len(src) == 0 || __b2c__len(needle) == 0) { return(src); } idx = __sbuf_malloc_handle(__b2c__len(src) + 1);" >> $g_CTEMP
    echo "if (flag > 0) { if (__b2c__option_compare == 0) reti = regcomp (&regex, needle, REG_EXTENDED); else reti = regcomp (&regex, needle, REG_EXTENDED | REG_ICASE);" >> $g_CTEMP
    echo "if (__b2c__trap && reti) { ERROR = 27; regerror (reti, &regex, __b2c__buf, sizeof (__b2c__buf)); fprintf (stderr, \"%s\n\", __b2c__buf); RUNTIMEFERR(\"EXTRACT$\", ERROR, k, l); }" >> $g_CTEMP
    echo "while ((reti = regexec (&regex, src, 1, where, 0)) == 0) { memcpy (__b2c__sbuffer[idx] + pos, src, (size_t) where[0].rm_so); pos += where[0].rm_so; src += (long) where[0].rm_eo;}" >> $g_CTEMP
    echo "regfree (&regex); len = strlen(src); memcpy (__b2c__sbuffer[idx] + pos, src, len); pos += len; } else { while ((tmp = strstr (src, needle)) != NULL) {" >> $g_CTEMP
    echo "memcpy (__b2c__sbuffer[idx] + pos , src, (size_t) (tmp - src) ); pos += tmp - src; src = tmp + __b2c__len(needle); }" >> $g_CTEMP
    echo "len = strlen(src); memcpy (__b2c__sbuffer[idx] + pos, src, len ); pos += len; }" >> $g_CTEMP
    echo "__b2c__SETLEN (__b2c__sbuffer[idx], pos); __b2c__sbuffer[idx][pos] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.extract.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.extract.o: bacon.extract.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.extract.c"

    g_CTEMP="$g_TEMPDIR/bacon.regex.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "long __b2c__regex(int l, char *k, char* x, char* y){regex_t reg; int reti; char buf[100]; regmatch_t where[1]; if(x == NULL || y == NULL) return(0); if(__b2c__option_compare == 0) reti = regcomp(&reg, y, REG_EXTENDED);" >> $g_CTEMP
    echo "else  reti = regcomp(&reg, y, REG_EXTENDED|REG_ICASE); if(__b2c__trap && reti){ERROR=27; regerror(reti, &reg, buf, sizeof(buf)); fprintf(stderr, \"%s\n\", buf); RUNTIMEFERR(\"REGEX\", ERROR, k, l);}" >> $g_CTEMP
    echo "reti = regexec(&reg, x, 1, where, 0); regfree(&reg); if( !reti ) {REGLEN = where[0].rm_eo - where[0].rm_so; return (where[0].rm_so+1);} else {REGLEN = 0; return (0);} }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.regex.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.regex.o: bacon.regex.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.regex.c"

    g_CTEMP="$g_TEMPDIR/bacon.replace.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "char *__b2c__replace(int l, char *k, char *haystack, char *needle, char *replace, int flag) { char *tmp; long replen, hstlen, ndllen, length = 0; regex_t regex; int i, reti; long idx; char buf[100]; regmatch_t where[1];" >> $g_CTEMP
    echo "if(haystack == NULL || needle == NULL) { return (haystack); } if(replace==NULL) { replace = EmptyString; } ndllen = __b2c__len(needle); hstlen = __b2c__len(haystack);" >> $g_CTEMP
    echo "if(hstlen == 0 || ndllen == 0) { return(haystack); } if (flag == 2) { idx = __sbuf_malloc_handle (hstlen + 1); strncpy (__b2c__sbuffer[idx], haystack, hstlen); for (i = 0; i < hstlen; i++){ if ((tmp = strchr (needle, __b2c__sbuffer[idx][i])) != NULL)" >> $g_CTEMP
    echo "{ __b2c__sbuffer[idx][i] = replace[tmp - needle]; } } __b2c__SETLEN (__b2c__sbuffer[idx], i); __b2c__sbuffer[idx][i] = '\0'; return (char *) (__b2c__sbuffer[idx]); } idx = __sbuf_malloc_handle (sizeof (char)); __b2c__sbuffer[idx][0] = '\0';" >> $g_CTEMP
    echo "replen = __b2c__len(replace); if (flag == 1) { if (__b2c__option_compare == 0) reti = regcomp (&regex, needle, REG_EXTENDED); else reti = regcomp (&regex, needle, REG_EXTENDED | REG_ICASE); if (__b2c__trap && reti) { ERROR = 27;" >> $g_CTEMP
    echo "regerror (reti, &regex, buf, sizeof (buf)); fprintf (stderr, \"%s\n\", buf); RUNTIMEFERR(\"REPLACE$\", ERROR, k, l); } while ((reti = regexec (&regex, haystack, 1, where, 0)) == 0) { __sbuf_need_realloc (idx, length + where[0].rm_so + replen + 1);" >> $g_CTEMP
    echo "memcpy (__b2c__sbuffer[idx] + length, haystack, (size_t) where[0].rm_so); length += where[0].rm_so; memcpy (__b2c__sbuffer[idx] + length, replace, replen); length += replen; haystack += (long) where[0].rm_eo; } regfree (&regex); }" >> $g_CTEMP
    echo "else { while ((tmp = strstr (haystack, needle)) != NULL) { __sbuf_need_realloc (idx, length + tmp - haystack + replen + 1); memcpy (__b2c__sbuffer[idx] + length, haystack, (size_t) (tmp - haystack)); length += tmp - haystack;" >> $g_CTEMP
    echo "memcpy (__b2c__sbuffer[idx] + length, replace, replen); length += replen; haystack = tmp + ndllen; }} hstlen = strlen (haystack); __sbuf_need_realloc (idx, length + hstlen + 1); memcpy (__b2c__sbuffer[idx] + length, haystack, hstlen);" >> $g_CTEMP
    echo "length += hstlen; __b2c__SETLEN (__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.replace.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.replace.o: bacon.replace.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.replace.c"

    g_CTEMP="$g_TEMPDIR/bacon.walk.c"
    g_TMP_FILES="$g_TMP_FILES $g_CTEMP"
    echo "#include \"${g_SOURCEFILE##*/}.generic.h\"" > $g_CTEMP
    echo "#ifndef PATH_MAX" >> $g_CTEMP
    echo "#define PATH_MAX 4096" >> $g_CTEMP
    echo "#endif" >> $g_CTEMP
    echo "void __b2c__recurse_dir(long idx, regex_t reg, int type, char *delim, int dlen, char *dir, int orgdirlen, int recurse) { DIR* here; struct dirent *item; char news[PATH_MAX] = { 0 }; regmatch_t where[1]; int reti, nlen, slen; struct stat buf; here = opendir(dir);" >> $g_CTEMP
    echo "if(here == NULL) { return; } while(1) { item = readdir(here); if(item == NULL) { break; } if(!strcmp(item->d_name, \".\") || !strcmp(item->d_name, \"..\")) { continue; } strcpy(news, dir); strcat(news, \"/\"); strcat(news, item->d_name); reti = regexec(&reg, news+orgdirlen, 1, where, 0);" >> $g_CTEMP
    echo "if(reti != REG_NOMATCH) { slen = __b2c__len(__b2c__sbuffer[idx]); nlen = __b2c__len(news); __sbuf_need_realloc(idx, slen+nlen+dlen+1); if(lstat(news, &buf) < 0 && __b2c__trap) { ERROR = 24; fprintf(stderr, \"%s: %s\n\", news, strerror(errno)); }" >> $g_CTEMP
    echo "else if((type == 1 && S_ISREG(buf.st_mode)) || (type == 2 && S_ISDIR(buf.st_mode)) || (type == 3 && S_ISCHR(buf.st_mode)) || (type == 4 && S_ISBLK(buf.st_mode)) || (type == 5 && S_ISFIFO(buf.st_mode)) || (type == 6 && S_ISLNK(buf.st_mode)) || (type == 7 && S_ISSOCK(buf.st_mode)) )" >> $g_CTEMP
    echo "{ memmove (__b2c__sbuffer[idx] + slen, news+orgdirlen, nlen-orgdirlen); memmove(__b2c__sbuffer[idx]+slen+nlen-orgdirlen, delim, dlen); __b2c__SETLEN(__b2c__sbuffer[idx], slen+nlen+dlen-orgdirlen); __b2c__sbuffer[idx][slen+nlen+dlen-orgdirlen] = '\0'; } }" >> $g_CTEMP
    echo "if(recurse) { __b2c__recurse_dir(idx, reg, type, delim, dlen, news, orgdirlen, recurse); } } closedir(here); }" >> $g_CTEMP
    echo "char *__b2c__walk(int l, char *k, char *dir, int type, char *exp, int recurse, ...) { regex_t reg; int reti, len, dlen; char buf[100]; long idx; va_list ap; char *delim; if(dir == NULL || exp == NULL){ return(EmptyString); } va_start(ap, recurse); delim = va_arg(ap, char *);" >> $g_CTEMP
    echo "va_end(ap); if (delim == NULL) { delim = __b2c__option_delim; } if((type < 1 || type > 7) && __b2c__trap) { ERROR = 5; RUNTIMEFERR(\"WALK\", ERROR, k, l); } if (__b2c__option_compare == 0){ reti = regcomp (&reg, exp, REG_EXTENDED); } else { reti = regcomp (&reg, exp, REG_EXTENDED | REG_ICASE); } if (__b2c__trap && reti)" >> $g_CTEMP
    echo "{ ERROR = 27; regerror(reti, &reg, buf, sizeof(buf)); fprintf(stderr, \"%s\n\", buf); RUNTIMEFERR(\"WALK\", ERROR, k, l); } dlen = __b2c__len(delim); idx = __sbuf_malloc_handle(PATH_MAX*sizeof(char)); __b2c__recurse_dir(idx, reg, type, delim, dlen, dir, __b2c__len(dir)+1, recurse);" >> $g_CTEMP
    echo "regfree(&reg); len = __b2c__len(__b2c__sbuffer[idx]); if(len == 0) { dlen = 0; } else { dlen = __b2c__len(delim); } __b2c__SETLEN(__b2c__sbuffer[idx], len-dlen); __b2c__sbuffer[idx][len-dlen] = '\0'; return (char *) (__b2c__sbuffer[idx]); }" >> $g_CTEMP
    g_OBJ_FILES="$g_OBJ_FILES bacon.walk.o"
    g_MAKE_LINE="$g_MAKE_LINE\nbacon.walk.o: bacon.walk.c\n\t$g_CCNAME $g_CCFLAGS -c bacon.walk.c"
    
    if [[ -n ${g_PRAGMA_REGEX} ]]
    then
        g_TMP_FILES="$g_TMP_FILES libregex.a"
        g_REBUILD_ARCHIVE="libregex.a"
        g_LDFLAGS="-lregex $g_LDFLAGS"
    fi
fi

# Include ALARM prototypes
if [[ -n $g_ALARM_PROTO ]]
then
    echo $g_ALARM_PROTO >> $g_HFILE
fi

# Include local buffers
if [[ -n $g_LOCAL_SBUFFER ]]
then
    echo ${g_LOCAL_SBUFFER} >> $g_HFILE
fi

# Include functions and subs
for i in $g_INCLUDE_FILES
do
    echo "#include \"${i}\"" >> $g_HFILE
done

# Check if generated source file exists
if [[ -f $SRCARRAYFILE ]]
then
    echo "#include \"$SRCARRAYFILE\"" >> $g_HFILE
    g_TMP_FILES="${g_TMP_FILES} $SRCARRAYFILE"
fi

((g_TOTAL_LINES+=$g_COUNTER))
ttime=$(($SECONDS-$ttime))
echo -e "\rConverting '${g_SOURCEFILE}'... done, ${g_TOTAL_LINES} lines were processed in ${ttime} seconds."

# Check MEMORY/FREE
if [[ $g_SEMANTIC -eq 0 ]]
then
    if [[ -n $(echo $g_SEMANTIC_MEMFREE) ]]
    then
	IFS="@"
        for i in $g_SEMANTIC_MEMFREE
	do
	    if [[ -n $i ]]
	    then
		echo -e "Warning: no FREE for the memory address $(echo ${i% *})!"
	    fi
	done
	IFS="${g_ORGIFS}"
    fi
fi

# Check OPEN/CLOSE handles
if [[ $g_SEMANTIC -eq 0 ]]
then
    if [[ -n $(echo $g_SEMANTIC_OPENCLOSE) ]]
    then
	IFS="@"
        for i in $g_SEMANTIC_OPENCLOSE
	do
	    if [[ -n $i ]]
	    then
		echo -e "Warning: no CLOSE for the OPEN handle $(echo ${i% *})!"
	    fi
	done
	IFS="${g_ORGIFS}"
    fi
fi

# Show error in case function has no end
if [[ -n $g_FUNCNAME ]]
then
    echo -e "Syntax error: the SUB/FUNCTION '$g_FUNCNAME' has no END in file '$g_CURFILE'!"
    exit 1
fi

# Indentation only when files are preserved
if [[ $g_TMP_PRESERVE -eq 1 ]]
then
    if [[ -n `which indent 2>/dev/null` ]]
    then
	echo -n "Applying indentation... "
	for i in $g_TMP_FILES
	do
	    if [[ $i != +(*.cpp) && $i != +(*.tmp) && $i != +(*.bac) && $i != +(*.a) ]]
	    then
		if [[ `uname` = "Darwin" || `uname` = +(*BSD*) ]]
		then
		    mv ${i} "${i}.BAK"
		    indent "${i}.BAK" ${i}
		    rm "${i}.BAK"
		else
		    indent $i
		    rm $i~
		fi
	    fi
	done
	echo "done."
    else
	echo "WARNING: 'indent' not found on this system!"
	echo "Generated source code cannot be beautified."
    fi
fi

# Check if we need to run xgettext
if [[ ${g_XGETTEXT} -eq 1 ]]
then
    if [[ -n `which xgettext 2>/dev/null` ]]
    then
	echo -n "Executing xgettext... "
	xgettext -d ${g_SOURCEFILE%.*} -s -o ${g_SOURCEFILE%.*}.pot $g_TMP_FILES
	if [[ ! -f "${g_SOURCEFILE%.*}.pot" ]]
	then
	    echo "WARNING: catalog file not created!"
	else
	    echo "done."
	fi
    else
	echo "WARNING: 'xgettext' not found on this system!"
    fi
fi

# Creation of the Makefile
echo -e "# Created with Shell BaCon $g_VERSION - (c) Peter van Eerten - MIT License\n" > $g_TEMPDIR/Makefile.bacon
BASE="${g_SOURCEFILE%.*}"
echo -e "${BASE##*/}$g_BINEXT: ${g_SOURCEFILE##*/}.o ${g_REBUILD_ARCHIVE}" >> $g_TEMPDIR/Makefile.bacon
echo -e "\t$g_CCNAME -o ${BASE##*/}$g_BINEXT ${g_SOURCEFILE##*/}.o $g_LDFLAGS ${g_LIB_TLS}" >> $g_TEMPDIR/Makefile.bacon
echo -e "${g_SOURCEFILE##*/}.o: ${g_SOURCEFILE##*/}.c" >> $g_TEMPDIR/Makefile.bacon
echo -e "\t$g_CCNAME $g_CCFLAGS -c ${g_SOURCEFILE##*/}.c" >> $g_TEMPDIR/Makefile.bacon
if [[ -n ${g_REBUILD_ARCHIVE} && $g_NO_COMPILE -eq 0 ]]
then
    echo -e "New BaCon archive requested! Creating..."
    rm -f $g_TEMPDIR/${g_REBUILD_ARCHIVE}
    echo -e "\n${g_REBUILD_ARCHIVE}: ${g_OBJ_FILES}" >> $g_TEMPDIR/Makefile.bacon
    echo -e "\t${g_ARNAME} ${g_REBUILD_ARCHIVE} ${g_OBJ_FILES} >/dev/null 2>&1" >> $g_TEMPDIR/Makefile.bacon
    if [[ -n ${g_RANLIB} ]]
    then
        echo -e "\t${g_RANLIB} ${g_REBUILD_ARCHIVE}" >> $g_TEMPDIR/Makefile.bacon
    fi
    echo -e "${g_MAKE_LINE}" >> $g_TEMPDIR/Makefile.bacon
fi
echo -e "\n.PHONY: clean" >> $g_TEMPDIR/Makefile.bacon
echo -e "clean:" >> $g_TEMPDIR/Makefile.bacon
echo -e "\trm -f *.o *.c ${g_SOURCEFILE%.*}$g_BINEXT ${g_SOURCEFILE%.bac}.*.* ${g_REBUILD_ARCHIVE} Makefile.bacon" >> $g_TEMPDIR/Makefile.bacon
g_TMP_FILES="$g_TMP_FILES $g_TEMPDIR/Makefile".bacon

# Start compilation
if [[ $g_NO_COMPILE -eq 0 ]]
then
    if [[ -z `which $g_CCNAME 2>/dev/null` ]]
    then
	echo "WARNING: '$g_CCNAME' not found on this system!"
	echo "Generated source code cannot be compiled."
	exit 0
    fi
    echo -n "Compiling '${g_SOURCEFILE}'... "

    # Make sure GCC uses English localization
    export LANG="C"

    # Using 'cd' here to be compatible with older make's
    cd $g_TEMPDIR
    make -f Makefile.bacon 2>${g_SOURCEFILE##*/}.log
    RETURN_CODE=$?

    # Go back to working directory
    cd - >/dev/null

    g_TMP_FILES="$g_TMP_FILES $g_TEMPDIR/${g_SOURCEFILE##*/}.log $g_TEMPDIR/${g_SOURCEFILE##*/}.o"

    if [[ -z `cat $g_TEMPDIR/${g_SOURCEFILE##*/}.log` ]]
    then
	echo "Done, program '${g_SOURCEFILE%.*}$g_BINEXT' ready."
    else
	# Only print first error
	echo -e "Compiler error:"
	while read -r g_ERROR
	do
            if [[ ( ${g_ERROR} != +(*from *) || ${g_ERROR} = +(*error:*from*) ) && ${g_ERROR} = +(*[0-9]*) && ${g_ERROR} = +(*: error:*) && $g_ERROR != +(*-----*) ]]
	    then
		g_ERRORTXT="Cause:\n\t${g_ERROR##*error:}"
		g_FILE_LINE=${g_ERROR%%error:*}
		break
	    elif [[ ( ${g_ERROR} != +(*from *) || ${g_ERROR} = +(*Error:*from*) ) && ${g_ERROR} = +(*[0-9]*) && ${g_ERROR} = +(*: Error:*) && $g_ERROR != +(*-----*) ]]
	    then
		g_ERRORTXT="Cause:\n\t${g_ERROR##*:}"
		g_FILE_LINE=${g_ERROR##*Error: }
		break
	    elif [[ ( ${g_ERROR} != +(*from *) || ${g_ERROR} = +(*warning:*from*) ) && ${g_ERROR} = +(*[0-9]*) && ${g_ERROR} = +(*: warning:*) && $g_ERROR != +(*-----*) ]]
	    then
		g_ERRORTXT="Cause:\n\t${g_ERROR##*warning:}"
		g_FILE_LINE=${g_ERROR%%warning:*}
		break
	    elif [[ ( ${g_ERROR} != +(*from *) || ${g_ERROR} = +(*:*from*) ) && ${g_ERROR} = +(*[0-9]:*) && $g_ERROR != +(*-----*) ]]
	    then
		g_ERRORTXT="Cause:\n\t${g_ERROR##*:}"
		g_FILE_LINE=${g_ERROR%:*}
		break
	    fi
	done < $g_TEMPDIR/${g_SOURCEFILE##*/}.log

	# Go find last mentioning of error file
	while read -r g_ERROR
	do
	    if [[ $g_ERROR = +(*:[0-9]*:[0-9]*:*) && $g_ERROR != +(*.bac.generic.h*) ]]
	    then
		g_FILE_LINE=${g_ERROR%% *}
	    fi
	done < $g_TEMPDIR/${g_SOURCEFILE##*/}.log

	# Restore $-symbol if there is any
	if [[ $g_ERRORTXT = +(*${g_STRINGSIGN}*) ]]
	then
	    LEN=${#g_STRINGSIGN}
	    POS=0
	    until [[ $POS -eq ${#g_ERRORTXT} ]]
	    do
		SUBSTR="${g_ERRORTXT:${POS}:${LEN}}"
		if [[ $SUBSTR = $g_STRINGSIGN ]]
		then
		    SUBSTR="${g_ERRORTXT:0:${POS}}$"
		    ((POS+=${LEN}))
		    g_ERRORTXT="${SUBSTR}${g_ERRORTXT:${POS}:${#g_ERRORTXT}}"
		    break
		fi
		((POS+=1))
	    done
	fi

	# Get the file where the error is
	g_FILE=$g_TEMPDIR/${g_FILE_LINE%%:*}
	# Tru64Unix helper
	g_FILE=${g_FILE%%,*}

	# Non-gcc or parse problem (file does not exist)
	if [[ $g_CCFLAGS = +(*Wall*) || ! -f $g_FILE || $g_FILE = +(*.bac.generic.h) ]]
	then
	    echo
	    cat $g_TEMPDIR/${g_SOURCEFILE##*/}.log
	    echo
	else
	    # Get the erroneous line
	    if [[ ${g_FILE_LINE#*:} = +(*line*) ]]
	    then
		g_LINE=${g_FILE_LINE#*line}
	    else
		g_LINE=${g_FILE_LINE#*:}
	    fi
            # If no line number was found
            if [[ $g_LINE = +(*[a-zA-Z]*) ]]
            then
                g_LINE=1
            fi
	    # Remove everything behind last colon
	    g_LINE=${g_LINE%%:*}
            # Get the filename
            g_FEED=$(grep '^#define __b2c_filename' $g_FILE)
            g_FEED=$(echo ${g_FEED##*__b2c_filename } | tr -d "\042")
            if [[ $g_FEED != +(*.bac) ]]
            then
                g_FEED="${g_TEMPDIR}/${g_FEED}"
            fi
            # Error is at end of file
            if [[ $g_LINE -ge $(wc -l $g_FILE | cut -d" " -f1) ]]
            then
                COUNTER=$(wc -l $g_FEED | cut -d" " -f1)
                LINE="undefined syntax error, hint: check for missing ENDIF, WEND, NEXT."
            else
                # Get the line number in the source
                let LINE=$(wc -l $g_FILE | cut -d" " -f1)-${g_LINE}
                COUNTER=$(cat $g_FILE | head -${LINE} | grep '^#define __b2c_lineno' | tail -1)
                COUNTER=${COUNTER##*__b2c_lineno }
                # Get the line text
                LINE=$(echo $(cat $g_FEED | head -${COUNTER} | tail -1) )
            fi
            # Print the error
	    echo -e "\nDescription:\n\t file '$g_FEED' line $COUNTER: ${LINE}"
	    echo -e "$g_ERRORTXT\n"
	    # Print extra hints
	    if [[ ${g_ERRORTXT} = +(*implicit*declaration*) ]]
	    then
		echo -e "\t hint: check for missing header file or library.\n"
	    fi
	fi
	# Preserve temp files
	g_TMP_PRESERVE=1
    fi
fi

# Cleanup
if [[ $g_TMP_PRESERVE -eq 0 ]]
then
    for i in $g_TMP_FILES
    do
	if [[ -f $i ]]
	then
	    rm $i
	else
	    echo -e "\nWarning: duplicate SUB or FUNCTION found! Temporary file $i already deleted."
	fi
    done
    if [[ -n $g_REBUILD_ARCHIVE ]]
    then
        rm -f $g_TEMPDIR/bacon.*.o
    fi
fi

exit $RETURN_CODE
