#!/usr/bin/env ksh # ____ ____ # | __ ) __ _ / ___|___ _ __ # | _ \ / _` | | / _ \| '_ \ # | |_) | (_| | |__| (_) | | | | --= A KORN BASIC-to-C converter =-- # |____/ \__,_|\____\___/|_| |_| # # Peter van Eerten - March 2009/December 2013. License: GPL version 3. # #--------------------------------------------------------------------------------------------------------------------- # CREDITS to all people of the BaCon forum. Without them BaCon would not be as it is now. #--------------------------------------------------------------------------------------------------------------------- # GLOBAL INITIALIZATIONS #--------------------------------------------------------------------------------------------------------------------- # If run with Zshell then emulate KSH if [[ -n $ZSH_NAME ]] then if [[ ${ZSH_VERSION%%.*} -lt 4 ]] then print "System error: this is ZShell version ${ZSH_VERSION}. BaCon needs ZShell 4.x or higher to run!" exit 1 else emulate ksh fi fi # Unset grep options unset GREP_OPTIONS # Version of BACON typeset -x g_VERSION="2.4.0" # Our numerical environment is POSIX export LC_NUMERIC="POSIX" # Find 'grep' and other coretools if [[ -z `which grep` || -z `which cat` || -z `which rm` || -z `which tr` || -z `which touch` || -z `which uname` || -z `which head` ]] then print "System error: 'grep', 'cat', 'rm', 'tr', 'touch', 'uname' or 'head' not found on this system!" exit 1 fi # Link flags if [[ `uname` = "OSF1" || `uname` = +(*BSD*) ]] then g_LDFLAGS="-lm" else g_LDFLAGS="-lm -ldl" fi # Solaris if [[ `uname` = +(*SunOS*) ]] then g_LDFLAGS="$g_LDFLAGS -lnsl -lsocket" fi # Global constant for miniparsing typeset -x g_PARSEVAR=`print "\001"` # Global to define '$'-replacement typeset -x g_STRINGSIGN="__b2c__string_var" # Global to define '"'-symbol typeset -x g_DQUOTESIGN=`print "\042"` # Global to define '''-symbol typeset -x g_SQUOTESIGN=`print "\047"` # Global to define CRLF combination typeset -x g_CRLF=`print "\015\012"` #----------------------------------------------------------- $2 = stdout or stderr function Print_Element { typeset TARGET CHECK VAR # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi # Check on string by reference variable VAR=`print -r ${1%%\(*}` CHECK=`grep -E "char \*${VAR} = NULL;" ${TARGET} 2>/dev/null` # Check if var is string var if [[ "${1%%\(*}" = +(*${g_STRINGSIGN}*) || "${1%%\(*}" = +(*${g_DQUOTESIGN}*) || "${1%%\(*}" = +(*gettext*|*ngettext*) || -n ${CHECK} ]] then print -r "__b2c__assign = ${1}; if(__b2c__assign != NULL) fprintf(${2}, \"%s\", __b2c__assign);" >> $g_CFILE else print -r "fprintf(${2}, \"%s\", STR${g_STRINGSIGN}(${1}));" >> $g_CFILE fi } #----------------------------------------------------------- $2 = stdout or stderr function Handle_Print { typeset FORMAT EXP LEN TOKEN LINE IN_STRING IN_FUNC CHAR ESCAPED TO TARGET CHECK SIZE STR AM1 AM2 TOPARSE IN_FUNC=0 # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # If no argument, do nothing if [[ "$1" != "PRINT" && "$1" != "EPRINT" ]] then # Get expression without ; if [[ -z ${1##*;} ]] then let LEN="${#1}"-1 typeset -L$LEN EXP="$1" else EXP="${1}" fi # Get rid of excaped '"' TOPARSE="${EXP//\\\\\"/ }" # Prepare for parsing AM1=`print ${TOPARSE%FORMAT *} | tr -d -C "\"" | wc -c` AM2=`print ${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 STR="${TO%${g_STRINGSIGN}*}" CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *${TO} = NULL;" >> $g_HFILE fi fi print -r "__b2c__assign = (char*)calloc($SIZE+1, sizeof(char));" >> $g_CFILE print -r "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#*\(} print -r "__b2c__${TO%%\(*}__location = __b2c__${TO%%\(*}__add(${STR};" >> $g_CFILE print -r "if(__b2c__${TO%%\(*}__location->__b2c_value != NULL) free(__b2c__${TO%%\(*}__location->__b2c_value); __b2c__${TO%%\(*}__location->__b2c_value = __b2c__assign;" >> $g_CFILE # Check for relations Relate_Recurse "${TO%%\(*}" "${STR}" "${TO}" "-1" else print -r "if(${TO} != NULL) free(${TO}); ${TO} = __b2c__assign;" >> $g_CFILE fi else print -r "fprintf(${2}, ${FORMAT%%;*}, ${EXP});" >> $g_CFILE fi else # Start miniparser, convert spaces LINE="${EXP// /${g_PARSEVAR}}" TOKEN= LEN=${#LINE} # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${LINE}" case $CHAR in ","|";") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then if [[ ${#TOKEN} -gt 0 ]] then Print_Element "${TOKEN}" "${2}" fi typeset -L0 CHAR="" TOKEN= ESCAPED=0 fi;; "\\") ESCAPED=1;; "\"") 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 typeset -R$LEN LINE="${LINE}" done if [[ ${#TOKEN} -gt 0 ]] then Print_Element "${TOKEN}" "${2}" fi # If line ends with ';' then skip newline if [[ -n ${1##*;} ]] then print -r "fprintf(${2}, \"\n\");" >> $g_CFILE fi fi else print -r "fprintf(${2}, \"\n\");" >> $g_CFILE fi # Flush buffer print -r "fflush(${2});" >> $g_CFILE } #----------------------------------------------------------- function Handle_Input { # Local variables typeset CHECK VAR TARGET STR LINE LEN IN_STRING IN_FUNC CHAR ESCAPED IN_FUNC=0 # Check if we have an argument at all if [[ "$1" = "INPUT" ]] then print "\nSyntax error: empty INPUT at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Start miniparser to see if we need to print something, convert spaces LINE="${1// /${g_PARSEVAR}}" VAR= LEN=${#LINE} # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${LINE}" case $CHAR in ","|";") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then if [[ ${#VAR} -gt 0 ]] then Print_Element "${VAR}" "stdout" fi typeset -L0 CHAR="" ESCAPED=0 VAR= fi;; "\\") ESCAPED=1;; "\"") 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 VAR="${VAR} " else VAR="${VAR}${CHAR}" fi let LEN=${#LINE}-1 typeset -R$LEN LINE="${LINE}" done # Remove spaces in variable VAR=`print ${VAR}` # Check if string is declared if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi # Not a string? elif [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) && "$VAR" != +(*\(*\)*) && "$VAR" != +(*->*) ]] then CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|,$VAR,|,$VAR;| $VAR=" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long $VAR;" >> $g_HFILE CHECK="long " fi else CHECK=`grep -E "DIR |FILE |int |short |long |float |double |char |void |STRING |NUMBER |FLOATING " $TARGET | grep -E " ${VAR%%\[*}| _${VAR%%\(*}| ${VAR##*.},| ${VAR##*.};|,${VAR##*.},|,${VAR##*.};"` fi # Check type of var, string? if [[ "${VAR}" = +(*${g_STRINGSIGN}) || "${VAR%%\(*}" = +(*${g_STRINGSIGN}) || "${VAR%%\[*}" = +(*${g_STRINGSIGN}) ]] then # Translate function to C function print -r "__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)" >> $g_CFILE print -r "{if(!__b2c__trap){ERROR = 35; if(!__b2c__catch_set) RUNTIMEERROR(\"INPUT\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE # Make sure internal var is copied to var of program print -r "__b2c__assign = (char*)realloc(__b2c__assign, ($g_BUFFER_SIZE+1)*__b2c__counter*sizeof(char));" >> $g_CFILE print -r "if(__b2c__counter == 1) strncpy(__b2c__assign, __b2c__input__buffer, $g_BUFFER_SIZE);" >> $g_CFILE print -r "else strncat(__b2c__assign, __b2c__input__buffer, $g_BUFFER_SIZE); __b2c__counter++;" >> $g_CFILE print -r "} while (!strstr(__b2c__input__buffer, \"\n\") && strlen(__b2c__input__buffer));" >> $g_CFILE # Cut off last newline print -r "if (strlen(__b2c__input__buffer)) __b2c__assign[strlen(__b2c__assign)-1]='\0'; else __b2c__assign=calloc(1, sizeof(char));" >> $g_CFILE # Now see if we have an assoc or a normal variable if [[ "${VAR}" = +(*\(*\)) ]] then STR=${VAR#*\(} print -r "__b2c__${VAR%%\(*}__location = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE print -r "if(__b2c__${VAR%%\(*}__location->__b2c_value != NULL) free(__b2c__${VAR%%\(*}__location->__b2c_value); __b2c__${VAR%%\(*}__location->__b2c_value = __b2c__assign;" >> $g_CFILE # Check for relations Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1" else print -r "if($VAR != NULL) free($VAR); $VAR = __b2c__assign;" >> $g_CFILE fi # Var is numeric else # Translate function to C function print -r "memset(__b2c__input__buffer, '\0', $g_BUFFER_SIZE); if(fgets(__b2c__input__buffer, $g_BUFFER_SIZE, stdin)==NULL)" >> $g_CFILE print -r "{if(!__b2c__trap){ERROR = 35; if(!__b2c__catch_set) RUNTIMEERROR(\"INPUT\", $g_COUNTER, \"$g_CURFILE\", ERROR); 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#*\(} print -r "__b2c__${VAR%%\(*}__location = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE if [[ "$CHECK" = +(*double *) || "$CHECK" = +(*float *) || "$CHECK" = +(*FLOATING *) ]] then print -r "__b2c__${VAR%%\(*}__location->__b2c_value = atof(__b2c__input__buffer);" >> $g_CFILE elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*NUMBER *) ]] then print -r "__b2c__${VAR%%\(*}__location->__b2c_value = atol(__b2c__input__buffer);" >> $g_CFILE else print -r "__b2c__${VAR%%\(*}__location->__b2c_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 print -r "$VAR = atof(__b2c__input__buffer);" >> $g_CFILE elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*NUMBER *) ]] then print -r "$VAR = atol(__b2c__input__buffer);" >> $g_CFILE else print -r "$VAR = atoi(__b2c__input__buffer);" >> $g_CFILE fi fi fi } #----------------------------------------------------------- function Handle_For { # Local variables typeset FROM TO TMP VAR STEP CHECK TARGET STR # Check if TO is available if [[ "${1}" != +(* TO *) && "${1}" != +(* IN *) ]] then print "\nSyntax error: missing IN/TO 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 *) ]] then # Get the variablename without (surrounding) spaces VAR=`print -r "${1%%=*}" | tr -d "\040"`; TMP=`print -r "${1#*=}"` # Get the starting and ending value FROM=`print -r "${TMP%% TO *}"` TO=`print -r "${TMP##* TO }"` # Check if there is a STEP if [[ "$TO" = +(* STEP *) ]] then STEP="${TO##* STEP }" TO="${TO%% STEP *}" else STEP=1 fi else # Get the variablename without (surrounding) spaces VAR=`print -r "${1%% IN *}" | tr -d "\040"`; TMP=`print -r "${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}*) ]] then g_STRINGARGS="${g_STRINGARGS} char *__b2c__forin_${VAR} = NULL;" g_STRINGARGS="${g_STRINGARGS} char *__b2c__forin_${VAR}_end = NULL;" fi else STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*__b2c__forin_${STR}${g_STRINGSIGN} = NULL;" ${g_HFILE}` if [[ -z $CHECK ]] then print -r "char *__b2c__forin_${VAR} = NULL;" >> $g_HFILE print -r "char *__b2c__forin_${VAR}_end = NULL;" >> $g_HFILE fi fi print -r "if($TMP != NULL) __b2c__forin_${VAR} = strdup(${TMP});" >> $g_CFILE fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Check if string is declared if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi # Not a string? elif [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) && "$VAR" != +(*\(*\)*) && "$VAR" != +(*->*) ]] then CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|,$VAR,|,$VAR;| $VAR=" | grep -v " noparse "` if [[ -z $CHECK ]] then if [[ $FROM$TO$STEP = +(*[0-9]*.*[0-9]*) ]] then print -r "double $VAR;" >> $g_HFILE else print -r "long $VAR;" >> $g_HFILE fi fi fi # Check type of var, string? if [[ "${VAR}" = +(*${g_STRINGSIGN}) || "${VAR%%\(*}" = +(*${g_STRINGSIGN}) || "${VAR%%\[*}" = +(*${g_STRINGSIGN}) ]] then print -r "__b2c__assign=(char*)__b2c__strdup(strtok_r(__b2c__forin_${VAR}, ${STEP}, &__b2c__forin_${VAR}_end));" >> $g_CFILE print -r "if($VAR != NULL) free($VAR); $VAR = __b2c__assign;" >> $g_CFILE print -r "while(${VAR} != NULL){" >> $g_CFILE if [[ $g_LOCALSTRINGS != +(*__b2c__forin_${VAR}*) ]] then g_LOCALSTRINGS="${g_LOCALSTRINGS} __b2c__forin_${VAR}" fi g_LOOPVAR[${g_LOOPCTR}]=${VAR} g_LOOPSTEP[${g_LOOPCTR}]="${STEP}" # Var is numeric else # Translate function to C function if [[ "${STEP}" = +(*-*) ]] then print -r "for($VAR=$FROM; $VAR >= $TO; $VAR+=$STEP){" >> $g_CFILE else print -r "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 print -r "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 print "\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}]##* } print -r "__b2c__${REL}__location = __b2c__${REL}__add(${2};" >> $g_CFILE if [[ "${REL}" = +(*${g_STRINGSIGN}*) ]] then print -r "__b2c__assign=(char*)__b2c__strdup(${3}); if(__b2c__assign==NULL)__b2c__assign=calloc(1, sizeof(char));" >> $g_CFILE print -r "if(__b2c__${REL}__location->__b2c_value != NULL) free(__b2c__${REL}__location->__b2c_value); __b2c__${REL}__location->__b2c_value = __b2c__assign; " >> $g_CFILE else print -r "__b2c__${REL}__location->__b2c_value = ${3};" >> $g_CFILE fi Relate_Recurse ${REL} ${2} ${3} ${LVL} fi ((CTR+=1)) done } #----------------------------------------------------------- function Handle_Let { # Local variables typeset VAR CHECK TMP TARGET LEN STR CTR REL PTR # Check if there is an asignment at all, if not exit if [[ "$1" != +(*=*) ]] then print "\nSyntax error: could not parse line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Get the variablename without surrounding spaces VAR=`print ${1%%=*}`; TMP=${1#*=} # Check if var is string var, exclude RECORD elements if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) && $g_DYNAMICARRAYS != +(*${VAR}*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi # Assume number, exclude RECORD elements elif [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) && "$VAR" != "ERROR" && "$VAR" != "RETVAL" && "$VAR" != +(*\(*\)*) && "$VAR" != +(*-\>*) ]] then CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|\*$VAR |,$VAR,|,$VAR;| $VAR=| ${VAR%%\[*}\[|,${VAR%%\[*}\[|\*$VAR\)" | grep -v " noparse "` if [[ -z $CHECK ]] then if [[ "$TMP" = +(*.*) && "$TMP" != +(*$g_DQUOTESIGN*) ]] then print -r "double $VAR;" >> $g_HFILE else print -r "long $VAR;" >> $g_HFILE fi fi fi # Check if there is associative array assignment if [[ "${VAR}" = +(*\(*\)) ]] then STR=${VAR#*\(} print -r "__b2c__${VAR%%\(*}__location = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) ]] then print -r "__b2c__assign=(char*)__b2c__strdup(${TMP}); if(__b2c__assign==NULL)__b2c__assign=calloc(1, sizeof(char));" >> $g_CFILE print -r "if(__b2c__${VAR%%\(*}__location->__b2c_value != NULL) free(__b2c__${VAR%%\(*}__location->__b2c_value); __b2c__${VAR%%\(*}__location->__b2c_value = __b2c__assign; " >> $g_CFILE else print -r "__b2c__${VAR%%\(*}__location->__b2c_value = ${TMP};" >> $g_CFILE fi # Check for relations Relate_Recurse "${VAR%%\(*}" "${STR}" "${TMP}" "-1" # Is there an array variable without subscript? elif [[ "${VAR}" != +(*\[*\]*) && $g_DYNAMICARRAYS = +(*${VAR}*) ]] then if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] then print -r "for(__b2c__ctr=0; __b2c__ctr<__b2c_array_$VAR+$g_OPTION_BASE; __b2c__ctr++)if($VAR[__b2c__ctr]!=NULL){free($VAR[__b2c__ctr]);}" >> $g_CFILE fi print -r "free($VAR);" >> $g_CFILE print -r "${g_WITHVAR}${1};" >> $g_CFILE # Do we have a STRING variable or STRING array? elif [[ "${VAR}" = +(*${g_STRINGSIGN}*) && "${VAR}" != +(*\[*${g_STRINGSIGN}*\]*) ]] then print -r "__b2c__assign=(char*)__b2c__strdup(${TMP}); if(__b2c__assign==NULL)__b2c__assign=calloc(1, sizeof(char)); if(${g_WITHVAR}${VAR} != NULL) free(${g_WITHVAR}${VAR}); ${g_WITHVAR}${VAR} = __b2c__assign; " >> $g_CFILE # Also check if string var already is used for IMPORT, if so, perform dlopen again PTR="${VAR//[[:punct:]]/}" CHECK=`grep -i "void\* __b2c__dlopen__pointer_$PTR;" $g_CFILE` if [[ -n $CHECK ]] then print -r "__b2c__dlopen__pointer_$PTR = dlopen($VAR, RTLD_LAZY);" >> $g_CFILE fi else print -r "${g_WITHVAR}${1};" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Open { # Local variables typeset MODE HANDLE TMP CHECK TARGET LABEL CTR BND TOKEN LEN CHAR LINE IN_FUNC ADDRESS SOURCE BND STR set -A FILE FROM # Check if FOR is available if [[ "$1" != +(* FOR *) ]] then print "\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 print "\nSyntax error: missing AS in OPEN statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Start miniparser, convert spaces LINE=`print "${1%% FOR *}" | tr " " "\001"` TOKEN= LEN=${#LINE} let CTR=0 # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${LINE}" case $CHAR in ",") if [[ $IN_FUNC -eq 0 ]] then FILE[$CTR]="${TOKEN}" typeset -L0 CHAR="" TOKEN= ((CTR+=1)) fi;; "(") ((IN_FUNC+=1));; ")") ((IN_FUNC-=1));; esac # Convert back to space if [[ "${CHAR}" = "${g_PARSEVAR}" ]] then TOKEN="${TOKEN} " else TOKEN="${TOKEN}${CHAR}" fi let LEN=${#LINE}-1 typeset -R$LEN LINE="${LINE}" done FILE[$CTR]="${TOKEN}" # Get the mode and handle TMP=`print "${1##* FOR }"` MODE=`print "${TMP%% AS *}"` HANDLE=`print "${TMP##* AS }"` # Check for SOURCE address let BND=0 if [[ ${HANDLE} = +(*FROM*) ]] then SOURCE=`print "${HANDLE##* FROM }"` typeset -R${#SOURCE} LINE="${SOURCE// /${g_PARSEVAR}}" # Start miniparser, convert spaces TOKEN= LEN=${#LINE} let IN_FUNC=0 # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${LINE}" case $CHAR in ",") if [[ $IN_FUNC -eq 0 ]] then FROM[$BND]="${TOKEN}" typeset -L0 CHAR="" TOKEN= ((BND+=1)) fi;; "(") ((IN_FUNC+=1));; ")") ((IN_FUNC-=1));; esac # Convert back to space if [[ "${CHAR}" = "${g_PARSEVAR}" ]] then TOKEN="${TOKEN} " else TOKEN="${TOKEN}${CHAR}" fi let LEN=${#LINE}-1 typeset -R$LEN LINE="${LINE}" done FROM[$BND]="${TOKEN}" HANDLE=`print "${HANDLE%% FROM *}"` fi # Check if var is string var if [[ "${HANDLE}" = +(*${g_STRINGSIGN}) && $MODE != "MEMORY" ]] then print "\nSyntax error: variable for OPEN at line $g_COUNTER in file '$g_CURFILE' cannot be string!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Check if variable was declared if [[ "$HANDLE" != +(*.*) ]] then CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $HANDLE,| $HANDLE;|,$HANDLE,|,$HANDLE;| $HANDLE=| ${HANDLE%%\[*}\[|,${HANDLE%%\[*}\[" | grep -v " noparse "` fi # File or dir? if [[ $MODE = "DIRECTORY" ]] then if [[ -z $CHECK ]] then print -r "DIR* $HANDLE;" >> $g_HFILE fi elif [[ $MODE = "MEMORY" ]] then STR=${HANDLE%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$HANDLE = NULL;" >> $g_HFILE fi CHECK=`grep -E "long" $TARGET | grep "__b2c_mem_$HANDLE;" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long __b2c_mem_$HANDLE;" >> $g_HFILE fi elif [[ $MODE = "NETWORK" || $MODE = "SERVER" || $MODE = "UDP" || $MODE = "DEVICE" ]] then if [[ -z $CHECK ]] then print -r "int $HANDLE;" >> $g_HFILE fi else if [[ -z $CHECK ]] then print -r "FILE* $HANDLE;" >> $g_HFILE fi fi # Convert to C syntax case $MODE in @(READING) ) print -r "$HANDLE = fopen(${FILE[0]}, \"r\");" >> $g_CFILE print -r "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR READING\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(WRITING) ) print -r "$HANDLE = fopen(${FILE[0]}, \"w\");" >> $g_CFILE print -r "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR WRITING\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(APPENDING) ) print -r "$HANDLE = fopen(${FILE[0]}, \"a\");" >> $g_CFILE print -r "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR APPENDING\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(READWRITE) ) print -r "$HANDLE = fopen(${FILE[0]}, \"r+\");" >> $g_CFILE print -r "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR READWRITE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(DIRECTORY) ) print -r "$HANDLE = opendir(${FILE[0]});" >> $g_CFILE print -r "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR DIRECTORY\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(MEMORY) ) if [[ "${HANDLE}" = +(*${g_STRINGSIGN}*) ]] then print -r "if(${HANDLE}!=NULL) free(${HANDLE});" >> $g_CFILE fi print -r "$HANDLE = (char*)${FILE[0]}; __b2c_mem_$HANDLE = ${FILE[0]};" >> $g_CFILE print -r "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); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(NETWORK) ) # Network code TMP=${CTR} # Setup the array of addresses print -r "__b2c__addr = calloc(${CTR}+1, sizeof(*__b2c__addr));" >> $g_CFILE until [[ ${TMP} -lt 0 ]] do print -r "if (strstr(${FILE[$TMP]}, \":\") == NULL) {ERROR = 10; RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;}" >> $g_CFILE print -r "strncpy(__b2c__data_client, ${FILE[${TMP}]}, $g_BUFFER_SIZE); __b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\"); __b2c__he = gethostbyname(__b2c__host);" >> $g_CFILE print -r "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 print -r "__b2c__addr[$TMP].sin_family = AF_INET; __b2c__addr[$TMP].sin_port = htons((long)atol(__b2c__port));" >> $g_CFILE print -r "__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 print -r "$HANDLE = socket(AF_INET, ${g_SOCKTYPE}, IPPROTO_SCTP);" >> $g_CFILE else print -r "$HANDLE = socket(AF_INET, ${g_SOCKTYPE}, 0);" >> $g_CFILE fi print -r "if ($HANDLE == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE # Set socket options print -r "__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 print -r "setsockopt($HANDLE, SOL_SOCKET, SO_BROADCAST, &__b2c__yes, sizeof(int));" >> $g_CFILE elif [[ ${g_NETWORKTYPE} = "MULTICAST" ]] then print -r "setsockopt($HANDLE, IPPROTO_IP, IP_MULTICAST_LOOP, &__b2c__yes, sizeof(int));" >> $g_CFILE print -r "__b2c__ttl=${g_MULTICAST_TTL}; setsockopt($HANDLE, IPPROTO_IP, IP_MULTICAST_TTL, &__b2c__ttl, sizeof(unsigned char));" >> $g_CFILE elif [[ ${g_NETWORKTYPE} = "SCTP" ]] then print -r "memset(&__b2c__initmsg, 0, sizeof(__b2c__initmsg)); __b2c__initmsg.sinit_max_attempts = 3;" >> $g_CFILE print -r "__b2c__initmsg.sinit_num_ostreams = ${g_SCTP_STREAMS}; __b2c__initmsg.sinit_max_instreams = ${g_SCTP_STREAMS};" >> $g_CFILE print -r "setsockopt(${HANDLE}, IPPROTO_SCTP, SCTP_INITMSG, &__b2c__initmsg, sizeof(__b2c__initmsg));" >> $g_CFILE fi print -r "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} print -r "__b2c__from = calloc(${BND}+1, sizeof(*__b2c__from));" >> $g_CFILE until [[ ${TMP} -lt 0 ]] do print "strncpy(__b2c__data_client, ${FROM[${TMP}]}, $g_BUFFER_SIZE);" >> $g_CFILE if [[ ${FROM[${TMP}]} = +(*:*) ]] then print -r "__b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\");" >> $g_CFILE else print -r "__b2c__host = __b2c__data_client;" >> $g_CFILE fi print -r "__b2c__he = gethostbyname(__b2c__host);" >> $g_CFILE print -r "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 print -r "__b2c__from[$TMP].sin_family = AF_INET;" >> $g_CFILE if [[ ${FROM[${TMP}]} = +(*:*) ]] then print -r "__b2c__from[$TMP].sin_port = htons((long)atol(__b2c__port));" >> $g_CFILE fi print -r "__b2c__from[$TMP].sin_addr = *((struct in_addr *)__b2c__he->h_addr);" >> $g_CFILE ((TMP-=1)) done # Set source address if [[ ${g_NETWORKTYPE} = "SCTP" ]] then # Perform a one-one SCTP bind for multiple homes print -r "__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 print -r "__b2c__result = bind($HANDLE, (struct sockaddr *)__b2c__from, sizeof(struct sockaddr));" >> $g_CFILE fi print -r "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); 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 print -r "#ifdef SCTP_SOCKOPT_CONNECTX_OLD" >> $g_CFILE print -r " __b2c__result = sctp_connectx($HANDLE, (struct sockaddr *)__b2c__addr, ${CTR}+1, NULL);" >> $g_CFILE print -r "#else" >> $g_CFILE print -r " __b2c__result = sctp_connectx($HANDLE, (struct sockaddr *)__b2c__addr, ${CTR}+1);" >> $g_CFILE print -r "#endif" >> $g_CFILE else # Create a socket for TCP or UDP print -r "__b2c__result = connect($HANDLE, (struct sockaddr *)__b2c__addr, sizeof(struct sockaddr));" >> $g_CFILE fi print -r "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); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(SERVER) ) # Network code ADDRESS=`print -r "${1%% FOR *}" | tr "," " " | tr "\"" " "` print -r "if(strcmp(__b2c__data_server, \"${ADDRESS}\")) {strncpy(__b2c__data_server, \"${ADDRESS}\", $g_BUFFER_SIZE);" >> $g_CFILE # Setup the array of addresses TMP=${CTR} print -r "__b2c__addr = calloc(${CTR}+1, sizeof(*__b2c__addr));" >> $g_CFILE until [[ ${TMP} -lt 0 ]] do print -r "if (strstr(${FILE[$TMP]}, \":\") == NULL) {ERROR = 10; RUNTIMEERROR(\"OPEN FOR NETWORK\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;}" >> $g_CFILE print -r "strncpy(__b2c__data_client, ${FILE[${TMP}]}, $g_BUFFER_SIZE); __b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\");" >> $g_CFILE print -r "if (strstr(${FILE[$TMP]}, \"INADDR_ANY:\") || strstr(${FILE[$TMP]}, \"*:\")){__b2c__addr[$TMP].sin_addr.s_addr = htonl(INADDR_ANY);} else" >> $g_CFILE print -r "{ __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); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "__b2c__addr[$TMP].sin_addr = *((struct in_addr *)__b2c__he->h_addr);}" >> $g_CFILE print -r "__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 print -r "__b2c__handle = socket(AF_INET, ${g_SOCKTYPE}, IPPROTO_SCTP);" >> $g_CFILE else print -r "__b2c__handle = socket(AF_INET, ${g_SOCKTYPE}, 0);" >> $g_CFILE fi print -r "if (__b2c__handle == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE if [[ ${g_NETWORKTYPE} = "SCTP" ]] then print -r "memset(&__b2c__initmsg, 0, sizeof(__b2c__initmsg)); __b2c__initmsg.sinit_max_attempts = 3;" >> $g_CFILE print -r "__b2c__initmsg.sinit_num_ostreams = ${g_SCTP_STREAMS}; __b2c__initmsg.sinit_max_instreams = ${g_SCTP_STREAMS};" >> $g_CFILE print -r "setsockopt(${HANDLE}, IPPROTO_SCTP, SCTP_INITMSG, &__b2c__initmsg, sizeof(__b2c__initmsg));" >> $g_CFILE fi print -r "__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 print -r "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 print -r "__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 print -r "__b2c__result = bind(__b2c__handle, (struct sockaddr *)__b2c__addr, sizeof(struct sockaddr));" >> $g_CFILE fi print -r "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); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE if [[ ${g_NETWORKTYPE} = "MULTICAST" ]] then print -r "__b2c__imreq.imr_multiaddr.s_addr = inet_addr(__b2c__host); __b2c__imreq.imr_interface.s_addr = INADDR_ANY;" >> $g_CFILE print -r "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 print -r "$HANDLE = __b2c__handle; }" >> $g_CFILE else print -r "__b2c__result = listen(__b2c__handle, $g_MAX_BACKLOG);" >> $g_CFILE print -r "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 18;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} } }" >> $g_CFILE print -r "__b2c__result = accept(__b2c__handle, NULL, 0);" >> $g_CFILE print -r "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 19;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "$HANDLE= __b2c__result;" >> $g_CFILE fi;; @(DEVICE) ) print -r "$HANDLE = open(${FILE[0]}, __b2c__option_open);" >> $g_CFILE print -r "if($HANDLE < 0){if(!__b2c__trap){ERROR = 32; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR DEVICE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; esac } #----------------------------------------------------------- function Handle_Readln { # Local variables typeset CHECK VAR FROM TARGET STR # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\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=`print ${1%% FROM *}` # Get filedescriptor FROM=`print ${1##* FROM }` # Check if var is string var if [[ "${VAR}" != +(*${g_STRINGSIGN}) && "${VAR%%\(*}" != +(*${g_STRINGSIGN}) && "${VAR%%\[*}" != +(*${g_STRINGSIGN}) ]] then print "\nSyntax error: variable for READLN at line $g_COUNTER in file '$g_CURFILE' must be string!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Check if string variable, and if so, if declared if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi fi # Translate function to C function print -r "__b2c__counter = 1; __b2c__assign = NULL; do{ memset(__b2c__input__buffer, '\0', $g_BUFFER_SIZE); if(fgets(__b2c__input__buffer, $g_BUFFER_SIZE, $FROM) == NULL) break;" >> $g_CFILE # Make sure internal var is copied to var of program print -r "__b2c__assign = (char*)realloc(__b2c__assign, ($g_BUFFER_SIZE+1)*__b2c__counter*sizeof(char));" >> $g_CFILE print -r "if(__b2c__counter == 1) memcpy(__b2c__assign, __b2c__input__buffer, $g_BUFFER_SIZE);" >> $g_CFILE print -r "else strncat(__b2c__assign, __b2c__input__buffer, $g_BUFFER_SIZE); __b2c__counter++;" >> $g_CFILE print -r "} while (!strstr(__b2c__input__buffer, \"\n\") && strlen(__b2c__input__buffer));" >> $g_CFILE # Cut off last newline print -r "if(__b2c__assign != NULL) {__b2c__ctr = strlen(__b2c__assign); if(__b2c__ctr > 0) {__b2c__assign[__b2c__ctr-1] = '\0'; __b2c__ctr--;}" >> $g_CFILE print -r "if(__b2c__ctr > 0 && __b2c__assign[__b2c__ctr-1] == '\r') __b2c__assign[__b2c__ctr-1] = '\0';}" >> $g_CFILE print -r "else __b2c__assign = calloc(1, sizeof(char));" >> $g_CFILE # Now see if we have a assoc or a normal variable if [[ "${VAR}" = +(*\(*\)) ]] then STR=${VAR#*\(} print -r "__b2c__${VAR%%\(*}__location = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE print -r "if(__b2c__${VAR%%\(*}__location->__b2c_value != NULL) free(__b2c__${VAR%%\(*}__location->__b2c_value); __b2c__${VAR%%\(*}__location->__b2c_value = __b2c__assign;" >> $g_CFILE # Check for relations Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1" else print -r "if($VAR != NULL) free($VAR); $VAR = __b2c__assign;" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Writeln { # Local variables typeset VAR TO LINE LEN CHAR IN_STRING IN_FUNC ESCAPED # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nSyntax error: missing TO in WRITELN statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get filedescriptor TO=`print -r ${1##* TO }` # Start miniparser to see if we need to print something, convert spaces LINE=`print -r "${1% TO *}" | tr " " "\001"` VAR= LEN=${#LINE} IN_STRING=0 # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${LINE}" case $CHAR in ",") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then # Check if var is string var if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) || "${VAR%%\(*}" = +(*${g_DQUOTESIGN}*) ]] then print -r "fprintf($TO, \"%s\", ${VAR});" >> $g_CFILE else print -r "fprintf($TO, \"%s\", STR${g_STRINGSIGN}(${VAR}));" >> $g_CFILE fi typeset -L0 CHAR="" ESCAPED=0 VAR= fi;; "\\") ESCAPED=1;; "\"") 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 VAR="${VAR} " else VAR="${VAR}${CHAR}" fi let LEN=${#LINE}-1 typeset -R$LEN LINE="${LINE}" done # Write last element to file if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) || "${VAR%%\(*}" = +(*${g_DQUOTESIGN}*) ]] then print -r "fprintf($TO, \"%s\n\", ${VAR});" >> $g_CFILE else print -r "fprintf($TO, \"%s\n\", STR${g_STRINGSIGN}(${VAR}));" >> $g_CFILE fi print -r "fflush($TO);" >> $g_CFILE } #----------------------------------------------------------- function Handle_Getbyte { # Local variables typeset POS FROM SIZE TARGET CHECK CHUNK # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\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=`print ${1%% FROM *}` # Get filedescriptor FROM=`print ${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 # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # 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 CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $SIZE,| $SIZE;|,$SIZE,|,$SIZE;| $SIZE=| ${SIZE%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long $SIZE;" >> $g_HFILE fi fi # Type of file descriptor CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $FROM,| $FROM;|,$FROM,|,$FROM;| $FROM=| ${FROM%%\[*}\[|,${FROM%%\[*}\[" | grep -v " noparse "` # Translate function to C function print -r "if(!__b2c__trap){if(__b2c__memory__check((void*)$POS, sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"GETBYTE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE if [[ $CHECK = +(*int*) ]] then print -r "if((${SIZE} = read($FROM, (void*)($POS), $CHUNK)) < 0)" >> $g_CFILE print -r "{if(!__b2c__trap){ERROR = 34; if(!__b2c__catch_set) RUNTIMEERROR(\"GETBYTE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE else print -r "${SIZE} = fread((void*)($POS), sizeof(__b2c__MEMTYPE), $CHUNK, $FROM);" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Putbyte { # Local variables typeset VAR TO SIZE POS TARGET CHECK CHUNK # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\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=`print ${1%% TO *}`; # Get filedescriptor TO=`print ${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 # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # 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 CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $SIZE,| $SIZE;|,$SIZE,|,$SIZE;| $SIZE=| ${SIZE%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long $SIZE;" >> $g_HFILE fi fi # Type of file descriptor CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $TO,| $TO;|,$TO,|,$TO;| $TO=| ${TO%%\[*}\[|,${TO%%\[*}\[" | grep -v " noparse "` # Translate function to C function print -r "if(!__b2c__trap){if(__b2c__memory__check((void*)$POS, sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"PUTBYTE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE if [[ $CHECK = +(*int*) ]] then print -r "if(($SIZE = write(${TO}, (void*)($POS), $CHUNK)) < 0)" >> $g_CFILE print -r "{if(!__b2c__trap){ERROR = 34; if(!__b2c__catch_set) RUNTIMEERROR(\"PUTBYTE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE else print -r "$SIZE = fwrite((void*)($POS), sizeof(__b2c__MEMTYPE), $CHUNK, $TO); fflush($TO);" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Getfile { # Local variables typeset VAR FROM SIZE TARGET STR # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\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=`print ${1%% FROM *}` # Get dirdescriptor FROM=`print ${1##* FROM }` # Check if var is string var if [[ "${VAR}" != +(*${g_STRINGSIGN}) && "${VAR%%\(*}" != +(*${g_STRINGSIGN}) && "${VAR%%\[*}" != +(*${g_STRINGSIGN}) ]] then print "\nSyntax error: variable for GETFILE at line $g_COUNTER in file '$g_CURFILE' must be string!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Check if string is declared if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi fi # Translate function to C function print -r "__b2c__dir = readdir($FROM);" >> $g_CFILE # Always realloc VAR to correct size, maybe it was resized somewhere else print -r "if(__b2c__dir != NULL) {__b2c__assign = calloc((strlen(__b2c__dir->d_name)+1), sizeof(char));" >> $g_CFILE # Make sure internal var is copied to var of program print -r "strcpy(__b2c__assign, __b2c__dir->d_name); __b2c__assign[strlen(__b2c__dir->d_name)] = '\0';}" >> $g_CFILE print -r "else {__b2c__assign = calloc(1, sizeof(char));}" >> $g_CFILE # Now see if we have an assoc or a normal variable if [[ "${VAR}" = +(*\(*\)) ]] then STR=${VAR#*\(} print -r "__b2c__${VAR%%\(*}__location = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE print -r "if(__b2c__${VAR%%\(*}__location->__b2c_value != NULL) free(__b2c__${VAR%%\(*}__location->__b2c_value); __b2c__${VAR%%\(*}__location->__b2c_value = __b2c__assign;" >> $g_CFILE # Check for relations Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1" else print -r "if($VAR != NULL) free($VAR); $VAR = __b2c__assign;" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Receive { # Local variables typeset CHECK VAR FROM TARGET STR CHUNK SIZE # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\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=`print ${1%% FROM *}` # Get filedescriptor FROM=`print ${1##* FROM }` # Check for optional chunksize if [[ $1 = +(* CHUNK *) ]] then CHUNK=${1##* CHUNK } FROM=${FROM%% CHUNK *} else CHUNK=$g_BUFFER_SIZE fi # Check for optional return variable if [[ $1 = +(* SIZE *) ]] then FROM=${FROM%% SIZE *} SIZE=${1##* SIZE } CHUNK=${CHUNK%% SIZE *} else SIZE= fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # 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 CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $SIZE,| $SIZE;|,$SIZE,|,$SIZE;| $SIZE=| ${SIZE%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long $SIZE;" >> $g_HFILE 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 STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi fi # Translate function to C function print -r "__b2c__assign = (char*)calloc(($CHUNK+1), sizeof(char));" >> $g_CFILE if [[ ${g_NETWORKTYPE} = "SCTP" ]] then print -r "if(($SIZE = sctp_recvmsg($FROM, (void*)__b2c__assign, $CHUNK, 0, 0, 0, 0)) < 0)" >> $g_CFILE else print -r "if(($SIZE = recv($FROM, (void*)__b2c__assign, $CHUNK, 0)) < 0)" >> $g_CFILE fi print -r "{if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set) RUNTIMEERROR(\"RECEIVE\", $g_COUNTER, \"$g_CURFILE\", ERROR); 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#*\(} print -r "__b2c__${VAR%%\(*}__location = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE print -r "if(__b2c__${VAR%%\(*}__location->__b2c_value != NULL) free(__b2c__${VAR%%\(*}__location->__b2c_value); __b2c__${VAR%%\(*}__location->__b2c_value = __b2c__assign;" >> $g_CFILE # Check for relations Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1" elif [[ "${VAR}" = +(*${g_STRINGSIGN}) || "${VAR%%\[*}" = +(*${g_STRINGSIGN}) ]] then print -r "if($VAR != NULL) free($VAR); $VAR = __b2c__assign;" >> $g_CFILE else print -r "memcpy((void*)${VAR}, (void*)__b2c__assign, $CHUNK); free(__b2c__assign);" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Send { # Local variables typeset VAR TO CHUNK SIZE TARGET CHECK # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\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=`print -r ${1%% TO *}`; # Get filedescriptor TO=`print -r ${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 # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # 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 CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $SIZE,| $SIZE;|,$SIZE,|,$SIZE;| $SIZE=| ${SIZE%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long $SIZE;" >> $g_HFILE fi else if [[ -z $SIZE ]] then SIZE="__b2c__counter" fi fi # Translate function to C function if [[ ${g_NETWORKTYPE} = "SCTP" ]] then print -r "if(($SIZE = sctp_sendmsg($TO, (void*)$VAR, $CHUNK, NULL, 0, 0, 0, 0, 0, 0)) < 0)" >> $g_CFILE else print -r "if(($SIZE = send($TO, (void*)$VAR, $CHUNK, 0)) < 0)" >> $g_CFILE fi print -r "{if(!__b2c__trap){ERROR = 15; if(!__b2c__catch_set) RUNTIMEERROR(\"SEND\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Getline { # Local variables typeset CHECK VAR FROM TARGET STR # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\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=`print -r ${1%% FROM *}` # Get filedescriptor FROM=`print -r ${1##* FROM }` # Check if var is string var if [[ "${VAR}" != +(*${g_STRINGSIGN}) && "${VAR%%\(*}" != +(*${g_STRINGSIGN}) && "${VAR%%\[*}" != +(*${g_STRINGSIGN}) ]] then print "\nSyntax error: variable for GETLINE at line $g_COUNTER in file '$g_CURFILE' must be string!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Check if string variable, and if so, if declared if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi fi # Translate function to C function print -r "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 print -r "__b2c__assign = 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#*\(} print -r "__b2c__${VAR%%\(*}__location = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE print -r "if(__b2c__${VAR%%\(*}__location->__b2c_value != NULL) free(__b2c__${VAR%%\(*}__location->__b2c_value); __b2c__${VAR%%\(*}__location->__b2c_value = __b2c__assign;" >> $g_CFILE # Check for relations Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1" else print -r "if($VAR != NULL) free($VAR); $VAR = __b2c__assign;" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Putline { # Local variables typeset VAR TO LINE LEN CHAR IN_STRING IN_FUNC # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nSyntax error: missing TO in PUTLINE statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get memorydescriptor TO=`print -r ${1##* TO }` # Start miniparser to see if we need to print something, convert spaces LINE=`print -r "${1% TO *}" | tr " " "\001"` VAR= LEN=${#LINE} IN_STRING=0 # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${LINE}" case $CHAR in ",") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then # Check if var is string var if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) || "${VAR%%\(*}" = +(*${g_DQUOTESIGN}*) ]] then print -r "strcat($TO, $VAR); $TO+=strlen($VAR);" >> $g_CFILE else print -r "strcat($TO, STR${g_STRINGSIGN}($VAR)); $TO+=strlen(STR${g_STRINGSIGN}($VAR));" >> $g_CFILE fi typeset -L0 CHAR="" ESCAPED=0 VAR= fi;; "\\") ESCAPED=1;; "\"") 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 VAR="${VAR} " else VAR="${VAR}${CHAR}" fi let LEN=${#LINE}-1 typeset -R$LEN LINE="${LINE}" done # Check if var is string var if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) || "${VAR%%\(*}" = +(*${g_DQUOTESIGN}*) ]] then print -r "strcat($TO, $VAR); strcat($TO, \"\n\"); $TO+=strlen($VAR)+1;" >> $g_CFILE else print -r "strcat($TO, STR${g_STRINGSIGN}($VAR)); strcat($TO, \"\n\"); $TO+=strlen(STR${g_STRINGSIGN}($VAR))+1;" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Import { # Local variables typeset TMP SYM LIB CHECK TOKEN PTR TYPE ALIAS # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\nSyntax error: missing FROM in IMPORT statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get the symbolname without surrounding spaces and doublequotes if [[ "$1" = +(*\(*) ]] then SYM=`print ${1%%\(*} | tr -d "\042"`; TMP=${1#* FROM } TOKEN=`print ${1%%\)*}` else SYM=`print ${1%% FROM *} | tr -d "\042"`; TMP=${1#* FROM } TOKEN= fi # Check if TYPE is available if [[ "$1" != +(* TYPE *) ]] then print "\nSyntax error: missing TYPE in IMPORT statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get library and type LIB=`print ${TMP%% TYPE *}` TYPE=`print ${TMP##* TYPE }` # Check if ALIAS is there if [[ $TYPE = +(* ALIAS *) ]] then ALIAS=`print ${TYPE##* ALIAS } | tr -d "\042"` print -r "#define $ALIAS $SYM" >> $g_HFILE 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 # Create name from libname PTR="${LIB//[[:punct:]]/}" # Check if variable was declared CHECK=`grep -i "void\* __b2c__dlopen__pointer_$PTR;" $g_CFILE` if [[ -z $CHECK ]] then print -r "void* __b2c__dlopen__pointer_$PTR;" >> $g_CFILE print -r "__b2c__dlopen__pointer_$PTR = dlopen($LIB, RTLD_LAZY);" >> $g_CFILE fi print -r "if(__b2c__dlopen__pointer_$PTR == NULL){if(!__b2c__trap){ERROR = 3;if(!__b2c__catch_set) RUNTIMEERROR(\"IMPORT\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE # Check if token was declared CHECK=`grep -i "$TYPE (\*$SYM)" $g_HFILE` if [[ -z $CHECK ]] then print -r "$TYPE (*$SYM)(${TOKEN#*\(});" >> $g_HFILE fi # Translate to C function print -r "*($TYPE **) (&$SYM) = dlsym(__b2c__dlopen__pointer_$PTR, \"$SYM\");" >> $g_CFILE print -r "if($SYM == NULL) {if(!__b2c__trap){ERROR = 4;if(!__b2c__catch_set) RUNTIMEERROR(\"IMPORT\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE fi # Make symbol known to parser g_IMPORTED="$SYM $g_IMPORTED" } #----------------------------------------------------------- # $1 = TYPE - $2 = VAR - $3 = ARRAY - $4 = static function Normal_Dyn_Array { typeset i, j, TYPE, NR, OLD, TMP_ARR, IDX, END for i in $2 do TYPE="$1" g_DYNAMICARRAYS="${g_DYNAMICARRAYS} $i" # Initialize strings if [[ "${TYPE}" = +(*STRING*|*char\*) || "${i}" = +(*${g_STRINGSIGN}*) ]] then if [[ $3 = +(* *) ]] then print "\nSyntax error: string array cannot have more than one dimension line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi if [[ -n $g_FUNCNAME ]] then print -r "$TYPE* $i;" >> $g_CFILE 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+$g_OPTION_BASE; __b2c__ctr++)if($i[__b2c__ctr]!=NULL){free($i[__b2c__ctr]);}" g_LOCALSTRINGS="$g_LOCALSTRINGS ${i}" fi else print -r "$TYPE* $i;" >> $g_HFILE print -r "long __b2c_array_$i; /* noparse */" >> $g_HFILE fi print -r "$i = (${TYPE}*)calloc(${3}+$g_OPTION_BASE, sizeof(${TYPE}));" >> $g_CFILE print -r "__b2c_array_$i = ${3};" >> $g_CFILE print -r "for(__b2c__ctr=0; __b2c__ctr < $3+$g_OPTION_BASE; __b2c__ctr++) $i[__b2c__ctr] = calloc(1, sizeof(char));" >> $g_CFILE else # Count elements NR=0 for j in $3 do ((NR+=1)) TYPE="${TYPE}*" done # Declare top most dimension if [[ -n $g_FUNCNAME ]] then print -r "$TYPE $i;" >> $g_CFILE if [[ $4 -eq 0 ]] then g_LOCALSTRINGS="$g_LOCALSTRINGS ${i}" fi else print -r "$TYPE $i;" >> $g_HFILE fi print -r "$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 [[ -n $g_FUNCNAME ]] then g_STRINGARGS="$g_STRINGARGS int __b2c_${i}${NR};" else print -r "int __b2c_${i}${NR};" >> $g_HFILE fi IDX="$IDX[__b2c_${i}${NR}]" print -r "for(__b2c_${i}${NR} = 0; __b2c_${i}${NR} < $OLD+$g_OPTION_BASE; __b2c_${i}${NR}++){" >> $g_CFILE TYPE="${TYPE%\**}" print -r "${IDX} = (${TYPE})calloc((size_t)${j}+$g_OPTION_BASE, sizeof(${TYPE%\**}));" >> $g_CFILE END="$END }" OLD="$j" done print -r ${END} >> $g_CFILE 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} if(${IDX}!=NULL) free (${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 for i in $2 do TYPE="$1" g_DYNAMICARRAYS="${g_DYNAMICARRAYS} $i" # Initialize strings if [[ "${TYPE}" = +(*STRING*|*char\*) || "${i}" = +(*${g_STRINGSIGN}*) ]] then if [[ $3 = +(* *) ]] then print "\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 print -r "$TYPE* $i; /* noparse */" >> $g_CFILE 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] = calloc(1, sizeof(char));" if [[ $4 -eq 0 ]] then g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<__b2c_array_$i+$g_OPTION_BASE; __b2c__ctr++)if($g_RECORDVAR.$i[__b2c__ctr]!=NULL){free($g_RECORDVAR.$i[__b2c__ctr]);}" g_LOCALSTRINGS="$g_LOCALSTRINGS $g_RECORDVAR.${i}" fi else print -r "$TYPE* $i; /* noparse */" >> $g_HFILE 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] = calloc(1, sizeof(char));" fi else # Count elements NR=0 for j in $3 do ((NR+=1)) TYPE="${TYPE}*" done # Declare top most dimension if [[ -n $g_FUNCNAME ]] then print -r "$TYPE $i; /* noparse */" >> $g_CFILE if [[ $4 -eq 0 ]] then g_LOCALSTRINGS="$g_LOCALSTRINGS $g_RECORDVAR.${i}" fi else print -r "$TYPE $i; /* noparse */" >> $g_HFILE 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} if(${IDX}!=NULL) free (${IDX}); }" IDX="${IDX%\[*}" ((NR+=1)) fi done if [[ $4 -eq 0 ]] then g_STRINGARRAYS="$g_STRINGARRAYS $END" fi fi fi fi done } #----------------------------------------------------------- function Handle_Declare { # Local variables typeset VAR TYPE CHECK NEW VALUE OPTION ARRAY if [[ -n $g_RECORDNAME ]] then print "\nSyntax error: DECLARE 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}" print -r "struct $g_RECORDNAME{" >> $g_HFILE g_RECORDVAR=${1#* } # 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=`print -r "${1%% TYPE *}" | tr -d " "` TYPE=`print ${1##* TYPE }` if [[ ${TYPE} = +(* ARRAY *) ]] then ARRAY=${TYPE##* ARRAY } TYPE=${TYPE%% ARRAY *} fi elif [[ "$1" = +(* ASSOC *) ]] then VAR=`print -r "${1%% ASSOC *}" | tr -d " "` TYPE=`print ${1##* ASSOC }` else if [[ "${1}" = +(* ARRAY *) ]] then ARRAY=${1##* ARRAY } VAR=${1%% ARRAY *} else VAR=`print -r "${1}"` fi if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] then TYPE="char*" else TYPE="long" fi fi # Check if variable was already declared if [[ "$VAR" != +(*.*) ]] then VALUE=${VAR%%\[*} CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $g_HFILE | grep -E " $VALUE,| $VALUE;|,$VALUE,|,$VALUE;| $VALUE=| $VALUE\[|,$VALUE\[" | grep -v " noparse "` fi if [[ -n $CHECK ]] then print "\nSyntax error: variable in DECLARE or GLOBAL statement at line $g_COUNTER in file '$g_CURFILE' was defined previously!" exit 1 fi # If array, increase dimensions when OPTION BASE is set if [[ $VAR = +(*\[*\]*) && $VAR != +(*=*) ]] then NEW= while [[ ${VAR} = +(*\[*\]*) ]] do NEW="$NEW${VAR%%\[*}[" VALUE=${VAR#*\[} NEW="$NEW${VALUE%%\]*}+$g_OPTION_BASE]" VAR=${VAR#*\]} done VAR="${NEW}" fi # Check if it is a known type, if not BaCon has to use external .h file - create fake declaration for now if [[ ${TYPE%%\**} != +(DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING) ]] then print -r "/* long ${VAR//\*/}; */" >> $g_HFILE print -r "$TYPE $VAR;" >> $g_HFILE # Check for associative array elif [[ "${1}" = +(* ASSOC *) ]] then for i in ${VAR//,/ } do print -r "struct __b2c__${i}_type {char *__b2c_key; /* noparse */ ${TYPE} __b2c_value; /* noparse */};" >> $g_HFILE print -r "struct __b2c__${i}_type *__b2c__${i} = { NULL }; struct __b2c__${i}_type *__b2c__${i}__location; size_t __b2c__${i}_idx = 0;" >> $g_HFILE print -r "static int __b2c__${i}_comp(const void *__b2c__m1, const void *__b2c__m2){ " >> $g_HFILE print -r "struct __b2c__${i}_type *__b2c__mi1 = (struct __b2c__${i}_type *) __b2c__m1;" >> $g_HFILE print -r "struct __b2c__${i}_type *__b2c__mi2 = (struct __b2c__${i}_type *) __b2c__m2;" >> $g_HFILE print -r "if(__b2c__mi1->__b2c_key == NULL && __b2c__mi2->__b2c_key == NULL) return 0;" >> $g_HFILE print -r "if(__b2c__mi1->__b2c_key == NULL && __b2c__mi2->__b2c_key != NULL) return 1;" >> $g_HFILE print -r "if(__b2c__mi1->__b2c_key != NULL && __b2c__mi2->__b2c_key == NULL) return -1;" >> $g_HFILE print -r "return strcmp(__b2c__mi1->__b2c_key, __b2c__mi2->__b2c_key); }" >> $g_HFILE print -r "static int __b2c__${i}_sort(const void *__b2c__m1, const void *__b2c__m2){" >> $g_HFILE print -r "struct __b2c__${i}_type *__b2c__mi1 = (struct __b2c__${i}_type *) __b2c__m1;" >> $g_HFILE print -r "struct __b2c__${i}_type *__b2c__mi2 = (struct __b2c__${i}_type *) __b2c__m2;" >> $g_HFILE if [[ ${i} = +(*${g_STRINGSIGN}*) || ${TYPE} = +(*STRING*) || ${TYPE} = +(*char\**) ]] then print -r "if(__b2c__mi1->__b2c_value == NULL && __b2c__mi2->__b2c_value == NULL) return 0;" >> $g_HFILE print -r "if(__b2c__mi1->__b2c_value == NULL && __b2c__mi2->__b2c_value != NULL) return 1;" >> $g_HFILE print -r "if(__b2c__mi1->__b2c_value != NULL && __b2c__mi2->__b2c_value == NULL) return -1;" >> $g_HFILE print -r "return strcmp(__b2c__mi1->__b2c_value, __b2c__mi2->__b2c_value); }" >> $g_HFILE else print -r "if(__b2c__mi1->__b2c_value == __b2c__mi2->__b2c_value) return 0;" >> $g_HFILE print -r "else {if(__b2c__mi1->__b2c_value < __b2c__mi2->__b2c_value) return -1;" >> $g_HFILE print -r "else return 1; } }" >> $g_HFILE fi print -r "static int __b2c__${i}_sort_down(const void *__b2c__m1, const void *__b2c__m2){" >> $g_HFILE print -r "struct __b2c__${i}_type *__b2c__mi1 = (struct __b2c__${i}_type *) __b2c__m1;" >> $g_HFILE print -r "struct __b2c__${i}_type *__b2c__mi2 = (struct __b2c__${i}_type *) __b2c__m2;" >> $g_HFILE if [[ ${i} = +(*${g_STRINGSIGN}*) || ${TYPE} = +(*STRING*) || ${TYPE} = +(*char\**) ]] then print -r "if(__b2c__mi1->__b2c_value == NULL && __b2c__mi2->__b2c_value == NULL) return 0;" >> $g_HFILE print -r "if(__b2c__mi1->__b2c_value == NULL && __b2c__mi2->__b2c_value != NULL) return -1;" >> $g_HFILE print -r "if(__b2c__mi1->__b2c_value != NULL && __b2c__mi2->__b2c_value == NULL) return 1;" >> $g_HFILE print -r "return strcmp(__b2c__mi2->__b2c_value, __b2c__mi1->__b2c_value); }" >> $g_HFILE else print -r "if(__b2c__mi1->__b2c_value == __b2c__mi2->__b2c_value) return 0;" >> $g_HFILE print -r "else {if(__b2c__mi1->__b2c_value < __b2c__mi2->__b2c_value) return 1;" >> $g_HFILE print -r "else return -1; } }" >> $g_HFILE fi print -r "struct __b2c__${i}_type *__b2c__${i}__add_secure(int __b2c__action, char *__b2c__index, ...){struct __b2c__${i}_type __b2c__${i}_key, *__b2c__${i}__result; char *__b2c__nxt; va_list __b2c__ap;" >> $g_HFILE print -r "__b2c__${i}_key.__b2c_key = __b2c__strdup(__b2c__index); va_start (__b2c__ap, __b2c__index); while((__b2c__nxt = va_arg (__b2c__ap, char *)) != NULL){" >> $g_HFILE print -r "__b2c__${i}_key.__b2c_key = realloc(__b2c__${i}_key.__b2c_key, (strlen(__b2c__${i}_key.__b2c_key)+strlen(__b2c__nxt)+2)*sizeof(char)); strcat(__b2c__${i}_key.__b2c_key, \" \"); strcat(__b2c__${i}_key.__b2c_key, __b2c__nxt);} va_end (__b2c__ap);" >> $g_HFILE print -r "__b2c__${i}__result = lfind(&__b2c__${i}_key, __b2c__${i}, &__b2c__${i}_idx, sizeof(struct __b2c__${i}_type), __b2c__${i}_comp);" >> $g_HFILE print -r "if(__b2c__${i}__result == NULL && __b2c__action == 1){__b2c__${i}_idx++; __b2c__${i} = (struct __b2c__${i}_type *) realloc (__b2c__${i}, __b2c__${i}_idx * sizeof (struct __b2c__${i}_type));" >> $g_HFILE print -r "__b2c__${i}[__b2c__${i}_idx - 1].__b2c_key = __b2c__${i}_key.__b2c_key; __b2c__${i}[__b2c__${i}_idx-1].__b2c_value = 0;" >> $g_HFILE print -r "__b2c__${i}__result = &__b2c__${i}[__b2c__${i}_idx - 1];} else free(__b2c__${i}_key.__b2c_key); return(__b2c__${i}__result);}" >> $g_HFILE print -r "#define __b2c__${i}__add(...) __b2c__${i}__add_secure(1, __VA_ARGS__, NULL)" >> $g_HFILE print -r "#define __b2c__${i}__find(...) __b2c__${i}__add_secure(0, __VA_ARGS__, NULL)" >> $g_HFILE print -r "void __b2c__${i}__del(struct __b2c__${i}_type *__b2c__${i}__arg){int __b2c__x, __b2c__y;" >> $g_HFILE print -r "if(__b2c__${i}__arg != NULL) {for(__b2c__x=0; __b2c__x < __b2c__${i}_idx; __b2c__x++) if(!strcmp(__b2c__${i}__arg->__b2c_key, __b2c__${i}[__b2c__x].__b2c_key)) break;" >> $g_HFILE print -r "free(__b2c__${i}[__b2c__x].__b2c_key); for(__b2c__y=__b2c__x; __b2c__y < __b2c__${i}_idx-1; __b2c__y++) __b2c__${i}[__b2c__y] = __b2c__${i}[__b2c__y+1];" >> $g_HFILE print -r "__b2c__${i}_idx--; __b2c__${i} = (struct __b2c__${i}_type *) realloc (__b2c__${i}, __b2c__${i}_idx * sizeof (struct __b2c__${i}_type));} }" >> $g_HFILE print -r "${TYPE} _${i}(char *__b2c__index, ...){struct __b2c__${i}_type __b2c__${i}_key, *__b2c__${i}__result; char *__b2c__nxt; va_list __b2c__ap;" >> $g_HFILE print -r "__b2c__${i}_key.__b2c_key = __b2c__strdup(__b2c__index); va_start (__b2c__ap, __b2c__index); while((__b2c__nxt = va_arg (__b2c__ap, char *)) != NULL){" >> $g_HFILE print -r "__b2c__${i}_key.__b2c_key = realloc(__b2c__${i}_key.__b2c_key, (strlen(__b2c__${i}_key.__b2c_key)+strlen(__b2c__nxt)+2)*sizeof(char)); strcat(__b2c__${i}_key.__b2c_key, \" \"); strcat(__b2c__${i}_key.__b2c_key, __b2c__nxt); } va_end (__b2c__ap);" >> $g_HFILE print -r "__b2c__${i}__result = lfind(&__b2c__${i}_key, __b2c__${i}, &__b2c__${i}_idx, sizeof(struct __b2c__${i}_type), __b2c__${i}_comp); free(__b2c__${i}_key.__b2c_key);" >> $g_HFILE if [[ ${i} = +(*${g_STRINGSIGN}*) || ${TYPE} = +(*STRING*) || ${TYPE} = +(*char\**) ]] then print -r "if(__b2c__${i}__result == NULL) return(\"\"); return __b2c__${i}__result->__b2c_value;}" >> $g_HFILE else print -r "if(__b2c__${i}__result == NULL) return(0); return __b2c__${i}__result->__b2c_value;}" >> $g_HFILE fi print -r "#define ${i}(...) _${i}(__VA_ARGS__, NULL)" >> $g_HFILE done # Check for dynamic array declaration elif [[ -n ${ARRAY} ]] then Normal_Dyn_Array "$TYPE" "${VAR//,/ }" "${ARRAY//,/ }" # Check if var is string var elif [[ ( "${VAR}" = +(*${g_STRINGSIGN}*) || "${TYPE}" = +(STRING|char\*) ) && "${VAR}" != +(*=*) ]] then CHECK=`grep -E "char \*${VAR} = NULL;" $g_HFILE` if [[ -z $CHECK ]] then for i in ${VAR//,/ } do if [[ "${i}" = +(*\[*\]*) ]] then print -r "char *$i = { NULL };" >> $g_HFILE else print -r "char *$i = NULL;" >> $g_HFILE # Pointer var should not be initialized if [[ "${i}" = +(*${g_STRINGSIGN}*) ]] then print -r "$i = calloc(1, sizeof(char));" >> $g_CFILE fi fi done fi # Var is string array assignment elif [[ ( "${VAR}" = +(*${g_STRINGSIGN}*) || "${TYPE}" = +(*STRING*|*char\**) ) && "${VAR}" = +(*=*) ]] then print -r "char* ${VAR%%\{*} {" >> $g_HFILE OPTION=$g_OPTION_BASE while [[ ${OPTION} -gt 0 ]] do print -r " \"\", " >> $g_HFILE ((OPTION-=1)) done print -r "${VAR#*\{};" >> $g_HFILE # Assume char assignment or number else if [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]] then for i in ${VAR//,/ } do print -r "$TYPE $i = { 0 };" >> $g_HFILE done elif [[ "$VAR" = +(*\[*\]*) && "$VAR" = +(*=*) ]] then print -r "$TYPE ${VAR%%\{*} {" >> $g_HFILE OPTION=$g_OPTION_BASE while [[ ${OPTION} -gt 0 ]] do print -r " 0, " >> $g_HFILE ((OPTION-=1)) done print -r "${VAR#*\{};" >> $g_HFILE elif [[ "$VAR" != +(*=*) && "$VAR" != +(*\(*\)*) && "$VAR" != +(*\**) && "${TYPE}" = +(*char*|*short*|*int*|*long*|*double*|*float*|*NUMBER*|*FLOATING*) ]] then print -r "$TYPE $VAR;" >> $g_HFILE print -r "${VAR//,/=} = 0;" >> $g_CFILE else print -r "$TYPE $VAR;" >> $g_HFILE fi fi fi } #----------------------------------------------------------- function Handle_Local { # Local variables typeset VAR TYPE CHECK TARGET DIM NEW VALUE i OPTION ARRAY STATIC # Get the variablename and type if [[ "$1" = +(* TYPE *) ]] then VAR=`print -r "${1%% TYPE *}" | tr -d " "` TYPE=`print ${1##* TYPE }` if [[ ${TYPE} = +(* ARRAY *) ]] then ARRAY=${TYPE##* ARRAY } TYPE=${TYPE%% ARRAY *} fi else if [[ "${1}" = +(* ARRAY *) ]] then ARRAY=${1##* ARRAY } VAR=${1%% ARRAY *} else VAR=`print -r "${1%% ARRAY *}"` fi if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] then TYPE="char*" else TYPE="long" fi fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET=$g_CFILE else TARGET=$g_HFILE fi touch $TARGET # Check if variable was already declared if [[ "$VAR" != +(*.*) ]] then VALUE=${VAR%%\[*} CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VALUE,| $VALUE;|,$VALUE,|,$VALUE;| $VALUE=| $VALUE\[|,$VALUE\[" | grep -v " noparse "` fi if [[ -n $CHECK ]] then print "\nSyntax error: variable in LOCAL statement at line $g_COUNTER in file '$g_CURFILE' was defined previously!" exit 1 fi # If array, increase dimensions when OPTION BASE is set if [[ $VAR = +(*\[*\]*) && $VAR != +(*=*) ]] then NEW= while [[ ${VAR} = +(*\[*\]*) ]] do NEW="$NEW${VAR%%\[*}[" VALUE=${VAR#*\[} NEW="$NEW${VALUE%%\]*}+$g_OPTION_BASE]" VAR=${VAR#*\]} done VAR="${NEW}" fi # Check if it is a known type, if not BaCon has to use external .h file - create fake declaration for now if [[ ${TYPE%%\**} != +(DIR|FILE|*int|*short|*long|*float|*double|*char|void|STRING|NUMBER|FLOATING) ]] then print -r "/* long ${VAR//\*/}; */" >> $g_CFILE print -r "$TYPE $VAR;" >> $g_CFILE # Check for dynamic array declaration elif [[ -n ${ARRAY} ]] then if [[ $ARRAY = +(*STATIC*) ]] then STATIC=1 ARRAY=`print ${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 fi # Check if var is string var and not an argument in an array itself elif [[ ( "${TYPE}" = +(STRING|char\*) || "${VAR}" = +(*${g_STRINGSIGN}*) ) && "${VAR}" != +(*=*) && "${VAR}" != +(*\[*${g_STRINGSIGN}\]*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = " ${TARGET}` if [[ -z $CHECK ]] then for i in ${VAR//,/ } do # Check on multidimensional stringarrays if [[ "${i}" = +(*\[*\]*\]*) ]] then print "\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 print -r "char *$i;" >> $g_CFILE DIM=${i##*\[}; DIM=${DIM%%\]*} g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++)if($g_RECORDVAR.${i%%\[*}[__b2c__ctr]!=NULL){free($g_RECORDVAR.${i%%\[*}[__b2c__ctr]);}" else print -r "char *$i; /* noparse */" >> $g_CFILE fi else if [[ "${i}" = +(*\[*\]*) ]] then print -r "char *$i = { NULL };" >> $g_CFILE DIM=${i##*\[}; DIM=${DIM%%\]*} g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++)if(${g_WITHVAR}${i%%\[*}[__b2c__ctr]!=NULL){free(${g_WITHVAR}${i%%\[*}[__b2c__ctr]);}" else print -r "char *$i = NULL;" >> $g_CFILE # Pointer var should not be initialized if [[ "${i}" = +(*${g_STRINGSIGN}*) ]] then print -r "$i = calloc(1, sizeof(char));" >> $g_CFILE g_LOCALSTRINGS="$g_LOCALSTRINGS ${i}" fi fi fi # We are in the mainprogram else if [[ -n $g_RECORDNAME ]] then print -r "char *$i; /* noparse */" >> $g_HFILE else if [[ "${i}" = +(*\[*\]*) ]] then print -r "char *$i = { NULL };" >> $g_HFILE else print -r "char *$i = NULL;" >> $g_HFILE # Pointer var should not be initialized if [[ "${i}" = +(*${g_STRINGSIGN}*) ]] then print -r "$i = calloc(1, sizeof(char));" >> $g_CFILE fi fi fi fi done fi elif [[ ( "${VAR}" = +(*${g_STRINGSIGN}*) || "${TYPE}" = +(*STRING*|*char\**) ) && "${VAR}" = +(*=*) ]] then if [[ -n $g_FUNCNAME ]] then # String array assignment print -r "char* ${VAR%%\{*} {" >> $g_CFILE OPTION=$g_OPTION_BASE while [[ ${OPTION} -gt 0 ]] do print -r " \"\", " >> $g_CFILE ((OPTION-=1)) done print -r "${VAR#*\{};" >> $g_CFILE else # String array assignment print -r "char* ${VAR%%\{*} {" >> $g_HFILE OPTION=$g_OPTION_BASE while [[ ${OPTION} -gt 0 ]] do print -r " \"\", " >> $g_HFILE ((OPTION-=1)) done print -r "${VAR#*\{};" >> $g_HFILE fi # Assume number or complicated type else if [[ -n $g_FUNCNAME ]] then if [[ -n $g_RECORDNAME ]] then print -r "$TYPE $VAR; /* noparse */" >> $g_CFILE else if [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]] then for i in ${VAR//,/ } do print -r "$TYPE $i = { 0 };" >> $g_CFILE done elif [[ "$VAR" = +(*\[*\]*) && "$VAR" = +(*=*) ]] then # Numeric array assignment print -r "$TYPE ${VAR%%\{*} {" >> $g_CFILE OPTION=$g_OPTION_BASE while [[ ${OPTION} -gt 0 ]] do print -r " 0, " >> $g_CFILE ((OPTION-=1)) done print -r "${VAR#*\{};" >> $g_CFILE elif [[ "$VAR" != +(*=*) && "$VAR" != +(*\(*\)*) && "$VAR" != +(*\**) && "${TYPE}" = +(*char*|*short*|*int*|*long*|*double*|*float*|*NUMBER*|*FLOATING*) ]] then print -r "$TYPE $VAR;" >> $g_CFILE print -r "${VAR//,/=} = 0;" >> $g_CFILE else print -r "$TYPE $VAR;" >> $g_CFILE fi fi else if [[ -n $g_RECORDNAME ]] then print -r "$TYPE $VAR; /* noparse */" >> $g_HFILE else if [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]] then for i in ${VAR//,/ } do print -r "$TYPE $i = { 0 };" >> $g_HFILE done elif [[ "$VAR" = +(*\[*\]*) && "$VAR" = +(*=*) ]] then # Numeric array assignment print -r "$TYPE ${VAR%%\{*} {" >> $g_HFILE OPTION=$g_OPTION_BASE while [[ ${OPTION} -gt 0 ]] do print -r " 0, " >> $g_HFILE ((OPTION-=1)) done print -r "${VAR#*\{};" >> $g_HFIL elif [[ "$VAR" != +(*=*) && "$VAR" != +(*\(*\)*) && "$VAR" != +(*\**) && "${TYPE}" = +(*char*|*short*|*int*|*long*|*double*|*float*|*NUMBER*|*FLOATING*) ]] then print -r "$TYPE $VAR;" >> $g_HFILE print -r "${VAR//,/=} = 0;" >> $g_CFILE else print -r "$TYPE $VAR;" >> $g_HFILE fi fi fi fi } #----------------------------------------------------------- function Handle_Read { # Local variables typeset CHECK TARGET STR ITEM # Check if we have an argument at all if [[ "$1" = "READ" ]] then print "\nSyntax error: empty READ at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET for ITEM in ${1//,/ } do # Check if string variable, and if so, if declared if [[ "${ITEM}" = +(*${g_STRINGSIGN}) && "$ITEM" != +(*.*) ]] then STR=${ITEM%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$ITEM = NULL;" >> $g_HFILE fi # Variable may not be array, these should be defined with DECLARE elif [[ "${ITEM}" != +(*\[*\]*) && "${ITEM}" != +(*.*) && "$ITEM" != +(*\(*\)*) && "$ITEM" != +(*->*) ]] then # Not declared? Assume long CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " ${ITEM},| ${ITEM};|,${ITEM},|,${ITEM};| ${ITEM}=| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long ${ITEM};" >> $g_HFILE CHECK="long " fi else # See how var was declared CHECK=`grep -E "DIR |FILE |int |short |long |float |double |char |void |STRING |NUMBER |FLOATING " $TARGET | grep -E " ${ITEM%%\[*}| _${ITEM%%\(*}| ${ITEM##*.},| ${ITEM##*.};|,${ITEM##*.},|,${ITEM##*.};"` fi # Check type of var, string? if [[ "${ITEM}" = +(*${g_STRINGSIGN}) || "${ITEM%%\(*}" = +(*${g_STRINGSIGN}) || "${ITEM%%\[*}" = +(*${g_STRINGSIGN}) ]] then # Convert to C print -r "__b2c__assign = (char*)calloc((strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1), sizeof(char));" >> $g_CFILE print -r "strcpy(__b2c__assign, __b2c__stringarray[__b2c__stringarray_ptr]); __b2c__stringarray_ptr++;" >> $g_CFILE if [[ "${ITEM}" = +(*\(*\)) ]] then STR=${ITEM#*\(} print -r "__b2c__${ITEM%%\(*}__location = __b2c__${ITEM%%\(*}__add(${STR};" >> $g_CFILE print -r "if(__b2c__${ITEM%%\(*}__location->__b2c_value != NULL) free(__b2c__${ITEM%%\(*}__location->__b2c_value); __b2c__${ITEM%%\(*}__location->__b2c_value = __b2c__assign;" >> $g_CFILE # Check for relations Relate_Recurse "${ITEM%%\(*}" "${STR}" "${ITEM}" "-1" else print -r "if($ITEM != NULL) free($ITEM); $ITEM = __b2c__assign;" >> $g_CFILE fi else # Now see if we have an assoc or a normal variable CHECK=${CHECK##*:} if [[ "${ITEM}" = +(*\(*\)) ]] then print -r "__b2c__${ITEM%%\(*}__location = __b2c__${ITEM%%\(*}__add(${ITEM#*\(};" >> $g_CFILE print -r "__b2c__${ITEM%%\(*}__location->__b2c_value = (${CHECK%% *})__b2c__floatarray[__b2c__floatarray_ptr];" >> $g_CFILE print -r "__b2c__floatarray_ptr++;" >> $g_CFILE # Check for relations Relate_Recurse "${ITEM%%\(*}" "${STR}" "${ITEM}" "-1" else print -r "${ITEM} = (${CHECK%% *})__b2c__floatarray[__b2c__floatarray_ptr];" >> $g_CFILE print -r "__b2c__floatarray_ptr++;" >> $g_CFILE fi fi done } #----------------------------------------------------------- function Handle_Endfunction { # Check if return was found if [[ -z $g_FUNCTYPE ]] then print "\nSyntax error: function '$g_FUNCNAME' was defined without returning a value or string!" exit 1 fi # Put prototype to header file print -r "$g_FUNCTYPE ${g_PROTOTYPE}; /* noparse */" >> $g_HFILE g_PROTOTYPE= # Now setup function in main program print -r "/* Created with KSH BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h print -r "/* noparse $g_CURFILE BACON LINE $g_COPY_COUNTER */" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h if [[ $g_ORIGFUNCNAME != +(*\(*\)*) ]] then print -r "$g_FUNCTYPE $g_ORIGFUNCNAME(void) {" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h else print -r "$g_FUNCTYPE $g_ORIGFUNCNAME {" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h fi # Add function body print -r "${g_STRINGARGS}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h cat $g_CFILE >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h print -r "__B2C__PROGRAM__EXIT: ;" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h # Make sure the function always returns something if [[ $g_FUNCTYPE = +(*char\**) ]] then print -r "return (NULL);}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h else print -r "return (0);}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h fi # Include header file if [[ ${g_INCLUDE_FILES} != +(*${g_CURFILE%\.*}.$g_FUNCNAME.h*) ]] then g_INCLUDE_FILES="$g_INCLUDE_FILES ${g_CURFILE%\.*}.$g_FUNCNAME.h" fi # Add to total filelist g_TMP_FILES="$g_TMP_FILES ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h" # Delete temp funcfile rm $g_CFILE # Restore mainfile g_CFILE=$g_COPY_CFILE # Restore CATCH routine g_CATCHGOTO="$g_ORIGCATCHGOTO" # Clear function variables g_ORIGFUNCNAME= g_FUNCNAME= g_FUNCTYPE= g_LOCALSTRINGS= g_STRINGARRAYS= g_STRINGARGS= } #----------------------------------------------------------- function Handle_Return { # Local variables local CHECK STR ARG # Check if we have an argument at all, if not, we return from a GOSUB if [[ "${1}" = "RETURN" ]] then print -r "if(__b2c__gosub_buffer_ptr >= 0) longjmp(__b2c__gosub_buffer[__b2c__gosub_buffer_ptr], 1);" >> $g_CFILE return fi CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $g_CFILE | grep -E " $1,| $1;|,$1,|,$1;| $1=| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v " noparse "` # Check type of returned var, is it a string? if [[ "${1}" = +(*${g_STRINGSIGN}) || "${1%%\(*}" = +(*${g_STRINGSIGN}) || "${1%%\[*}" = +(*${g_STRINGSIGN}) || "${1}" = +(*${g_DQUOTESIGN}) || ${g_FUNCNAME} = +(*${g_STRINGSIGN}) ]] then # Static dynamic array or array created by SPLIT or LOOKUP if [[ ${g_DYNAMICARRAYS} = +(* ${1}*) || ${g_STRINGARGS} = +(* __b2c__split__${1} *) ]] then g_FUNCTYPE="char** " ARG="${1}" # We return a string else g_FUNCTYPE="char* " print -r "__b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= $g_MAX_RBUFFERS) __b2c__rbuffer_ptr=0; if($1 != NULL)" >> $g_CFILE print -r " {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)__rbuf_realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen($1)+1)*sizeof(char));" >> $g_CFILE print -r "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], $1);}" >> $g_CFILE print -r "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)__rbuf_realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], sizeof(char));" >> $g_CFILE print -r "*__b2c__rbuffer[__b2c__rbuffer_ptr] = '\0';}" >> $g_CFILE ARG="__b2c__rbuffer[__b2c__rbuffer_ptr]" fi # Assume variable, check if declared before elif [[ -n $CHECK ]] then case $CHECK in +(*DIR *) ) g_FUNCTYPE="DIR* ";; +(*FILE *) ) g_FUNCTYPE="FILE* ";; +(*int\* *) ) g_FUNCTYPE="int* ";; +(*short\* *) ) g_FUNCTYPE="short* ";; +(*float\* *) ) g_FUNCTYPE="float* ";; +(*double\* *) ) g_FUNCTYPE="double* ";; +(*char\* *|*STRING *) ) g_FUNCTYPE="char* ";; +(*long\* *) ) g_FUNCTYPE="long* ";; +(*void\* *) ) g_FUNCTYPE="void* ";; +(*int *) ) g_FUNCTYPE="int ";; +(*short *) ) g_FUNCTYPE="short ";; +(*float *) ) g_FUNCTYPE="float ";; +(*double *|*FLOATING *) ) g_FUNCTYPE="double ";; +(*char *) ) g_FUNCTYPE="char ";; +(*long *|*NUMBER *) ) g_FUNCTYPE="long ";; +(*void *) ) g_FUNCTYPE="void ";; esac ARG="${1}" # Not declared, assume actual value else if [[ "${1}" = +(*.*) ]] then g_FUNCTYPE="double " else g_FUNCTYPE="long " fi ARG="${1}" fi # Free strings variables if there are any print -r "${g_STRINGARRAYS}" >> $g_CFILE for STR in $g_LOCALSTRINGS do print -r "if($STR != NULL) free($STR);" >> $g_CFILE done # The actual return value print -r "__b2c__catch_set = __b2c__catch_set_backup;" >> $g_CFILE print -r "return (${ARG});" >> $g_CFILE } #----------------------------------------------------------- function Handle_Push { # Local variables typeset CHECK TARGET # Check if we have an argument at all if [[ "$1" = "PUSH" ]] then print "\nSyntax error: empty PUSH at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET if [[ "$VAR" != +(*.*) ]] then CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $1,| $1;|,$1,|,$1;| $1=| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v " noparse "` fi # Allocate space for type print -r "__b2c__typestack = (int*)realloc(__b2c__typestack, (__b2c__stackptr+1)*sizeof(int));" >> $g_CFILE # Check type of var, string? if [[ "${1}" = +(*${g_STRINGSIGN}) || "${1%%\(*}" = +(*${g_STRINGSIGN}) || "${1%%\[*}" = +(*${g_STRINGSIGN}) || "${1}" = +(*${g_DQUOTESIGN}*) ]] then print -r "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" >> $g_CFILE print -r "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen($1)+1)*sizeof(char));" >> $g_CFILE print -r "strcpy(__b2c__stringstack[__b2c__stackptr], $1);} else __b2c__stringstack[__b2c__stackptr] = __b2c__strdup($1);" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 1;" >> $g_CFILE # Check if float elif [[ "$1" = +(*.*) ]] then print -r "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" >> $g_CFILE print -r "__b2c__doublestack[__b2c__stackptr] = $1;" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 2;" >> $g_CFILE # Check if no alpha chars (then integer value) elif [[ "$1" = +(![a-zA-Z]) ]] then print -r "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE print -r "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE # Assume variable, check if declared before elif [[ -n $CHECK ]] then if [[ $CHECK = +(double*) ]] then print -r "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" >> $g_CFILE print -r "__b2c__doublestack[__b2c__stackptr] = $1;" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 2;" >> $g_CFILE else print -r "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE print -r "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE fi # Not declared, assume integer variable else print -r "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE print -r "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE fi # Increase stackpointer print -r "__b2c__stackptr++;" >> $g_CFILE } #----------------------------------------------------------- function Handle_Pull { typeset CHECK TARGET STR # Check if we have an argument at all if [[ "$1" = "PULL" ]] then print "\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 print "\nSyntax error: argument in PULL statement at line $g_COUNTER in file '$g_CURFILE' is not a variable!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Check if string is declared if [[ "${1}" = +(*${g_STRINGSIGN}) && "${1}" != +(*.*) ]] then STR="${1%${g_STRINGSIGN}*}" CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *${1} = NULL;" >> $g_HFILE fi # Not a string? elif [[ "${1}" != +(*\[*\]*) && "${1}" != +(*.*) && "${1}" != +(*\(*\)*) && "${1}" != +(*->*) ]] then CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " ${1},| ${1};|,${1},|,${1};| ${1}=" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long ${1};" >> $g_HFILE CHECK="long " fi else CHECK=`grep -E "DIR |FILE |int |short |long |float |double |char |void |STRING |NUMBER |FLOATING " $TARGET | grep -E " ${1%%\[*}| _${1%%\(*}| ${1##*.},| ${1##*.};|,${1##*.},|,${1##*.};"` fi # Decrease stackpointer again print -r "__b2c__stackptr--; if(__b2c__stackptr < 0) __b2c__stackptr=0;" >> $g_CFILE # Get the string from stack if [[ "${1}" = +(*${g_STRINGSIGN}) || "${1%%\(*}" = +(*${g_STRINGSIGN}) || "${1%%\[*}" = +(*${g_STRINGSIGN}) ]] then print -r "if(__b2c__typestack[__b2c__stackptr] == 1) {__b2c__assign = (char*)calloc(strlen(__b2c__stringstack[__b2c__stackptr])+1, sizeof(char));" >> $g_CFILE print -r "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#*\(} print -r "__b2c__${1%%\(*}__location = __b2c__${1%%\(*}__add(${STR};" >> $g_CFILE print -r "if(__b2c__${1%%\(*}__location->__b2c_value != NULL) free(__b2c__${1%%\(*}__location->__b2c_value); __b2c__${1%%\(*}__location->__b2c_value = __b2c__assign;" >> $g_CFILE # Check for relations Relate_Recurse "${1%%\(*}" "${STR}" "${1}" "-1" else print -r "if(${1} != NULL) free(${1}); ${1} = __b2c__assign;" >> $g_CFILE fi else # Now see if we have an assoc or a normal variable if [[ "${1}" = +(*\(*\)) ]] then STR=${1#*\(} print -r "__b2c__${1%%\(*}__location = __b2c__${1%%\(*}__add(${STR};" >> $g_CFILE if [[ "$CHECK" = +(*double *) || "$CHECK" = +(*float *) || "$CHECK" = +(*FLOATING *) ]] then print -r "__b2c__${1%%\(*}__location->__b2c_value = __b2c__doublestack[__b2c__stackptr];" >> $g_CFILE else print -r "__b2c__${1%%\(*}__location->__b2c_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 print -r "if(__b2c__typestack[__b2c__stackptr] == 2) ${1} = __b2c__doublestack[__b2c__stackptr];" >> $g_CFILE else print -r "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 # Check argument if [[ `print ${1}` = "SUB" || `print ${1}` = "FUNCTION" ]] then print "\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 print "\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 g_ORIGFUNCNAME=`print ${1%%\(*}"("` g_PROTOTYPE=`print ${1%%\(*}"("` # Start miniparser to duplicate string arguments, convert spaces ARGS=`print -r "${1##*\(}" | tr " " "\001"` TOKEN= LEN=${#ARGS} # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${ARGS}" if [[ $CHAR = "," ]] then if [[ ${TOKEN} = +(*STRING*) || ${TOKEN} = +(*char\**) ]] then TOKEN=`print ${TOKEN}` 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 char *__b2c_${TOKEN##* }," g_STRINGARGS="$g_STRINGARGS char* ${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++)if(${ARR%%\[*}[__b2c__ctr]!=NULL){free(${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##* } = __b2c__strdup(__b2c_${TOKEN##* });" g_LOCALSTRINGS="$g_LOCALSTRINGS ${TOKEN##* }" g_PROTOTYPE="$g_PROTOTYPE ${TOKEN}," fi else TOKEN=`print ${TOKEN}` if [[ $TOKEN = +(*\[*\]*\]*) ]] then print "\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 for(__b2c__ctr=0; __b2c__ctr<${DIM%%\]*}+$g_OPTION_BASE; __b2c__ctr++){ ${ARR%%\[*}[__b2c__ctr] = __b2c_${ARR%%\[*}[__b2c__ctr];}" elif [[ $TOKEN = +(*VAR *) ]] then print "\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 typeset -L0 CHAR="" TOKEN= fi # Convert back to space if [[ "${CHAR}" = "${g_PARSEVAR}" ]] then TOKEN="${TOKEN} " else TOKEN="${TOKEN}${CHAR}" fi let LEN=${#ARGS}-1 typeset -R$LEN ARGS="${ARGS}" done # Last token in the sequence of arguments TOKEN=${TOKEN%%\)*} TOKEN=`print ${TOKEN}` if [[ ${TOKEN} = +(*STRING*) || ${TOKEN} = +(*char\**) ]] then 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 char *__b2c_${TOKEN##* })" g_STRINGARGS="$g_STRINGARGS char* ${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++)if(${ARR%%\[*}[__b2c__ctr]!=NULL){free(${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##* } = __b2c__strdup(__b2c_${TOKEN##* });" g_LOCALSTRINGS="$g_LOCALSTRINGS ${TOKEN##* }" g_PROTOTYPE="$g_PROTOTYPE ${TOKEN})" fi else if [[ -z ${TOKEN} || ${TOKEN} = `print ${1}` ]] then TOKEN="void" fi if [[ $TOKEN = +(*\[*\]*\]*) ]] then print "\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 for(__b2c__ctr=0; __b2c__ctr<${DIM%%\]*}+$g_OPTION_BASE; __b2c__ctr++){ ${ARR%%\[*}[__b2c__ctr] = __b2c_${ARR%%\[*}[__b2c__ctr];}" elif [[ $TOKEN = +(*VAR *) ]] then if [[ $g_PROTOTYPE = +(*,*) ]] then print "\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 print "\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 print "\nSyntax error: variable argument list is not string at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $g_HFILE | grep -E " $SIZE,| $SIZE;|,$SIZE,|,$SIZE;| $SIZE=| ${SIZE%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` if [[ -z $CHECK ]] then g_STRINGARGS="$g_STRINGARGS long ${SIZE};" fi 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}" g_ORIGFUNCNAME="${g_ORIGFUNCNAME}char *__b2c__name, ...)" TOKEN="char*, ..." g_STRINGARRAYS="$g_STRINGARRAYS if($ARR != NULL) {for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr<=__b2c__var_$ARR; __b2c__ctr++) if($ARR[__b2c__ctr]!=NULL){free($ARR[__b2c__ctr]);} free($ARR);}" else g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN})" fi g_PROTOTYPE="$g_PROTOTYPE ${TOKEN})" fi # Get original function name if [[ "$g_ORIGFUNCNAME" = +(* \(*\)*) ]] then g_FUNCNAME=`print ${g_ORIGFUNCNAME%% *}` elif [[ "$g_ORIGFUNCNAME" = +(*\(*\)*) ]] then g_FUNCNAME=`print ${g_ORIGFUNCNAME%%\(*}` else g_FUNCNAME=`print $g_ORIGFUNCNAME` fi # Add macro in case of VAR argument if [[ $TOKEN = +(* ...*) ]] then print -r "#define ${g_FUNCNAME}(...) __${g_FUNCNAME}(__VA_ARGS__, NULL)" >> $g_HFILE g_ORIGFUNCNAME="__${g_ORIGFUNCNAME}" fi # Make symbol known to parser g_IMPORTED="$g_FUNCNAME $g_IMPORTED" # Save CATCH routine g_ORIGCATCHGOTO="$g_CATCHGOTO" g_CATCHGOTO="__B2C__PROGRAM__EXIT" g_STRINGARGS="$g_STRINGARGS __b2c__catch_set_backup = __b2c__catch_set; __b2c__catch_set = 0;" # 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 # Put prototype to header file print -r "void ${g_PROTOTYPE}; /* noparse */" >> $g_HFILE g_PROTOTYPE= # Get original function name print -r "/* Created with KSH BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h print -r "/* noparse $g_CURFILE BACON LINE $g_COPY_COUNTER */" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h if [[ "$g_ORIGFUNCNAME" = +(* \(*\)*) ]] then print -r "void ${g_ORIGFUNCNAME} {" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h elif [[ "$g_ORIGFUNCNAME" = +(*\(*\)*) ]] then print -r "void ${g_ORIGFUNCNAME} {" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h else print -r "void ${g_FUNCNAME}(void) {" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h fi # Finalize sub print -r "${g_STRINGARGS}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h cat $g_CFILE >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h # Free strings variables if there are any print -r "${g_STRINGARRAYS}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h for STR in $g_LOCALSTRINGS do print -r "if($STR != NULL) free(${STR});" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h done print -r "__B2C__PROGRAM__EXIT: ;" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h print -r "__b2c__catch_set = __b2c__catch_set_backup;" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h print -r "}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h # Include header file if [[ ${g_INCLUDE_FILES} != +(*${g_CURFILE%\.*}.$g_FUNCNAME.h*) ]] then g_INCLUDE_FILES="$g_INCLUDE_FILES ${g_CURFILE%\.*}.$g_FUNCNAME.h" fi # Add to total filelist g_TMP_FILES="$g_TMP_FILES ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h" # Delete temp funcfile rm $g_CFILE # Restore mainfile g_CFILE=$g_COPY_CFILE # Restore CATCH routine g_CATCHGOTO="$g_ORIGCATCHGOTO" # Reset variables g_ORIGFUNCNAME= g_FUNCNAME= g_LOCALSTRINGS= g_STRINGARRAYS= g_STRINGARGS= } #----------------------------------------------------------- function Handle_Deffn { typeset SYM # Check if we have an argument at all if [[ "$1" = "DEF" ]] then print "\nSyntax error: empty DEF FN at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Translate to C macro SYM=${1#* } print -r "#define ${SYM%%=*} (${SYM#*=})" >> $g_HFILE # Make symbol known to parser g_IMPORTED="${SYM%%\(*} $g_IMPORTED" } #----------------------------------------------------------- function Handle_Const { # Check if we have an argument at all if [[ "$1" = "CONST" ]] then print "\nSyntax error: empty CONST at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi print -r "#define ${1%%=*} (${1#*=})" >> $g_HFILE } #----------------------------------------------------------- function Handle_Seek { typeset FILE OFFSET WHENCE # Check if we have an argument at all if [[ "$1" = "SEEK" ]] then print "\nSyntax error: empty SEEK at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if TO is available if [[ "$1" != +(* OFFSET *) ]] then print "\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=`print ${1%% OFFSET *}`; # Get filedescriptor OFFSET=`print ${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) ) print -r "fseek($FILE, $OFFSET, SEEK_SET);" >> $g_CFILE;; +(CURRENT) ) print -r "fseek($FILE, $OFFSET, SEEK_CUR);" >> $g_CFILE;; +(END) ) print -r "fseek($FILE, $OFFSET, SEEK_END);" >> $g_CFILE;; *) print -r "fseek($FILE, $OFFSET, SEEK_SET);" >> $g_CFILE;; esac } #----------------------------------------------------------- function Handle_Copy { typeset FROM TO # Check if we have an argument at all if [[ "$1" = "COPY" ]] then print "\nSyntax error: empty COPY at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nSyntax error: missing TO in COPY statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get the filename and copyname FROM=`print ${1%% TO *}` TO=`print ${1##* TO }` # Translate to C function print -r "__b2c__inFile = fopen($FROM, \"r\"); __b2c__outFile = fopen($TO, \"w\"); __b2c__Byte = 0;" >> $g_CFILE print -r "if (__b2c__inFile != NULL && __b2c__outFile != NULL){while(__b2c__Byte!=EOF){" >> $g_CFILE print -r "__b2c__Byte=fgetc(__b2c__inFile); if(__b2c__Byte!=EOF){" >> $g_CFILE print -r "fputc(__b2c__Byte,__b2c__outFile); }}" >> $g_CFILE print -r "fclose(__b2c__inFile); fclose(__b2c__outFile);}" >> $g_CFILE print -r "else {if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"COPY\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Rename { typeset FROM TO # Check if we have an argument at all if [[ "$1" = "RENAME" ]] then print "\nSyntax error: empty RENAME at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nSyntax error: missing TO in RENAME statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get the filename and copyname FROM=`print ${1%% TO *}` TO=`print ${1##* TO }` # Translate to C function print -r "if(rename($FROM, $TO) < 0) {if(!__b2c__trap){ERROR = 9; if(!__b2c__catch_set) RUNTIMEERROR(\"RENAME\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Color { typeset TO FROM BFG COL # Check if we have an argument at all if [[ "$1" = "COLOR" ]] then print "\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 print -r "fprintf(stdout,\"\033[0m\"); fflush(stdout);" >> $g_CFILE elif [[ "$1" = +(*INTENSE*) ]] then print -r "fprintf(stdout,\"\033[1m\"); fflush(stdout);" >> $g_CFILE elif [[ "$1" = +(*INVERSE*) ]] then print -r "fprintf(stdout,\"\033[7m\"); fflush(stdout);" >> $g_CFILE elif [[ "$1" = +(*NORMAL*) ]] then print -r "fprintf(stdout,\"\033[22m\"); fflush(stdout);" >> $g_CFILE # Check if TO is available elif [[ "$1" != +(* TO *) ]] then print "\nSyntax error: missing TO in COLOR statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Get the target and colorname FROM=`print ${1%% TO *}` case $FROM in FG) BFG=3;; BG) BFG=4;; [01]) ((BFG=${FROM}+3));; *) BFG=${FROM};; esac TO=`print ${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 print -r "fprintf(stdout,\"\033[%ld%ldm\", (long)${BFG}, (long)${COL}); fflush(stdout);" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Gotoxy { typeset X Y # Check if we have an argument at all if [[ "$1" = "GOTOXY" ]] then print "\nSyntax error: empty GOTOXY at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get the target and colorname if [[ "$1" = +(*,*) ]] then X=`print ${1%%,*}` Y=`print ${1##*,}` else print "\nSyntax error: missing coordinate in GOTOXY at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Translate to C print -r "fprintf(stdout, \"\033[%ld;%ldH\",(long)(${Y}),(long)(${X}));fflush(stdout);" >> $g_CFILE } #----------------------------------------------------------- function Handle_Split { typeset SOURCE REST BY TO SIZE TARGET CHECK STATIC # Check if we have an argument at all if [[ "$1" = "SPLIT" ]] then print "\nSyntax error: empty SPLIT at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if BY is available if [[ "$1" != +(* BY *) ]] then print "\nSyntax error: missing BY in SPLIT statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\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 print "\nSyntax error: missing SIZE in SPLIT statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get the source string SOURCE=`print ${1%% BY *}` REST=`print ${1##* BY }` BY=`print ${REST%% TO *}` REST=`print ${REST##* TO }` TO=`print ${REST%% SIZE *}` SIZE=`print ${REST##* SIZE }` if [[ $SIZE = +(* STATIC*) ]] then SIZE=${SIZE%% STATIC*} STATIC=1 else STATIC=0 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # 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 CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $SIZE,| $SIZE;|,$SIZE,|,$SIZE;| $SIZE=| ${SIZE%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long $SIZE;" >> $g_HFILE fi fi # Translate to C code if [[ -n $g_FUNCNAME ]] then if [[ $g_STRINGARGS != +(*\*\*$TO*) ]] then g_STRINGARGS="$g_STRINGARGS char **$TO = NULL; char *__b2c__${TO}__dup = NULL; int __b2c__split__$TO = $g_OPTION_BASE;" fi else if [[ -z `grep "$TO = NULL;" $g_HFILE` ]] then print -r "char **$TO = NULL; char *__b2c__${TO}__dup = NULL; int __b2c__split__$TO = $g_OPTION_BASE;" >> $g_HFILE fi fi # If the split array was used before in a loop, clear it if [[ $TO = +(*${g_STRINGSIGN}*) ]] then print -r "if($TO != NULL) {for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr <= __b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr]!=NULL) {free($TO[__b2c__ctr]);} free($TO); $TO = NULL; }" >> $g_CFILE fi print -r "__b2c__split__$TO = $g_OPTION_BASE;" >> $g_CFILE print -r "if(__b2c__${TO}__dup != NULL) {free(__b2c__${TO}__dup); __b2c__${TO}__dup = NULL;}" >> $g_CFILE # Run the SPLIT code print -r "if ($SOURCE != NULL && strlen($SOURCE) > 0 && $BY != NULL && strlen($BY) > 0) {__b2c__${TO}__dup = __b2c__strdup($SOURCE); __b2c__split_tmp = __b2c__${TO}__dup;" >> $g_CFILE print -r "while(1) {if((__b2c__split = strstr(__b2c__split_tmp, $BY)) != NULL) *__b2c__split = '\0'; if(strlen(__b2c__split_tmp) >0 || (strlen(__b2c__split_tmp) == 0 && __b2c__collapse == 0)) {" >> $g_CFILE print -r "$TO = (char **)realloc($TO, (__b2c__split__$TO + 1) * sizeof(char*));" >> $g_CFILE if [[ $TO = +(*${g_STRINGSIGN}*) ]] then print -r "${TO}[__b2c__split__${TO}++] = __b2c__strdup(__b2c__split_tmp);}" >> $g_CFILE else print -r "${TO}[__b2c__split__${TO}++] = __b2c__split_tmp;}" >> $g_CFILE fi print -r "if(__b2c__split == NULL) break; __b2c__split_tmp = __b2c__split + strlen($BY); } } $SIZE = __b2c__split__$TO - $g_OPTION_BASE; if(__b2c__split__$TO > 0) __b2c__split__$TO--;" >> $g_CFILE # Add declared array to array list if we are in a function if [[ -n $g_FUNCNAME && $g_STRINGARRAYS != +(*${TO}*) ]] then g_LOCALSTRINGS="${g_LOCALSTRINGS} __b2c__${TO}__dup" if [[ $STATIC -eq 0 ]] then if [[ $TO = +(*${g_STRINGSIGN}*) ]] then g_STRINGARRAYS="$g_STRINGARRAYS if($TO != NULL) {for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr<=__b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr]!=NULL){free($TO[__b2c__ctr]);} }" fi g_LOCALSTRINGS="$g_LOCALSTRINGS $TO" fi fi } #----------------------------------------------------------- function Handle_Join { typeset SOURCE REST BY TO SIZE TARGET CHECK STR # Check if we have an argument at all if [[ "$1" = "JOIN" ]] then print "\nSyntax error: empty JOIN at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if BY is available if [[ "$1" != +(* BY *) ]] then print "\nSyntax error: missing BY in JOIN statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\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 print "\nSyntax error: missing SIZE in JOIN statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get the source string SOURCE=`print ${1%% BY *}` REST=`print ${1##* BY }` BY=`print ${REST%% TO *}` REST=`print ${REST##* TO }` TO=`print ${REST%% SIZE *}` SIZE=`print ${REST##* SIZE }` # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Check type of var, string? if [[ "${TO}" != +(*${g_STRINGSIGN}) && "${TO%%\(*}" != +(*${g_STRINGSIGN}) && "${TO%%\[*}" != +(*${g_STRINGSIGN}) ]] then print "\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 STR=${TO%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$TO = NULL;" >> $g_HFILE fi fi fi print -r "${TO} = realloc(${TO}, (strlen(${SOURCE}[0+$g_OPTION_BASE])+1)*sizeof(char)); strcpy(${TO}, ${SOURCE}[0+$g_OPTION_BASE]);" >> $g_CFILE print -r "for(__b2c__ctr=1; __b2c__ctr < ${SIZE}; __b2c__ctr++){if(${SOURCE}[__b2c__ctr+$g_OPTION_BASE]!=NULL){" >> $g_CFILE print -r "${TO} = realloc(${TO}, (strlen(${TO})+strlen(${BY})+strlen(${SOURCE}[__b2c__ctr+$g_OPTION_BASE])+1)*sizeof(char));" >> $g_CFILE print -r "strcat(${TO}, ${BY}); strcat(${TO}, ${SOURCE}[__b2c__ctr+$g_OPTION_BASE]);} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Sort { typeset STR CHECK DIM TARGET TYPE VAR TMP DOWN # Check if we have an argument at all if [[ "$1" = "SORT" ]] then print "\nSyntax error: empty SORT at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE 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 # If variable is part of RECORD if [[ ${VAR} = +(*.*) ]] then TMP=${VAR##*.} else TMP=${VAR} fi # What kind of array are we dealing with? Associative CHECK=`grep -E "DIR|FILE|struct|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep "__b2c__${TMP}_type"` if [[ -n $CHECK ]] then CHECK="assoc" else # Static Array? Determine data type CHECK=`grep -E "DIR|FILE|struct|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E "${TMP}\[.*\]"` if [[ -n $CHECK ]] then if [[ -z $DIM ]] then DIM=${CHECK##*\[}; DIM=${DIM%%\]*} fi else # Assuming dynamic array - determine data type CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $TMP,| $TMP;|,$TMP,|,$TMP;| $TMP="` if [[ -z $CHECK ]] then STR=${TMP%${g_STRINGSIGN}*} CHECK=`grep -E "__b2c__split__${STR}${g_STRINGSIGN}" $TARGET` if [[ -z $CHECK && ${g_STRINGARGS} != +(* __b2c__split__${1} *) ]] then print "\nSyntax error: variable '${VAR}' not an array at line $g_COUNTER in file '$g_CURFILE'!" exit 1 elif [[ -z $DIM ]] then DIM="__b2c__split__${TMP}+1" fi elif [[ -z $DIM ]] then print "\nSyntax error: SORT needs SIZE in case of dynamic array at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi fi fi # Check if it is an assoc array if [[ "${CHECK}" = "assoc" ]] then print -r "qsort(__b2c__$VAR, __b2c__${VAR}_idx, sizeof(struct __b2c__${VAR}_type), __b2c__${VAR}_sort$DOWN);" >> $g_CFILE # Check if we have a string elif [[ "${TMP}" = +(*${g_STRINGSIGN}) ]] then print -r "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-${g_OPTION_BASE}, sizeof(char*), __b2c__sortstr$DOWN);" >> $g_CFILE # It is a value else TYPE=${CHECK% *} if [[ $TYPE = +(*double*) || $TYPE = +(*FLOATING*) ]] then print -r "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-${g_OPTION_BASE}, sizeof(double), __b2c__sortnrd$DOWN);" >> $g_CFILE elif [[ $TYPE = +(*float*) ]] then print -r "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-${g_OPTION_BASE}, sizeof(float), __b2c__sortnrf$DOWN);" >> $g_CFILE elif [[ $TYPE = +(*long*) || $TYPE = +(*NUMBER*) ]] then print -r "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-${g_OPTION_BASE}, sizeof(long), __b2c__sortnrl$DOWN);" >> $g_CFILE else print -r "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-${g_OPTION_BASE}, sizeof(int), __b2c__sortnri$DOWN);" >> $g_CFILE fi fi } #----------------------------------------------------------- function Handle_Alias { typeset ORG NEW # Check if we have an argument at all if [[ "$1" = "ALIAS" ]] then print "\nSyntax error: empty ALIAS at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nSyntax error: missing TO in ALIAS statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get the source string ORG=`print -r ${1%% TO *} | tr -d "\042"` NEW=`print -r ${1##* TO } | tr -d "\042"` print -r "#define $NEW $ORG" >> $g_HFILE g_IMPORTED="$NEW $g_IMPORTED" } #----------------------------------------------------------- function Handle_Lookup { typeset SOURCE REST TO SIZE TARGET CHECK STATIC # Check if we have an argument at all if [[ "$1" = "LOOKUP" ]] then print "\nSyntax error: empty LOOKUP at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\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 print "\nSyntax error: missing SIZE in LOOKUP statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get the source string SOURCE=`print ${1%% TO *}` REST=`print ${1##* TO }` TO=`print ${REST%% SIZE *}` SIZE=`print ${REST##* SIZE }` if [[ $SIZE = +(* STATIC*) ]] then SIZE=${SIZE%% STATIC*} STATIC=1 else STATIC=0 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # 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 CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $SIZE,| $SIZE;|,$SIZE,|,$SIZE;| $SIZE=| ${SIZE%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long $SIZE;" >> $g_HFILE 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__split__$TO = $g_OPTION_BASE;" fi else if [[ -z `grep "$TO = NULL;" $g_HFILE` ]] then print -r "char **$TO = NULL; int __b2c__split__$TO = $g_OPTION_BASE;" >> $g_HFILE fi fi # If the split array was used before in a loop, clear it print -r "if($TO != NULL) {for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr <= __b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr]!=NULL)" >> $g_CFILE print -r "{free($TO[__b2c__ctr]);} free($TO); $TO = NULL;} __b2c__split__$TO = $g_OPTION_BASE;" >> $g_CFILE # Run the LOOKUP code print -r "for(__b2c__ctr = $g_OPTION_BASE; __b2c__ctr < __b2c__${SOURCE}_idx + $g_OPTION_BASE; __b2c__ctr++){$TO = (char **)realloc($TO, (__b2c__split__$TO + 1) * sizeof(char*));" >> $g_CFILE if [[ $TO = +(*${g_STRINGSIGN}*) ]] then print -r "$TO[__b2c__split__$TO++] = __b2c__strdup(__b2c__${SOURCE}[__b2c__ctr-$g_OPTION_BASE].__b2c_key);" >> $g_CFILE else print -r "$TO[__b2c__split__$TO++] = __b2c__${SOURCE}[__b2c__ctr-$g_OPTION_BASE].__b2c_key;" >> $g_CFILE fi print -r "} $SIZE = __b2c__split__$TO - $g_OPTION_BASE;if(__b2c__split__$TO > 0) __b2c__split__$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=$g_OPTION_BASE; __b2c__ctr<=__b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr]!=NULL){free($TO[__b2c__ctr]);} }" fi g_LOCALSTRINGS="$g_LOCALSTRINGS $TO" fi fi } #----------------------------------------------------------- function Handle_Relate { typeset SOURCE TO TARGET CHECK STR # Check if we have an argument at all if [[ "$1" = "RELATE" ]] then print "\nSyntax error: empty RELATE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nSyntax error: missing TO in RELATE statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Get the source string SOURCE=`print ${1%% TO *}` TO=`print ${1##* TO } | tr "," " "` # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Check if variable is declared as ASSOC CHECK=`grep -E "__b2c__${SOURCE}_type" $TARGET` if [[ -z $CHECK ]] then print "\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 CHECK=`grep -E "__b2c__${STR}_type" $TARGET` if [[ -z $CHECK ]] then print "\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 VAR LEN IN_STRING CHAR ESCAPED FCTR CCTR # Check if we have an argument at all if [[ "$1" = "DATA" ]] then print "\nSyntax error: empty DATA at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Start miniparser to see if we need to print something, convert spaces LINE="${1// /${g_PARSEVAR}}" VAR= LEN=${#LINE} IN_STRING=0 FCTR=0 CCTR=0 # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${LINE}" case $CHAR in ",") if [[ $IN_STRING -eq 0 ]] then # Check if var is string var if [[ "${VAR}" = +(*${g_DQUOTESIGN}*) ]] then print -r "${VAR}, " >> $STRINGARRAYFILE ((CCTR+=1)) else print -r "${VAR}, " >> $FLOATARRAYFILE ((FCTR+=1)) fi typeset -L0 CHAR="" ESCAPED=0 VAR= fi;; "\\") ESCAPED=1;; "\"") if [[ $ESCAPED -eq 0 ]] then if [[ $IN_STRING -eq 0 ]] then IN_STRING=1 else IN_STRING=0 fi fi ESCAPED=0;; *) ESCAPED=0;; esac # Convert back to space if [[ "${CHAR}" = "${g_PARSEVAR}" ]] then VAR="${VAR} " else VAR="${VAR}${CHAR}" fi let LEN=${#LINE}-1 typeset -R$LEN LINE="${LINE}" done # Write last element to file if [[ "${VAR}" = +(*${g_DQUOTESIGN}*) ]] then print -r "${VAR}, " >> $STRINGARRAYFILE ((CCTR+=1)) else print -r "${VAR}, " >> $FLOATARRAYFILE ((FCTR+=1)) fi print -r "__b2c__stringarray_ctr += ${CCTR};" >> $g_CFILE print -r "__b2c__floatarray_ctr += ${FCTR};" >> $g_CFILE } #----------------------------------------------------------- function Handle_Redim { typeset TARGET VAR TO CHECK TYPE # Check if we have an argument at all if [[ "$1" = "REDIM" ]] then print "\nSyntax error: empty REDIM at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nSyntax error: missing TO in REDIM statement at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Get the variable and resize VAR=`print ${1%% TO *}` TO=`print ${1##* TO }` CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " ${VAR##*.};"` if [[ -z $CHECK ]] then print "\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*|*char\*\*) || "${VAR}" = +(*${g_STRINGSIGN}) ]] then print -r "if(${TO}<__b2c_array_${VAR##*.}) {for(__b2c__ctr=${TO}+$g_OPTION_BASE; __b2c__ctr<__b2c_array_${VAR##*.}+$g_OPTION_BASE; __b2c__ctr++) {if($VAR[__b2c__ctr]!=NULL) free($VAR[__b2c__ctr]);} }" >> $g_CFILE fi # Realloc TYPE=${CHECK##*:} TYPE=${TYPE%;*} print -r "${VAR} = (${TYPE%% *})realloc(${VAR}, (${TO}+$g_OPTION_BASE)*sizeof(${TYPE%\**}));" >> $g_CFILE # Re-initialize strings if new area is bigger if [[ "${CHECK%% *}" = +(*STRING*|*char\*\*) || "${VAR}" = +(*${g_STRINGSIGN}) ]] then print -r "if(${TO}>__b2c_array_${VAR##*.}) {for(__b2c__ctr=__b2c_array_${VAR##*.}+$g_OPTION_BASE; __b2c__ctr<${TO}+$g_OPTION_BASE; __b2c__ctr++) $VAR[__b2c__ctr] = calloc(1, sizeof(char));}" >> $g_CFILE print -r "__b2c_array_${VAR##*.} = $TO;" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Swap { typeset TARGET VAR TO CHECK TYPE # Check if we have an argument at all if [[ "$1" = "SWAP" ]] then print "\nSyntax error: empty SWAP at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Get the variable names without spaces VAR=`print ${1%%,*} | tr -d "\040"` TO=`print ${1##*,} | tr -d "\040"` # Determine type if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] then TYPE="char *" else CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|,$VAR,|,$VAR;| $VAR=| ${VAR%%\[*}\[|,${VAR%%\[*}\[" | grep -v " noparse "` if [[ -z $CHECK ]] then print "\nSyntax error: cannot determine type of variables in SWAP at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi TYPE=${CHECK%% *} fi # Declare temp variable if [[ -n $g_FUNCNAME ]] then CHECK=`grep -E "__b2c__${VAR%%\[*}_swap;" $g_CFILE` if [[ -z $CHECK ]] then print -r "${TYPE} __b2c__${VAR%%\[*}_swap;" >> $g_CFILE fi else CHECK=`grep -E "__b2c__${VAR%%\[*}_swap;" $g_HFILE` if [[ -z $CHECK ]] then print -r "${TYPE} __b2c__${VAR%%\[*}_swap;" >> $g_HFILE fi fi print -r "__b2c__${VAR%%\[*}_swap = ${VAR}; ${VAR} = ${TO}; ${TO} = __b2c__${VAR%%\[*}_swap;" >> $g_CFILE } #----------------------------------------------------------- function Handle_Setserial { typeset DESC VALUE # Check if we have an argument at all if [[ "$1" = "SETSERIAL" ]] then print "\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 print "\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 print -r "memset (&__b2c__tty, 0, sizeof __b2c__tty); if (tcgetattr (${DESC}, &__b2c__tty) != 0)" >> $g_CFILE print -r "{if(!__b2c__trap){ERROR = 33; if(!__b2c__catch_set) RUNTIMEERROR(\"SETSERIAL\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE case $1 in +(*IMODE*) ) if [[ $VALUE = +(*~*) ]] then print -r "__b2c__tty.c_iflag &= ${VALUE};" >> $g_CFILE else print -r "__b2c__tty.c_iflag |= ${VALUE};" >> $g_CFILE fi ;; +(*OMODE*) ) if [[ $VALUE = +(*~*) ]] then print -r "__b2c__tty.c_oflag &= ${VALUE};" >> $g_CFILE else print -r "__b2c__tty.c_oflag |= ${VALUE};" >> $g_CFILE fi ;; +(*CMODE*) ) if [[ $VALUE = +(*~*) ]] then print -r "__b2c__tty.c_cflag &= ${VALUE};" >> $g_CFILE else print -r "__b2c__tty.c_cflag |= ${VALUE};" >> $g_CFILE fi ;; +(*LMODE*) ) if [[ $VALUE = +(*~*) ]] then print -r "__b2c__tty.c_lflag &= ${VALUE};" >> $g_CFILE else print -r "__b2c__tty.c_lflag |= ${VALUE};" >> $g_CFILE fi ;; +(*OTHER*) ) print -r "__b2c__tty.c_cc[${VALUE%=*}] = ${VALUE#*=};" >> $g_CFILE ;; +(*SPEED*) ) print -r "cfsetospeed (&__b2c__tty, ${VALUE}); cfsetispeed (&__b2c__tty, ${VALUE});" >> $g_CFILE ;; esac print -r "if (tcsetattr (${DESC}, TCSANOW, &__b2c__tty) != 0)" >> $g_CFILE print -r "{if(!__b2c__trap){ERROR = 33; if(!__b2c__catch_set) RUNTIMEERROR(\"SETSERIAL\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Call { typeset CHECK STR TARGET VAR # Check if we have an argument at all if [[ "$1" = "CALL" ]] then print "\nSyntax error: empty CALL at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Just call, no assignment if [[ "${1}" != +(* TO *) ]] then if [[ "${1}" = +(*\(*\)*) ]] then print -r "${1};" >> $g_CFILE else print -r "${1}();" >> $g_CFILE fi else VAR="${1##*TO }" # Check if string is declared if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "${VAR}" != +(*.*) ]] then STR="${VAR%${g_STRINGSIGN}*}" CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *${VAR} = NULL;" >> $g_HFILE fi # Not a string? elif [[ "${VAR}" != +(*\[*\]*) && "${VAR}" != +(*.*) && "${VAR}" != +(*\(*\)*) && "${VAR}" != +(*->*) ]] then CHECK=`grep -E "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " ${VAR},| ${VAR};|,${VAR},|,${VAR};| ${VAR}=" | grep -v " noparse "` if [[ -z $CHECK ]] then print -r "long ${VAR};" >> $g_HFILE fi fi # String variable? if [[ "${VAR}" = +(*${g_STRINGSIGN}) || "${VAR%%\(*}" = +(*${g_STRINGSIGN}) || "${VAR%%\[*}" = +(*${g_STRINGSIGN}) ]] then if [[ "${1%% TO*}" = +(*\(*\)*) ]] then print -r "__b2c__assign=(char*)__b2c__strdup(${1%% TO*});" >> $g_CFILE else print -r "__b2c__assign=(char*)__b2c__strdup(${1%% TO*}());" >> $g_CFILE fi print -r "if(__b2c__assign==NULL) __b2c__assign = calloc(1, sizeof(char));" >> $g_CFILE # Now see if we have a assoc or a normal variable if [[ "${VAR}" = +(*\(*\)) ]] then STR=${VAR#*\(} print -r "__b2c__${VAR%%\(*}__location = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE print -r "if(__b2c__${VAR%%\(*}__location->__b2c_value != NULL) free(__b2c__${VAR%%\(*}__location->__b2c_value); __b2c__${VAR%%\(*}__location->__b2c_value = __b2c__assign;" >> $g_CFILE # Check for relations Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1" else print -r "if(${VAR} != NULL) free(${VAR}); ${VAR} = __b2c__assign;" >> $g_CFILE fi else # Now see if we have an assoc or a normal variable if [[ "${VAR}" = +(*\(*\)) ]] then STR=${VAR#*\(} print -r "__b2c__${VAR%%\(*}__location = __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE if [[ "${1%% TO*}" = +(*\(*\)*) ]] then print -r "__b2c__${VAR%%\(*}__location->__b2c_value = ${1%% TO*};" >> $g_CFILE else print -r "__b2c__${VAR%%\(*}__location->__b2c_value = ${1%% TO*};" >> $g_CFILE fi # Check for relations Relate_Recurse "${VAR%%\(*}" "${STR}" "${VAR}" "-1" else if [[ "${1%% TO*}" = +(*\(*\)*) ]] then print -r "${VAR} = ${1%% TO*};" >> $g_CFILE else print -r "${VAR} = ${1%% TO*}();" >> $g_CFILE fi fi fi 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 typeset LEN SEQ TOTAL EXP LINE TO_PARSE # Get statement without spaces if [[ ${1} != +(*\*/) ]] then STATEMENT=`print -r "${1%% *}"` else STATEMENT="${1}" fi # Check if enclosed IF/ELIF/ELSE needs to be closed if [[ $g_IF_PARSE -eq 1 ]] then if [[ "${STATEMENT}" != +(ELIF*) && "${STATEMENT}" != +(ELSE*) ]] then print -r "}" >> $g_CFILE g_IF_PARSE=0 fi fi # In TRACE MODE show linenr and code if [[ $g_TRACE -eq 1 && ${1} != +(*FUNCTION *) && ${1} != +(*SUB *) ]] then print -r "if(__b2c__getch() == 27) exit(EXIT_SUCCESS); /* noparse */" >> $g_CFILE LINE=`print -r "${1}" | tr "\042" "\047"` if [[ $LINE = +(* FORMAT *) ]] then LINE=`print -r "${LINE}" | tr "\045" "\072"` fi print -r "fprintf(stderr, \"$g_CURFILE %d: ${LINE}\n\", $g_COUNTER); /* noparse */" >> $g_CFILE fi # See if we need to pass C code if [[ $g_USE_C -eq 1 ]] then if [[ ${@} = +(END*USEC) ]] then let g_USE_C=0 elif [[ ${@} = +(END*ENUM) ]] then let g_USE_C=0 print -r "};" >> $g_CFILE else print -r "${1}" >> $g_CFILE fi elif [[ $g_USE_H -eq 1 ]] then if [[ ${@} = +(END*USEH) ]] then let g_USE_H=0 else print -r "${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;; "PRINT") Handle_Print "${1#* }" "stdout";; "EPRINT") Handle_Print "${1#* }" "stderr";; "INPUT") Handle_Input "${1#* }";; "FOR") ((g_LOOPCTR+=1)) Handle_For "${1#* }";; "NEXT") if [[ ${g_LOOPVAR[${g_LOOPCTR}]} = +(*${g_STRINGSIGN}*) ]] then print -r "__b2c__assign=(char*)__b2c__strdup(strtok_r(NULL, ${g_LOOPSTEP[${g_LOOPCTR}]}, &__b2c__forin_${g_LOOPVAR[${g_LOOPCTR}]}_end)); if(${g_LOOPVAR[${g_LOOPCTR}]} != NULL) free(${g_LOOPVAR[${g_LOOPCTR}]}); ${g_LOOPVAR[${g_LOOPCTR}]} = __b2c__assign; }" >> $g_CFILE print -r "if(__b2c__forin_${g_LOOPVAR[${g_LOOPCTR}]}!=NULL) { free(__b2c__forin_${g_LOOPVAR[${g_LOOPCTR}]}); __b2c__forin_${g_LOOPVAR[${g_LOOPCTR}]} = NULL; }" >> $g_CFILE g_LOOPVAR[${g_LOOPCTR}]= g_LOOPSTEP[${g_LOOPCTR}]= else print -r "}" >> $g_CFILE fi if [[ $g_LOOPCTR -gt 0 ]] then ((g_LOOPCTR-=1)) if [[ $g_LOOPCTR -gt 0 ]] then print -r "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") g_IF_PARSE=0 # Check if THEN is available if [[ "${1}" != +(* THEN*) ]] then print "\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*}" print -r "if(${g_EQUATION}){" >> $g_CFILE if [[ ${SYM##* THEN } != +(*THEN*) ]] then Tokenize "${SYM##* THEN }" g_IF_PARSE=1 fi fi;; "ELIF") g_IF_PARSE=0 # Check if THEN is available if [[ "${1}" != +(* THEN*) ]] then print "\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*}" print -r "} else if(${g_EQUATION}){" >> $g_CFILE if [[ ${SYM##* THEN } != +(*THEN*) ]] then Tokenize "${SYM##* THEN }" g_IF_PARSE=1 fi fi;; "ELSE") g_IF_PARSE=0 print -r "} else {" >> $g_CFILE if [[ ${1##*ELSE } != +(*ELSE*) ]] then Tokenize "${1##*ELSE }" g_IF_PARSE=1 fi;; "ENDIF") print -r "}" >> $g_CFILE;; "FI") print -r "}" >> $g_CFILE;; "WHILE") ((g_LOOPCTR+=1)) Handle_While "${1#* }";; "WEND") print -r "}" >> $g_CFILE if [[ $g_LOOPCTR -gt 0 ]] then ((g_LOOPCTR-=1)) if [[ $g_LOOPCTR -gt 0 ]] then print -r "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 [[ "${1%% *}" != "${1#* }" && ${1#* } != "0" ]] then print -r "__b2c__break_ctr = ${1#* }-1; __b2c__break_flag = 1;" >> $g_CFILE fi print -r "break;" >> $g_CFILE;; "CONTINUE") # Check argument if [[ "${1%% *}" != "${1#* }" && ${1#* } != "0" ]] then print -r "__b2c__break_ctr = ${1#* }-1; __b2c__break_flag = 2;" >> $g_CFILE fi if [[ ${1#* } -gt 1 ]] then print -r "break;" >> $g_CFILE else print -r "continue;" >> $g_CFILE fi;; "REPEAT") ((g_LOOPCTR+=1)) print -r "do{" >> $g_CFILE;; "UNTIL") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty UNTIL at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Convert to legal C code Parse_Equation "${1#* }" print -r "} while(!(${g_EQUATION}));" >> $g_CFILE if [[ $g_LOOPCTR -gt 0 ]] then ((g_LOOPCTR-=1)) if [[ $g_LOOPCTR -gt 0 ]] then print -r "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#* }";; +(REM*) ) ;; +(\'*) ) ;; +(/\**) ) g_COMMENT="true";; "SYSTEM") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty SYSTEM at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else print -r "SYSTEM (${1#* });" >> $g_CFILE fi;; "SLEEP") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty SLEEP at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else print -r "usleep(${1#* }*1000);" >> $g_CFILE fi;; "OPEN") Handle_Open "${1#* }";; "CLOSE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty CLOSE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else if [[ "${1}" = +(* FILE *) ]] then print -r "fclose(${1##* });" >> $g_CFILE elif [[ "${1}" = +(* DIRECTORY *) ]] then print -r "closedir(${1##* });" >> $g_CFILE elif [[ "${1}" = +(* MEMORY *) ]] then print -r "${1##* } = NULL;" >> $g_CFILE elif [[ "${1}" = +(* NETWORK *) || "${1}" = +(* SERVER *) || "$1" = +(* UDP *) || "${1}" = +(* DEVICE *) ]] then print -r "close(${1##* });" >> $g_CFILE else print "\nSyntax error: erronuous CLOSE argument at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi fi;; "REWIND") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty REWIND at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else print -r "rewind(${1#* });" >> $g_CFILE fi;; "MEMREWIND") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty MEMREWIND at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else print -r "${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") if [[ "${1#* }" = +(*IF*) ]] then print -r "}" >> $g_CFILE elif [[ "${1#* }" = +(*RECORD*) ]] then if [[ -n $g_FUNCNAME ]] then print -r "};" >> $g_CFILE print -r "struct $g_RECORDNAME $g_RECORDVAR = { 0 } ;" >> $g_CFILE else print -r "};" >> $g_HFILE print -r "struct $g_RECORDNAME $g_RECORDVAR = { 0 } ;" >> $g_HFILE print -r $g_RECORDEND_HEADER >> $g_HFILE fi print -r $g_RECORDEND_BODY >> $g_CFILE g_RECORDNAME= g_RECORDVAR= g_RECORDEND_BODY= g_RECORDEND_HEADER= # Restore function name if GLOBAL was used if [[ -n $g_RECORDCACHE ]] then g_FUNCNAME=$g_RECORDCACHE g_RECORDCACHE= fi elif [[ "${1#* }" = +(*FUNCTION*) ]] then Handle_Endfunction elif [[ "${1#* }" = +(*SUB*) ]] then Handle_Endsub elif [[ "${1#* }" = +(*WITH*) ]] then g_WITHVAR= elif [[ "${1#* }" = +(*SELECT*) ]] then if [[ $g_SELECTVAR_CTR -eq 0 ]] then print "\nSyntax error: invalid END SELECT at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else print -r "}" >> $g_CFILE g_SELECTVAR[$g_SELECTVAR_CTR]= g_IN_CASE[$g_SELECTVAR_CTR]= g_CASE_FALL= ((g_SELECTVAR_CTR-=1)) fi elif [[ "${1#* }" != "END" ]] then print -r "exit(${1#* });" >> $g_CFILE else print -r "exit(EXIT_SUCCESS);" >> $g_CFILE fi;; "SUB") Handle_SubFunc "${1#* }";; "ENDSUB") Handle_Endsub;; "ENDWITH") g_WITHVAR=;; "ENDSELECT") if [[ $g_SELECTVAR_CTR -eq 0 ]] then print "\nSyntax error: invalid END SELECT at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else print -r "}" >> $g_CFILE g_SELECTVAR[$g_SELECTVAR_CTR]= g_IN_CASE[$g_SELECTVAR_CTR]= g_CASE_FALL= ((g_SELECTVAR_CTR-=1)) fi;; "CALL") Handle_Call "${1#* }";; "FUNCTION") Handle_SubFunc "${1#* }";; "ENDFUNCTION") Handle_Endfunction;; "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 print -r "if(__b2c__floatarray_ptr > 0) __b2c__floatarray_ptr = 0;" >> $g_CFILE print -r "if(__b2c__stringarray_ptr > 0) __b2c__stringarray_ptr = 0;" >> $g_CFILE else print -r "if(__b2c__floatarray_ptr > 0) __b2c__floatarray_ptr = __b2c__label_floatarray_${1#* };" >> $g_CFILE print -r "if(__b2c__stringarray_ptr > 0) __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 print "\nSyntax error: empty SEED at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else print -r "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=`print ${1#* } | tr -d "\042"` # Check argument if [[ ! -f ${INC%%,*} || "${1%% *}" = "${1#* }" ]] then print "\nSystem error: missing file '${INC%%,*}' for INCLUDE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Clear current terminal line print -n "\033[2K" TO_PARSE=0 # See if there are arguments if [[ ${INC} = +(*,*) ]] then EXP=`print ${INC#*,} | tr "," " "` INC=${INC%%,*} else TO_PARSE=2 fi # Check if the C Preprocessor needs to run if [[ $g_CPP -eq 1 ]] then if [[ -n `which cpp 2>/dev/null` ]] then cpp -P -w ${INC} ${INC}.cpp NEWFEED=${INC}.cpp g_TMP_FILES="$g_TMP_FILES ${INC}.cpp" else print "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 # Get rid of absolute path g_CURFILE=${NEWFEED##*/} while read -r LINE do print -n "\rConverting '${NEWFEED}'... ${g_COUNTER}\033[0J" # 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 [[ "$LINE" = +(* \\) && "$LINE" != +(REM*) && "$LINE" != +(${g_SQUOTESIGN}*) ]] then let LEN="${#LINE}"-2 typeset -L$LEN SEQ="${LINE}" TOTAL=$TOTAL$SEQ else print -r "/* noparse ${NEWFEED} BACON LINE $g_COUNTER */" >> $g_HFILE print -r "/* noparse ${NEWFEED} BACON LINE $g_COUNTER */" >> $g_CFILE TOTAL="${TOTAL}${LINE}" if [[ "${TOTAL}" != +(REM*) && "${TOTAL}" != +(${g_SQUOTESIGN}*) ]] then 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 # Restore original counter g_COUNTER=$COPY_COUNTER # Restore original file g_CURFILE=$COPY_CURFILE fi;; "POKE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty POKE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else SYM=${1#* } print -r "if (!__b2c__trap){if(__b2c__memory__check((void*)${SYM%%,*}, sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"POKE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "*(__b2c__MEMTYPE*)(${SYM%%,*}) = (__b2c__MEMTYPE)(${SYM#*,});" >> $g_CFILE fi;; "RESIZE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty RESIZE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else SYM=${1#* } print -r "if(!__b2c__trap) {if(__b2c__memory__check((void*)${SYM%%,*}, sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"RESIZE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "${SYM%%,*} = (long)realloc((void*)${SYM%%,*}, sizeof(__b2c__MEMTYPE)*(${SYM##*,}+1));" >> $g_CFILE print -r "if(!__b2c__trap) {if((void*)${SYM%%,*} == NULL) {ERROR=6; if(!__b2c__catch_set) RUNTIMEERROR(\"RESIZE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE fi;; "COPY") Handle_Copy "${1#* }";; "DELETE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty DELETE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Translate to C function if [[ "${1#* }" = +(*FILE*) ]] then print -r "if (unlink(${1#*FILE })==-1){if(!__b2c__trap){ERROR = 7; if(!__b2c__catch_set) RUNTIMEERROR(\"DELETE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE elif [[ "${1#* }" = +(*DIRECTORY*) ]] then print -r "if (rmdir(${1#*DIRECTORY }) == -1){if(!__b2c__trap){ERROR = 20;if(!__b2c__catch_set) RUNTIMEERROR(\"DELETE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE elif [[ "${1#* }" = +(*RECURSIVE*) ]] then print -r "if (__b2c__rmrecursive(${1#*RECURSIVE }) == -1){if(!__b2c__trap){ERROR = 20;if(!__b2c__catch_set) RUNTIMEERROR(\"DELETE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE else print "\nSyntax error: 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 print "\nSyntax error: empty MAKEDIR at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Translate to C function print -r "if (__b2c__makedir(${1#* }) != 0){if(!__b2c__trap){ERROR = 21;if(!__b2c__catch_set) RUNTIMEERROR(\"MAKEDIR\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE fi;; "CHANGEDIR") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty CHANGEDIR at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Translate to C function print -r "if (chdir(${1#* }) == -1){if(!__b2c__trap) {ERROR = 22;if(!__b2c__catch_set) RUNTIMEERROR(\"CHANGEDIR\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE fi;; "FREE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty FREE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Translate to C function if [[ ${1#* } = +(*\(*\)*) ]] then EXP=${1#* } print -r "__b2c__${EXP%%\(*}__location = __b2c__${EXP%%\(*}__find(${1#*\(};" >> $g_CFILE if [[ ${EXP%%\(*} = +(*${g_STRINGSIGN}*) ]] then print -r "if(__b2c__${EXP%%\(*}__location != NULL) {free(__b2c__${EXP%%\(*}__location->__b2c_value); __b2c__${EXP%%\(*}__location->__b2c_value = NULL;}" >> $g_CFILE else print -r "if(__b2c__${EXP%%\(*}__location != NULL) {__b2c__${EXP%%\(*}__location->__b2c_value = 0;}" >> $g_CFILE fi print -r "__b2c__${EXP%%\(*}__del(__b2c__${EXP%%\(*}__location);" >> $g_CFILE else print -r "if(!__b2c__trap){if(__b2c__memory__check((char *)${1#* }, sizeof(__b2c__MEMTYPE)))" >> $g_CFILE print -r "{ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"FREE\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} } free((void*)${1#* });" >> $g_CFILE fi fi;; "GOTO") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty GOTO at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Translate to C label print -r "goto ${1#* };" >> $g_CFILE fi;; "GOSUB") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty GOSUB at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Translate to C label print -r "__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); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;}" >> $g_CFILE print -r "if(!setjmp(__b2c__gosub_buffer[__b2c__gosub_buffer_ptr])) goto ${1#* };" >> $g_CFILE print -r "__b2c__gosub_buffer_ptr--; if(__b2c__gosub_buffer_ptr < -1) __b2c__gosub_buffer_ptr = -1;" >> $g_CFILE fi;; "LABEL") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty LABEL at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Translate to C label print -r "${1#* }:" >> $g_CFILE print -r ";" >> $g_CFILE # Needed for RESTORE print -r "int __b2c__label_floatarray_${1#* };" >> $g_HFILE print -r "__b2c__label_floatarray_${1#* } = __b2c__floatarray_ctr;" >> $g_CFILE print -r "int __b2c__label_stringarray_${1#* };" >> $g_HFILE print -r "__b2c__label_stringarray_${1#* } = __b2c__stringarray_ctr;" >> $g_CFILE fi;; "TRAP") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty TRAP at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else if [[ "${1#* }" = "SYSTEM" ]] then print -r "/* Error trapping by OS */" >> $g_CFILE print -r "__b2c__trap = 1;" >> $g_CFILE print -r "signal(SIGILL, __b2c__catch_signal);" >> $g_CFILE print -r "signal(SIGABRT, __b2c__catch_signal);" >> $g_CFILE print -r "signal(SIGFPE, __b2c__catch_signal);" >> $g_CFILE print -r "signal(SIGSEGV, __b2c__catch_signal);" >> $g_CFILE elif [[ "${1#* }" = "LOCAL" ]] then print -r "/* Error catching is disabled */" >> $g_CFILE print -r "__b2c__trap = 0;" >> $g_CFILE print -r "signal(SIGILL, SIG_DFL);" >> $g_CFILE print -r "signal(SIGABRT, SIG_DFL);" >> $g_CFILE print -r "signal(SIGFPE, SIG_DFL);" >> $g_CFILE print -r "signal(SIGSEGV, SIG_DFL);" >> $g_CFILE else print "\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 print "\nSyntax error: empty CATCH at line $g_COUNTER in file '$g_CURFILE'!" exit 1 elif [[ "${1#* }" = +(*GOTO*) ]] then print -r "__b2c__catch_set = 1;" >> $g_CFILE g_CATCHGOTO="${1##* GOTO }" elif [[ "${1#* }" = +(*RESET*) ]] then print -r "__b2c__catch_set = 0;" >> $g_CFILE g_CATCHGOTO="__B2C__PROGRAM__EXIT" else print "\nSyntax error: CATCH without GOTO or RESET at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi;; "RESUME") print -r "longjmp(__b2c__jump, 1);" >> $g_CFILE;; "CLEAR") print -r "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 print "\nSyntax error: empty RECORD at line $g_COUNTER in file '$g_CURFILE'!" exit 1 elif [[ -n $g_RECORDNAME ]] then print "\nSyntax error: cannot define a record within a record!" exit 1 else # Translate to C typedef struct if [[ -n $g_FUNCNAME ]] then g_RECORDNAME="RECORD_${g_FUNCNAME}_${g_COUNTER}" print -r "struct $g_RECORDNAME{" >> $g_CFILE else g_RECORDNAME="RECORD_${g_COUNTER}" print -r "struct $g_RECORDNAME{" >> $g_HFILE fi g_RECORDVAR=${1#* } fi;; "WITH") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty WITH at line $g_COUNTER in file '$g_CURFILE'!" exit 1 elif [[ -n $g_RECORDNAME ]] then print "\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 print "\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= fi;; "CASE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty CASE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else if [[ -n ${g_IN_CASE[$g_SELECTVAR_CTR]} ]] then if [[ ${g_SELECTVAR[$g_SELECTVAR_CTR]%%\(*} = +(*${g_STRINGSIGN}*) ]] then # Get expression without ; if [[ -z ${1##*;} ]] then let LEN="${#1}"-1; typeset -L$LEN EXP="${1}" g_CASE_FALL="|| !__b2c__strcmp(${g_SELECTVAR[$g_SELECTVAR_CTR]}, ${EXP#* }) ${g_CASE_FALL}" else print -r "} else if (!__b2c__strcmp(${g_SELECTVAR[$g_SELECTVAR_CTR]}, ${1#* }) ${g_CASE_FALL}){" >> $g_CFILE g_CASE_FALL= fi else # Get expression without ; if [[ -z ${1##*;} ]] then let LEN="${#1}"-1; typeset -L$LEN EXP="${1}" g_CASE_FALL="|| ${g_SELECTVAR[$g_SELECTVAR_CTR]} == (${EXP#* }) ${g_CASE_FALL}" else print -r "} else if (${g_SELECTVAR[$g_SELECTVAR_CTR]} == (${1#* }) ${g_CASE_FALL}){" >> $g_CFILE g_CASE_FALL= fi fi else if [[ ${g_SELECTVAR[$g_SELECTVAR_CTR]%%\(*} = +(*${g_STRINGSIGN}*) ]] then # Get expression without ; if [[ -z ${1##*;} ]] then let LEN="${#1}"-1; typeset -L$LEN EXP="${1}" g_CASE_FALL="|| !__b2c__strcmp(${g_SELECTVAR[$g_SELECTVAR_CTR]}, ${EXP#* }) ${g_CASE_FALL}" else print -r "if (!__b2c__strcmp(${g_SELECTVAR[$g_SELECTVAR_CTR]}, ${1#* }) ${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; typeset -L$LEN EXP="${1}" g_CASE_FALL="|| ${g_SELECTVAR[$g_SELECTVAR_CTR]} == (${EXP#* }) ${g_CASE_FALL}" else print -r "if (${g_SELECTVAR[$g_SELECTVAR_CTR]} == (${1#* }) ${g_CASE_FALL}){" >> $g_CFILE g_IN_CASE[$g_SELECTVAR_CTR]=1 g_CASE_FALL= fi fi fi fi;; "DEFAULT") if [[ -n ${g_IN_CASE[$g_SELECTVAR_CTR]} ]] then print -r "} else {" >> $g_CFILE else print "\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 print "\nSyntax error: empty SETENVIRON at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else # Resolve this with C macro print -r "SETENVIRON(${1#* });" >> $g_CFILE fi;; "SORT") Handle_Sort "${1#* }";; "STOP") print -r "kill(getpid(), SIGSTOP);" >> $g_CFILE ;; "TRACE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty TRACE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else if [[ "${1#* }" = +(*ON*) ]] then g_TRACE=1 elif [[ "${1#* }" = +(*OFF*) ]] then g_TRACE=0 fi fi;; "OPTION") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\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=${1##*BASE } else print "\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 print -r "__b2c__option_compare = ${1##*COMPARE };" >> $g_CFILE else print "\nSyntax error: invalid argument to OPTION COMPARE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi elif [[ "${1#* }" = +(*SOCKET*) ]] then if [[ "${1##*SOCKET }" = +([0123456789]) ]] then g_OPTION_SOCKET=${1##*SOCKET } else print "\nSyntax error: invalid argument to OPTION SOCKET at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi elif [[ "${1#* }" = +(*MEMSTREAM*) ]] then if [[ "${1##*MEMSTREAM }" = +([01]|TRUE|FALSE) ]] then print -r "__b2c__option_memstream = ${1##*MEMSTREAM };" >> $g_CFILE else print "\nSyntax error: invalid argument to OPTION MEMSTREAM at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi elif [[ "${1#* }" = +(*MEMTYPE*) ]] then print -r "#undef __b2c__MEMTYPE" >> $g_CFILE print -r "#define __b2c__MEMTYPE ${1##*MEMTYPE }" >> $g_CFILE elif [[ "${1#* }" = +(*COLLAPSE*) ]] then if [[ "${1##*COLLAPSE }" = +([01]|TRUE|FALSE) ]] then print -r "__b2c__collapse = ${1##*COLLAPSE };" >> $g_CFILE else print "\nSyntax error: invalid argument to OPTION COLLAPSE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi elif [[ "${1#* }" = +(*DEVICE*) ]] then print -r "__b2c__option_open = (${1##*DEVICE });" >> $g_CFILE elif [[ "${1#* }" = +(*STARTPOINT*) ]] then if [[ "${1##*STARTPOINT }" = +([01]|TRUE|FALSE) ]] then print -r "__b2c__option_startpoint = ${1##*STARTPOINT };" >> $g_CFILE else print "\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 }" = +([01]|TRUE|FALSE) ]] then print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print -r "setlocale(LC_ALL, \"\");" >> $g_CFILE print -r "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); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "if(textdomain(\"${g_SOURCEFILE%.*}\")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set) RUNTIMEERROR(\"OPTION INTERNATIONAL\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE else print "\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*) print -r "#include " >> $g_HFILE print -r "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 ;; *) print "\nSyntax error: invalid argument to OPTION SOCKET at line $g_COUNTER in file '$g_CURFILE'!" exit 1 ;; esac else print "\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 print "\nSyntax error: empty PROTO at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else SYM=`print ${1#* } | tr -d "\042"` # Check if ALIAS is there if [[ $SYM = +(* ALIAS *) ]] then print -r "#define ${SYM##* ALIAS } ${SYM%% ALIAS *}" >> $g_HFILE g_IMPORTED="${SYM##* ALIAS } $g_IMPORTED" g_IMPORTED="${SYM%% ALIAS *} $g_IMPORTED" else g_IMPORTED="${SYM//,/ } $g_IMPORTED" fi fi;; "INCR") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty INC at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else EXP=${1#* } # Check if there is associative array assignment if [[ "${EXP}" = +(*\(*\)*) && "${EXP}" != +(*\]) && "${EXP}" != +(*,*\(*) ]] then if [[ ${EXP} = +(*\)*,*) ]] then SYM="${EXP#*,}" EXP=${EXP%%,*} else SYM="1" >> $g_CFILE fi INC=${EXP#*\(} print -r "__b2c__${EXP%%\(*}__location = __b2c__${EXP%%\(*}__add(${INC};" >> $g_CFILE print -r "__b2c__${EXP%%\(*}__location->__b2c_value = ${EXP} + (${SYM});" >> $g_CFILE # Check for relations Relate_Recurse "${EXP%%\(*}" "${INC}" "${EXP}+(${SYM})" "-1" else if [[ ${EXP} = +(*,*) ]] then SYM="${EXP#*,}" EXP=${EXP%%,*} else SYM="1" >> $g_CFILE fi print -r "${EXP} = ${EXP} + (${SYM});" >> $g_CFILE fi fi;; "DECR") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty DEC at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else EXP=${1#* } # Check if there is associative array assignment if [[ "${EXP}" = +(*\(*\)*) && "${EXP}" != +(*\]) && "${EXP}" != +(*,*\(*) ]] then if [[ ${EXP} = +(*\)*,*) ]] then SYM="${EXP#*,}" EXP=${EXP%%,*} else SYM="1" >> $g_CFILE fi INC=${EXP#*\(} print -r "__b2c__${EXP%%\(*}__location = __b2c__${EXP%%\(*}__add(${INC};" >> $g_CFILE print -r "__b2c__${EXP%%\(*}__location->__b2c_value = ${EXP} - (${SYM});" >> $g_CFILE # Check for relations Relate_Recurse "${EXP%%\(*}" "${INC}" "${EXP}-(${SYM})" "-1" else if [[ ${EXP} = +(*,*) ]] then SYM="${EXP#*,}" EXP=${EXP%%,*} else SYM="1" >> $g_CFILE fi print -r "${EXP} = ${EXP} - (${SYM});" >> $g_CFILE fi fi;; "ALARM") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty ALARM at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else EXP=${1#* } if [[ ${EXP} = +(*,*) ]] then print -r "signal(SIGALRM, (void*)${EXP%,*});" >> $g_CFILE print -r "__b2c__alarm.it_value.tv_sec = (long)(${EXP#*,})/1000; __b2c__alarm.it_value.tv_usec = ((${EXP#*,})%1000)*1000;" >> $g_CFILE print -r "__b2c__alarm.it_interval.tv_sec = 0; __b2c__alarm.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &__b2c__alarm, NULL);" >> $g_CFILE else print "\nSyntax error: missing argument in ALARM at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi fi;; "CURSOR") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nSyntax error: empty CURSOR at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else EXP=1 if [[ "${1#* }" = +(*OFF*) ]] then print -r "fprintf(stdout,\"\033[?25l\"); fflush(stdout);" >> $g_CFILE elif [[ "${1#* }" = +(*ON*) ]] then print -r "fprintf(stdout,\"\033[?25h\"); fflush(stdout);" >> $g_CFILE elif [[ "${1#* }" = +(*UP*) ]] then if [[ ${1##*UP } != +(*UP*) ]] then EXP=${1##*UP } fi print -r "fprintf(stdout,\"\033[%ldA\", (long)${EXP}); fflush(stdout);" >> $g_CFILE elif [[ "${1#* }" = +(*DOWN*) ]] then if [[ ${1##*DOWN } != +(*DOWN*) ]] then EXP=${1##*DOWN } fi print -r "fprintf(stdout,\"\033[%ldB\", (long)${EXP}); fflush(stdout);" >> $g_CFILE elif [[ "${1#* }" = +(*FORWARD*) ]] then if [[ ${1##*FORWARD } != +(*FORWARD*) ]] then EXP=${1##*FORWARD } fi print -r "fprintf(stdout,\"\033[%ldC\", (long)${EXP}); fflush(stdout);" >> $g_CFILE elif [[ "${1#* }" = +(*BACK*) ]] then if [[ ${1##*BACK } != +(*BACK*) ]] then EXP=${1##*BACK } fi print -r "fprintf(stdout,\"\033[%ldD\", (long)${EXP}); fflush(stdout);" >> $g_CFILE fi fi;; "SCROLL") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\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 print -r "fprintf(stdout,\"\033[%ldS\", (long)${EXP}); fflush(stdout);" >> $g_CFILE elif [[ "${1#* }" = +(*DOWN*) ]] then if [[ ${1##*DOWN } != +(*DOWN*) ]] then EXP=${1##*DOWN } fi print -r "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 print "\nSyntax error: empty TEXTDOMAIN at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else EXP=${1#* } if [[ ${EXP} = +(*,*) ]] then print -r "if(bindtextdomain(${EXP})==NULL){if(!__b2c__trap){ERROR = 6;if(!__b2c__catch_set) RUNTIMEERROR(\"TEXTDOMAIN\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "if(textdomain(${EXP%,*})==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set) RUNTIMEERROR(\"TEXTDOMAIN\", $g_COUNTER, \"$g_CURFILE\", ERROR); if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE else print "\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 print "\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 print -r "${g_STRINGARRAYS}" >> $g_CFILE for EXP in $g_LOCALSTRINGS do print -r "if($EXP != NULL) free($EXP);" >> $g_CFILE done print -r "__b2c__catch_set = __b2c__catch_set_backup;" >> $g_CFILE # The actual exit if [[ "${g_FUNCNAME}" = +(*${g_STRINGSIGN}*) ]] then print "return(NULL);" >> $g_CFILE else print "return;" >> $g_CFILE fi;; "PRAGMA") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\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#* }" = +(*LDFLAGS*) ]] then if [[ ${1##*LDFLAGS } = +(*config*) ]] then EXP=`print -r ${1##*LDFLAGS } |tr -d "\140"` g_LDFLAGS="$g_LDFLAGS `eval ${EXP}`" else for EXP in ${1##*LDFLAGS } do g_LDFLAGS="$g_LDFLAGS -l${EXP}" done fi elif [[ "${1#* }" = +(*INCLUDE*) ]] then for EXP in ${1##*INCLUDE } do if [[ ! -f "/usr/include/$EXP" ]] then print -r "#include \"${EXP}\"" >> $g_HFILE else print -r "#include <${EXP}>" >> $g_HFILE fi done else print "\nSyntax error: argument to PRAGMA at line $g_COUNTER in file '$g_CURFILE' not recognized!" exit 1 fi fi;; "SWAP") Handle_Swap "${1#* }";; "SETSERIAL") Handle_Setserial "${1#* }";; "ENUM") print -r "enum {" >> $g_CFILE let g_USE_C=1;; *) # Check on imported symbols first FOUND=0 for SYM in $g_IMPORTED do if [[ "$SYM" = ${1%%\(*} || "$SYM" = ${1%% *} ]] then FOUND=1 if [[ "$1" != +(*\(*\)*) ]] then print -r "$SYM();" >> $g_CFILE else print -r "$SYM(${1#*\(};" >> $g_CFILE fi fi done # Not an imported symbol? Check if assignment if [[ $FOUND -eq 0 ]] then Handle_Let "$1" fi;; esac fi } #----------------------------------------------------------- function Tokenize { typeset CHAR IS_ESCAPED IS_STRING IS_STATEMENT TOKEN DATA LEN typeset INLEN INCHAR INTOKEN INSPAC INSTR ITEM1 ITEM2 RESULT DIRECT INESCAPED ISQUOTE # If we have C code, skip tokenization if [[ $g_USE_C -eq 1 ]] then Parse_Line "${1}" return fi # Initialize miniparser, convert spaces DATA="${1// /${g_PARSEVAR}}" while true do IS_ESCAPED=0 IS_STRING=0 IS_STATEMENT="" TOKEN= LEN=${#DATA} until [[ $LEN -eq 0 ]] do typeset -L5 CHAR="${DATA}" if [[ "${CHAR}" = "INTL$" ]] then if [[ $IS_STRING -eq 0 ]] then let LEN=${#DATA}-5 typeset -R$LEN DATA="${DATA}" TOKEN="${TOKEN}gettext" fi elif [[ "${CHAR}" = "NNTL$" ]] then if [[ $IS_STRING -eq 0 ]] then let LEN=${#DATA}-5 typeset -R$LEN DATA="${DATA}" TOKEN="${TOKEN}ngettext" fi fi typeset -L1 CHAR="${DATA}" case $CHAR in ":") if [[ $IS_STRING -eq 0 ]] then Parse_Line "${TOKEN}" typeset -L0 CHAR="" TOKEN= IS_STATEMENT="" fi;; "$") if [[ $IS_STRING -eq 0 || ${1} = +(*IMPORT*FROM*TYPE*) ]] then TOKEN="${TOKEN}${g_STRINGSIGN}" typeset -L0 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 ]] then typeset -L${#TOKEN} INTOKEN="" # ITEMIZER1: Get item on the left side INTOKEN=`print -r "${TOKEN}" | tr " " "\001"` INLEN=${#INTOKEN} ITEM1= BRACKET=0 INSPAC=0 INSTR=0 DIRECT=0 ISQUOTE=0 until [[ $INLEN -eq 0 ]] do typeset -R1 INCHAR="${INTOKEN}" 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;; ":") ISQUOTE=0 if [[ ${INSTR} -eq 0 ]] then break fi;; esac if [[ "${INCHAR}" = "${g_PARSEVAR}" ]] then ITEM1=" ${ITEM1}" else ITEM1="${INCHAR}${ITEM1}" fi let INLEN=${#INTOKEN}-1 typeset -L$INLEN INTOKEN="${INTOKEN}" done # If ITEM is a string element continue if [[ ${ITEM1} = +(*${g_STRINGSIGN}*) || "${ITEM1}" = +(*${g_DQUOTESIGN}*) ]] then typeset -L0 CHAR="" TOKEN=`print -r ${INTOKEN}| tr "\001" " "` # ITEMIZER2: Get item on the right side ((LEN-=1)) typeset -R$LEN INTOKEN="${DATA}" INLEN=${#INTOKEN} ITEM2= BRACKET=0 INSTR=0 INESCAPED=0 INSPAC=0 DIRECT=0 until [[ $INLEN -eq 0 ]] do typeset -L1 INCHAR="${INTOKEN}" case $INCHAR in "(") ((DIRECT+=1)) if [[ ${INSTR} -eq 0 ]] then ((BRACKET+=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 ]] 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}" else ITEM2="${ITEM2}$" fi else ITEM2="${ITEM2}${INCHAR}" fi let INLEN=${#INTOKEN}-1 typeset -R$INLEN INTOKEN="${INTOKEN}" done ((INLEN+=1)) typeset -R$INLEN DATA="${DATA}" TOKEN="${TOKEN} CONCAT${g_STRINGSIGN}(${ITEM1},${ITEM2}) " 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}" else TOKEN="${TOKEN}${CHAR}" fi let LEN=${#DATA}-1 typeset -R$LEN DATA="${DATA}" done # Check if all nested '&' have been parsed if [[ "${TOKEN}" = "${RESULT}" || ${1} != +(*\&*) ]] then break fi RESULT=${TOKEN} typeset -R${#TOKEN} DATA=`print -r "${TOKEN}" | tr " " "\001"` done Parse_Line "${TOKEN}" } #----------------------------------------------------------- function Parse_Chunk { typeset CHAR IS_ESCAPED IS_STRING TOKEN DATA LEN TERM EQ IS_EQUATION IS_ESCAPED=0 IS_STRING=0 IS_EQUATION=0 TOKEN= EQ="!" # Initialize miniparser, convert spaces DATA=`print -r "${1}" | tr " " "\001"` LEN=${#DATA} until [[ $LEN -eq 0 ]] do typeset -L2 CHAR="${DATA}" case $CHAR in "==") if [[ $IS_STRING -eq 0 ]] then let LEN=${#DATA}-2 typeset -R$LEN DATA="${DATA}" ((LEN+=2)) typeset -R$LEN DATA="= ${DATA}" fi;; "<>") if [[ $IS_STRING -eq 0 ]] then let LEN=${#DATA}-2 typeset -R$LEN DATA="${DATA}" ((LEN+=2)) typeset -R$LEN DATA="!=${DATA}" fi;; esac typeset -L1 CHAR="${DATA}" case $CHAR in "=") if [[ $IS_STRING -eq 0 ]] then if [[ "${1%%\(*}" = +(*${g_STRINGSIGN}*) || "${1%%\(*}" = +(*${g_DQUOTESIGN}*) ]] then TERM="${TOKEN}" TOKEN= 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 [[ "${1%%\(*}" = +(*${g_STRINGSIGN}*) || "${1%%\(*}" = +(*${g_DQUOTESIGN}*) ]] then EQ="" elif [[ $IS_EQUATION -eq 0 ]] then TOKEN="${TOKEN}!=" IS_ESCAPED=0 let LEN=${#DATA}-1 typeset -R$LEN DATA="${DATA}" else TOKEN="${TOKEN}!" IS_EQUATION=0 fi else TOKEN="${TOKEN}!" fi;; "<") IS_EQUATION=1 TOKEN="${TOKEN}<";; ">") IS_EQUATION=1 TOKEN="${TOKEN}>";; "#") IS_EQUATION=1 TOKEN="${TOKEN}#";; "\\") if [[ $IS_ESCAPED -eq 0 ]] then IS_ESCAPED=1 else IS_ESCAPED=0 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}\"";; *) # Convert back to space if [[ "${CHAR}" = "${g_PARSEVAR}" ]] then TOKEN="${TOKEN} " else TOKEN="${TOKEN}${CHAR}" fi IS_ESCAPED=0;; esac let LEN=${#DATA}-1 typeset -R$LEN DATA="${DATA}" done if [[ "${1%%\(*}" = +(*${g_STRINGSIGN}*) || "${1%%\(*}" = +(*${g_DQUOTESIGN}*) ]] then TOKEN="((__b2c__option_compare == 0) ? ${EQ}__b2c__strcmp(${TERM}, $TOKEN) : ${EQ}__b2c__strcasecmp(${TERM}, $TOKEN))" fi g_EQUATION="${g_EQUATION} ${TOKEN} ${2}" } #----------------------------------------------------------- function Parse_Equation { typeset CHAR IS_ESCAPED IS_STRING TOKEN DATA LEN typeset AND OR g_EQUATION= IS_ESCAPED=0 IS_STRING=0 TOKEN= AND=`print " AND " | tr " " "\001"` OR=`print " OR " | tr " " "\001"` # Initialize miniparser, convert spaces DATA=`print -r "${1}" | tr " " "\001"` LEN=${#DATA} until [[ $LEN -eq 0 ]] do typeset -L5 CHAR="${DATA}" if [[ "${CHAR}" = "${AND}" ]] then if [[ $IS_STRING -eq 0 ]] then Parse_Chunk "${TOKEN}" " AND " let LEN=${#DATA}-4 typeset -R$LEN DATA="${DATA}" TOKEN= typeset -L0 CHAR="" fi fi typeset -L4 CHAR="${DATA}" if [[ "${CHAR}" = "${OR}" ]] then if [[ $IS_STRING -eq 0 ]] then Parse_Chunk "${TOKEN}" " OR " let LEN=${#DATA}-3 typeset -R$LEN DATA="${DATA}" TOKEN= typeset -L0 CHAR="" fi fi typeset -L1 CHAR="${DATA}" 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 typeset -R$LEN DATA="${DATA}" done Parse_Chunk "${TOKEN}" } #----------------------------------------------------------- # # Main program # #----------------------------------------------------------- # Default BACON settings let g_MAX_DIGITS=32 # Maximum of internal buffers needed for string processing let g_MAX_BUFFERS=256 # This is the size for static buffers like fgets, read etc. let g_BUFFER_SIZE=512 # Maximum RETURN buffers let g_MAX_RBUFFERS=32 # Defaults for parameters g_CCNAME=cc g_TEMPDIR=. g_INCFILES= g_CCFLAGS= g_BINEXT= let g_NO_COMPILE=0 let g_TMP_PRESERVE=0 let g_CPP=0 let g_XGETTEXT=0 let g_SAVE_CONFIG=0 let g_USE_C=0 let g_USE_H=0 let g_MAX_BACKLOG=4 g_INCLUDE_FILES= let g_TRACE=0 let g_OPTION_BASE=0 let g_OPTION_SOCKET=5 let g_IF_PARSE=0 # Some global declarations g_CURFILE= g_FUNCNAME= g_FUNCTYPE= g_PROTOTYPE= g_TMP_FILES= g_LOCALSTRINGS= g_STRINGARRAYS= g_STRINGARGS= g_DYNAMICARRAYS= g_RECORDCACHE= let g_LOOPCTR=0 set -A g_LOOPVAR set -A g_LOOPSTEP g_ERRORTXT= g_EQUATION= g_COMMENT="false" # Always create a final label g_CATCHGOTO="__B2C__PROGRAM__EXIT" # Records g_RECORDNAME= g_RECORDVAR= 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 set -A g_SELECTVAR set -A g_IN_CASE g_SELECTVAR_CTR=0 # Relate set -A g_RELATE g_RELATE_CTR=0 # Read any configfile values if [[ -f $HOME/.bacon/bacon.cfg ]] then while read -r LINE do case ${LINE%% *} in ccname) g_CCNAME=${LINE#ccname};; tempdir) g_TEMPDIR=${LINE#tempdir}; g_TEMPDIR=`print $g_TEMPDIR`;; incfiles) g_INCFILES=${LINE#incfiles};; ldflags) g_LDFLAGS=${LINE#ldflags};; ccflags) g_CCFLAGS=${LINE#ccflags};; esac done < $HOME/.bacon/bacon.cfg fi # Get arguments while getopts ":c:d:i:l:o:xnjfpvw" 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" ]] then print "System error: included C header file from -i option not found!" exit 1 fi if [[ ! -f "/usr/include/$OPTARG" ]] then g_INCFILES="$g_INCFILES ${OPTARG}" else g_INCFILES="$g_INCFILES <${OPTARG}>" fi;; l) if [[ $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;; j) g_CPP=1;; f) g_CCFLAGS="$g_CCFLAGS -shared -rdynamic" if [[ `uname -a` = +(*x86_64*) ]] then g_CCFLAGS="$g_CCFLAGS -fPIC" fi g_BINEXT=".so";; p) g_TMP_PRESERVE=1;; x) g_XGETTEXT=1;; v) print print "BaCon version $g_VERSION - KSH - (c) Peter van Eerten - GPL v3." print exit 0;; w) g_SAVE_CONFIG=1;; \?|h) print print "USAGE: bacon [options] program[.bac]" print print "OPTIONS:" print print " -c \tCompiler to use (default: $g_CCNAME)" print " -l \tPass libraries to linker" print " -o \tPass compiler options" print " -i \tAdd include file to C code" print " -d \tTemporary directory (default: $g_TEMPDIR)" print " -x \t\tExtract gettext strings" print " -f \t\tCreate Shared Object" print " -n \t\tDo not compile, only convert" print " -j \t\tInvoke C Preprocessor" print " -p \t\tPreserve temporary files" print " -w \t\tSave options to BaCon configfile" print " -v \t\tShow version" print " -h \t\tShow help" print exit 0;; esac done shift $(($OPTIND-1)) # See if configfile must be written if [[ $g_SAVE_CONFIG -eq 1 ]] then if [[ ! -d $HOME/.bacon ]] then mkdir $HOME/.bacon fi print "ccname $g_CCNAME" > $HOME/.bacon/bacon.cfg print "tempdir $g_TEMPDIR" >> $HOME/.bacon/bacon.cfg print "incfiles $g_INCFILES" >> $HOME/.bacon/bacon.cfg print "ldflags $g_LDFLAGS" >> $HOME/.bacon/bacon.cfg print "ccflags $g_CCFLAGS" >> $HOME/.bacon/bacon.cfg fi # Check if a filename was entered, if so get it if [[ $# -eq 0 ]] then print "System error: no filename? Run with '-h' to see usage." exit 1 elif [[ "$1" = +(http://*) ]] then if [[ -z `which telnet 2>/dev/null` ]] then print "System error: No telnet client found! Cannot retrieve file." exit 1 fi print -n "Fetching file... " # Remove http part g_SOURCEFILE="${1#*http://}" # Get header to see if file exists, and if so, get length HEAD=`(print "set crlf on"; print "open ${g_SOURCEFILE%%/*} 80"; sleep 1; print "HEAD /${g_SOURCEFILE#*/} HTTP/1.1"; print "Host: ${g_SOURCEFILE%%/*}"; print; sleep 1; print "quit";) | telnet 2>/dev/null` LEN=`print -r ${HEAD#*Content-Length: }` # No file found on server if [[ "${LEN%% *}" = "telnet>" || "${HEAD}" != +(*Content-Length*) ]] then print "System error: file not found! Check URL and try again." exit 1 fi # Get the actual contents of the file typeset -R${LEN%% *} DOWNLOAD=`(print "set crlf on"; print "open ${g_SOURCEFILE%%/*} 80"; sleep 2; print "GET /${g_SOURCEFILE#*/} HTTP/1.1"; print "Host: ${g_SOURCEFILE%%/*}"; print; sleep 2; print "quit";) | telnet 2>/dev/null` # Set the final filename and save g_SOURCEFILE="${1##*/}" print -r "${DOWNLOAD}" > $g_SOURCEFILE # Check resulting filesize with HTTP header FILELEN=`wc -c $g_SOURCEFILE` let FILELEN=${FILELEN%% *}-1 if [[ ${FILELEN} -ne ${LEN%% *} ]] then print "System error: file could not be downloaded probably due to a timeout. Try again later." exit 1 fi print "done." elif [[ "$@" != +(*.bac) ]] then g_SOURCEFILE="$@.bac" else g_SOURCEFILE="$@" fi # Check if file exists if [[ ! -f $g_SOURCEFILE ]] then print "System error: file 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 # 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 [[ ${LEN} -gt 0 ]] then read ANSWER?"WARNING: ${LEN} temporary files found! Do you want to delete them (y/n)? " if [[ ${ANSWER} = "y" ]] then rm -f $g_TEMPDIR/${g_SOURCEFILE%.bac}.*.* print "Temporary files were deleted." else print "Exiting..." exit 1 fi fi # Create basic C file print -r "/* Created with KSH BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > $g_CFILE print -r "#include \"${g_SOURCEFILE##*/}.h\"" >> $g_CFILE print -r "int main(int argc, const char **argv){" >> $g_CFILE # See if we have the detector print -r "if(argc==2 && !strcmp(argv[1], \"-bacon\")){fprintf(stderr, \"Compiled with %s.\n\", COMPILED_BY_WHICH_BACON${g_STRINGSIGN}); exit(EXIT_FAILURE);}" >> $g_CFILE # Put arguments into reserved variable ARGUMENT print -r "/* Setup the reserved variable 'ARGUMENT' */" >> $g_CFILE print -r "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" >> $g_CFILE print -r "{if(strstr(argv[__b2c__counter], \" \")||strstr(argv[__b2c__counter], \"\011\")) __b2c__arglen += strlen(argv[__b2c__counter]) + 3;" >> $g_CFILE print -r "else __b2c__arglen += strlen(argv[__b2c__counter]) + 1;} __b2c__arglen++; ARGUMENT${g_STRINGSIGN} = (char*)calloc(__b2c__arglen, sizeof(char));" >> $g_CFILE print -r "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++){if(strstr(argv[__b2c__counter], \" \")||strstr(argv[__b2c__counter], \"\011\")){" >> $g_CFILE print -r "strcat(ARGUMENT${g_STRINGSIGN}, \"\042\"); strcat(ARGUMENT${g_STRINGSIGN}, argv[__b2c__counter]); strcat(ARGUMENT${g_STRINGSIGN}, \"\042\");}" >> $g_CFILE print -r "else strcat(ARGUMENT${g_STRINGSIGN}, argv[__b2c__counter]); if(__b2c__counter != argc - 1) strcat(ARGUMENT${g_STRINGSIGN}, \" \");}" >> $g_CFILE print -r "/* By default seed random generator */" >> $g_CFILE print -r "srandom((unsigned int)time(NULL));" >> $g_CFILE print -r "/* Initialize internal stackpointer */" >> $g_CFILE print -r "__b2c__typestack = (int*)calloc(1, sizeof(int));" >> $g_CFILE print -r "__b2c__stringstack = (char**)realloc(__b2c__stringstack, sizeof(char*)); __b2c__stringstack[0] = calloc(1, sizeof(char));" >> $g_CFILE print -r "/* Determine current moment and keep it for TIMER function */" >> $g_CFILE print -r "gettimeofday(&__b2c__tm, NULL); __b2c__elapsed_usecs = __b2c__tm.tv_usec; __b2c__elapsed_secs = __b2c__tm.tv_sec;" >> $g_CFILE print -r "/* Rest of the program */" >> $g_CFILE # Create basic H file, functions are converted using macros print -r "/* Created with KSH BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC if [[ `uname` = +(*BSD*) ]] then print -r "#include " >> $g_GENERIC fi print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "static jmp_buf __b2c__jump;" >> $g_GENERIC print -r "static int __b2c__trap = 0;" >> $g_GENERIC print -r "static int __b2c__catch_set_backup, __b2c__catch_set = 0;" >> $g_GENERIC print -r "static int ERROR = 0;" >> $g_GENERIC print -r "static int __b2c__option_compare = 0;" >> $g_GENERIC print -r "static int __b2c__option_memstream = 0;" >> $g_GENERIC print -r "static int __b2c__option_startpoint = 0;" >> $g_GENERIC print -r "static int __b2c__option_open = O_RDWR|O_NOCTTY|O_SYNC;" >> $g_GENERIC print -r "#define __b2c__MEMTYPE char" >> $g_GENERIC print -r "static int __b2c__collapse = 0;" >> $g_GENERIC print -r "int __b2c__break_ctr = 0;" >> $g_GENERIC print -r "int __b2c__break_flag = 0;" >> $g_GENERIC print -r "int RETVAL = 0;" >> $g_GENERIC print -r "int REGLEN = 0;" >> $g_GENERIC print -r "struct timeval __b2c__tm; time_t __b2c__elapsed_secs; int __b2c__elapsed_usecs;" >> $g_GENERIC print -r "struct itimerval __b2c__alarm;" >> $g_GENERIC print -r "char __b2c__chop_default[] = \"\r\n\t \";" >> $g_GENERIC print -r "char VERSION${g_STRINGSIGN}[] = \"$g_VERSION\";" >> $g_GENERIC print >> $g_GENERIC # Add user include files print -r "/* User include files */" >> $g_GENERIC for i in $g_INCFILES do if [[ "$i" = +(*\<*) ]] then print -r "#include $i" >> $g_GENERIC else print -r "#include \"$i\"" >> $g_GENERIC fi done print -r "/* READ/DATA include files */" >> $g_GENERIC print -r "int __b2c__stringarray_ptr = 0, __b2c__stringarray_ctr = 0;" >> $g_GENERIC print -r "#include \"${g_SOURCEFILE##*/}.string.h\"" >> $g_GENERIC print -r "int __b2c__floatarray_ptr = 0, __b2c__floatarray_ctr = 0;" >> $g_GENERIC print -r "#include \"${g_SOURCEFILE##*/}.float.h\"" >> $g_GENERIC print -r "int __b2c__ctr;" >> $g_GENERIC print >> $g_GENERIC print -r "/* Math functions */" >> $g_GENERIC print -r "extern double round(double __b2c__x);" >> $g_GENERIC print -r "extern long int lrint(double __b2c__x);" >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#define SQR(__b2c__x) sqrt((double)__b2c__x)" >> $g_GENERIC print -r "#define POW(__b2c__x, __b2c__y) pow((double)__b2c__x, (double)__b2c__y)" >> $g_GENERIC print -r "#define SIN(__b2c__x) sin((double)__b2c__x)" >> $g_GENERIC print -r "#define COS(__b2c__x) cos((double)__b2c__x)" >> $g_GENERIC print -r "#define TAN(__b2c__x) tan((double)__b2c__x)" >> $g_GENERIC print -r "#define ASIN(__b2c__x) asin((double)__b2c__x)" >> $g_GENERIC print -r "#define ACOS(__b2c__x) acos((double)__b2c__x)" >> $g_GENERIC print -r "#define ATN(__b2c__x) atan((double)__b2c__x)" >> $g_GENERIC print -r "#define LOG(__b2c__x) log((double)__b2c__x)" >> $g_GENERIC print -r "#define EXP(__b2c__x) exp((double)__b2c__x)" >> $g_GENERIC print -r "#define SGN(__b2c__x) ((__b2c__x) == 0 ? 0 : ((__b2c__x) < 0 ? -1 : 1))" >> $g_GENERIC print -r "#define ROUND(__b2c__x) lrint((double)__b2c__x)" >> $g_GENERIC print -r "#define INT(__b2c__x) lrint((double)__b2c__x)" >> $g_GENERIC print -r "#define MOD(__b2c__x, __b2c__y) ((long)(__b2c__x) % (long)(__b2c__y))" >> $g_GENERIC print -r "#define EVEN(__b2c__x) (((long)(__b2c__x) % 2 == 0) ? 1 : 0)" >> $g_GENERIC print -r "#define ODD(__b2c__x) (((long)(__b2c__x) % 2 != 0) ? 1 : 0)" >> $g_GENERIC print -r "#define FLOOR(__b2c__x) (long)floor(__b2c__x)" >> $g_GENERIC print -r "#undef ABS" >> $g_GENERIC print -r "#define ABS(__b2c__x) (((__b2c__x) < 0) ? -(__b2c__x) : (__b2c__x))" >> $g_GENERIC print -r "#define RND random()" >> $g_GENERIC if [[ `uname` = +(*SunOS*|*OSF1*) ]] then print -r "#define MAXRANDOM 2147483647" >> $g_GENERIC else print -r "#define MAXRANDOM RAND_MAX" >> $g_GENERIC fi print -r "#define RANDOM(__b2c__x) ((__b2c__x) != 0 ? random()/(MAXRANDOM/(__b2c__x)) : 0)" >> $g_GENERIC print >> $g_GENERIC print -r "/* Other functions */" >> $g_GENERIC print -r "#define VAL(__b2c__x) ((__b2c__x) != NULL ? atof(__b2c__x) : 0)" >> $g_GENERIC print >> $g_GENERIC print -r "/* Unix functions */" >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#define SYSTEM(__b2c__x) do {if (__b2c__x != NULL) {RETVAL = system(__b2c__x); if(WIFEXITED(RETVAL)) RETVAL = WEXITSTATUS(RETVAL);} else RETVAL=0;} while(0)" >> $g_GENERIC print >> $g_GENERIC print -r "/* String functions */" >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "char __b2c__input__buffer[$g_BUFFER_SIZE];" >> $g_GENERIC print -r "char* __b2c__sbuffer[$g_MAX_BUFFERS] = { NULL };" >> $g_GENERIC print -r "long __b2c__sbuffer_length[$g_MAX_BUFFERS] = { 0 };" >> $g_GENERIC print -r "int __b2c__sbuffer_ptr = 0;" >> $g_GENERIC print -r "char* __b2c__rbuffer[$g_MAX_RBUFFERS] = { NULL };" >> $g_GENERIC print -r "long __b2c__rbuffer_length[$g_MAX_RBUFFERS] = { 0 };" >> $g_GENERIC print -r "int __b2c__rbuffer_ptr = 0;" >> $g_GENERIC print -r "static jmp_buf __b2c__gosub_buffer[$g_MAX_RBUFFERS] = { 0 };" >> $g_GENERIC print -r "int __b2c__gosub_buffer_ptr = -1;" >> $g_GENERIC print -r "char **__b2c__deltree = { NULL }; int __b2c__del_ctr = 0;" >> $g_GENERIC print -r "/* Temporary pointer to perform assignments */" >> $g_GENERIC print -r "char *__b2c__assign = NULL;" >> $g_GENERIC print -r "char *__b2c__split = NULL; char *__b2c__split_tmp = NULL;" >> $g_GENERIC print -r "char *ERR${g_STRINGSIGN}(int);" >> $g_GENERIC print -r "#define RUNTIMEERROR(__b2c__a, __b2c__x, __b2c__y, __b2c__z) do {fprintf(stderr, \"Runtime error: statement '%s' at line %d in '%s': %s\n\", __b2c__a, __b2c__x, __b2c__y, ERR${g_STRINGSIGN}(__b2c__z)); exit(__b2c__z);} while(0)" >> $g_GENERIC print -r "#define RUNTIMEFERR(__b2c__a, __b2c__x, __b2c__y, __b2c__z) do {fprintf(stderr, \"Runtime error: function '%s': %s\n\", __b2c__y, ERR${g_STRINGSIGN}(__b2c__z)); exit(__b2c__z);} while(0)" >> $g_GENERIC print -r "void *__rbuf_realloc(void *__b2c__ptr, size_t __b2c__size){if(__b2c__rbuffer_length[__b2c__rbuffer_ptr] < __b2c__size)" >> $g_GENERIC print -r "{__b2c__rbuffer_length[__b2c__rbuffer_ptr] = (long)__b2c__size*4; return(realloc(__b2c__ptr, __b2c__size*4));} return(__b2c__ptr);}" >> $g_GENERIC print -r "void *__sbuf_realloc(void *__b2c__ptr, size_t __b2c__size){if(__b2c__sbuffer_length[__b2c__sbuffer_ptr] < __b2c__size)" >> $g_GENERIC print -r "{__b2c__sbuffer_length[__b2c__sbuffer_ptr] = (long)__b2c__size*4; return(realloc(__b2c__ptr, __b2c__size*4));} return(__b2c__ptr);}" >> $g_GENERIC print -r "char *__b2c__strdup(const char *__b2c__s){if(__b2c__s == NULL) return(NULL); return(strdup(__b2c__s));}" >> $g_GENERIC print -r "int __b2c__strcmp(const char *__b2c__s1, const char *__b2c__s2){if(__b2c__s1 == NULL && __b2c__s2 == NULL) return 0;" >> $g_GENERIC print -r "if(__b2c__s1 == NULL)return(-1); if(__b2c__s2 == NULL)return(1); return(strcmp(__b2c__s1, __b2c__s2));}" >> $g_GENERIC print -r "int __b2c__strcasecmp(const char *__b2c__s1, const char *__b2c__s2){if(__b2c__s1 == NULL && __b2c__s2 == NULL) return 0;" >> $g_GENERIC print -r "if(__b2c__s1 == NULL)return(-1); if(__b2c__s2 == NULL)return(1); return(strcasecmp(__b2c__s1, __b2c__s2));}" >> $g_GENERIC print -r "/* Functions for sort */" >> $g_GENERIC print -r "int __b2c__sortnrd(const void *__b2c__a, const void *__b2c__b)" >> $g_GENERIC print -r "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return -1; else return 1;}" >> $g_GENERIC print -r "int __b2c__sortnrd_down(const void *__b2c__a, const void *__b2c__b)" >> $g_GENERIC print -r "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return 1; else return -1;}" >> $g_GENERIC print -r "int __b2c__sortnrf(const void *__b2c__a, const void *__b2c__b)" >> $g_GENERIC print -r "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return -1; else return 1;}" >> $g_GENERIC print -r "int __b2c__sortnrf_down(const void *__b2c__a, const void *__b2c__b)" >> $g_GENERIC print -r "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return 1; else return -1;}" >> $g_GENERIC print -r "int __b2c__sortnrl(const void *__b2c__a, const void *__b2c__b)" >> $g_GENERIC print -r "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return -1; else return 1;}" >> $g_GENERIC print -r "int __b2c__sortnrl_down(const void *__b2c__a, const void *__b2c__b)" >> $g_GENERIC print -r "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return 1; else return -1;}" >> $g_GENERIC print -r "int __b2c__sortnri(const void *__b2c__a, const void *__b2c__b)" >> $g_GENERIC print -r "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return -1; else return 1;}" >> $g_GENERIC print -r "int __b2c__sortnri_down(const void *__b2c__a, const void *__b2c__b)" >> $g_GENERIC print -r "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return 1; else return -1;}" >> $g_GENERIC print -r "int __b2c__sortstr(const void *__b2c__a, const void *__b2c__b)" >> $g_GENERIC print -r "{if(*(char **)__b2c__a == NULL) return -1; if(*(char **)__b2c__b == NULL) return 1; return strcmp(*(char **)__b2c__a, *(char **)__b2c__b);}" >> $g_GENERIC print -r "int __b2c__sortstr_down(const void *__b2c__a, const void *__b2c__b)" >> $g_GENERIC print -r "{if(*(char **)__b2c__a == NULL) return -1; if(*(char **)__b2c__b == NULL) return 1; return strcmp(*(char **)__b2c__b, *(char **)__b2c__a);}" >> $g_GENERIC print -r "/* Actual functions */" >> $g_GENERIC print -r "int __b2c__remove(const char *__b2c__path, const struct stat *__b2c__sb, int __b2c__flag){" >> $g_GENERIC print -r "__b2c__del_ctr++; __b2c__deltree = realloc(__b2c__deltree, __b2c__del_ctr*sizeof(char*)); __b2c__deltree[__b2c__del_ctr-1] = strdup(__b2c__path); return (0);}" >> $g_GENERIC print -r "int __b2c__rmrecursive(char *__b2c__path){int __b2c__result = 0; __b2c__result = ftw(__b2c__path, __b2c__remove, FOPEN_MAX); qsort(&__b2c__deltree[0], __b2c__del_ctr, sizeof(char*), __b2c__sortstr);" >> $g_GENERIC print -r "while(__b2c__del_ctr>0) {__b2c__del_ctr--; if(!__b2c__result) __b2c__result = remove(__b2c__deltree[__b2c__del_ctr]); free(__b2c__deltree[__b2c__del_ctr]);} free(__b2c__deltree); __b2c__deltree = NULL; return(__b2c__result);}" >> $g_GENERIC print -r "char* __b2c__curdir(void){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE*sizeof(char));" >> $g_GENERIC print -r "return (char*)(getcwd(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE));}" >> $g_GENERIC print -r "#define CURDIR${g_STRINGSIGN} __b2c__curdir()" >> $g_GENERIC print -r "char* __b2c__reverse(char *__b2c__src){long __b2c__i, __b2c__l; if (__b2c__src == NULL) return (\"\"); __b2c__l = strlen(__b2c__src); __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__l+2)*sizeof(char));" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__l+1);" >> $g_GENERIC print -r "for(__b2c__i=0;__b2c__i<__b2c__l; __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__src[__b2c__l-1-__b2c__i];}" >> $g_GENERIC print -r "return(char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define REVERSE${g_STRINGSIGN}(__b2c__x) __b2c__reverse(__b2c__x)" >> $g_GENERIC print -r "char* __b2c__str(double __b2c__d){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS*sizeof(char));" >> $g_GENERIC print -r "if(floor(__b2c__d) == __b2c__d) snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%ld\", (long)__b2c__d); else snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%g\", (double)__b2c__d); return(char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define STR${g_STRINGSIGN}(__b2c__x) __b2c__str(__b2c__x)" >> $g_GENERIC print -r "char * __b2c__concat (char *__b2c__first, ...) { long __b2c__len, __b2c__new; char *__b2c__next; va_list __b2c__ap; __b2c__sbuffer_ptr++; if (__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr = 0;" >> $g_GENERIC print -r "if (__b2c__first != NULL && (__b2c__len = strlen(__b2c__first)) > 0) {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__len * sizeof (char));" >> $g_GENERIC print -r "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first, __b2c__len*sizeof(char)); } else { __b2c__len = 0; __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], sizeof (char));}" >> $g_GENERIC print -r "va_start (__b2c__ap, __b2c__first); while ((__b2c__next = va_arg (__b2c__ap, char *)) != NULL) { __b2c__new = strlen (__b2c__next); __b2c__sbuffer[__b2c__sbuffer_ptr] =" >> $g_GENERIC print -r "(char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len+__b2c__new + 1) * sizeof (char)); memcpy(__b2c__sbuffer[__b2c__sbuffer_ptr]+__b2c__len*sizeof(char), __b2c__next, __b2c__new*sizeof(char));" >> $g_GENERIC print -r "__b2c__len += __b2c__new; } va_end (__b2c__ap); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\0'; return (char *) (__b2c__sbuffer[__b2c__sbuffer_ptr]); }" >> $g_GENERIC print -r "#define CONCAT${g_STRINGSIGN}(...) __b2c__concat(__VA_ARGS__, (char*)NULL)" >> $g_GENERIC print -r "char* __b2c__left(char *__b2c__src, long __b2c__n){long __b2c__l; if(__b2c__src != NULL)__b2c__l = strlen(__b2c__src); if(__b2c__src == NULL || __b2c__n > __b2c__l || __b2c__n < 0) return(__b2c__src);" >> $g_GENERIC print -r "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__l+1)*sizeof(char));" >> $g_GENERIC print -r "memcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src, __b2c__n*sizeof(char)); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__n] = '\0';" >> $g_GENERIC print -r "return (char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define LEFT${g_STRINGSIGN}(__b2c__x, __b2c__y) __b2c__left(__b2c__x, __b2c__y)" >> $g_GENERIC print -r "char* __b2c__right(char *__b2c__src, long __b2c__n){long __b2c__l; if(__b2c__src != NULL)__b2c__l = strlen(__b2c__src); if(__b2c__src == NULL || __b2c__n > __b2c__l || __b2c__n < 0) return(__b2c__src);" >> $g_GENERIC print -r "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__l+1)*sizeof(char));" >> $g_GENERIC print -r "memcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src + (__b2c__l - __b2c__n)*sizeof(char), __b2c__n*sizeof(char)); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__n] = '\0';" >> $g_GENERIC print -r "return (char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define RIGHT${g_STRINGSIGN}(__b2c__x, __b2c__y) __b2c__right(__b2c__x, __b2c__y)" >> $g_GENERIC print -r "char* __b2c__mid(char *__b2c__src, ...){ va_list __b2c__ap; long __b2c__start, __b2c__len, __b2c__l; if(__b2c__src == NULL) return(\"\"); " >> $g_GENERIC print -r "va_start(__b2c__ap, __b2c__src); __b2c__start = va_arg(__b2c__ap, long); if(__b2c__start < 1) return(__b2c__src); __b2c__l = strlen(__b2c__src); if(__b2c__start > __b2c__l) return(\"\"); __b2c__len = va_arg(__b2c__ap, long);" >> $g_GENERIC print -r "if(__b2c__len < 0 || __b2c__start+__b2c__len > __b2c__l) __b2c__len = __b2c__l-__b2c__start+1; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0; __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len+1)*sizeof(char));" >> $g_GENERIC print -r "memcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+(__b2c__start-1)*sizeof(char), __b2c__len*sizeof(char)); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\0'; va_end(__b2c__ap); return (char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define MID${g_STRINGSIGN}(__b2c__string, ...) __b2c__mid(__b2c__string, __VA_ARGS__, -1)" >> $g_GENERIC print -r "long __b2c__instr(char *__b2c__first, ...){char *__b2c__tmp, *__b2c__res; int __b2c__pos; va_list __b2c__ap; if(__b2c__first == NULL) return (0); va_start(__b2c__ap, __b2c__first);" >> $g_GENERIC print -r "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL) return (0);__b2c__pos = va_arg(__b2c__ap, int);" >> $g_GENERIC print -r "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); __b2c__res = strstr(__b2c__first + __b2c__pos - 1, __b2c__tmp);" >> $g_GENERIC print -r "if(__b2c__res == NULL) return (0); return (long)(__b2c__res - __b2c__first + 1);}" >> $g_GENERIC print -r "#define INSTR(...) __b2c__instr(__VA_ARGS__, -1)" >> $g_GENERIC print -r "long __b2c__instrrev (char *__b2c__first, ...){char *__b2c__tmp, *__b2c__res = NULL, *__b2c__found = NULL; long __b2c__pos, __b2c__l; va_list __b2c__ap;if (__b2c__first == NULL) return (0);" >> $g_GENERIC print -r "va_start (__b2c__ap, __b2c__first); __b2c__tmp = va_arg (__b2c__ap, char *); if (__b2c__tmp == NULL) return (0); __b2c__pos = va_arg (__b2c__ap, int); if (__b2c__pos < 0) __b2c__pos = 0;" >> $g_GENERIC print -r "va_end (__b2c__ap); __b2c__l = strlen(__b2c__first); __b2c__found = __b2c__first; do {__b2c__res = strstr (__b2c__found, __b2c__tmp); if(__b2c__res != NULL && __b2c__res <= __b2c__first + __b2c__l - __b2c__pos)" >> $g_GENERIC print -r "{__b2c__found = __b2c__res + 1; continue;}if(__b2c__res > __b2c__first + __b2c__l - __b2c__pos) __b2c__res = NULL;} while (__b2c__res != NULL); if (__b2c__option_startpoint){if(__b2c__l - (__b2c__found - __b2c__first)+1 > __b2c__l) return 0;" >> $g_GENERIC print -r "return (long)(__b2c__l - (__b2c__found - __b2c__first)+1);} return (long)(__b2c__found - __b2c__first);}" >> $g_GENERIC print -r "#define INSTRREV(...) __b2c__instrrev(__VA_ARGS__, -1)" >> $g_GENERIC print -r "char* __b2c__spc(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 32, __b2c__x); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__x] = '\0'; return(char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define SPC${g_STRINGSIGN}(__b2c__x) ((__b2c__x) >= 0 ? __b2c__spc(__b2c__x) : \"\")" >> $g_GENERIC print -r "char* __b2c__tab(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 9, __b2c__x); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__x] = '\0'; return(char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define TAB${g_STRINGSIGN}(__b2c__x) ((__b2c__x) >= 0 ? __b2c__tab(__b2c__x) : \"\")" >> $g_GENERIC print -r "char* __b2c__fill(unsigned long __b2c__x, unsigned char __b2c__y){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__y, __b2c__x); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__x] = '\0'; return(char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define FILL${g_STRINGSIGN}(__b2c__x, __b2c__y) ((__b2c__y) >= 0 && (__b2c__y) < 256 ? __b2c__fill(__b2c__x, __b2c__y) : \"\")" >> $g_GENERIC print -r "long __b2c__count(char* __b2c_x, unsigned char __b2c_y){int __b2c_i, __b2c_z = 0; for(__b2c_i = 0; __b2c_i < strlen(__b2c_x); __b2c_i++) if(*(__b2c_x+__b2c_i) == __b2c_y) __b2c_z++; return __b2c_z;}" >> $g_GENERIC print -r "#define COUNT(__b2c__x, __b2c__y) ((__b2c__x) != NULL ? __b2c__count(__b2c__x, __b2c__y) : 0)" >> $g_GENERIC print -r "char* __b2c__chop(char *__b2c__src, ...){char *__b2c__tmp, *__b2c__str; long __b2c__i, __b2c__l, __b2c__loc = 0; va_list __b2c__ap; if(__b2c__src == NULL || strlen(__b2c__src) == 0) return(__b2c__src);" >> $g_GENERIC print -r "va_start (__b2c__ap, __b2c__src); __b2c__str = va_arg (__b2c__ap, char*); if(__b2c__str == 0) __b2c__str = (char*)__b2c__chop_default; else __b2c__loc = va_arg (__b2c__ap, int); va_end (__b2c__ap); __b2c__l = strlen(__b2c__str);" >> $g_GENERIC print -r "if(__b2c__loc == 0 || __b2c__loc == 1) {while (*__b2c__src != '\0') {for(__b2c__i = 0; __b2c__i < __b2c__l; __b2c__i++) {if (*__b2c__src == *(__b2c__str+__b2c__i)) {__b2c__src++; break; } }" >> $g_GENERIC print -r "if(__b2c__i == __b2c__l) break;} if (*__b2c__src == '\0') return(\"\");} __b2c__tmp = __b2c__src + strlen(__b2c__src) - 1;" >> $g_GENERIC print -r "if(__b2c__loc == 0 || __b2c__loc == 2) {while (__b2c__tmp >= __b2c__src && *__b2c__tmp != '\0') {for(__b2c__i = 0; __b2c__i < __b2c__l; __b2c__i++) {if (*__b2c__tmp == *(__b2c__str+__b2c__i))" >> $g_GENERIC print -r "{__b2c__tmp--; break; } } if(__b2c__i == __b2c__l) break;} } __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_GENERIC print -r "for(__b2c__i = 0; __b2c__i <= __b2c__tmp - __b2c__src; __b2c__i++) __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__src[__b2c__i];" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i] = '\0'; return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define CHOP${g_STRINGSIGN}(...) __b2c__chop(__VA_ARGS__, 0)" >> $g_GENERIC print -r "char * __b2c__extract (int __b2c__ln, const char *__b2c__fl, ...) { int __b2c__i, __b2c__j, __b2c__flag, __b2c__reti, __b2c__ere, __b2c__pos = 0; char *__b2c__src, *__b2c__needle, *__b2c__tmp;" >> $g_GENERIC print -r "regex_t __b2c__reg; char __b2c__buf[100]; regmatch_t __b2c__where[1]; va_list __b2c__ap; va_start (__b2c__ap, __b2c__fl); __b2c__src = va_arg (__b2c__ap, char *); __b2c__needle = va_arg (__b2c__ap, char *);" >> $g_GENERIC print -r "__b2c__ere = va_arg (__b2c__ap, int); va_end (__b2c__ap); if (__b2c__src == NULL || __b2c__needle == NULL) return (char *) (__b2c__src); if (strlen (__b2c__src) == 0 || strlen (__b2c__needle) == 0)" >> $g_GENERIC print -r "return (char *) (__b2c__src); __b2c__sbuffer_ptr++; if (__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr = 0; __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr]," >> $g_GENERIC print -r "(strlen (__b2c__src) + 1) * sizeof (char)); if (__b2c__ere > 0) { if (__b2c__option_compare == 0) __b2c__reti = regcomp (&__b2c__reg, __b2c__needle, REG_EXTENDED); else __b2c__reti =" >> $g_GENERIC print -r "regcomp (&__b2c__reg, __b2c__needle, REG_EXTENDED | REG_ICASE); if (!__b2c__trap && __b2c__reti) { ERROR = 27; regerror (__b2c__reti, &__b2c__reg, __b2c__buf, sizeof (__b2c__buf));" >> $g_GENERIC print -r "fprintf (stderr, \"%s\n\", __b2c__buf); RUNTIMEFERR (__b2c__ln, __b2c__fl, \"EXTRACT$\", ERROR); } while ((__b2c__reti = regexec (&__b2c__reg, __b2c__src, 1, __b2c__where, 0)) == 0) {" >> $g_GENERIC print -r "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos * sizeof (char), __b2c__src, (size_t) __b2c__where[0].rm_so * sizeof (char)); __b2c__pos += __b2c__where[0].rm_so;" >> $g_GENERIC print -r "__b2c__src += (long) __b2c__where[0].rm_eo; } regfree (&__b2c__reg); memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos * sizeof (char), __b2c__src, strlen (__b2c__src) * sizeof (char));" >> $g_GENERIC print -r "__b2c__pos += strlen (__b2c__src); } else { while ((__b2c__tmp = strstr (__b2c__src, __b2c__needle)) != NULL) {" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__pos + (__b2c__tmp - __b2c__src) + 1) * sizeof (char));" >> $g_GENERIC print -r "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos * sizeof (char), __b2c__src, (size_t) (__b2c__tmp - __b2c__src) * sizeof (char)); __b2c__pos += __b2c__tmp - __b2c__src;" >> $g_GENERIC print -r "__b2c__src = __b2c__tmp+strlen(__b2c__needle)*sizeof(char); } __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__pos + strlen(__b2c__src) + 1) * sizeof (char));" >> $g_GENERIC print -r "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos * sizeof (char), __b2c__src, strlen(__b2c__src) * sizeof (char)); __b2c__pos += strlen(__b2c__src); }" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__pos] = '\0'; return (char *) (__b2c__sbuffer[__b2c__sbuffer_ptr]); }" >> $g_GENERIC print -r "#define EXTRACT${g_STRINGSIGN}(...) __b2c__extract(__LINE__, __FILE__, __VA_ARGS__, -1)" >> $g_GENERIC print -r "char * __b2c__replace (int __b2c__ln, const char *__b2c__fl, ...) { char *__b2c__tmp, *__b2c__haystack, *__b2c__needle, *__b2c__replace; long __b2c__rep, __b2c__hst, __b2c__ndl, __b2c__len = 0; regex_t __b2c__reg; int __b2c__reti, __b2c__flag; char __b2c__buf[100];" >> $g_GENERIC print -r "regmatch_t __b2c__where[1]; va_list __b2c__ap; va_start (__b2c__ap, __b2c__fl); __b2c__haystack = va_arg (__b2c__ap, char*); __b2c__needle = va_arg (__b2c__ap, char*); __b2c__replace = va_arg (__b2c__ap, char*); __b2c__flag = va_arg (__b2c__ap, int); va_end (__b2c__ap);" >> $g_GENERIC print -r "if(__b2c__haystack == NULL || __b2c__needle == NULL || __b2c__replace == NULL) return (char*)(__b2c__haystack); __b2c__ndl = strlen (__b2c__needle); if (strlen (__b2c__haystack) == 0 || __b2c__ndl == 0) return (char *) (__b2c__haystack);" >> $g_GENERIC print -r "__b2c__sbuffer_ptr++; if (__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr = 0; __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], sizeof (char)); *__b2c__sbuffer[__b2c__sbuffer_ptr] = '\0';" >> $g_GENERIC print -r "__b2c__rep = strlen (__b2c__replace); if(__b2c__flag > 0) { if (__b2c__option_compare == 0) __b2c__reti = regcomp (&__b2c__reg, __b2c__needle, REG_EXTENDED); else __b2c__reti = regcomp (&__b2c__reg, __b2c__needle, REG_EXTENDED | REG_ICASE);" >> $g_GENERIC print -r "if (!__b2c__trap && __b2c__reti) { ERROR = 27; regerror (__b2c__reti, &__b2c__reg, __b2c__buf, sizeof (__b2c__buf)); fprintf (stderr, \"%s\n\", __b2c__buf); RUNTIMEFERR (__b2c__ln, __b2c__fl, \"REPLACE$\", ERROR); }" >> $g_GENERIC print -r "while ((__b2c__reti = regexec (&__b2c__reg, __b2c__haystack, 1, __b2c__where, 0)) == 0) { __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len + __b2c__where[0].rm_so + __b2c__rep + 1) * sizeof (char));" >> $g_GENERIC print -r "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len * sizeof (char), __b2c__haystack, (size_t) __b2c__where[0].rm_so * sizeof (char)); __b2c__len += __b2c__where[0].rm_so;" >> $g_GENERIC print -r "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len * sizeof (char), __b2c__replace, __b2c__rep * sizeof (char)); __b2c__len += __b2c__rep; __b2c__haystack += (long) __b2c__where[0].rm_eo; } regfree (&__b2c__reg); }" >> $g_GENERIC print -r "else {while ((__b2c__tmp = strstr (__b2c__haystack, __b2c__needle)) != NULL) {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len + (__b2c__tmp - __b2c__haystack) + __b2c__rep + 1) * sizeof (char));" >> $g_GENERIC print -r "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len * sizeof (char), __b2c__haystack, (size_t) (__b2c__tmp - __b2c__haystack) * sizeof (char)); __b2c__len += __b2c__tmp - __b2c__haystack;" >> $g_GENERIC print -r "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len * sizeof (char), __b2c__replace, __b2c__rep * sizeof (char)); __b2c__len += __b2c__rep; __b2c__haystack = __b2c__tmp + __b2c__ndl; } } __b2c__hst = strlen (__b2c__haystack);" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len + __b2c__hst + 1) * sizeof (char)); memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len * sizeof (char), __b2c__haystack, __b2c__hst * sizeof (char));" >> $g_GENERIC print -r "__b2c__len += __b2c__hst; __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\0'; return (char *) (__b2c__sbuffer[__b2c__sbuffer_ptr]); }" >> $g_GENERIC print -r "#define REPLACE${g_STRINGSIGN}(...) __b2c__replace(__LINE__, __FILE__, __VA_ARGS__, -1)" >> $g_GENERIC print -r "#define LEN(__b2c__x) ((__b2c__x) != NULL ? strlen(__b2c__x) : 0)" >> $g_GENERIC print -r "#define EQUAL(__b2c__x, __b2c__y) ((__b2c__x) != NULL && (__b2c__y) != NULL && __b2c__option_compare == 0 ? !strcmp(__b2c__x, __b2c__y) : ((__b2c__x) != NULL && (__b2c__y) != NULL && __b2c__option_compare == 1 ? !strcasecmp(__b2c__x, __b2c__y) : 0) )" >> $g_GENERIC print -r "char * __b2c__getenv(char *__b2c__env){char * __b2c__tmp; __b2c__tmp = getenv(__b2c__env); if (__b2c__tmp == NULL)" >> $g_GENERIC print -r "{return \"\";} return __b2c__tmp;}" >> $g_GENERIC print -r "#define GETENVIRON${g_STRINGSIGN}(__b2c__x) ((__b2c__x) != NULL ? __b2c__getenv(__b2c__x) : \"null\")" >> $g_GENERIC print -r "#define SETENVIRON(__b2c__x, __b2c__y) if((__b2c__x) != NULL && (__b2c__y) != NULL) setenv(__b2c__x, __b2c__y, 1)" >> $g_GENERIC print >> $g_GENERIC print -r "/* CHAR functions */" >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "char* __b2c__ucase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_GENERIC print -r "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=toupper(__b2c__s[__b2c__i]);}" >> $g_GENERIC print -r "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define UCASE${g_STRINGSIGN}(__b2c__x) ((__b2c__x) != NULL ? __b2c__ucase(__b2c__x) : \"null\")" >> $g_GENERIC print -r "char* __b2c__lcase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_GENERIC print -r "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=tolower(__b2c__s[__b2c__i]);}" >> $g_GENERIC print -r "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define LCASE${g_STRINGSIGN}(__b2c__x) ((__b2c__x) != NULL ? __b2c__lcase(__b2c__x) : \"null\")" >> $g_GENERIC print >> $g_GENERIC print -r "/* I/O functions */" >> $g_GENERIC print -r "FILE *__b2c__inFile; FILE *__b2c__outFile; int __b2c__Byte; struct dirent *__b2c__dir;" >> $g_GENERIC print -r "char* __b2c__dec2hex(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS);" >> $g_GENERIC print -r "snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%X\", __b2c__i); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "long __b2c__hex2dec(int __b2c__ln, const char *__b2c__fl, char *__b2c__h){unsigned int __b2c__i; if(sscanf(__b2c__h, \"%X\", &__b2c__i) == EOF && !__b2c__trap){ERROR = 5;" >> $g_GENERIC print -r "RUNTIMEFERR(__b2c__ln, __b2c__fl, \"DEC\", ERROR);} return(long)(__b2c__i);}" >> $g_GENERIC print -r "char* __b2c__asc2char(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char));" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, 2*sizeof(char)); snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], 2, \"%c\", __b2c__i);" >> $g_GENERIC print -r "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "/* Function FILEEXISTS contributed by Armando Rivera */ " >> $g_GENERIC print -r "long __b2c__fileexists(const char *__b2c__x) {struct stat __b2c__buf; if (stat(__b2c__x, &__b2c__buf) != -1) return 1; return 0;}" >> $g_GENERIC print -r "#define FILEEXISTS(__b2c__x) __b2c__fileexists(__b2c__x)" >> $g_GENERIC print -r "long __b2c__filelen(int __b2c__ln, const char *__b2c__fl, const char *__b2c__x) {struct stat __b2c__buf; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"FILELEN\", ERROR);}" >> $g_GENERIC print -r "if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0) return -1; else return(long)(__b2c__buf.st_size);}" >> $g_GENERIC print -r "#define FILELEN(__b2c__x) __b2c__filelen(__LINE__, __FILE__, __b2c__x)" >> $g_GENERIC print -r "long __b2c__filetime(int __b2c__ln, const char *__b2c__fl, const char *__b2c__x, int __b2c__y) {struct stat __b2c__buf; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"FILETIME\", ERROR);}" >> $g_GENERIC print -r "if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0 || __b2c__y < 0 || __b2c__y > 2) return -1; switch(__b2c__y) {case 0: return(long)(__b2c__buf.st_atime); break;" >> $g_GENERIC print -r "case 1: return(long)(__b2c__buf.st_mtime); break;} return(long)(__b2c__buf.st_ctime);}" >> $g_GENERIC print -r "#define FILETIME(__b2c__x, __b2c__y) __b2c__filetime(__LINE__, __FILE__, __b2c__x, __b2c__y)" >> $g_GENERIC print -r "long __b2c__filetype(int __b2c__ln, const char *__b2c__fl, const char *__b2c__x) {long __b2c_fs = 0; struct stat __b2c__buf; if(__b2c__x == NULL) return 0; if(lstat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap)" >> $g_GENERIC print -r "{ERROR = 24; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"FILETYPE\", ERROR);}" >> $g_GENERIC print -r "if (S_ISREG(__b2c__buf.st_mode)) __b2c_fs = 1; if (S_ISDIR(__b2c__buf.st_mode)) __b2c_fs = 2;" >> $g_GENERIC print -r "if (S_ISCHR(__b2c__buf.st_mode)) __b2c_fs = 3; if (S_ISBLK(__b2c__buf.st_mode)) __b2c_fs = 4; if (S_ISFIFO(__b2c__buf.st_mode)) __b2c_fs = 5;" >> $g_GENERIC print -r "if (S_ISLNK(__b2c__buf.st_mode)) __b2c_fs = 6; if (S_ISSOCK(__b2c__buf.st_mode)) __b2c_fs = 7; return __b2c_fs;}" >> $g_GENERIC print -r "#define FILETYPE(__b2c__x) __b2c__filetype(__LINE__, __FILE__, __b2c__x)" >> $g_GENERIC print -r "long __b2c__search(int __b2c__ln, const char *__b2c__fl, FILE* __b2c__x, char* __b2c__y){long __b2c__off, __b2c__pos; char* __b2c__ptr; size_t __b2c__tot;" >> $g_GENERIC print -r "if(__b2c__x == NULL && !__b2c__trap){ERROR = 2; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"SEARCH\", ERROR);}" >> $g_GENERIC print -r "if(__b2c__y == NULL && !__b2c__trap){ERROR = 25; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"SEARCH\", ERROR);}" >> $g_GENERIC print -r "__b2c__pos = ftell(__b2c__x); __b2c__ptr = (char*)malloc((strlen(__b2c__y)+1)*sizeof(char)); __b2c__off = 0; do {" >> $g_GENERIC print -r "fseek(__b2c__x, __b2c__off, SEEK_SET);memset(__b2c__ptr, 0, sizeof(char)*(strlen(__b2c__y)+1));" >> $g_GENERIC print -r "__b2c__tot = fread(__b2c__ptr, sizeof(char), strlen(__b2c__y), __b2c__x);__b2c__off+=1;" >> $g_GENERIC print -r "} while(!feof(__b2c__x) && strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y)));" >> $g_GENERIC print -r "if(strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y))) __b2c__off = 0; fseek(__b2c__x, __b2c__pos, SEEK_SET); free(__b2c__ptr); return (--__b2c__off);}" >> $g_GENERIC print -r "#define SEARCH(__b2c__x, __b2c__y) __b2c__search(__LINE__, __FILE__, __b2c__x, __b2c__y)" >> $g_GENERIC print -r "char *__b2c__exec(int __b2c__ln, const char *__b2c__fl, char *__b2c__x, ...){int __b2c__r, __b2c__len, __b2c__i; int __b2c__wpipe[2], __b2c__rpipe[2]; char *__b2c__str, *__b2c__ans = NULL; va_list __b2c__ap;" >> $g_GENERIC print -r "va_start(__b2c__ap, __b2c__x); __b2c__str = va_arg (__b2c__ap, char*); va_end(__b2c__ap); if (pipe (__b2c__rpipe) < 0 || pipe (__b2c__wpipe) < 0){if(!__b2c__trap) {ERROR=29; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"EXEC$\", ERROR);}}" >> $g_GENERIC print -r "if ((__b2c__r = fork ()) < 0){if(!__b2c__trap) {ERROR=29; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"EXEC$\", ERROR);}} else if (__b2c__r == 0){" >> $g_GENERIC print -r "close(__b2c__wpipe[1]);close (__b2c__rpipe[0]);dup2 (__b2c__wpipe[0], STDIN_FILENO);close (__b2c__wpipe[0]);dup2 (__b2c__rpipe[1], STDOUT_FILENO);close (__b2c__rpipe[1]); __b2c__r = system (__b2c__x); if(WIFEXITED(__b2c__r)) __b2c__i = WEXITSTATUS(__b2c__r); else __b2c__i=0; exit(__b2c__i);}" >> $g_GENERIC print -r "else{close (__b2c__wpipe[0]);close (__b2c__rpipe[1]); __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0; __b2c__sbuffer[__b2c__sbuffer_ptr] = __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], sizeof (char));" >> $g_GENERIC print -r "__b2c__ans = (char *) malloc ($g_BUFFER_SIZE * sizeof (char)); __b2c__len = 0;" >> $g_GENERIC print -r "if(__b2c__str!=NULL) __b2c__i = write(__b2c__wpipe[1], __b2c__str, strlen(__b2c__str)+1); do{__b2c__i = read (__b2c__rpipe[0], __b2c__ans, $g_BUFFER_SIZE);if (__b2c__i == -1 && !__b2c__trap){ERROR=30; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"EXEC$\", ERROR);}" >> $g_GENERIC print -r "if (__b2c__i == 0)break; __b2c__sbuffer[__b2c__sbuffer_ptr] = __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len + __b2c__i + 1)*sizeof(char));" >> $g_GENERIC print -r "if (__b2c__sbuffer[__b2c__sbuffer_ptr] == NULL && !__b2c__trap){ERROR=6; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"EXEC$\", ERROR);} memcpy(__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len*sizeof(char), __b2c__ans, __b2c__i*sizeof(char));" >> $g_GENERIC print -r " __b2c__len += __b2c__i;} while (__b2c__i > 0); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\0'; close (__b2c__wpipe[1]);" >> $g_GENERIC print -r "close (__b2c__rpipe[0]);free (__b2c__ans); wait(&RETVAL); RETVAL = WEXITSTATUS(RETVAL);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define EXEC${g_STRINGSIGN}(...) __b2c__exec(__LINE__, __FILE__, __VA_ARGS__, (char*)NULL)" >> $g_GENERIC print -r "#define ENDFILE(__b2c__x) feof(__b2c__x)" >> $g_GENERIC print -r "#define TELL(__b2c__x) ftell(__b2c__x)" >> $g_GENERIC print -r "#define HEX${g_STRINGSIGN}(__b2c__x) __b2c__dec2hex(__b2c__x)" >> $g_GENERIC print -r "#define DEC(__b2c__x) __b2c__hex2dec(__LINE__, __FILE__, __b2c__x)" >> $g_GENERIC print -r "#define ASC(__b2c__x) (unsigned char) *__b2c__x" >> $g_GENERIC print -r "#define CHR${g_STRINGSIGN}(__b2c__x) __b2c__asc2char(__b2c__x)" >> $g_GENERIC print -r "#define MEMTELL(__b2c__x) (long)__b2c__x" >> $g_GENERIC print -r "#define ISKEY(__b2c_x, ...) ( (__b2c__ ## __b2c_x ## __add_secure(0, __VA_ARGS__, NULL) == NULL) ? 0 : 1)" >> $g_GENERIC print >> $g_GENERIC print -r "/* Dynamic loading, errors */" >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#include " >> $g_GENERIC print >> $g_GENERIC print -r "/* GETKEY */" >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "struct termios __b2c__tty;" >> $g_GENERIC print -r "long __b2c__getch(){long __b2c__ch; struct termios __b2c__oldt, __b2c__newt; tcgetattr(STDIN_FILENO, &__b2c__oldt);" >> $g_GENERIC print -r "__b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);" >> $g_GENERIC print -r "__b2c__ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt); return __b2c__ch;} " >> $g_GENERIC print -r "#define GETKEY __b2c__getch()" >> $g_GENERIC print -r "long __b2c__getxy(int __b2c__type){char __b2c__asw[$g_BUFFER_SIZE]; struct termios __b2c__old, __b2c__new; int __b2c__len, __b2c__x, __b2c__y; ssize_t __b2c__tot;" >> $g_GENERIC print -r "tcgetattr(STDIN_FILENO, &__b2c__old); __b2c__new = __b2c__old;__b2c__new.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__new);" >> $g_GENERIC print -r "__b2c__tot = write(STDOUT_FILENO, \"\033[6n\", strlen(\"\033[6n\")); __b2c__len = read(STDIN_FILENO, __b2c__asw, $g_BUFFER_SIZE);__b2c__asw[__b2c__len] = '\0'; " >> $g_GENERIC print -r "tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__old); sscanf(__b2c__asw, \"\033[%d;%dR\", &__b2c__y, &__b2c__x); if (!__b2c__type) return(long)__b2c__x; return(long)__b2c__y;}" >> $g_GENERIC print -r "#define GETX __b2c__getxy(0)" >> $g_GENERIC print -r "#define GETY __b2c__getxy(1)" >> $g_GENERIC print -r "long __b2c__screen(int __b2c__type){long __b2c__x; fprintf(stdout,\"\033[s\"); fprintf(stdout,\"\033[?25l\"); fprintf(stdout,\"\033[999;999H\"); fflush(stdout);" >> $g_GENERIC print -r "__b2c__x = __b2c__getxy(__b2c__type); fprintf(stdout,\"\033[u\"); fprintf(stdout,\"\033[?25h\"); fflush(stdout); return(__b2c__x); }" >> $g_GENERIC print -r "#define COLUMNS __b2c__screen(0)" >> $g_GENERIC print -r "#define ROWS __b2c__screen(1)" >> $g_GENERIC print >> $g_GENERIC print -r "/* Constants, logical stuff */" >> $g_GENERIC print -r "#define PI 3.1415926536" >> $g_GENERIC print -r "#define NOT(__b2c__x) (!(__b2c__x))" >> $g_GENERIC print -r "#define AND &&" >> $g_GENERIC print -r "#define OR ||" >> $g_GENERIC print -r "#define IS ==" >> $g_GENERIC print -r "#define NE !=" >> $g_GENERIC print -r "#define ISNOT !=" >> $g_GENERIC print -r "#define LT <" >> $g_GENERIC print -r "#define GT >" >> $g_GENERIC print -r "#define LE <=" >> $g_GENERIC print -r "#define GE >=" >> $g_GENERIC print -r "#define EQ ==" >> $g_GENERIC print -r "#undef TRUE" >> $g_GENERIC print -r "#define TRUE 1" >> $g_GENERIC print -r "#undef FALSE" >> $g_GENERIC print -r "#define FALSE 0" >> $g_GENERIC print -r "#define NL${g_STRINGSIGN} \"\n\"" >> $g_GENERIC print -r "#define STRING char*" >> $g_GENERIC print -r "#define NUMBER long" >> $g_GENERIC print -r "#define FLOATING double" >> $g_GENERIC print -r "#define ISTRUE(__b2c__x) ((__b2c__x) != 0)" >> $g_GENERIC print -r "#define ISFALSE(__b2c__x) ((__b2c__x) == 0)" >> $g_GENERIC print -r "#define SIZEOF(__b2c__x) sizeof(__b2c__x)" >> $g_GENERIC print >> $g_GENERIC print -r "/* Date and time */" >> $g_GENERIC print -r "#include " >> $g_GENERIC print -r "#define NOW (long)time(NULL)" >> $g_GENERIC print -r "long __b2c__time(time_t __b2c__now, int __b2c__which){struct tm *__b2c__ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS); __b2c__ts = localtime(&__b2c__now); switch(__b2c__which) { case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%d\", __b2c__ts); break;" >> $g_GENERIC print -r "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%m\", __b2c__ts); break; case 3: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%Y\", __b2c__ts); break;" >> $g_GENERIC print -r "case 4: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%H\", __b2c__ts); break; case 5: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%M\", __b2c__ts); break;" >> $g_GENERIC print -r "case 6: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%S\", __b2c__ts); break; case 7: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%W\", __b2c__ts); break;}" >> $g_GENERIC print -r "return(atol(__b2c__sbuffer[__b2c__sbuffer_ptr]));}" >> $g_GENERIC print -r "#define DAY(x) __b2c__time(x, 1)" >> $g_GENERIC print -r "#define MONTH(x) __b2c__time(x, 2)" >> $g_GENERIC print -r "#define YEAR(x) __b2c__time(x, 3)" >> $g_GENERIC print -r "#define HOUR(x) __b2c__time(x, 4)" >> $g_GENERIC print -r "#define MINUTE(x) __b2c__time(x, 5)" >> $g_GENERIC print -r "#define SECOND(x) __b2c__time(x, 6)" >> $g_GENERIC print -r "#define WEEK(x) __b2c__time(x, 7)" >> $g_GENERIC print -r "char * __b2c__datename(time_t __b2c__now, int __b2c__which){struct tm *__b2c__ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS); __b2c__ts = localtime(&__b2c__now); switch(__b2c__which){case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%A\", __b2c__ts); break;" >> $g_GENERIC print -r "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%B\", __b2c__ts); break;} return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define WEEKDAY${g_STRINGSIGN}(x) __b2c__datename(x, 1)" >> $g_GENERIC print -r "#define MONTH${g_STRINGSIGN}(x) __b2c__datename(x, 2)" >> $g_GENERIC print -r "unsigned long __b2c__epoch(int __b2c__year, int __b2c__month, int __b2c__day, int __b2c__hour, int __b2c__minute, int __b2c__second){" >> $g_GENERIC print -r "struct tm tm; time_t __b2c__t; tm.tm_year = __b2c__year - 1900; tm.tm_mon = __b2c__month - 1; tm.tm_mday = __b2c__day;" >> $g_GENERIC print -r "tm.tm_hour = __b2c__hour; tm.tm_min = __b2c__minute; tm.tm_sec = __b2c__second;" >> $g_GENERIC print -r "tm.tm_isdst = -1; __b2c__t = mktime(&tm); if (__b2c__t == -1) return (0); return(long) __b2c__t; }" >> $g_GENERIC print -r "#define TIMEVALUE(x,y,z,a,b,c) __b2c__epoch(x,y,z,a,b,c)" >> $g_GENERIC print -r "unsigned long __b2c__timer(){struct timeval __b2c__time; gettimeofday(&__b2c__time, NULL); if(difftime(__b2c__time.tv_sec, __b2c__elapsed_secs) < 1) return(unsigned long)((__b2c__time.tv_usec-__b2c__elapsed_usecs)/1000);" >> $g_GENERIC print -r "else return(unsigned long)((difftime(__b2c__time.tv_sec, __b2c__elapsed_secs)-1)*1000+((1000000-__b2c__elapsed_usecs)+__b2c__time.tv_usec)/1000);}" >> $g_GENERIC print -r "#define TIMER __b2c__timer()" >> $g_GENERIC print -r "char* __b2c__os(int __b2c__ln, const char *__b2c__fl){struct utsname __b2c__buf; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE);" >> $g_GENERIC print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_BUFFER_SIZE); if(uname(&__b2c__buf) < 0 && !__b2c__trap) {ERROR = 26; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"OS$\", ERROR);}" >> $g_GENERIC print -r "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.sysname); strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], \" \");" >> $g_GENERIC print -r "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.machine); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define OS${g_STRINGSIGN} __b2c__os(__LINE__, __FILE__)" >> $g_GENERIC print >> $g_GENERIC print -r "/* Signal trapping activated with TRAP */" >> $g_GENERIC print -r "void __b2c__catch_signal(int __b2c__sig){" >> $g_GENERIC print -r "switch (__b2c__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_GENERIC print -r "case SIGFPE: fprintf(stderr, \"ERROR: signal for FPE received - division by zero? Examine the calculations in the program.\n\"); break;" >> $g_GENERIC print -r "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_GENERIC print -r "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(__b2c__sig);}" >> $g_GENERIC print -r "/* Peek and Poke */" >> $g_GENERIC print -r "void __b2c__segv(int __b2c__sig){longjmp(__b2c__jump, 1);}" >> $g_GENERIC print -r "int __b2c__memory__check(void* __b2c__x, int __b2c__size){volatile char __b2c__c; int __b2c__i, __b2c__illegal = 0; signal(SIGSEGV, __b2c__segv);" >> $g_GENERIC print -r "if(!setjmp(__b2c__jump)) for(__b2c__i = 0; __b2c__i < __b2c__size; __b2c__i++) __b2c__c = *((char*)__b2c__x+__b2c__i); else __b2c__illegal = 1;" >> $g_GENERIC print -r "if(__b2c__trap) signal(SIGSEGV, __b2c__catch_signal); else signal(SIGSEGV, SIG_DFL); return(__b2c__illegal);}" >> $g_GENERIC print -r "#define MEMCHECK(__b2c__x) !(__b2c__memory__check((void*)__b2c__x, sizeof(__b2c__MEMTYPE)))" >> $g_GENERIC print -r "int __b2c__memory_err(int __b2c__ln, const char *__b2c__fl) {ERROR = 6; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"MEMORY\", ERROR); return(0);}" >> $g_GENERIC print -r "#define MEMORY(__b2c__x)( (__b2c__assign = calloc(__b2c__x+__b2c__option_memstream, sizeof(__b2c__MEMTYPE))) != NULL ? (long)__b2c__assign : __b2c__memory_err(__LINE__, __FILE__) )" >> $g_GENERIC print -r "int __b2c__peek_check(int __b2c__ln, const char *__b2c__fl, void* __b2c__x, int __b2c__size) {if(!__b2c__trap) {if(__b2c__memory__check(__b2c__x, __b2c__size)) {ERROR=1; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"PEEK\", ERROR);} } return(0); }" >> $g_GENERIC print -r "#define PEEK(__b2c__x) (__b2c__peek_check(__LINE__, __FILE__, (void*)__b2c__x, sizeof(__b2c__MEMTYPE)) == 0 ? *(__b2c__MEMTYPE *)(__b2c__x) : 0)" >> $g_GENERIC print -r "#define ADDRESS(__b2c__x) (long)(&__b2c__x)" >> $g_GENERIC print -r "#define FP(__b2c__x) (void*)(&__b2c__x)" >> $g_GENERIC print >> $g_GENERIC print -r "/* Network variables and functions */" >> $g_GENERIC print -r "struct timeval __b2c__to; struct hostent *__b2c__he; char *__b2c__host; char *__b2c__port; int __b2c__yes = 1; char __b2c__ttl = 1; struct sockaddr_in *__b2c__addr, *__b2c__from; struct ip_mreq __b2c__imreq;" >> $g_GENERIC print -r "int __b2c__result; char __b2c__data_client[$g_BUFFER_SIZE] = { 0 }; char __b2c__data_server[$g_BUFFER_SIZE] = { 0 }; int __b2c__handle;" >> $g_GENERIC print -r "long __b2c__netpeek(int __b2c__ln, const char *__b2c__fl, int __b2c__fd, int __b2c__usec){fd_set __b2c__rfds; struct timeval __b2c__tv; long __b2c__retval; struct termios __b2c__oldt, __b2c__newt;" >> $g_GENERIC print -r "if(__b2c__fd == STDIN_FILENO){tcgetattr(STDIN_FILENO, &__b2c__oldt); __b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);}" >> $g_GENERIC print -r "FD_ZERO(&__b2c__rfds); FD_SET(__b2c__fd, &__b2c__rfds);__b2c__tv.tv_usec = (__b2c__usec%1000)*1000; __b2c__tv.tv_sec = __b2c__usec/1000;" >> $g_GENERIC print -r "__b2c__retval = select(__b2c__fd + 1, &__b2c__rfds, NULL, NULL, &__b2c__tv); if (__b2c__retval == -1 && !__b2c__trap) {ERROR = 16; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"WAIT\", ERROR);}" >> $g_GENERIC print -r "if(__b2c__fd == STDIN_FILENO){if(__b2c__retval) if(read(__b2c__fd, &__b2c__retval, 1)==0) __b2c__retval=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt);} return(__b2c__retval);}" >> $g_GENERIC print -r "#define WAIT(__b2c__x, __b2c__y) __b2c__netpeek(__LINE__, __FILE__, __b2c__x, __b2c__y)" >> $g_GENERIC print -r "char* __b2c__nethost(int __b2c__ln, const char *__b2c__fl, char* __b2c__host) {int __b2c__y; int __b2c__flag = 0; struct in_addr __b2c__address; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE); memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_BUFFER_SIZE);" >> $g_GENERIC print -r "for(__b2c__y=0; __b2c__y < strlen(__b2c__host); __b2c__y++) {if(isalpha(*(__b2c__host+__b2c__y))) {__b2c__flag = 1; break;}} if(__b2c__flag) __b2c__he = gethostbyname(__b2c__host); " >> $g_GENERIC print -r "else {if(inet_aton(__b2c__host, &__b2c__address)) __b2c__he = gethostbyaddr((void*)&__b2c__address, sizeof(struct in_addr), AF_INET); } if (__b2c__he == NULL || __b2c__he->h_addr == NULL || __b2c__he->h_name == NULL)" >> $g_GENERIC print -r "{if(!__b2c__trap){ERROR = 11; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"HOST$\", ERROR);} else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"Host not found\", $g_BUFFER_SIZE-1); } else {if(__b2c__flag) {__b2c__addr = calloc(1, sizeof(*__b2c__addr));__b2c__addr->sin_addr = *((struct in_addr *)__b2c__he->h_addr);" >> $g_GENERIC print -r "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], inet_ntoa(__b2c__addr->sin_addr), $g_BUFFER_SIZE-1); free(__b2c__addr);} else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__he->h_name, $g_BUFFER_SIZE-1);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define HOST${g_STRINGSIGN}(__b2c__x) __b2c__nethost(__LINE__, __FILE__, __b2c__x)" >> $g_GENERIC if [[ `uname` = "OSF1" ]] then LEN="int" else LEN="unsigned int" fi print -r "char* __b2c__getpeer(int __b2c__ln, const char *__b2c__fl, int __b2c__x){struct sockaddr_in *__b2c__peer; ${LEN} __b2c__len = sizeof(__b2c__peer); char __b2c__port[6]; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_GENERIC print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE); memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_BUFFER_SIZE);" >> $g_GENERIC print -r "__b2c__peer = calloc(1, sizeof(*__b2c__peer)); if(getpeername(__b2c__x, (struct sockaddr*)__b2c__peer, &__b2c__len) <0){if(!__b2c__trap){ERROR = 16; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"GETPEER$\", ERROR);}" >> $g_GENERIC print -r "else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"Peer not found\", $g_BUFFER_SIZE-1);} else {strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], inet_ntoa(__b2c__peer->sin_addr), $g_BUFFER_SIZE-7);" >> $g_GENERIC print -r "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], \":\"); snprintf(__b2c__port, 6, \"%d\", ntohs(__b2c__peer->sin_port)); strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__port);}" >> $g_GENERIC print -r "free(__b2c__peer); return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_GENERIC print -r "#define GETPEER${g_STRINGSIGN}(__b2c__x) __b2c__getpeer(__LINE__, __FILE__, __b2c__x)" >> $g_GENERIC print >> $g_GENERIC print -r "/* Regex */" >> $g_GENERIC print -r "long __b2c__regex(int __b2c__ln, const char *__b2c__fl, char* __b2c__x, char* __b2c__y){regex_t __b2c__reg; int __b2c__reti; char __b2c__buf[100]; regmatch_t __b2c__where[1]; if(__b2c__option_compare == 0) __b2c__reti = regcomp(&__b2c__reg, __b2c__y, REG_EXTENDED);" >> $g_GENERIC print -r "else __b2c__reti = regcomp(&__b2c__reg, __b2c__y, REG_EXTENDED|REG_ICASE); if(!__b2c__trap && __b2c__reti){ERROR=27; regerror(__b2c__reti, &__b2c__reg, __b2c__buf, sizeof(__b2c__buf)); fprintf(stderr, \"%s\n\", __b2c__buf);" >> $g_GENERIC print -r "RUNTIMEFERR(__b2c__ln, __b2c__fl, \"REGEX\", ERROR);} __b2c__reti = regexec(&__b2c__reg, __b2c__x, 1, __b2c__where, 0);" >> $g_GENERIC print -r "regfree(&__b2c__reg); if( !__b2c__reti ) {REGLEN = __b2c__where[0].rm_eo - __b2c__where[0].rm_so; return (__b2c__where[0].rm_so+1);} else {REGLEN = 0; return (0);} }" >> $g_GENERIC print -r "#define REGEX(__b2c__x, __b2c__y) __b2c__regex(__LINE__, __FILE__, __b2c__x, __b2c__y)" >> $g_GENERIC print >> $g_GENERIC print -r "/* Declare reserved variable 'ARGUMENT' */" >> $g_GENERIC print -r "int __b2c__counter;" >> $g_GENERIC print -r "int __b2c__arglen = 0;" >> $g_GENERIC print -r "char *ARGUMENT${g_STRINGSIGN};" >> $g_GENERIC print >> $g_GENERIC print -r "/* Initialize stack arrays and pointer */" >> $g_GENERIC print -r "char **__b2c__stringstack = NULL; double *__b2c__doublestack = NULL;" >> $g_GENERIC print -r "long *__b2c__longstack = NULL; int *__b2c__typestack = NULL;" >> $g_GENERIC print -r "int __b2c__stackptr = 0;" >> $g_GENERIC # Makedir function print -r "int __b2c__makedir(char* __b2c__in){char *__b2c__i, *__b2c__dir; if(__b2c__in == NULL || strlen(__b2c__in)==0) return 0; if(*__b2c__in != '/'){__b2c__dir = calloc(strlen(__b2c__in)+3, sizeof (char));" >> $g_GENERIC print -r "strncpy(__b2c__dir, \"./\", 2); __b2c__dir = strcat(__b2c__dir, __b2c__in);} else __b2c__dir = __b2c__strdup(__b2c__in); __b2c__i = __b2c__dir; do { __b2c__i++; while(*__b2c__i != '/' && *__b2c__i != '\0') __b2c__i++;" >> $g_GENERIC print -r "if(*__b2c__i == '/') {*__b2c__i = '\0'; mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); *__b2c__i = '/';} else if (*__b2c__i == '\0') mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);" >> $g_GENERIC print -r "if(errno != EEXIST && errno != 0) {free(__b2c__dir); return errno;} } while (*__b2c__i != '\0'); free(__b2c__dir); return 0;}" >> $g_GENERIC # Add error function print >> $g_GENERIC print -r "/* Initialize error function */" >> $g_GENERIC print -r "char *ERR${g_STRINGSIGN}(int __b2c__nr){static char __b2c__warn[$g_BUFFER_SIZE] = { 0 }; const char* __b2c__err;" >> $g_GENERIC print -r "switch(__b2c__nr){" >> $g_GENERIC print -r "case 0: strcpy(__b2c__warn,\"Success\"); break;" >> $g_GENERIC print -r "case 1: strcpy(__b2c__warn,\"Trying to access illegal memory: \"); strncat(__b2c__warn,strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 2: strcpy(__b2c__warn,\"Error opening file: \"); strncat(__b2c__warn,strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 3: strcpy(__b2c__warn, \"Could not open library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, $g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 4: strcpy(__b2c__warn, \"Symbol not found in library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, $g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 5: strcpy(__b2c__warn, \"Wrong hexvalue: \"); strncat(__b2c__warn, strerror(errno), $g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 6: strcpy(__b2c__warn, \"Unable to claim memory.\"); break;" >> $g_GENERIC print -r "case 7: strcpy(__b2c__warn, \"Unable to delete file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 8: strcpy(__b2c__warn, \"Could not open directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 9: strcpy(__b2c__warn, \"Unable to rename file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 10: strcpy(__b2c__warn, \"NETWORK argument should contain colon with port number\"); break;" >> $g_GENERIC print -r "case 11: strcpy(__b2c__warn, \"Could not resolve hostname!\"); break;" >> $g_GENERIC print -r "case 12: strcpy(__b2c__warn, \"Socket error: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 13: strcpy(__b2c__warn, \"Unable to open address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 14: strcpy(__b2c__warn, \"Error reading from socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 15: strcpy(__b2c__warn, \"Error sending to socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 16: strcpy(__b2c__warn, \"Error checking socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 17: strcpy(__b2c__warn, \"Unable to bind the specified socket address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 18: strcpy(__b2c__warn, \"Unable to listen to socket address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 19: strcpy(__b2c__warn, \"Cannot accept incoming connection: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 20: strcpy(__b2c__warn, \"Unable to remove directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 21: strcpy(__b2c__warn, \"Unable to create directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 22: strcpy(__b2c__warn, \"Unable to change to directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 23: strcpy(__b2c__warn, \"GETENVIRON argument does not exist as environment variable\"); break;" >> $g_GENERIC print -r "case 24: strcpy(__b2c__warn, \"Unable to stat file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 25: strcpy(__b2c__warn, \"Search contains illegal string\"); break;" >> $g_GENERIC print -r "case 26: strcpy(__b2c__warn, \"Cannot return OS name: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 27: strcpy(__b2c__warn, \"Illegal regex expression\"); break;" >> $g_GENERIC print -r "case 28: strcpy(__b2c__warn, \"Unable to create bidirectional pipes: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 29: strcpy(__b2c__warn, \"Unable to fork process: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 30: strcpy(__b2c__warn, \"Cannot read from pipe: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 31: strcpy(__b2c__warn, \"Gosub nesting too deep!\"); break;" >> $g_GENERIC print -r "case 32: strcpy(__b2c__warn, \"Could not open device: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 33: strcpy(__b2c__warn, \"Error configuring serial port: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 34: strcpy(__b2c__warn, \"Error accessing device: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "case 35: strcpy(__b2c__warn, \"Error in INPUT: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_GENERIC print -r "}; ERROR = 0; return(__b2c__warn);}" >> $g_GENERIC if [[ -n $ZSH_NAME ]] then print -r "#define COMPILED_BY_WHICH_BACON${g_STRINGSIGN} \"ZSH BaCon $g_VERSION\"" >> $g_GENERIC else print -r "#define COMPILED_BY_WHICH_BACON${g_STRINGSIGN} \"KSH BaCon $g_VERSION\"" >> $g_GENERIC fi print -r "/* Created with KSH BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > $g_HFILE print -r "#include \"${g_SOURCEFILE##*/}.generic.h\"" >> $g_HFILE # Initialize the arrayfiles for DATA statement print -r "char *__b2c__stringarray[] = {" > $STRINGARRAYFILE print -r "double __b2c__floatarray[] = {" > $FLOATARRAYFILE # There are no imported symbols yet g_IMPORTED= # Check if the C Preprocessor needs to run if [[ $g_CPP -eq 1 ]] then if [[ -n `which cpp 2>/dev/null` ]] then cpp -P -w $g_SOURCEFILE $g_SOURCEFILE.cpp g_FEED=${g_SOURCEFILE}.cpp g_TMP_FILES="$g_TMP_FILES ${g_SOURCEFILE}.cpp" else print "System error: the C Preprocessor 'cpp' not found on this system! Exiting..." exit 1 fi else g_FEED=${g_SOURCEFILE} fi g_CURFILE=${g_SOURCEFILE##*/} # Initialize LEN= TOTAL= SEQ= g_COUNTER=1 # Detect if this is a Windows file if [[ `head -1 ${g_FEED}` = +(*${g_CRLF}) ]] then print "System error: Windows file detected! Remove non-Unix CR line separators first. Exiting..." exit 1 fi # Start walking through program while read -r LINE do print -n "\rConverting '${g_FEED}'... ${g_COUNTER}\033[0J" # Line is not empty? if [[ -n "$LINE" ]] then if [[ "$LINE" = +(* \\) && "$LINE" != +(REM*) && "$LINE" != +(${g_SQUOTESIGN}*) ]] then let LEN="${#LINE}"-2 typeset -L$LEN SEQ="${LINE}" TOTAL="$TOTAL$SEQ" else TOTAL="${TOTAL}${LINE}" if [[ "${TOTAL}" != +(REM*) && "${TOTAL}" != +(${g_SQUOTESIGN}*) ]] then print -r "/* noparse $g_FEED BACON LINE $g_COUNTER */" >> $g_HFILE print -r "/* noparse $g_FEED BACON LINE $g_COUNTER */" >> $g_CFILE Tokenize "${TOTAL}" fi TOTAL= fi fi ((g_COUNTER+=1)) done < ${g_FEED} # Check if enclosed IF/ELIF/ELSE needs to be closed if [[ $g_IF_PARSE -eq 1 ]] then print -r "}" >> $g_CFILE fi # Finalize main C-file print -r "__B2C__PROGRAM__EXIT:" >> $g_CFILE print -r "return 0;" >> $g_CFILE print -r "}" >> $g_CFILE # Finalize STRING ARRAY file for DATA print -r " \"\" };" >> $STRINGARRAYFILE # Finalize FLOAT ARRAY file for DATA print -r " 0.0};" >> $FLOATARRAYFILE # Include functions and subs for i in $g_INCLUDE_FILES do print "#include \"${i}\"" >> $g_HFILE done print "\rConverting '${g_FEED}'... done.\033[0J" # Indentation only when files are preserved if [[ $g_TMP_PRESERVE -eq 1 ]] then if [[ -n `which indent 2>/dev/null` ]] then print -n "Applying indentation... " for i in $g_TMP_FILES do if [[ $i != +(*.cpp) ]] 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 print "done." else print "WARNING: 'indent' not found on this system!" print "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 print -n "Executing xgettext... " xgettext -d ${g_SOURCEFILE%.*} -s -o ${g_SOURCEFILE%.*}.pot $g_TMP_FILES if [[ ! -f "${g_SOURCEFILE%.*}.pot" ]] then print "WARNING: catalog file not created!" else print "done." fi else print "WARNING: 'xgettext' not found on this system!" fi fi # Start compilation if [[ $g_NO_COMPILE -eq 0 ]] then if [[ -z `which $g_CCNAME 2>/dev/null` ]] then print "WARNING: '$g_CCNAME' not found on this system!" print "Generated source code cannot be compiled." exit 0 fi print -n "Compiling '${g_FEED}'... " # Make sure GCC uses English localization export LANG="C" $g_CCNAME $g_CCFLAGS -o "${g_SOURCEFILE%.*}$g_BINEXT" $g_CFILE $g_LDFLAGS > $g_TEMPDIR/${g_SOURCEFILE##*/}.log 2>&1 g_TMP_FILES="$g_TMP_FILES $g_TEMPDIR/${g_SOURCEFILE##*/}.log" if [[ -z `cat $g_TEMPDIR/${g_SOURCEFILE##*/}.log` ]] then print "done." print "Program '${g_SOURCEFILE%.*}$g_BINEXT' ready." else # Only print first error print "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 # Restore $-symbol if there is any if [[ ${g_ERRORTXT} = +(*${g_STRINGSIGN}*) ]] then POS=${#g_ERRORTXT} until [[ $POS -eq 0 ]] do typeset -R$POS SUBSTR="${g_ERRORTXT}" if [[ $SUBSTR = +($g_STRINGSIGN*) ]] then ((LEN=${#g_ERRORTXT}-$POS)) typeset -L$LEN SUBSTR1="${g_ERRORTXT}" ((LEN=$POS-${#g_STRINGSIGN})) typeset -R$LEN SUBSTR2="${g_ERRORTXT}" g_ERRORTXT="${SUBSTR1}\$${SUBSTR2}" break fi ((POS-=1)) done fi # Get the file where the error is g_FILE=${g_FILE_LINE%%:*} # Tru64Unix helper g_FILE=${g_FILE%%,*} # Non-gcc or parse problem (file does not exist) if [[ -z $g_ERROR || $g_CCFLAGS = +(*Wall*) || ! -f $g_FILE ]] then print cat $g_TEMPDIR/${g_SOURCEFILE##*/}.log print 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 # Initiate error file name and error line in C code g_FEED=${g_FILE_LINE%%:*} g_CURLINE=${g_LINE%%:*} # Remove everything behind last colon g_LINE=${g_LINE%%:*} g_COUNTER=1 while read -r LINE do if [[ $LINE = +(*BACON LINE*) && $LINE = +(*noparse*) ]] then g_CURLINE=${LINE##*BACON LINE } g_FEED=${LINE##*noparse } g_FEED=${g_FEED%% BACON LINE*} fi if [[ ${g_COUNTER} -eq ${g_LINE} ]] then COUNTER=1 while read -r LINE do if [[ $COUNTER -eq ${g_CURLINE%% *} ]] then print "\nProblem:\n\t file '$g_FEED' line $COUNTER: ${LINE}" print "$g_ERRORTXT\n" break fi ((COUNTER+=1)) done < $g_FEED break fi ((g_COUNTER+=1)) done < ${g_FILE} 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 print "\nWarning: duplicate SUB or FUNCTION found! Temporary file $i already deleted." fi done elif [[ $g_CPP -eq 1 ]] then mv ${g_SOURCEFILE}.cpp $g_TEMPDIR/${g_SOURCEFILE##*/}.cpp fi exit 0