#!/usr/bin/env bash # # Bash BASIC-to-C converter --= BACON =-- # # Peter van Eerten - March 2009/April 2010. License: GPL version 3. # # Global variables should be preceded with a 'g_'. # #--------------------------------------------------------------------------------------------------------------------- # CREDITS: # - James C. Fuller for endless testing and patiently pointing to many issues # - John Spikowksi for providing the forum and giving some hints to improve the language # #--------------------------------------------------------------------------------------------------------------------- # GLOBAL INITIALIZATIONS #--------------------------------------------------------------------------------------------------------------------- # Set the extending globbing option in BASH shopt -s extglob # Make sure GCC uses English localization export LC_CTYPE="C" export LANG="C" # Version of BACON g_VERSION="1.0 build 12" # Find 'grep' and other coretools if [[ -z `which grep` || -z `which cat` || -z `which rm` || -z `which tr` || -z `which touch` || -z `which uname` ]] then echo "ERROR: 'grep', 'cat', 'rm', 'tr', 'touch' or 'uname' 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 # Global constant for miniparsing declare -rx g_PARSEVAR=`echo -e "\001"` # Global to define '$'-replacement declare -rx g_STRINGSIGN="__b2c__string_var" #----------------------------------------------------------- function Print_Element { local DQ FUNC VAR # Get the element without (surrounding) spaces VAR=`echo "${1}" | tr -d "\040"` DQ="${VAR: -1}" FUNC="${VAR:0:3}" # Check type of var, func using string but returning a value? if [[ ${FUNC} = "INS" || ${FUNC} = "VAL" || ${FUNC} = "LEN" || ${FUNC} = "SEA" || ${FUNC} = "REG" || ${FUNC} = "ASC" || "$1" = +(FILE*) ]] then echo "fprintf(stdout, \"%.10g\", (double)($1));" >> $g_CFILE # String function? elif [[ "$1" = +(*${g_STRINGSIGN}*) && "$1" = +(*\(*\)*) ]] then echo "fprintf(stdout, \"%s\", $1);" >> $g_CFILE # Is there a "$" symbol? Then it is always a string, or stringvariable elif [[ "$1" = +(*${g_STRINGSIGN}*) ]] then echo "if($1 != NULL) fprintf(stdout, \"%s\", $1);" >> $g_CFILE echo "else fprintf(stdout, \"\");" >> $g_CFILE # Check if it is a normal string elif [[ $DQ = "\"" ]] then echo "fprintf(stdout, \"%s\", $1);" >> $g_CFILE # Other numeric variable else echo "fprintf(stdout, \"%.10g\", (double)($1));" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Print { local FORMAT EXP LEN TOKEN LINE IN_STRING IN_FUNC CHAR ESCAPED IN_FUNC=0 # If no argument, do nothing if [[ "$1" != "PRINT" ]] then # Get expression without ; if [[ -z ${1##*;} ]] then let LEN="${#1}"-1 EXP="${1:0:$LEN}" else EXP="${1}" fi # If there is FORMAT/format argument if [[ "$EXP" = +(* FORMAT *) ]] then FORMAT=${EXP##* FORMAT} echo "fprintf(stdout, ${FORMAT%%;*}, ${EXP%%FORMAT *});" >> $g_CFILE else # Start miniparser, convert spaces LINE=`echo "${EXP}" | tr " " "\001"` TOKEN= LEN=${#LINE} # Get the characters until [[ $LEN -eq 0 ]] do CHAR="${LINE:0:1}" case $CHAR in ",") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then Print_Element "${TOKEN}" TOKEN= CHAR= 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 LINE="${LINE: -$LEN}" done Print_Element "${TOKEN}" # If line ends with ';' then skip newline if [[ -n ${1##*;} ]] then echo "fprintf(stdout, \"\n\");" >> $g_CFILE fi fi else echo "fprintf(stdout, \"\n\");" >> $g_CFILE fi # Flush buffer echo "fflush(stdout);" >> $g_CFILE } #----------------------------------------------------------- function Handle_Input { # Local variables local 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 echo -e "\nERROR: 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=`echo "${1}" | tr " " "\001"` VAR= LEN=${#LINE} # Get the characters until [[ $LEN -eq 0 ]] do CHAR="${LINE:0:1}" case $CHAR in ",") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then Print_Element "${VAR}" VAR= CHAR= 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 VAR="${VAR} " else VAR="${VAR}${CHAR}" fi let LEN=${#LINE}-1 LINE="${LINE: -$LEN}" done # Check type of var, string? if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] then if [[ ${VAR} != +(*\[*\]*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then echo "char *$VAR = NULL;" >> $g_HFILE fi fi # Translate function to C function echo "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\0', $g_BUFFER_SIZE);" >> $g_CFILE echo "fgets(__b2c__input__buffer, $g_BUFFER_SIZE, stdin);" >> $g_CFILE # Make sure internal var is copied to var of program echo "$VAR = (char*)realloc($VAR, ($g_BUFFER_SIZE+1)*__b2c__counter*sizeof(char));" >> $g_CFILE echo "if(__b2c__counter == 1) strncpy($VAR, __b2c__input__buffer, $g_BUFFER_SIZE);" >> $g_CFILE echo "else strncat($VAR, __b2c__input__buffer, $g_BUFFER_SIZE); __b2c__counter++;" >> $g_CFILE echo "} while (!strstr(__b2c__input__buffer, \"\n\") && strlen(__b2c__input__buffer));" >> $g_CFILE # Cut off last newline echo "if (strlen(__b2c__input__buffer)) $VAR[strlen($VAR)-1]='\0';" >> $g_CFILE # Var is numeric or stringarray else # Variable may not be array, these should be defined with DECLARE if [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) ]] then # Not declared? Assume long CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|,$VAR,|,$VAR;" | grep -v "\/\*noparse\*\/"` if [[ -z $CHECK ]] then echo "long $VAR;" >> $g_HFILE CHECK="long " fi else CHECK=`grep -E "DIR |FILE |int |long |float |double |char |void |STRING |NUMBER |FLOATING " $TARGET | grep -E " ${VAR%%\[*}" | grep -v "\/\*noparse\*\/"` fi # Translate function to C function echo "memset(__b2c__input__buffer, '\0', $g_BUFFER_SIZE); fgets(__b2c__input__buffer, $g_BUFFER_SIZE, stdin);" >> $g_CFILE # Make sure internal var is copied to var of program if [[ "$CHECK" = +(*double *) || "$CHECK" = +(*float *) || "$CHECK" = +(*FLOATING *) ]] then echo "$VAR = atof(__b2c__input__buffer);" >> $g_CFILE elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*NUMBER *) ]] then echo "$VAR = atol(__b2c__input__buffer);" >> $g_CFILE else echo "$VAR = atoi(__b2c__input__buffer);" >> $g_CFILE fi fi } #----------------------------------------------------------- function Handle_For { # Local variables local FROM TO TMP VAR STEP CHECK TARGET # Get the variablename without (surrounding) spaces VAR=`echo "${1%%=*}" | tr -d "\040"`; TMP=`echo "${1#*=}"` # Do we have a STRING var? if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] then echo -e "\nERROR: variable in FOR statement at line $g_COUNTER in file $g_CURFILE cannot be string!" exit 1 fi # Check if TO is available if [[ "$TMP" != +(* TO *) ]] then echo -e "\nERROR: missing TO in FOR statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the starting and ending value FROM=`echo "${TMP%% TO *}"` TO=`echo "${TMP##* TO }"` # Check if there is a STEP if [[ "$TO" = +(* STEP *) ]] then STEP="${TO##* STEP }" TO="${TO%% STEP *}" else STEP=1 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 [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) ]] then # Declare variable if not done yet, assuming long CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|,$VAR,|,$VAR;| ${VAR%%\[*}\[|,${VAR%%\[*}\[" | grep -v "\/\*noparse\*\/"` if [[ -z $CHECK ]] then echo "long $VAR;" >> $g_HFILE fi fi # Translate function to C function if [[ "${STEP}" = +(*-*) ]] then echo "for($VAR=$FROM; $VAR >= $TO; $VAR+=$STEP){" >> $g_CFILE else echo "for($VAR=$FROM; $VAR <= $TO; $VAR+=$STEP){" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_While { # Check if DO is available if [[ "$1" != +(* DO) ]] then echo "while(${1}){" >> $g_CFILE else echo "while(${1% *}){" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Let { # Local variables local VAR CHECK TMP TARGET LEN STR # Check if there is an asignment at all, if not exit if [[ "$1" != +(*=*) ]] then echo -e "\nERROR: 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=`echo ${1%%=*}`; TMP=${1#*=} # Check if var is string var, exclude RECORD elements if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then echo "char *$VAR = NULL;" >> $g_HFILE fi # Assume number, exclude RECORD and ASSOC elements elif [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) && "$VAR" != "ERROR" && "$VAR" != +(*\(*\)*) ]] then CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|,$VAR,|,$VAR;| ${VAR%%\[*}\[|,${VAR%%\[*}\[" | grep -v "\/\*noparse\*\/"` if [[ -z $CHECK ]] then if [[ "$TMP" = +(*.*) ]] then echo "double $VAR;" >> $g_HFILE else echo "long $VAR;" >> $g_HFILE fi fi fi # Check if there is associative array assignment if [[ "${VAR}" = +(*\(*\)) ]] then STR=${VAR#*\(} echo "if(${VAR} == 0){__b2c__${VAR%%\(*}_idx++; __b2c__${VAR%%\(*} = (struct __b2c__${VAR%%\(*}_type *)realloc(__b2c__${VAR%%\(*}," >> $g_CFILE echo "__b2c__${VAR%%\(*}_idx * sizeof(struct __b2c__${VAR%%\(*}_type)); __b2c__${VAR%%\(*}[__b2c__${VAR%%\(*}_idx-1].key = NULL;}" >> $g_CFILE echo "__b2c__${VAR%%\(*}[__b2c__${VAR%%\(*}_idx-1].key = realloc(__b2c__${VAR%%\(*}[__b2c__${VAR%%\(*}_idx-1].key, (strlen(${STR}+1)*sizeof(char));" >> $g_CFILE echo "strcpy(__b2c__${VAR%%\(*}[__b2c__${VAR%%\(*}_idx-1].key, ${STR}; __b2c__${VAR%%\(*}[__b2c__${VAR%%\(*}_idx-1].value = $TMP;" >> $g_CFILE # Do we have a STRING variable? elif [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] then echo "__b2c__assign = (char*) strdup ($TMP); ${g_WITHVAR}${VAR} = (char*)realloc(${g_WITHVAR}${VAR}, (strlen(__b2c__assign)+1)*sizeof(char));" >> $g_CFILE echo "strcpy(${g_WITHVAR}${VAR}, __b2c__assign); free(__b2c__assign);" >> $g_CFILE else echo "${g_WITHVAR}${1};" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Open { # Local variables local FILE MODE HANDLE TMP CHECK TARGET LABEL # Check if FOR is available if [[ "$1" != +(* FOR *) ]] then echo -e "\nERROR: Missing FOR in OPEN statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if AS is available if [[ "$1" != +(* AS *) ]] then echo -e "\nERROR: Missing AS in OPEN statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the file, mode and handle FILE=`echo "${1%% FOR *}"` TMP=`echo "${1##* FOR }"` MODE=`echo "${TMP%% AS *}"` HANDLE=`echo "${TMP##* AS }"` # Check if var is string var if [[ "${HANDLE}" = +(*${g_STRINGSIGN}) && $MODE != "MEMORY" ]] then echo -e "\nERROR: 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|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $HANDLE,| $HANDLE;|,$HANDLE,|,$HANDLE;| ${HANDLE%%\[*}\[|,${HANDLE%%\[*}\[" | grep -v "\/\*noparse\*\/"` fi # File or dir? if [[ $MODE = "DIRECTORY" ]] then if [[ -z $CHECK ]] then echo "DIR *$HANDLE;" >> $g_HFILE fi elif [[ $MODE = "MEMORY" ]] then echo $CHECK if [[ -z $CHECK ]] then echo "char *$HANDLE;" >> $g_HFILE fi CHECK=`grep -E "long" $TARGET | grep " __b2c_mem_$HANDLE;" | grep -v "\/\*noparse\*\/"` if [[ -z $CHECK ]] then echo "long __b2c_mem_$HANDLE;" >> $g_HFILE fi elif [[ $MODE = "NETWORK" || $MODE = "SERVER" ]] then if [[ -z $CHECK ]] then echo "int $HANDLE;" >> $g_HFILE fi else if [[ -z $CHECK ]] then echo "FILE *$HANDLE;" >> $g_HFILE fi fi # Convert to C syntax case $MODE in @(READING) ) echo "$HANDLE = fopen($FILE, \"r\");" >> $g_CFILE echo "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(WRITING) ) echo "$HANDLE = fopen($FILE, \"w\");" >> $g_CFILE echo "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(APPENDING) ) echo "$HANDLE = fopen($FILE, \"a\");" >> $g_CFILE echo "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(READWRITE) ) echo "$HANDLE = fopen($FILE, \"r+\");" >> $g_CFILE echo "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(DIRECTORY) ) echo "$HANDLE = opendir($FILE);" >> $g_CFILE echo "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(MEMORY) ) echo "$HANDLE = (char*)$FILE; __b2c_mem_$HANDLE = $FILE;" >> $g_CFILE echo "if(!__b2c__trap){__b2c__memory__check($HANDLE); if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(NETWORK) ) # Network code echo "if (strstr($FILE, \":\") == NULL) {if(!__b2c__trap){ERROR = 10;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "strncpy(__b2c__data, $FILE, $g_BUFFER_SIZE); __b2c__host = strtok(__b2c__data, \":\"); __b2c__port = strtok(NULL, \":\"); __b2c__he = gethostbyname(__b2c__host);" >> $g_CFILE echo "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "$HANDLE = socket(PF_INET, SOCK_STREAM, 0);" >> $g_CFILE echo "if ($HANDLE == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "__b2c__to.tv_sec = $g_OPTION_SOCKET; __b2c__to.tv_usec = 0; setsockopt($HANDLE, SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" >> $g_CFILE echo "setsockopt($HANDLE, SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int)); __b2c__addr.sin_family = AF_INET; __b2c__addr.sin_port = htons((long)atol(__b2c__port));" >> $g_CFILE echo "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr); memset(&(__b2c__addr.sin_zero), '\0', sizeof(__b2c__addr.sin_zero));" >> $g_CFILE echo "__b2c__result = connect($HANDLE, (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" >> $g_CFILE echo "if(__b2c__result == -1) {if(!__b2c__trap){ERROR = 13;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(SERVER) ) # Network code echo "if (strstr($FILE, \":\") == NULL){if(!__b2c__trap){ERROR = 10;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "strncpy(__b2c__data, $FILE, $g_BUFFER_SIZE); __b2c__host = strtok(__b2c__data, \":\"); __b2c__port = strtok(NULL, \":\"); __b2c__he = gethostbyname(__b2c__host);" >> $g_CFILE echo "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "$HANDLE = socket(AF_INET, SOCK_STREAM, 0);" >> $g_CFILE echo "if ($HANDLE == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "__b2c__to.tv_sec = $g_OPTION_SOCKET; __b2c__to.tv_usec = 0; setsockopt($HANDLE, SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" >> $g_CFILE echo "setsockopt($HANDLE, SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int)); __b2c__addr.sin_family = AF_INET; __b2c__addr.sin_port = htons((long)atol(__b2c__port));" >> $g_CFILE echo "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr); memset(&(__b2c__addr.sin_zero), '\0', sizeof(__b2c__addr.sin_zero));" >> $g_CFILE echo "__b2c__result = bind($HANDLE, (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" >> $g_CFILE echo "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 17;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "__b2c__result = listen($HANDLE, $g_MAX_BACKLOG);" >> $g_CFILE echo "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 18;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "__b2c__result = accept($HANDLE, NULL, 0);" >> $g_CFILE echo "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 19;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "$HANDLE= __b2c__result;" >> $g_CFILE;; esac } #----------------------------------------------------------- function Handle_Readln { # Local variables local CHECK VAR FROM TARGET STR # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then echo -e "\nERROR: Missing FROM in READLN statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`echo ${1%% FROM *}` # Get filedescriptor FROM=`echo ${1##* FROM }` # Check if var is string var if [[ "${VAR}" != +(*${g_STRINGSIGN}*) ]] then echo -e "\nERROR: 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 variable is declared if [[ ${VAR} != +(*\[*\]*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then echo "char *$VAR = NULL;" >> $g_HFILE fi fi # Translate function to C function echo "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\0', $g_BUFFER_SIZE);" >> $g_CFILE echo "fgets(__b2c__input__buffer, $g_BUFFER_SIZE, $FROM);" >> $g_CFILE # Make sure internal var is copied to var of program echo "$VAR = (char*)realloc($VAR, ($g_BUFFER_SIZE+1)*__b2c__counter*sizeof(char));" >> $g_CFILE echo "if(__b2c__counter == 1) strncpy($VAR, __b2c__input__buffer, $g_BUFFER_SIZE);" >> $g_CFILE echo "else strncat($VAR, __b2c__input__buffer, $g_BUFFER_SIZE); __b2c__counter++;" >> $g_CFILE echo "} while (!strstr(__b2c__input__buffer, \"\n\") && strlen(__b2c__input__buffer));" >> $g_CFILE # Cut off last newline echo "if (strlen(__b2c__input__buffer)) $VAR[strlen($VAR)-1]='\0';" >> $g_CFILE } #----------------------------------------------------------- function Handle_Writeln { # Local variables local VAR TO LINE LEN CHAR IN_STRING IN_FUNC # Check if TO is available if [[ "$1" != +(* TO *) ]] then echo -e "\nERROR: Missing TO in WRITELN statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get filedescriptor TO=`echo ${1##* TO }` # Start miniparser to see if we need to print something, convert spaces LINE=`echo "${1%% TO *}" | tr " " "\001"` VAR= LEN=${#LINE} IN_STRING=0 # Get the characters until [[ $LEN -eq 0 ]] do CHAR="${LINE:0:1}" case $CHAR in ",") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then # Check if var is string var if [[ "${VAR}" = +(*${g_STRINGSIGN}*) || "${VAR}" != `echo "${VAR}" | tr -d "\042"` ]] then echo "fprintf($TO, \"%s\", ${VAR});" >> $g_CFILE VAR= CHAR= ESCAPED=0 else echo -e "\nERROR: Argument for WRITELN at line $g_COUNTER in file $g_CURFILE must be string!" exit 1 fi 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 LINE="${LINE: -$LEN}" done # Write to file echo "fprintf($TO, \"%s\n\", ${VAR});" >> $g_CFILE echo "fflush($TO);" >> $g_CFILE } #----------------------------------------------------------- function Handle_Getbyte { # Local variables local POS FROM SIZE TARGET CHECK # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then echo -e "\nERROR: Missing FROM in GETBYTE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces POS=`echo ${1%% FROM *}` # Get filedescriptor FROM=`echo ${1##* FROM }` SIZE= # Check if SIZE is available if [[ "$1" = +(* SIZE *) ]] then SIZE=${FROM##* SIZE } FROM=${FROM%% SIZE *} else SIZE=1 fi # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Declare variable if not done yet, assuming long if [[ "$POS" != +(*.*) ]] then CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $POS,| $POS;|,$POS,|,$POS;| ${POS%%\[*}\[|,${POS%%\[*}\[" | grep -v "\/\*noparse\*\/"` if [[ -z $CHECK ]] then echo "long $POS;" >> $g_HFILE fi fi # Translate function to C function echo "if(!__b2c__trap){__b2c__memory__check((char *)$POS); if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "fread((void*)$POS, sizeof(char), $SIZE, $FROM);" >> $g_CFILE } #----------------------------------------------------------- function Handle_Putbyte { # Local variables local VAR TO SIZE POS # Check if TO is available if [[ "$1" != +(* TO *) ]] then echo -e "\nERROR: Missing TO in PUTBYTE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces POS=`echo ${1%% TO *}`; # Get filedescriptor TO=`echo ${1##* TO }` SIZE= # Check if SIZE is available if [[ "$1" = +(* SIZE *) ]] then SIZE=${TO##* SIZE } TO=${TO%% SIZE *} else SIZE=1 fi # Translate function to C function echo "if(!__b2c__trap){__b2c__memory__check((char *)$POS); if(ERROR){if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE echo "fwrite((void*)$POS, sizeof(char), $SIZE, $TO);" >> $g_CFILE } #----------------------------------------------------------- function Handle_Getfile { # Local variables local VAR FROM SIZE TARGET STR # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then echo -e "\nERROR: Missing FROM in GETFILE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`echo ${1%% FROM *}` # Get dirdescriptor FROM=`echo ${1##* FROM }` # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Translate function to C function echo "__b2c__dir = readdir($FROM);" >> $g_CFILE # Check if variable is declared STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then echo "char *$VAR = NULL;" >> $g_HFILE fi # Always realloc VAR to correct size, maybe it was resized somewhere else echo "if(__b2c__dir != NULL) {$VAR = realloc($VAR, (strlen(__b2c__dir->d_name)+1)*sizeof(char));" >> $g_CFILE # Make sure internal var is copied to var of program echo "strcpy($VAR, __b2c__dir->d_name); $VAR[strlen(__b2c__dir->d_name)] = '\0';}" >> $g_CFILE echo "else {$VAR[0] = '\0';}" >> $g_CFILE } #----------------------------------------------------------- function Handle_Receive { # Local variables local CHECK VAR FROM TARGET STR SIZE # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then echo -e "\nERROR: Missing FROM in RECEIVE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`echo ${1%% FROM *}` # Get filedescriptor FROM=`echo ${1##* FROM }` # Check for optional chunksize if [[ $FROM = +(* SIZE *) ]] then SIZE=${FROM##* SIZE } FROM=${FROM%% SIZE *} else SIZE=$g_BUFFER_SIZE fi # Check if var is string var if [[ "${VAR}" != +(*${g_STRINGSIGN}) ]] then echo -e "\nERROR: Variable for RECEIVE 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 variable is declared STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then echo "char *$VAR = NULL;" >> $g_HFILE fi # Translate function to C function echo "$VAR = (char*)realloc($VAR, ($SIZE+1)*sizeof(char)); memset($VAR, '\0', $SIZE+1);" >> $g_CFILE echo "if(recv($FROM, $VAR, $SIZE, 0) < 0) {if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Send { # Local variables local VAR TO # Check if TO is available if [[ "$1" != +(* TO *) ]] then echo -e "\nERROR: Missing TO in SEND statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`echo ${1%% TO *}`; # Get filedescriptor TO=`echo ${1##* TO }` # Check if var is string var if [[ "${VAR}" != +(*${g_STRINGSIGN}*) && "$VAR" = `echo "$VAR" | tr -d "\042"` ]] then echo -e "\nERROR: Variable for SEND at line $g_COUNTER in file $g_CURFILE must be string!" exit 1 fi # Translate function to C function echo "if(send($TO, $VAR, strlen($VAR), 0) < 0) {if(!__b2c__trap){ERROR = 15; if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Getline { # Local variables local CHECK VAR FROM TARGET STR # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then echo -e "\nERROR: Missing FROM in GETLINE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`echo ${1%% FROM *}` # Get filedescriptor FROM=`echo ${1##* FROM }` # Check if var is string var if [[ "${VAR}" != +(*${g_STRINGSIGN}*) ]] then echo -e "\nERROR: 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 variable is declared if [[ ${VAR} != +(*\[*\]*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then echo "char *$VAR = NULL;" >> $g_HFILE fi fi # Translate function to C function echo "if ($FROM == NULL || *$FROM == '\0') {$VAR = (char*)realloc($VAR, 2*sizeof(char)); strcpy($VAR, \"\");}" >> $g_CFILE echo "else { __b2c__assign = $FROM; while(*$FROM != '\0' && *$FROM != '\n') $FROM++;" >> $g_CFILE # Make sure internal var is copied to var of program echo "$VAR = (char*)realloc($VAR, ($FROM-__b2c__assign+1)*sizeof(char));" >> $g_CFILE echo "strncpy($VAR, __b2c__assign, $FROM-__b2c__assign);" >> $g_CFILE # Make sure to end the string echo "$VAR[($FROM-__b2c__assign)] = '\0'; $FROM++;}" >> $g_CFILE } #----------------------------------------------------------- function Handle_Putline { # Local variables local VAR TO LINE LEN CHAR IN_STRING IN_FUNC # Check if TO is available if [[ "$1" != +(* TO *) ]] then echo -e "\nERROR: Missing TO in PUTLINE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get memorydescriptor TO=`echo ${1##* TO }` # Start miniparser to see if we need to print something, convert spaces LINE=`echo "${1%% TO *}" | tr " " "\001"` VAR= LEN=${#LINE} IN_STRING=0 # Get the characters until [[ $LEN -eq 0 ]] do CHAR="${LINE:0:1}" case $CHAR in ",") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then # Check if var is string var if [[ "${VAR}" = +(*${g_STRINGSIGN}*) || "${VAR}" != `echo "${VAR}" | tr -d "\042"` ]] then echo "strcat($TO, $VAR); $TO+=strlen($VAR);" >> $g_CFILE VAR= CHAR= ESCAPED=0 else echo -e "\nERROR: Variable for PUTLINE at line $g_COUNTER in file $g_CURFILE must be string!" exit 1 fi 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 LINE="${LINE: -$LEN}" done # Check if var is string var if [[ "${VAR}" = +(*${g_STRINGSIGN}*) || "$VAR" != `echo "$VAR" | tr -d "\042"` ]] then # Translate function to C function echo "strcat($TO, $VAR); strcat($TO, \"\n\"); $TO+=strlen($VAR)+1;" >> $g_CFILE else echo -e "\nERROR: Variable for PUTLINE at line $g_COUNTER in file $g_CURFILE must be string!" exit 1 fi } #----------------------------------------------------------- function Handle_Import { # Local variables local TMP SYM LIB CHECK TOKEN PTR TYPE # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then echo -e "\nERROR: 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=`echo ${1%%\(*} | tr -d "\042"`; TMP=${1#* FROM } TOKEN=`echo ${1%\)*}` else SYM=`echo ${1%% FROM *} | tr -d "\042"`; TMP=${1#* FROM } TOKEN= fi # Check if TYPE is available if [[ "$1" != +(* TYPE *) ]] then echo -e "\nERROR: missing TYPE in IMPORT statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get library and type LIB=`echo ${TMP%% TYPE *}` TYPE=`echo ${TMP##* TYPE }` # 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=`echo $LIB | tr -d [:punct:]` # Check if variable was declared CHECK=`grep -i "void\* __b2c__dlopen__pointer_$PTR;" $g_HFILE` if [[ -z $CHECK ]] then echo "void* __b2c__dlopen__pointer_$PTR;" >> $g_HFILE echo "__b2c__dlopen__pointer_$PTR = dlopen($LIB, RTLD_LAZY);" >> $g_CFILE echo "if(__b2c__dlopen__pointer_$PTR == NULL){if(!__b2c__trap){ERROR = 3;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE fi # Check if token was declared CHECK=`grep -i "$TYPE (\*$SYM)" $g_HFILE` if [[ -z $CHECK ]] then echo "$TYPE (*$SYM)(${TOKEN#*\(});" >> $g_HFILE fi # Translate to C function echo "*($TYPE **) (&$SYM) = dlsym(__b2c__dlopen__pointer_$PTR, \"$SYM\");" >> $g_CFILE echo "if($SYM == NULL) {if(!__b2c__trap){ERROR = 4;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE fi # Make symbol known to parser g_IMPORTED="$SYM $g_IMPORTED" } #----------------------------------------------------------- function Handle_Declare { # Local variables local VAR TYPE CHECK NEW VALUE # Check on a GLOBAL RECORD if [[ "$1" = +(*RECORD *) ]] then # Translate to C typedef struct g_RECORDNAME="RECORD_${g_COUNTER}" echo "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=`echo ${1%% TYPE *}` TYPE=`echo ${1##* TYPE }` elif [[ "$1" = +(* ASSOC *) ]] then VAR=`echo ${1%% ASSOC *}` TYPE=`echo ${1##* ASSOC }` else VAR=`echo ${1}` TYPE="long" fi # Check if variable was already declared if [[ "$VAR" != +(*.*) ]] then CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $g_HFILE | grep -E " $VAR,| $VAR;|,$VAR,|,$VAR;| ${VAR%%\[*}\[|,${VAR%%\[*}\[" | grep -v "\/\*noparse\*\/"` fi if [[ -n $CHECK ]] then echo -e "\nERROR: 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 for associative array if [[ "${1}" = +(* ASSOC *) ]] then echo "struct __b2c__${VAR}_type {char *key; /*noparse*/ ${TYPE} value; /*noparse*/ };" >> $g_HFILE echo "struct __b2c__${VAR}_type *__b2c__${VAR} = { NULL }; int __b2c__${VAR}_idx = 0;" >> $g_HFILE echo "static int __b2c__${VAR}_comp(const void *__b2c__m1, const void *__b2c__m2){ " >> $g_HFILE echo "struct __b2c__${VAR}_type *__b2c__mi1 = (struct __b2c__${VAR}_type *) __b2c__m1;" >> $g_HFILE echo "struct __b2c__${VAR}_type *__b2c__mi2 = (struct __b2c__${VAR}_type *) __b2c__m2;" >> $g_HFILE echo "return strcmp(__b2c__mi1->key, __b2c__mi2->key); }" >> $g_HFILE echo "${TYPE} ${VAR}(char *__b2c__index){struct __b2c__${VAR}_type __b2c__${VAR}_key, *__b2c__${VAR}__result;" >> $g_HFILE echo "qsort(__b2c__${VAR}, __b2c__${VAR}_idx, sizeof(struct __b2c__${VAR}_type), __b2c__${VAR}_comp);" >> $g_HFILE echo "__b2c__${VAR}_key.key = __b2c__index; __b2c__${VAR}__result = bsearch(&__b2c__${VAR}_key, __b2c__${VAR}," >> $g_HFILE echo "__b2c__${VAR}_idx, sizeof(struct __b2c__${VAR}_type), __b2c__${VAR}_comp);" >> $g_HFILE echo "if(__b2c__${VAR}__result == NULL) return(0); return __b2c__${VAR}__result->value;}" >> $g_HFILE # Check if var is string var elif [[ "${VAR}" = +(*${g_STRINGSIGN}*) || "${TYPE}" = +(*STRING*|*char\**) && "${VAR}" != +(*=*) ]] then #STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR} = NULL;" $g_HFILE` if [[ -z $CHECK ]] then STR=`echo ${VAR} | tr ',' ' '` for i in $STR do if [[ "${i}" = +(*\[*\]*) ]] then echo "char *$i = { NULL };" >> $g_HFILE else echo "char *$i = NULL;" >> $g_HFILE fi done fi # Assume char assignment or number else echo "$TYPE $VAR;" >> $g_HFILE if [[ "$VAR" != +(*=*) && "$VAR" != +(*\(*\)*) && "$VAR" != +(*\[*\]*) ]] then echo "$VAR = 0;" | tr "," "=" >> $g_CFILE fi fi fi } #----------------------------------------------------------- function Handle_Local { # Local variables local VAR TYPE CHECK TARGET DIM NEW VALUE # Get the variablename and type if [[ "$1" = +(* TYPE *) ]] then VAR=`echo ${1%% TYPE *}` TYPE=`echo ${1##* TYPE }` else VAR=`echo ${1}` TYPE="long" 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 CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|,$VAR,|,$VAR;| ${VAR%%\[*}\[|,${VAR%%\[*}\[" | grep -v "\/\*noparse\*\/"` fi if [[ -n $CHECK ]] then echo -e "\nERROR: 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 var is string var if [[ "${TYPE}" = +(*STRING*|*char\**) || "${VAR}" = +(*${g_STRINGSIGN}*) && "${VAR}" != +(*\[*${g_STRINGSIGN}*\]*) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = " ${TARGET}` if [[ -z $CHECK ]] then STR=`echo ${VAR} | tr ',' ' '` for i in $STR do # Check on multidimensional stringarrays if [[ "${i}" = +(*\[*\]*\]*) ]] then echo -e "\nERROR: multidimensional stringarrays at line $g_COUNTER in file $g_CURFILE are not supported!" exit 1 fi # Are we in a function? if [[ -n $g_FUNCNAME ]] then if [[ -n $g_RECORDNAME ]] then if [[ "${i}" = +(*\[*\]*) ]] then echo "char *$i;" >> $g_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 echo "char *$i; /*noparse*/" >> $g_CFILE fi else if [[ "${i}" = +(*\[*\]*) ]] then echo "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 echo "char *$i = NULL;" >> $g_CFILE g_LOCALSTRINGS="$g_LOCALSTRINGS ${i}" fi fi # We are in the mainprogram else if [[ -n $g_RECORDNAME ]] then echo "char *$i; /*noparse*/" >> $g_HFILE else if [[ "${i}" = +(*\[*\]*) ]] then echo "char *$i = { NULL };" >> $g_CFILE else echo "char *$i = NULL;" >> $g_HFILE fi fi fi done fi # Assume number else if [[ -n $g_FUNCNAME ]] then if [[ -n $g_RECORDNAME ]] then echo "$TYPE $VAR; /*noparse*/" >> $g_CFILE else echo "$TYPE $VAR;" >> $g_CFILE if [[ "$VAR" != +(*=*) && "$VAR" != +(*\(*\)*) && "$VAR" != +(*\[*\]*) ]] then echo "$VAR = 0;" | tr "," "=" >> $g_CFILE fi fi else if [[ -n $g_RECORDNAME ]] then echo "$TYPE $VAR; /*noparse*/" >> $g_HFILE else echo "$TYPE $VAR;" >> $g_HFILE if [[ "$VAR" != +(*=*) && "$VAR" != +(*\(*\)*) && "$VAR" != +(*\[*\]*) ]] then echo "$VAR = 0;" | tr "," "=" >> $g_CFILE fi fi fi fi } #----------------------------------------------------------- function Handle_Read { # Local variables local CHECK TARGET STR # Check if we have an argument at all if [[ "$1" = "READ" ]] then echo -e "\nERROR: 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 # Check type of var, string? if [[ "${1}" = +(*${g_STRINGSIGN}) ]] then STR=${1%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then echo "char *$1 = NULL;" >> $g_HFILE fi # Convert to C echo "$1 = (char*)realloc($1, (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" >> $g_CFILE echo "strcpy($1, __b2c__stringarray[__b2c__stringarray_ptr]);" >> $g_CFILE echo "__b2c__stringarray_ptr++;" >> $g_CFILE else # Variable may not be array, these should be defined with DECLARE if [[ "$1" != +(*\[*\]*) && "$1" != +(*.*) ]] then # Not declared? Assume long CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $1,| $1;|,$1,|,$1;| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v "\/\*noparse\*\/"` if [[ -z $CHECK ]] then echo "long $1;" >> $g_HFILE CHECK="long " fi else # See how var was declared CHECK=`grep -E "DIR |FILE |int |long |float |double |char |void |STRING |NUMBER |FLOATING " $TARGET | grep -E " ${1%%\[*}" | grep -v "\/\*noparse\*\/"` fi # Convert to C if [[ "$CHECK" = +(*double *) || "$CHECK" = +(*float *) || "$CHECK" = +(*FLOATING *) ]] then echo "${1} = __b2c__floatarray[__b2c__floatarray_ptr];" >> $g_CFILE echo "__b2c__floatarray_ptr++;" >> $g_CFILE elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*int *) || "$CHECK" = +(*NUMBER *) ]] then echo "${1} = __b2c__intarray[__b2c__intarray_ptr];" >> $g_CFILE echo "__b2c__intarray_ptr++;" >> $g_CFILE else echo "${1} = (char*)realloc($1, (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" >> $g_CFILE echo "strcpy(${1}, __b2c__stringarray[__b2c__stringarray_ptr]);" >> $g_CFILE echo "__b2c__stringarray_ptr++;" >> $g_CFILE fi fi } #----------------------------------------------------------- function Handle_Endfunction { # Check if return was found if [[ -z $g_FUNCTYPE ]] then echo -e "\nERROR: function '$g_FUNCNAME' was defined without returning a value or string!" exit 1 fi # Now setup function in main program if [[ $g_ORIGFUNCNAME != +(*\(*\)*) ]] then echo "$g_FUNCTYPE $g_ORIGFUNCNAME(void) {" > ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h else echo "$g_FUNCTYPE $g_ORIGFUNCNAME {" > ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h fi # Add function body echo "${g_STRINGARGS}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h cat $g_CFILE >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h echo "__B2C__PROGRAM__EXIT: ;" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h # Make sure the function always returns something if [[ $g_FUNCTYPE = +(*char\**) ]] then echo "return (\"\");}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h else echo "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 DQ FUNC ARG # Check if we have an argument at all if [[ "$1" = "RETURN" ]] then echo -e "\nERROR: empty RETURN at line $g_COUNTER in file $g_CURFILE!" exit 1 fi CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $g_CFILE | grep -E " $1,| $1;|,$1,|,$1;| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v "\/\*noparse\*\/"` # Determine if argument ends with Double Quote DQ="${1: -1}" FUNC="${1:0:3}" # Check type of var, func using string but returning a value? See also PRINT miniparser if [[ ${FUNC} = "INS" || ${FUNC} = "VAL" || ${FUNC} = "LEN" || ${FUNC} = "SEA" || ${FUNC} = "ASC" || "${1}" = +(FILE*) || "${1}" = +(REGEX*) ]] then g_FUNCTYPE="double " ARG="${1}" # Check type of var, string or normal string? elif [[ "${1}" = +(*${g_STRINGSIGN}*) || "$DQ" = "\"" || "$DQ" = "\"" || ${g_FUNCNAME} = +(*${g_STRINGSIGN}*) ]] then g_FUNCTYPE="char* " echo "__b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= $g_MAX_RBUFFERS) __b2c__rbuffer_ptr=0; if($1 != NULL)" >> $g_CFILE echo " {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen($1)+1)*sizeof(char));" >> $g_CFILE echo "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], $1);}" >> $g_CFILE echo "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], 2*sizeof(char));" >> $g_CFILE echo "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], \"\");}" >> $g_CFILE ARG="__b2c__rbuffer[__b2c__rbuffer_ptr]" # Check if float elif [[ "$1" = +(*.*) ]] then g_FUNCTYPE="double " ARG="${1}" # Check if no alpha chars (then integer value) elif [[ "$1" = +([0-9]) ]] then g_FUNCTYPE="long " ARG="${1}" # 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* ";; +(*float\* *) ) g_FUNCTYPE="float* ";; +(*double\* *) ) g_FUNCTYPE="double* ";; +(*char\* *) ) g_FUNCTYPE="char* ";; +(*long\* *) ) g_FUNCTYPE="long* ";; +(*void\* *) ) g_FUNCTYPE="void* ";; +(*int *) ) g_FUNCTYPE="int ";; +(*float *) ) g_FUNCTYPE="float ";; +(*double *) ) g_FUNCTYPE="double ";; +(*char *) ) g_FUNCTYPE="char ";; +(*long *) ) g_FUNCTYPE="long ";; +(*void *) ) g_FUNCTYPE="void ";; esac ARG="${1}" # Not declared, assume integer variable else g_FUNCTYPE="long " ARG="${1}" fi # Free strings variables if there are any for STR in $g_LOCALSTRINGS do echo "if($STR != NULL) free($STR);" >> $g_CFILE done echo "${g_STRINGARRAYS}" >> $g_CFILE # The actual return value echo "return (${ARG});" >> $g_CFILE } #----------------------------------------------------------- function Handle_Push { # Local variables local CHECK TARGET # Check if we have an argument at all if [[ "$1" = "PUSH" ]] then echo -e "\nERROR: 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|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $1,| $1;|,$1,|,$1;| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v "\/\*noparse\*\/"` fi # Allocate space for type echo "__b2c__typestack = (int*)realloc(__b2c__typestack, (__b2c__stackptr+1)*sizeof(int));" >> $g_CFILE # Check type of var, string? if [[ "${1}" = +(*${g_STRINGSIGN}*) ]] then echo "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" >> $g_CFILE echo "__b2c__stringstack[__b2c__stackptr] = strdup($1);" >> $g_CFILE echo "__b2c__typestack[__b2c__stackptr] = 1;" >> $g_CFILE # Check if it is a normal string elif [[ "$1" != `echo "$1" | tr -d "\042"` ]] then echo "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" >> $g_CFILE echo "__b2c__stringstack[__b2c__stackptr] = strdup($1);" >> $g_CFILE echo "__b2c__typestack[__b2c__stackptr] = 1;" >> $g_CFILE # Check if float elif [[ "$1" = +(*.*) ]] then echo "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" >> $g_CFILE echo "__b2c__doublestack[__b2c__stackptr] = $1;" >> $g_CFILE echo "__b2c__typestack[__b2c__stackptr] = 2;" >> $g_CFILE # Check if no alpha chars (then integer value) elif [[ "$1" = +(![a-zA-Z]) ]] then echo "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE echo "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE echo "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE # Assume variable, check if declared before elif [[ -n $CHECK ]] then if [[ $CHECK = +(double*) ]] then echo "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" >> $g_CFILE echo "__b2c__doublestack[__b2c__stackptr] = $1;" >> $g_CFILE echo "__b2c__typestack[__b2c__stackptr] = 2;" >> $g_CFILE else echo "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE echo "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE echo "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE fi # Not declared, assume integer variable else echo "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE echo "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE echo "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE fi # Increase stackpointer echo "__b2c__stackptr++;" >> $g_CFILE } #----------------------------------------------------------- function Handle_Pull { local CHECK TARGET STR # Check if we have an argument at all if [[ "$1" = "PULL" ]] then echo -e "\nERROR: empty PULL at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Argument must be a variable if [[ "$1" = +(![a-zA-Z]) ]] then echo -e "\nERROR: 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 # Decrease stackpointer again echo "__b2c__stackptr--;" >> $g_CFILE echo "if(__b2c__stackptr < 0) __b2c__stackptr=0;" >> $g_CFILE # Get the last value from stack if [[ "${1}" = +(*${g_STRINGSIGN}) ]] then STR=${1%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` if [[ -z $CHECK ]] then echo "char *$1 = NULL;" >> $g_HFILE fi echo "if(__b2c__typestack[__b2c__stackptr] == 1) {" >> $g_CFILE echo "$1 = (char*)realloc($1, (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" >> $g_CFILE echo "strcpy($1, __b2c__stringstack[__b2c__stackptr]); free(__b2c__stringstack[__b2c__stackptr]);}" >> $g_CFILE else # Variable may not be array, these should be defined with DECLARE if [[ "$1" != +(*\[*\]*) && "$VAR" != +(*.*) ]] then # Not declared? Assume long CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $1,| $1;|,$1,|,$1;| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v "\/\*noparse\*\/"` if [[ -z $CHECK ]] then echo "long $1;" >> $g_HFILE CHECK="long " fi else # See how var was declared CHECK=`grep -E "DIR |FILE |int |long |float |double |char |void |STRING |NUMBER |FLOATING " $TARGET | grep -E " ${1%%\[*}" | grep -v "\/\*noparse\*\/"` fi # Make sure internal var is copied to var of program if [[ "$CHECK" = +(*double *) || "$CHECK" = +(*float *) || "$CHECK" = +(*FLOATING *) ]] then echo "if(__b2c__typestack[__b2c__stackptr] == 2) $1=__b2c__doublestack[__b2c__stackptr];" >> $g_CFILE elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*int *) || "$CHECK" = +(*NUMBER *) ]] then echo "if(__b2c__typestack[__b2c__stackptr] == 3) $1=__b2c__longstack[__b2c__stackptr];" >> $g_CFILE else echo "if(__b2c__typestack[__b2c__stackptr] == 1) {" >> $g_CFILE echo "$1 = (char*)realloc($1, (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" >> $g_CFILE echo "strcpy($1, __b2c__stringstack[__b2c__stackptr]); free(__b2c__stringstack[__b2c__stackptr]);}" >> $g_CFILE fi fi } #----------------------------------------------------------- function Handle_SubFunc { local ARGS TOKEN LEN CHAR # Check argument if [[ "${1}" = "SUB" ]] then echo -e "\nERROR: empty SUB/FUNCTION at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if we are in a sub already if [[ -n $g_FUNCNAME ]] then echo -e "\nERROR: 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=`echo ${1%%\(*}"("` # Start miniparser to duplicate string arguments, convert spaces ARGS=`echo "${1##*\(}" | tr " " "\001"` TOKEN= LEN=${#ARGS} # Get the characters until [[ $LEN -eq 0 ]] do CHAR="${ARGS:0:1}" if [[ $CHAR = "," ]] then if [[ ${TOKEN} = +(*STRING*) || ${TOKEN} = +(*char\**) ]] then g_ORIGFUNCNAME="$g_ORIGFUNCNAME STRING __b2c_${TOKEN##* }," g_STRINGARGS="$g_STRINGARGS char* ${TOKEN##* } = strdup(__b2c_${TOKEN##* });" g_LOCALSTRINGS="$g_LOCALSTRINGS ${TOKEN##* }" else g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN}," fi TOKEN= CHAR= fi # Convert back to space if [[ "${CHAR}" = "${g_PARSEVAR}" ]] then TOKEN="${TOKEN} " else TOKEN="${TOKEN}${CHAR}" fi let LEN=${#ARGS}-1 ARGS="${ARGS: -$LEN}" done TOKEN=${TOKEN%%\)*} if [[ ${TOKEN} = +(*STRING*) || ${TOKEN} = +(*char\**) ]] then g_ORIGFUNCNAME="$g_ORIGFUNCNAME STRING __b2c_${TOKEN##* })" g_STRINGARGS="$g_STRINGARGS char* ${TOKEN##* } = strdup(__b2c_${TOKEN##* });" g_LOCALSTRINGS="$g_LOCALSTRINGS ${TOKEN##* }" elif [[ ${TOKEN} != ${1} ]] then g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN})" else g_ORIGFUNCNAME="$g_ORIGFUNCNAME void)" fi # Get original function name if [[ "$g_ORIGFUNCNAME" = +(* \(*\)*) ]] then g_FUNCNAME=`echo ${g_ORIGFUNCNAME%% *}` elif [[ "$g_ORIGFUNCNAME" = +(*\(*\)*) ]] then g_FUNCNAME=`echo ${g_ORIGFUNCNAME%%\(*}` else g_FUNCNAME=`echo $g_ORIGFUNCNAME` fi # Make symbol known to parser g_IMPORTED="$g_FUNCNAME $g_IMPORTED" # Switch to header file g_COPY_CFILE=$g_CFILE g_CFILE=${g_CFILE%.*}.$g_FUNCNAME.tmp # Save CATCH routine g_ORIGCATCHGOTO="$g_CATCHGOTO" g_CATCHGOTO="__B2C__PROGRAM__EXIT" touch $g_CFILE } #----------------------------------------------------------- function Handle_Endsub { typeset STR # Get original function name if [[ "$g_ORIGFUNCNAME" = +(* \(*\)*) ]] then echo "void ${g_ORIGFUNCNAME} {" > ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h elif [[ "$g_ORIGFUNCNAME" = +(*\(*\)*) ]] then echo "void ${g_ORIGFUNCNAME} {" > ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h else echo "void ${g_FUNCNAME}(void) {" > ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h fi # Finalize sub echo "${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 for STR in $g_LOCALSTRINGS do echo "if($STR != NULL) free(${STR});" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h done echo "${g_STRINGARRAYS}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h echo "__B2C__PROGRAM__EXIT: ;" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h echo "}" >> ${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 { local SYM # Check if we have an argument at all if [[ "$1" = "DEF" ]] then echo -e "\nERROR: empty DEF FN at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Translate to C macro SYM=${1#* } echo "#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 echo -e "\nERROR: empty CONST at line $g_COUNTER in file $g_CURFILE!" exit 1 fi echo "#define ${1%%=*} (${1#*=})" >> $g_HFILE } #----------------------------------------------------------- function Handle_Seek { local FILE OFFSET WHENCE # Check if we have an argument at all if [[ "$1" = "SEEK" ]] then echo -e "\nERROR: empty SEEK at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if TO is available if [[ "$1" != +(* OFFSET *) ]] then echo -e "\nERROR: Missing OFFSET in SEEK statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces FILE=`echo ${1%% OFFSET *}`; # Get filedescriptor OFFSET=`echo ${1##* OFFSET }` WHENCE= # Check if WHENCE is available if [[ "$1" = +(* WHENCE *) ]] then WHENCE=${OFFSET##* WHENCE } OFFSET=${OFFSET%% WHENCE *} fi # Convert to C function case $WHENCE in +(START) ) echo "fseek($FILE, $OFFSET, SEEK_SET);" >> $g_CFILE;; +(CURRENT) ) echo "fseek($FILE, $OFFSET, SEEK_CUR);" >> $g_CFILE;; +(END) ) echo "fseek($FILE, $OFFSET, SEEK_END);" >> $g_CFILE;; *) echo "fseek($FILE, $OFFSET, SEEK_SET);" >> $g_CFILE;; esac } #----------------------------------------------------------- function Handle_Copy { local FROM TO # Check if we have an argument at all if [[ "$1" = "COPY" ]] then echo -e "\nERROR: empty COPY at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then echo -e "\nERROR: Missing TO in COPY statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the filename and copyname FROM=`echo ${1%% TO *}` TO=`echo ${1##* TO }` #translate to C function echo "__b2c__inFile = fopen($FROM, \"r\"); __b2c__outFile = fopen($TO, \"w\"); __b2c__Byte = 0;" >> $g_CFILE echo "if (__b2c__inFile != NULL && __b2c__outFile != NULL){while(__b2c__Byte!=EOF){" >> $g_CFILE echo "__b2c__Byte=fgetc(__b2c__inFile); if(__b2c__Byte!=EOF){" >> $g_CFILE echo "fputc(__b2c__Byte,__b2c__outFile); }}" >> $g_CFILE echo "fclose(__b2c__inFile); fclose(__b2c__outFile);}" >> $g_CFILE echo "else {if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Rename { local FROM TO # Check if we have an argument at all if [[ "$1" = "RENAME" ]] then echo -e "\nERROR: empty RENAME at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then echo -e "\nERROR: Missing TO in RENAME statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the filename and copyname FROM=`echo ${1%% TO *}` TO=`echo ${1##* TO }` # Translate to C function echo "if(rename($FROM, $TO) < 0) {if(!__b2c__trap){ERROR = 9; if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Color { local TO FROM # Check if we have an argument at all if [[ "$1" = "COLOR" ]] then echo -e "\nERROR: empty COLOR at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if we need to reset if [[ "$1" = +(*RESET*) ]] then echo "printf(\"\033[0m\");" >> $g_CFILE elif [[ "$1" = +(*INTENSE*) ]] then echo "printf(\"\033[1m\");" >> $g_CFILE elif [[ "$1" = +(*INVERSE*) ]] then echo "printf(\"\033[7m\");" >> $g_CFILE elif [[ "$1" = +(*NORMAL*) ]] then echo "printf(\"\033[22m\");" >> $g_CFILE # Check if TO is available elif [[ "$1" != +(* TO *) ]] then echo -e "\nERROR: Missing TO in COLOR statement at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Get the target and colorname FROM=`echo ${1%% TO *}` TO=`echo ${1##* TO }` # Now select color if [[ $FROM = +(*FG*) ]] then case $TO in "BLACK") echo "printf(\"\033[30m\");" >> $g_CFILE;; "RED") echo "printf(\"\033[31m\");" >> $g_CFILE;; "GREEN") echo "printf(\"\033[32m\");" >> $g_CFILE;; "YELLOW") echo "printf(\"\033[33m\");" >> $g_CFILE;; "BLUE") echo "printf(\"\033[34m\");" >> $g_CFILE;; "MAGENTA") echo "printf(\"\033[35m\");" >> $g_CFILE;; "CYAN") echo "printf(\"\033[36m\");" >> $g_CFILE;; "WHITE") echo "printf(\"\033[37m\");" >> $g_CFILE;; esac elif [[ $FROM = +(*BG*) ]] then case $TO in "BLACK") echo "printf(\"\033[40m\");" >> $g_CFILE;; "RED") echo "printf(\"\033[41m\");" >> $g_CFILE;; "GREEN") echo "printf(\"\033[42m\");" >> $g_CFILE;; "YELLOW") echo "printf(\"\033[43m\");" >> $g_CFILE;; "BLUE") echo "printf(\"\033[44m\");" >> $g_CFILE;; "MAGENTA") echo "printf(\"\033[45m\");" >> $g_CFILE;; "CYAN") echo "printf(\"\033[46m\");" >> $g_CFILE;; "WHITE") echo "printf(\"\033[47m\");" >> $g_CFILE;; esac fi fi } #----------------------------------------------------------- function Handle_Gotoxy { local X Y # Check if we have an argument at all if [[ "$1" = "GOTOXY" ]] then echo -e "\nERROR: empty GOTOXY at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the target and colorname if [[ "$1" = +(*,*) ]] then X=`echo ${1%%,*}` Y=`echo ${1##*,}` else echo -e "\nERROR: missing coordinate in GOTOXY at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Translate to C echo "printf(\"\033[${Y};${X}H\");" >> $g_CFILE } #----------------------------------------------------------- function Handle_Split { local SOURCE REST BY TO SIZE TARGET CHECK # Check if we have an argument at all if [[ "$1" = "SPLIT" ]] then echo -e "\nERROR: empty SPLIT at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if BY is available if [[ "$1" != +(* BY *) ]] then echo -e "\nERROR: 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 echo -e "\nERROR: Missing TO in SPLIT statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if SIZE is available if [[ "$1" != +(* SIZE *) ]] then echo -e "\nERROR: Missing SIZE in SPLIT statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the source string SOURCE=`echo ${1%% BY *}` REST=`echo ${1##* BY }` BY=`echo ${REST%% TO *}` REST=`echo ${REST##* TO }` TO=`echo ${REST%% SIZE *}` SIZE=`echo ${REST##* SIZE }` # 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" != +(*.*) ]] then # Declare variable if not done yet, assuming long CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $SIZE,| $SIZE;|,$SIZE,|,$SIZE;| ${SIZE%%\[*}\[|,${SIZE%%\[*}\[" | grep -v "\/\*noparse\*\/"` if [[ -z $CHECK ]] then echo "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 echo "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 echo "if($TO != NULL) {for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr<=__b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr]!=NULL)" >> $g_CFILE echo "{free($TO[__b2c__ctr]);} free($TO); $TO = NULL;} __b2c__split__$TO = $g_OPTION_BASE;" >> $g_CFILE # Run the SPLIT code echo "if ($SOURCE != NULL && strlen($SOURCE) > 0 && $BY != NULL && strlen($BY) > 0) {__b2c__split_tmp = strdup($SOURCE); __b2c__split_ptr = __b2c__split_tmp; while((__b2c__split = strstr(__b2c__split_tmp, $BY)) != NULL)" >> $g_CFILE echo "{if(__b2c__split-__b2c__split_tmp >= 0) {$TO = (char **)realloc($TO, (__b2c__split__$TO + 1) * sizeof(char*)); if(__b2c__split-__b2c__split_tmp == 0) $TO[__b2c__split__$TO++] = strdup(\"\"); else $TO[__b2c__split__$TO++] = __b2c__strndup(__b2c__split_tmp, __b2c__split-__b2c__split_tmp);}" >> $g_CFILE echo "__b2c__split_tmp = __b2c__split + strlen($BY);} if(strlen(__b2c__split_tmp) >= 0) {$TO = (char **)realloc($TO, (__b2c__split__$TO + 1) * sizeof(char*)); if(strlen(__b2c__split_tmp) == 0) $TO[__b2c__split__$TO++] = strdup(\"\");" >> $g_CFILE echo "else $TO[__b2c__split__$TO++] = strdup(__b2c__split_tmp);} free(__b2c__split_ptr);} $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_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]);} free($TO);}" fi } #----------------------------------------------------------- function Handle_Sort { local STR CHECK DIM TARGET TYPE VAR DOWN # Check if we have an argument at all if [[ "$1" = "SORT" ]] then print "\nERROR: 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 argument if [[ ${1} = +(*DOWN*) ]] then VAR=${1%% DOWN} DOWN="_down" else VAR=${1} DOWN= fi # Declared before? if [[ "${VAR}" = +(*${g_STRINGSIGN}) ]] then STR=${VAR%${g_STRINGSIGN}*} CHECK=`grep -E "char \*${STR}${g_STRINGSIGN}\[" ${TARGET}` else CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " ${VAR}" | grep -v "\/\*noparse\*\/"` fi # Verify if the array was declared at SPLIT if [[ -z ${CHECK} ]] then CHECK=`grep -E "__b2c__split__${STR}${g_STRINGSIGN}" $TARGET` if [[ -z ${CHECK} ]] then print "\nERROR: argument to SORT not an array at line $g_COUNTER in file $g_CURFILE!" exit 1 else DIM="__b2c__split__${VAR}+1" fi else DIM=${CHECK##*\[}; DIM=${DIM%%\]*} fi # Check if we have a string if [[ "${VAR}" = +(*${g_STRINGSIGN}) ]] then echo "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 echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-$g_OPTION_BASE, sizeof(double), __b2c__sortnrd$DOWN);" >> $g_CFILE elif [[ $TYPE = +(*float*) ]] then echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-$g_OPTION_BASE, sizeof(float), __b2c__sortnrf$DOWN);" >> $g_CFILE elif [[ $TYPE = +(*long*) || $TYPE = +(*NUMBER*) ]] then echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-$g_OPTION_BASE, sizeof(long), __b2c__sortnrl$DOWN);" >> $g_CFILE else echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-$g_OPTION_BASE, sizeof(int), __b2c__sortnri$DOWN);" >> $g_CFILE 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 { local FOUND SYM INC COPY_COUNTER COPY_CURFILE STATEMENT local LEN SEQ TOTAL EXP LINE TOKEN LEN DATA CHAR ESCAPED IN_STRING # Replace STRING symbol if [[ ${1} = +(*\$*) ]] then # Start miniparser, convert spaces DATA=`echo "${1}" | tr " " "\001"` LEN=${#DATA} until [[ $LEN -eq 0 ]] do CHAR="${DATA:0:1}" case $CHAR in "$") if [[ $IN_STRING -eq 0 || ${1} = +(*IMPORT*FROM*TYPE*) ]] then TOKEN="${TOKEN}${g_STRINGSIGN}" unset CHAR ESCAPED=0 fi;; "\\") if [[ $ESCAPED -eq 0 ]] then ESCAPED=1 else ESCAPED=0 fi;; "\"") if [[ $ESCAPED -eq 0 ]] then if [[ $IN_STRING -eq 0 ]] then IN_STRING=1 else IN_STRING=0 fi fi ESCAPED=0;; *) ESCAPED=0;; esac # Convert back to space if [[ "${CHAR}" = "${g_PARSEVAR}" ]] then TOKEN="${TOKEN} " else TOKEN="${TOKEN}${CHAR}" fi let LEN=${#DATA}-1 DATA="${DATA: -$LEN}" done else TOKEN="${1}" fi # Get statement without spaces STATEMENT=`echo "${TOKEN%% *}"` # Check if enclosed IF/ELIF/ELSE needs to be closed if [[ $g_IF_PARSE -eq 1 ]] then if [[ "$STATEMENT" != +(ELIF*) && "$STATEMENT" != +(ELSE*) ]] then echo "}" >> $g_CFILE g_IF_PARSE=0 fi fi # In TRACE MODE show linenr and code if [[ $g_TRACE -eq 1 && ${TOKEN} != +(*FUNCTION*) && ${TOKEN} != +(*SUB*) ]] then echo "if(__b2c__getch() == 27) exit(EXIT_SUCCESS); /*noparse*/" >> $g_CFILE LINE=`echo "${TOKEN}" | tr "\042" "\047"` echo "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 [[ "$STATEMENT" = "END" || "$STATEMENT" = "ENDUSEC" ]] then let g_USE_C=0 else echo "${TOKEN}" >> $g_CFILE fi else case "$STATEMENT" in "USEC") let g_USE_C=1;; "PRINT") Handle_Print "${TOKEN#* }";; "INPUT") Handle_Input "${TOKEN#* }";; "FOR") Handle_For "${TOKEN#* }";; "NEXT") echo "}" >> $g_CFILE;; "IF") g_IF_PARSE=0 # Check if THEN is available if [[ "$TOKEN" != +(* THEN*) ]] then echo -e "\nERROR: Missing THEN in IF statement at line $g_COUNTER in file $g_CURFILE!" exit 1 else SYM="${TOKEN#* }" # Translate function to C function echo "if(${SYM% THEN*}){" >> $g_CFILE if [[ ${SYM##* THEN } != +(*THEN*) ]] then Parse_Line "${SYM##* THEN }" g_IF_PARSE=1 fi fi;; "ELIF") g_IF_PARSE=0 # Check if THEN is available if [[ "$TOKEN" != +(* THEN*) ]] then echo -e "\nERROR: Missing THEN in ELIF statement at line $g_COUNTER in file $g_CURFILE!" exit 1 else SYM="${TOKEN#* }" # Translate function to C function echo "} else if(${SYM% THEN*}){" >> $g_CFILE if [[ ${SYM##* THEN } != +(*THEN*) ]] then Parse_Line "${SYM##* THEN }" g_IF_PARSE=1 fi fi;; "ELSE") g_IF_PARSE=0 echo "} else {" >> $g_CFILE if [[ ${TOKEN##*ELSE } != +(*ELSE*) ]] then Parse_Line "${TOKEN##*ELSE }" g_IF_PARSE=1 fi;; "ENDIF") echo "}" >> $g_CFILE;; "WHILE") Handle_While "${TOKEN#* }";; "WEND") echo "}" >> $g_CFILE;; "BREAK") echo "break;" >> $g_CFILE;; "REPEAT") echo "do{" >> $g_CFILE;; "UNTIL") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty UNTIL at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Convert to legal C code echo "} while(!(${TOKEN#* }));" >> $g_CFILE fi;; "LET") Handle_Let "${TOKEN#* }";; +(REM*) ) ;; +(\'*) ) ;; "SYSTEM") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty SYSTEM at line $g_COUNTER in file $g_CURFILE!" exit 1 else echo "SYSTEM (${TOKEN#* });" >> $g_CFILE fi;; "SLEEP") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty SLEEP at line $g_COUNTER in file $g_CURFILE!" exit 1 else echo "usleep(${TOKEN#* }*1000);" >> $g_CFILE fi;; "OPEN") Handle_Open "${TOKEN#* }";; "CLOSE") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty CLOSE at line $g_COUNTER in file $g_CURFILE!" exit 1 else if [[ "$TOKEN" = +(* FILE *) ]] then echo "fclose(${TOKEN##* });" >> $g_CFILE elif [[ "$TOKEN" = +(* DIRECTORY *) ]] then echo "closedir(${TOKEN##* });" >> $g_CFILE elif [[ "$TOKEN" = +(* MEMORY *) ]] then echo "${TOKEN##* } = NULL;" >> $g_CFILE elif [[ "$TOKEN" = +(* NETWORK *) || "$TOKEN" = +(* SERVER *) ]] then echo "close(${TOKEN##* });" >> $g_CFILE else echo -e "\nERROR: erronuous CLOSE argument at line $g_COUNTER in file $g_CURFILE!" exit 1 fi fi;; "REWIND") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty REWIND at line $g_COUNTER in file $g_CURFILE!" exit 1 else echo "rewind(${TOKEN#* });" >> $g_CFILE fi;; "MEMREWIND") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty MEMREWIND at line $g_COUNTER in file $g_CURFILE!" exit 1 else echo "${TOKEN#* } = (char*)__b2c_mem_${TOKEN#* };" >> $g_CFILE fi;; "SEEK") Handle_Seek "${TOKEN#* }";; "READLN") Handle_Readln "${TOKEN#* }";; "WRITELN") Handle_Writeln "${TOKEN#* }";; "GETBYTE") Handle_Getbyte "${TOKEN#* }";; "PUTBYTE") Handle_Putbyte "${TOKEN#* }";; "GETFILE") Handle_Getfile "${TOKEN#* }";; "GETLINE") Handle_Getline "${TOKEN#* }";; "PUTLINE") Handle_Putline "${TOKEN#* }";; "END") if [[ "${TOKEN#* }" = +(*IF*) ]] then echo "}" >> $g_CFILE elif [[ "${TOKEN#* }" = +(*RECORD*) ]] then if [[ -n $g_FUNCNAME ]] then echo "};" >> $g_CFILE echo "struct $g_RECORDNAME $g_RECORDVAR = { } ;" >> $g_CFILE else echo "};" >> $g_HFILE echo "struct $g_RECORDNAME $g_RECORDVAR = { } ;" >> $g_HFILE fi g_RECORDNAME= g_RECORDVAR= # Restore function name if GLOBAL was used if [[ -n $g_RECORDCACHE ]] then g_FUNCNAME=$g_RECORDCACHE g_RECORDCACHE= fi elif [[ "${TOKEN#* }" = +(*FUNCTION*) ]] then Handle_Endfunction elif [[ "${TOKEN#* }" = +(*SUB*) ]] then Handle_Endsub elif [[ "${TOKEN#* }" = +(*WITH*) ]] then g_WITHVAR= elif [[ "${TOKEN#* }" = +(*SELECT*) ]] then echo "}" >> $g_CFILE g_SELECTVAR= g_IN_CASE= elif [[ "${TOKEN#* }" != "END" ]] then echo "exit(${TOKEN#* });" >> $g_CFILE else echo "exit(EXIT_SUCCESS);" >> $g_CFILE fi;; "SUB") Handle_SubFunc "${TOKEN#* }";; "ENDSUB") Handle_Endsub;; "ENDWITH") g_WITHVAR=;; "ENDSELECT") echo "}" >> $g_CFILE g_SELECTVAR= g_IN_CASE=;; "CALL") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty CALL at line $g_COUNTER in file $g_CURFILE!" exit 1 else SYM=`echo "${TOKEN#* }"` if [[ "$SYM" = +(* TO *) ]] then echo "${SYM##*TO } = " >> $g_CFILE if [[ "${SYM%% TO*}" = +(*\(*\)*) ]] then echo "${SYM%% TO*};" >> $g_CFILE EXP="${SYM%% TO*}" else echo "${SYM%% TO*}();" >> $g_CFILE EXP="${SYM%% TO*}()" fi if [[ ${g_INCLUDE_FILES} != +(*${g_CURFILE%.*}.${EXP%%\(*}.h*) ]] then g_INCLUDE_FILES="${g_CURFILE%.*}.${EXP%%\(*}.h ${g_INCLUDE_FILES}" fi else if [[ "$SYM" = +(*\(*\)*) ]] then echo "$SYM;" >> $g_CFILE EXP="${SYM}" else echo "$SYM();" >> $g_CFILE EXP="${SYM}()" fi if [[ ${g_INCLUDE_FILES} != +(*${g_CURFILE%.*}.${EXP%%\(*}.h*) ]] then g_INCLUDE_FILES="${g_CURFILE%.*}.${EXP%%\(*}.h ${g_INCLUDE_FILES}" fi fi fi;; "FUNCTION") Handle_SubFunc "${TOKEN#* }";; "ENDFUNCTION") Handle_Endfunction;; "RETURN") Handle_Return "${TOKEN#* }";; "IMPORT") Handle_Import "${TOKEN#* }";; "DECLARE") Handle_Declare "${TOKEN#* }";; "GLOBAL") Handle_Declare "${TOKEN#* }";; "LOCAL") Handle_Local "${TOKEN#* }";; "DATA") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty DATA at line $g_COUNTER in file $g_CURFILE!" exit 1 else if [[ "${TOKEN#* }" != `echo "${TOKEN#* }" | tr -d "\042"` ]] then echo "${TOKEN#* }, " >> $STRINGARRAYFILE else # Check if float if [[ "${TOKEN#* }" = +(*.*) ]] then echo "${TOKEN#* }, " >> $FLOATARRAYFILE else echo "${TOKEN#* }, " >> $INTARRAYFILE fi fi fi;; "RESTORE") echo "if(__b2c__intarray_ptr > 0) __b2c__intarray_ptr = 0;" >> $g_CFILE echo "if(__b2c__floatarray_ptr > 0) __b2c__floatarray_ptr = 0;" >> $g_CFILE echo "if(__b2c__stringarray_ptr > 0) __b2c__stringarray_ptr = 0;" >> $g_CFILE;; "READ") Handle_Read "${TOKEN#* }";; "PUSH") Handle_Push "${TOKEN#* }";; "PULL") Handle_Pull "${TOKEN#* }";; "SEED") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty SEED at line $g_COUNTER in file $g_CURFILE!" exit 1 else echo "srandom((unsigned int)${TOKEN#* });" >> $g_CFILE fi;; "DEF") Handle_Deffn "${TOKEN#* }";; "CONST") Handle_Const "${TOKEN#* }";; "INCLUDE") # Get rid of doublequotes if they are there INC=`echo ${TOKEN#* } | tr -d "\042"` # Check argument if [[ ! -f $INC || "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: missing file for INCLUDE at line $g_COUNTER in file $g_CURFILE!" exit 1 else # 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=${INC##*/} while read -r LINE do echo -e -n "\rStarting conversion... $g_COUNTER" # Line is not empty? if [[ -n "$LINE" ]] then if [[ "$LINE" = +(* \\) ]] then let LEN="${#LINE}"-1 SEQ="${LINE:0:$LEN}" TOTAL=$TOTAL$SEQ else Parse_Line "$TOTAL$LINE" TOTAL= fi fi ((g_COUNTER+=1)) done < $INC # Restore original counter g_COUNTER=$COPY_COUNTER # Restore original file g_CURFILE=$COPY_CURFILE fi;; "POKE") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty POKE at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Resolve this with C macro because of casting to (char) echo "POKE(${TOKEN#* });" >> $g_CFILE fi;; "RESIZE") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty RESIZE at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Resolve this with C macro because of casting to (char) SYM=${TOKEN#* } echo "${SYM%%,*}=(long)RESIZE(${SYM});" >> $g_CFILE fi;; "COPY") Handle_Copy "${TOKEN#* }";; "DELETE") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty DELETE at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C function if [[ "${TOKEN#* }" = +(*FILE*) ]] then echo "if (unlink(${TOKEN#*FILE })==-1){if(!__b2c__trap){ERROR = 7;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE elif [[ "${TOKEN#* }" = +(*DIRECTORY*) ]] then echo "if (rmdir(${TOKEN#*DIRECTORY }) == -1){if(!__b2c__trap){ERROR = 20;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE else echo "\nERROR: erronuous argument for DELETE at line $g_COUNTER in file $g_CURFILE!" exit 1 fi fi;; "RENAME") Handle_Rename "${TOKEN#* }";; "MAKEDIR") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty MAKEDIR at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C function echo "if (__b2c__makedir(${TOKEN#* }) != 0){if(!__b2c__trap){ERROR = 21;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE fi;; "CHANGEDIR") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty CHANGEDIR at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C function echo "if (chdir(${TOKEN#* }) == -1){if(!__b2c__trap) {ERROR = 22;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE fi;; "FREE") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty FREE at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C function echo "if(!__b2c__trap){__b2c__memory__check((char *)${TOKEN#* });" >> $g_CFILE echo "if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} } free((void*)${TOKEN#* });" >> $g_CFILE fi;; "GOTO") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty GOTO at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C label echo "goto ${TOKEN#* };" >> $g_CFILE fi;; "LABEL") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty LABEL at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C label echo "${TOKEN#* }:" >> $g_CFILE echo ";" >> $g_CFILE fi;; "TRAP") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty TRAP at line $g_COUNTER in file $g_CURFILE!" exit 1 else if [[ "${TOKEN#* }" = "SYSTEM" ]] then echo "/* Error catching is enabled */" >> $g_CFILE echo "__b2c__trap = 1;" >> $g_CFILE echo "signal(SIGILL, __b2c__catch_signal);" >> $g_CFILE echo "signal(SIGABRT, __b2c__catch_signal);" >> $g_CFILE echo "signal(SIGFPE, __b2c__catch_signal);" >> $g_CFILE echo "signal(SIGSEGV, __b2c__catch_signal);" >> $g_CFILE elif [[ "${TOKEN#* }" = "LOCAL" ]] then echo "/* Error catching is disabled */" >> $g_CFILE echo "__b2c__trap = 0;" >> $g_CFILE echo "signal(SIGILL, SIG_DFL);" >> $g_CFILE echo "signal(SIGABRT, SIG_DFL);" >> $g_CFILE echo "signal(SIGFPE, SIG_DFL);" >> $g_CFILE echo "signal(SIGSEGV, SIG_DFL);" >> $g_CFILE else echo -e "\nERROR: invalid argument for TRAP at line $g_COUNTER in file $g_CURFILE!" exit 1 fi fi;; "CATCH") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty CATCH at line $g_COUNTER in file $g_CURFILE!" exit 1 elif [[ "${TOKEN#* }" = +(*GOTO*) ]] then echo "__b2c__catch_set = 1;" >> $g_CFILE g_CATCHGOTO="${TOKEN##* GOTO }" elif [[ "${TOKEN#* }" = +(*RESET*) ]] then echo "__b2c__catch_set = 0;" >> $g_CFILE else echo -e "\nERROR: CATCH without GOTO or RESET at line $g_COUNTER in file $g_CURFILE!" exit 1 fi;; "RESUME") echo "longjmp(__b2c__jump, 1);" >> $g_CFILE;; "CLEAR") echo "printf(\"\033[2J\"); printf(\"\033[0;0f\");" >> $g_CFILE;; "COLOR") Handle_Color "${TOKEN#* }";; "GOTOXY") Handle_Gotoxy "${TOKEN#* }";; "RECEIVE") Handle_Receive "${TOKEN#* }";; "SEND") Handle_Send "${TOKEN#* }";; "RECORD") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty RECORD at line $g_COUNTER in file $g_CURFILE!" exit 1 elif [[ -n $g_RECORDNAME ]] then echo -e "\nERROR: 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}" echo "struct $g_RECORDNAME{" >> $g_CFILE else g_RECORDNAME="RECORD_${g_COUNTER}" echo "struct $g_RECORDNAME{" >> $g_HFILE fi g_RECORDVAR=${TOKEN#* } fi;; "WITH") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty WITH at line $g_COUNTER in file $g_CURFILE!" exit 1 elif [[ -n $g_RECORDNAME ]] then echo -e "\nERROR: cannot define a WITH within a WITH!" exit 1 else g_WITHVAR=${TOKEN#* } fi;; "SPLIT") Handle_Split "${TOKEN#* }";; "SELECT") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty SELECT at line $g_COUNTER in file $g_CURFILE!" exit 1 elif [[ -n $g_SELECTVAR ]] then echo -e "\nERROR: cannot define a SELECT within a SELECT!" exit 1 else g_SELECTVAR=${TOKEN#* } g_IN_CASE= g_CASE_FALL= fi;; "CASE") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo "\nERROR: empty CASE at line $g_COUNTER in file $g_CURFILE!" exit 1 else if [[ -n $g_IN_CASE ]] then if [[ ${g_SELECTVAR} = +(*${g_STRINGSIGN}*) ]] then # Get expression without ; if [[ -z ${TOKEN##*;} ]] then let LEN="${#TOKEN}"-1; EXP="${TOKEN:0:$LEN}" g_CASE_FALL="|| !strcmp(${g_SELECTVAR}, ${EXP#* }) ${g_CASE_FALL}" else echo "} else if (!strcmp(${g_SELECTVAR}, ${TOKEN#* }) ${g_CASE_FALL}){" >> $g_CFILE fi else # Get expression without ; if [[ -z ${TOKEN##*;} ]] then let LEN="${#TOKEN}"-1; EXP="${TOKEN:0:$LEN}" g_CASE_FALL="|| ${g_SELECTVAR} == (${EXP#* }) ${g_CASE_FALL}" else echo "} else if (${g_SELECTVAR} == (${TOKEN#* }) ${g_CASE_FALL}){" >> $g_CFILE fi fi else if [[ ${g_SELECTVAR} = +(*${g_STRINGSIGN}*) ]] then # Get expression without ; if [[ -z ${TOKEN##*;} ]] then let LEN="${#TOKEN}"-1; EXP="${TOKEN:0:$LEN}" g_CASE_FALL="|| !strcmp(${g_SELECTVAR}, ${EXP#* }) ${g_CASE_FALL}" else echo "if (!strcmp(${g_SELECTVAR}, ${TOKEN#* }) ${g_CASE_FALL}){" >> $g_CFILE g_IN_CASE=1 fi else # Get expression without ; if [[ -z ${TOKEN##*;} ]] then let LEN="${#TOKEN}"-1; EXP="${TOKEN:0:$LEN}" g_CASE_FALL="|| ${g_SELECTVAR} == (${EXP#* }) ${g_CASE_FALL}" else echo "if (${g_SELECTVAR} == (${TOKEN#* }) ${g_CASE_FALL}){" >> $g_CFILE g_IN_CASE=1 fi fi fi fi;; "DEFAULT") if [[ -n $g_IN_CASE ]] then echo "} else {" >> $g_CFILE else echo -e "\nERROR: cannot use DEFAULT without previous CASE at line $g_COUNTER in file $g_CURFILE!" exit 1 fi g_IN_CASE= g_CASE_FALL=;; "SETENVIRON") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty SETENVIRON at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Resolve this with C macro echo "SETENVIRON(${TOKEN#* });" >> $g_CFILE fi;; "SORT") Handle_Sort "${TOKEN#* }";; "STOP") echo "kill(getpid(), SIGSTOP);" >> $g_CFILE ;; "TRACE") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty TRACE at line $g_COUNTER in file $g_CURFILE!" exit 1 else if [[ "${TOKEN#* }" = +(*ON*) ]] then g_TRACE=1 elif [[ "${TOKEN#* }" = +(*OFF*) ]] then g_TRACE=0 fi fi;; "OPTION") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty OPTION at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else if [[ "${TOKEN#* }" = +(*BASE*) ]] then if [[ "${TOKEN##*BASE }" = +([0123456789]) ]] then g_OPTION_BASE=${TOKEN##*BASE } else echo -e "\nERROR: invalid argument to OPTION BASE at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi elif [[ "${TOKEN#* }" = +(*COMPARE*) ]] then echo "__b2c__option_compare = ${TOKEN##*COMPARE };" >> $g_CFILE elif [[ "${TOKEN#* }" = +(*SOCKET*) ]] then if [[ "${TOKEN##*SOCKET }" = +([0123456789]) ]] then g_OPTION_SOCKET=${TOKEN##*SOCKET } else echo -e "\nERROR: invalid argument to OPTION SOCKET at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi else echo -e "\nERROR: argument to OPTION at line $g_COUNTER in file '$g_CURFILE' not recognized!" exit 1 fi fi;; "PROTO") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty PROTO at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else SYM=`echo ${TOKEN#* } | tr -d "\042"` g_IMPORTED="${SYM} $g_IMPORTED" fi;; "INCR") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty INC at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else EXP=${TOKEN#* } if [[ ${EXP} = +(*,*) ]] then echo "${EXP%,*} = ${EXP%,*} + ${EXP#*,};" >> $g_CFILE else echo "${EXP} = ${EXP} + 1;" >> $g_CFILE fi fi;; "DECR") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty DEC at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else EXP=${TOKEN#* } if [[ ${EXP} = +(*,*) ]] then echo "${EXP%,*} = ${EXP%,*} - ${EXP#*,};" >> $g_CFILE else echo "${EXP} = ${EXP} - 1;" >> $g_CFILE fi fi;; "ALARM") # Check argument if [[ "${TOKEN%% *}" = "${TOKEN#* }" ]] then echo -e "\nERROR: empty ALARM at line $g_COUNTER in file '$g_CURFILE'!" exit 1 else EXP=${TOKEN#* } if [[ ${EXP} = +(*,*) ]] then echo "signal(SIGALRM, (void*)${EXP%,*});" >> $g_CFILE echo "alarm(${EXP#*,});" >> $g_CFILE else echo -e "\nERROR: missing argument in ALARM at line $g_COUNTER in file '$g_CURFILE'!" exit 1 fi fi;; *) # Check on imported symbols first FOUND=0 for SYM in $g_IMPORTED do if [[ "$SYM" = ${TOKEN%%\(*} || "$SYM" = ${TOKEN%% *} ]] then FOUND=1 if [[ "$TOKEN" != +(*\(*\)*) ]] then echo "$SYM();" >> $g_CFILE else echo "$SYM(${TOKEN#*\(};" >> $g_CFILE fi fi done # Not an imported symbol? Check if assignment if [[ $FOUND -eq 0 ]] then Handle_Let "$TOKEN" fi;; esac fi } #----------------------------------------------------------- # # Main program # #----------------------------------------------------------- # Default BACON settings let g_MAX_DIGITS=32 # Maximum of internal buffers needed for string processing let g_MAX_BUFFERS=32 # This is the size for static buffers like fgets, read etc. let g_BUFFER_SIZE=512 # Maximum RETURN buffers let g_MAX_RBUFFERS=8 let g_NO_COMPILE=0 let g_TMP_PRESERVE=0 let g_USE_C=0 let g_MAX_BACKLOG=4 let g_CPP=0 g_TEMPDIR=. g_CCNAME=cc g_CCFLAGS= g_INCFILES= g_INCLUDE_FILES= let g_TRACE=0 let g_OPTION_BASE=0 let g_OPTION_SOCKET=5 # Some global declarations g_CURFILE= g_FUNCNAME= g_FUNCTYPE= g_TMP_FILES= g_LOCALSTRINGS= g_STRINGARRAYS= g_STRINGARGS= g_BINEXT= g_RECORDCACHE= # Always create a final label g_CATCHGOTO="__B2C__PROGRAM__EXIT" # Records g_RECORDNAME= g_RECORDVAR= g_WITHVAR= # Get arguments while getopts ":c:d:i:l:s:njfpv" OPT do case $OPT in c) g_CCNAME=$OPTARG;; d) g_TEMPDIR=$OPTARG;; i) g_INCFILES="$g_INCFILES $OPTARG";; l) g_LDFLAGS="$g_LDFLAGS $OPTARG";; s) 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;; v) echo echo "BaCon version $g_VERSION - (c) Peter van Eerten - GPL v3." echo exit 0;; \?|h) echo echo "USAGE: bacon [options] program[.bac]" echo echo "OPTIONS:" echo echo -e " -c \tCompiler to use (default: $g_CCNAME)" echo -e " -i \tAdd include file to C code" echo -e " -s \tPass compiler flags" echo -e " -l \tPass linker flags" echo -e " -d \tTemporary directory (default: $g_TEMPDIR)" echo -e " -f \t\tCreate Shared Object" echo -e " -n \t\tDo not compile, only convert" echo -e " -j \t\tInvoke C Preprocessor" echo -e " -p \t\tPreserve temporary files" echo -e " -v \t\tShow version" echo -e " -h \t\tShow help" echo exit 0;; esac done shift $(($OPTIND-1)) # Check if a filename was entered, if so get it if [[ $# -eq 0 ]] then echo -e "ERROR: no filename? Run with '-h' to see usage." exit 1 elif [[ "$@" != +(*.bac) ]] then SOURCEFILE="$@.bac" else SOURCEFILE="$@" fi # Check if file exists if [[ ! -f $SOURCEFILE ]] then echo -e "ERROR: file not found!" exit 1 fi echo -n "Starting conversion..." # Now create the global filenames where to write to g_CFILE=$g_TEMPDIR/${SOURCEFILE##*/}.c g_HFILE=$g_TEMPDIR/${SOURCEFILE##*/}.h STRINGARRAYFILE=$g_TEMPDIR/${SOURCEFILE##*/}.string.h INTARRAYFILE=$g_TEMPDIR/${SOURCEFILE##*/}.int.h FLOATARRAYFILE=$g_TEMPDIR/${SOURCEFILE##*/}.float.h # Add to total file list g_TMP_FILES="$g_CFILE $g_HFILE $STRINGARRAYFILE $INTARRAYFILE $FLOATARRAYFILE" # Create basic C file echo "/* Created with BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > $g_CFILE echo "#include \"${SOURCEFILE##*/}.h\"" >> $g_CFILE echo "int main(int argc, const char **argv)" >> $g_CFILE echo "{" >> $g_CFILE echo "/* Default is: system traps signals */" >> $g_CFILE echo "signal(SIGILL, __b2c__catch_signal);" >> $g_CFILE echo "signal(SIGABRT, __b2c__catch_signal);" >> $g_CFILE echo "signal(SIGFPE, __b2c__catch_signal);" >> $g_CFILE echo "signal(SIGSEGV, __b2c__catch_signal);" >> $g_CFILE echo "/* Make sure internal string buffers are empty */" >> $g_CFILE echo "for(__b2c__sbuffer_ptr = 0; __b2c__sbuffer_ptr < $g_MAX_BUFFERS; __b2c__sbuffer_ptr++) __b2c__sbuffer[__b2c__sbuffer_ptr] = NULL;" >> $g_CFILE echo "__b2c__sbuffer_ptr = 0;" >> $g_CFILE echo "for(__b2c__rbuffer_ptr=0; __b2c__rbuffer_ptr < $g_MAX_RBUFFERS; __b2c__rbuffer_ptr++) __b2c__rbuffer[__b2c__rbuffer_ptr] = NULL;" >> $g_CFILE echo "__b2c__rbuffer_ptr=0;" >> $g_CFILE # Put arguments into reserved variable ARGUMENT echo "/* Setup the reserved variable 'ARGUMENT' */" >> $g_CFILE echo "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" >> $g_CFILE echo "{__b2c__arglen += strlen(argv[__b2c__counter]) + 1;} __b2c__arglen++;" >> $g_CFILE echo "ARGUMENT${g_STRINGSIGN} = (char*)calloc(__b2c__arglen, sizeof(char)); strcpy(ARGUMENT${g_STRINGSIGN}, \"\");" >> $g_CFILE echo "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" >> $g_CFILE echo "{strcat(ARGUMENT${g_STRINGSIGN}, argv[__b2c__counter]); if(__b2c__counter != argc - 1) strcat(ARGUMENT${g_STRINGSIGN}, \" \");}" >> $g_CFILE echo "/* By default seed random generator */" >> $g_CFILE echo "srandom((unsigned int)time(NULL));" >> $g_CFILE echo "/* Rest of the program */" >> $g_CFILE # Create basic H file, functions are converted using macros echo "/* Created with BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > $g_HFILE echo >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE if [[ `uname` = +(*BSD*) ]] then echo "#include " >> $g_HFILE fi echo "#include " >> $g_HFILE echo "static jmp_buf __b2c__jump;" >> $g_HFILE echo "static int __b2c__trap = 1;" >> $g_HFILE echo "static int __b2c__catch_set = 0;" >> $g_HFILE echo "static int ERROR = 0;" >> $g_HFILE echo "static int __b2c__option_compare = 0;" >> $g_HFILE echo "const char VERSION${g_STRINGSIGN}[] = \"$g_VERSION\";" >> $g_HFILE echo >> $g_HFILE # Add user include files echo "/* User include files */" >> $g_HFILE for i in $g_INCFILES do if [[ "$i" = +(*<*) ]] then echo "#include $i" >> $g_HFILE else echo "#include \"$i\"" >> $g_HFILE fi done echo "/* READ/DATA include files */" >> $g_HFILE echo "int __b2c__stringarray_ptr = 0;" >> $g_HFILE echo "#include \"${SOURCEFILE##*/}.string.h\"" >> $g_HFILE echo "int __b2c__intarray_ptr = 0;" >> $g_HFILE echo "#include \"${SOURCEFILE##*/}.int.h\"" >> $g_HFILE echo "int __b2c__floatarray_ptr = 0;" >> $g_HFILE echo "#include \"${SOURCEFILE##*/}.float.h\"" >> $g_HFILE echo "int __b2c__ctr;" >> $g_HFILE echo >> $g_HFILE echo "/* Math functions */" >> $g_HFILE echo "extern double round(double __b2c__x);" >> $g_HFILE echo "extern long int lrint(double __b2c__x);" >> $g_HFILE echo "#include " >> $g_HFILE echo "#define SQR(__b2c__x) sqrt(__b2c__x)" >> $g_HFILE echo "#define POW(__b2c__x, __b2c__y) pow(__b2c__x, __b2c__y)" >> $g_HFILE echo "#define SIN(__b2c__x) sin(__b2c__x)" >> $g_HFILE echo "#define COS(__b2c__x) cos(__b2c__x)" >> $g_HFILE echo "#define TAN(__b2c__x) tan(__b2c__x)" >> $g_HFILE echo "#define ROUND(__b2c__x) lrint(__b2c__x)" >> $g_HFILE echo "#define INT(__b2c__x) lrint(__b2c__x)" >> $g_HFILE echo "#define MOD(__b2c__x, __b2c__y) ((long)__b2c__x % (long)__b2c__y)" >> $g_HFILE echo "#define EVEN(__b2c__x) ((__b2c__x % 2 == 0) ? 1 : 0)" >> $g_HFILE echo "#define ODD(__b2c__x) ((__b2c__x % 2 != 0) ? 1 : 0)" >> $g_HFILE echo "#define FLOOR(__b2c__x) (long)floor(__b2c__x)" >> $g_HFILE echo "#define ABS(__b2c__x) abs(__b2c__x)" >> $g_HFILE echo "#define RND random()" >> $g_HFILE echo "#define MAXRANDOM RAND_MAX" >> $g_HFILE echo "#define RANDOM(__b2c__x) ((__b2c__x != 0) ? random()/(RAND_MAX/__b2c__x) : 0)" >> $g_HFILE echo >> $g_HFILE echo "/* Other functions */" >> $g_HFILE echo "#define VAL(__b2c__x) ((__b2c__x != NULL) ? atof(__b2c__x) : 0)" >> $g_HFILE echo >> $g_HFILE echo "/* Unix functions */" >> $g_HFILE echo "#include " >> $g_HFILE echo "#define SYSTEM(__b2c__x) ((__b2c__x != NULL) ? system(__b2c__x) : 0)" >> $g_HFILE echo >> $g_HFILE echo "/* String functions */" >> $g_HFILE echo "#include " >> $g_HFILE echo "char *__b2c__strndup(const char *__b2c__s, size_t __b2c__n){size_t __b2c__avail;" >> $g_HFILE echo "char *__b2c__p; if (!__b2c__s) return 0; __b2c__avail = strlen(__b2c__s) + 1;" >> $g_HFILE echo "if (__b2c__avail > __b2c__n + 1) __b2c__avail = __b2c__n + 1; __b2c__p = malloc(__b2c__avail);" >> $g_HFILE echo "memcpy(__b2c__p, __b2c__s, __b2c__avail); __b2c__p[__b2c__avail - 1] = '\0'; return __b2c__p;}" >> $g_HFILE echo "char __b2c__input__buffer[$g_BUFFER_SIZE];" >> $g_HFILE echo "char* __b2c__sbuffer[$g_MAX_BUFFERS];" >> $g_HFILE echo "int __b2c__sbuffer_ptr;" >> $g_HFILE echo "char* __b2c__rbuffer[$g_MAX_RBUFFERS];" >> $g_HFILE echo "int __b2c__rbuffer_ptr;" >> $g_HFILE echo "/* Temporary pointer to perform assignments */" >> $g_HFILE echo "char *__b2c__assign = NULL;" >> $g_HFILE echo "char *__b2c__split = NULL; char *__b2c__split_tmp = NULL; char *__b2c__split_ptr = NULL;" >> $g_HFILE echo "char *ERR${g_STRINGSIGN}(int);" >> $g_HFILE echo "/* Functions for sort */" >> $g_HFILE echo "int __b2c__sortnrd(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE echo "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return -1; else return 1;}" >> $g_HFILE echo "int __b2c__sortnrd_down(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE echo "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return 1; else return -1;}" >> $g_HFILE echo "int __b2c__sortnrf(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE echo "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return -1; else return 1;}" >> $g_HFILE echo "int __b2c__sortnrf_down(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE echo "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return 1; else return -1;}" >> $g_HFILE echo "int __b2c__sortnrl(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE echo "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return -1; else return 1;}" >> $g_HFILE echo "int __b2c__sortnrl_down(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE echo "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return 1; else return -1;}" >> $g_HFILE echo "int __b2c__sortnri(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE echo "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return -1; else return 1;}" >> $g_HFILE echo "int __b2c__sortnri_down(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE echo "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return 1; else return -1;}" >> $g_HFILE echo "int __b2c__sortstr(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE echo "{return strcmp(*(char **) __b2c__a, *(char **) __b2c__b);}" >> $g_HFILE echo "int __b2c__sortstr_down(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE echo "{return strcmp(*(char **) __b2c__b, *(char **) __b2c__a);}" >> $g_HFILE echo "/* Actual functions */" >> $g_HFILE echo "char* __b2c__curdir(void){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE*sizeof(char));" >> $g_HFILE echo "return (getcwd(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE));}" >> $g_HFILE echo "#define CURDIR${g_STRINGSIGN} __b2c__curdir()" >> $g_HFILE echo "char* __b2c__reverse(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__s)+2)*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)+1);" >> $g_HFILE echo "for(__b2c__i=0;__b2c__i> $g_HFILE echo "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define REVERSE${g_STRINGSIGN}(x) ((x != NULL) ? __b2c__reverse(x) : \"null\")" >> $g_HFILE echo "char* __b2c__str(double d){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS);" >> $g_HFILE echo "if(floor(d) == d) snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%ld\", (long)d); else snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%g\", d);" >> $g_HFILE echo "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define STR${g_STRINGSIGN}(x) __b2c__str(x)" >> $g_HFILE echo "char* __b2c__concat(char *__b2c__first, ...){char *__b2c__tmp; va_list __b2c__ap; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "if(__b2c__first != NULL) { __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__first)+1)*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first);}" >> $g_HFILE echo "else {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"\");} va_start(__b2c__ap, __b2c__first);" >> $g_HFILE echo "while((__b2c__tmp = va_arg(__b2c__ap, char *)) != NULL) {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__tmp)+strlen(__b2c__sbuffer[__b2c__sbuffer_ptr])+1)*sizeof(char));" >> $g_HFILE echo "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__tmp);} va_end(__b2c__ap); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define CONCAT${g_STRINGSIGN}(...) __b2c__concat(__VA_ARGS__, (char*)NULL)" >> $g_HFILE echo "char* __b2c__left(char *__b2c__src, long __b2c__n){if(__b2c__src == NULL || __b2c__n > strlen(__b2c__src) || __b2c__n < 0) return(__b2c__src);" >> $g_HFILE echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src, (__b2c__n));" >> $g_HFILE echo "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define LEFT${g_STRINGSIGN}(__b2c__x, __b2c__y) __b2c__left(__b2c__x, __b2c__y)" >> $g_HFILE echo "char* __b2c__right(char *__b2c__src, long __b2c__n){if(__b2c__src == NULL || __b2c__n > strlen(__b2c__src) || __b2c__n < 0) return(__b2c__src);" >> $g_HFILE echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+ strlen(__b2c__src)- __b2c__n);" >> $g_HFILE echo "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define RIGHT${g_STRINGSIGN}(__b2c__x, __b2c__y) __b2c__right(__b2c__x, __b2c__y)" >> $g_HFILE echo "char* __b2c__mid(char *__b2c__src, ...){ va_list __b2c__ap; int __b2c__start, __b2c__end; if(__b2c__src == NULL) return(\"\");" >> $g_HFILE echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); va_start(__b2c__ap, __b2c__src);" >> $g_HFILE echo "__b2c__start = va_arg(__b2c__ap, long); if(__b2c__start < 1) return(__b2c__src); __b2c__end = va_arg(__b2c__ap, long); if((__b2c__end) == -1) __b2c__end = strlen(__b2c__src);" >> $g_HFILE echo "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+(long)(__b2c__start)-1, (__b2c__end)); va_end(__b2c__ap); return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define MID${g_STRINGSIGN}(__b2c__string, ...) __b2c__mid(__b2c__string, __VA_ARGS__, -1)" >> $g_HFILE echo "long __b2c__instr(char *__b2c__first, ...){char *__b2c__tmp; char *__b2c__res; int __b2c__pos; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "va_list __b2c__ap; if(__b2c__first == NULL) return (0); __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" >> $g_HFILE echo "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" >> $g_HFILE echo "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL || strlen(__b2c__tmp) == 0) return (0);__b2c__pos = va_arg(__b2c__ap, int);" >> $g_HFILE echo "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); __b2c__res = strstr(__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos - 1, __b2c__tmp);" >> $g_HFILE echo "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" >> $g_HFILE echo "#define INSTR(...) __b2c__instr(__VA_ARGS__, -1)" >> $g_HFILE echo "long __b2c__instrrev(char *__b2c__first, ...){char *__b2c__tmp; char *__b2c__res = NULL; int __b2c__pos; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "va_list __b2c__ap; if(__b2c__first == NULL) return (0); __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" >> $g_HFILE echo "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" >> $g_HFILE echo "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL || strlen(__b2c__tmp) == 0) return (0);__b2c__pos = va_arg(__b2c__ap, int);" >> $g_HFILE echo "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); while(__b2c__res == NULL && __b2c__pos <= strlen(__b2c__sbuffer[__b2c__sbuffer_ptr])) {" >> $g_HFILE echo "__b2c__res = strstr(__b2c__sbuffer[__b2c__sbuffer_ptr] + strlen(__b2c__sbuffer[__b2c__sbuffer_ptr]) - __b2c__pos, __b2c__tmp); __b2c__pos+=1;}" >> $g_HFILE echo "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" >> $g_HFILE echo "#define INSTRREV(...) __b2c__instrrev(__VA_ARGS__, -1)" >> $g_HFILE echo "char* __b2c__spc(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 32, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define SPC${g_STRINGSIGN}(x) ((x > -1) ? __b2c__spc(x) : \"\")" >> $g_HFILE echo "char* __b2c__tab(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 9, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define TAB${g_STRINGSIGN}(x) ((x > -1) ? __b2c__tab(x) : \"\")" >> $g_HFILE echo "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_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__y, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define FILL${g_STRINGSIGN}(x, y) ((y > -1 && y < 256) ? __b2c__fill(x, y) : \"\")" >> $g_HFILE echo "char* __b2c__chop(char *__b2c__src){char *__b2c__tmp; int __b2c__i; if(strlen(__b2c__src) == 0) return(__b2c__src);" >> $g_HFILE echo "while ((*__b2c__src == 10 || *__b2c__src == 13 || *__b2c__src == 9 || *__b2c__src == 32) && *__b2c__src != '\0') __b2c__src++;" >> $g_HFILE echo "if (*__b2c__src == '\0') return(\"\"); __b2c__tmp = __b2c__src + strlen(__b2c__src) - 1;" >> $g_HFILE echo "while ((*__b2c__tmp == 10 || *__b2c__tmp == 13 || *__b2c__tmp == 9 || *__b2c__tmp == 32) && *__b2c__src != '\0') __b2c__tmp--;" >> $g_HFILE echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE echo "for(__b2c__i = 0; __b2c__i <= __b2c__tmp - __b2c__src; __b2c__i++) __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__src[__b2c__i];" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i] = '\0'; return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define CHOP${g_STRINGSIGN}(x) ((x != NULL) ? __b2c__chop(x) : 0)" >> $g_HFILE echo "char* __b2c__replace(char* __b2c__x, char* __b2c__y, char* __b2c__z){" >> $g_HFILE echo "char *__b2c__tmp, *__b2c__buf, *__b2c__haystack, *__b2c__dup = NULL; __b2c__sbuffer_ptr++;" >> $g_HFILE echo "if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0; __b2c__haystack = strdup(__b2c__x); __b2c__dup = __b2c__haystack;" >> $g_HFILE echo "__b2c__buf = strdup(\"\"); while((__b2c__tmp = strstr(__b2c__haystack, __b2c__y)) != NULL) {*__b2c__tmp = '\0';" >> $g_HFILE echo "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + strlen(__b2c__z) + 1)*sizeof(char));" >> $g_HFILE echo "strcat(__b2c__buf, __b2c__haystack);strcat(__b2c__buf, __b2c__z);__b2c__haystack = __b2c__tmp+strlen(__b2c__y);}" >> $g_HFILE echo "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + 1)*sizeof(char));strcat(__b2c__buf, __b2c__haystack);" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__buf)+1)*sizeof(char));" >> $g_HFILE echo "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf);free(__b2c__buf);free(__b2c__dup);return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define REPLACE${g_STRINGSIGN}(x, y, z)((x!=NULL && y!=NULL && z!= NULL) ? __b2c__replace(x, y, z) : 0)" >> $g_HFILE echo "#define LEN(x) ((x != NULL) ? strlen(x) : 0)" >> $g_HFILE echo "#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_HFILE echo "char * __b2c__getenv(char *__b2c__env){static char * __b2c__tmp; __b2c__tmp = getenv(__b2c__env); if (__b2c__tmp == NULL)" >> $g_HFILE echo "{return \"\";} return __b2c__tmp;}" >> $g_HFILE echo "#define GETENVIRON${g_STRINGSIGN}(x) ((x != NULL) ? __b2c__getenv(x) : \"null\")" >> $g_HFILE echo "#define SETENVIRON(x, y) if(x != NULL && y != NULL) setenv(x, y, 1)" >> $g_HFILE echo >> $g_HFILE echo "/* CHAR functions */" >> $g_HFILE echo "#include " >> $g_HFILE echo "char* __b2c__ucase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE echo "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=toupper(__b2c__s[__b2c__i]);}" >> $g_HFILE echo "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define UCASE${g_STRINGSIGN}(x) ((x != NULL) ? __b2c__ucase(x) : \"null\")" >> $g_HFILE echo "char* __b2c__lcase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE echo "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=tolower(__b2c__s[__b2c__i]);}" >> $g_HFILE echo "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define LCASE${g_STRINGSIGN}(x) ((x != NULL) ? __b2c__lcase(x) : \"null\")" >> $g_HFILE echo >> $g_HFILE echo "/* I/O functions */" >> $g_HFILE echo "FILE *__b2c__inFile; FILE *__b2c__outFile; int __b2c__Byte; struct dirent *__b2c__dir;" >> $g_HFILE echo "char* __b2c__dec2hex(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS);" >> $g_HFILE echo "snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%X\", __b2c__i); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "unsigned int __b2c__hex2dec(char *__b2c__h){unsigned int __b2c__i; if(sscanf(__b2c__h, \"%X\", &__b2c__i) == EOF && !__b2c__trap){ERROR = 5;" >> $g_HFILE echo "fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} return(int)(__b2c__i);}" >> $g_HFILE echo "unsigned char __b2c__char2asc(char *__b2c__c){return (unsigned char)*__b2c__c;}" >> $g_HFILE echo "char* __b2c__asc2char(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char));" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, 2*sizeof(char)); snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], 2, \"%c\", __b2c__i);" >> $g_HFILE echo "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "/* Function FILEEXISTS contributed by Armando Rivera */ " >> $g_HFILE echo "long __b2c__fileexists(const char *__b2c__x) {struct stat __b2c__buf; if (stat(__b2c__x, &__b2c__buf) != -1) return 1; return 0;}" >> $g_HFILE echo "#define FILEEXISTS(x) __b2c__fileexists(x)" >> $g_HFILE echo "long __b2c__filelen(const char *__b2c__x) {struct stat __b2c__buf; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE echo "if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0) return -1; else return(long)(__b2c__buf.st_size);}" >> $g_HFILE echo "#define FILELEN(x) __b2c__filelen(x)" >> $g_HFILE echo "long __b2c__filetype(const char *__b2c__x) {struct stat __b2c__buf; if(__b2c__x == NULL) return 0; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap)" >> $g_HFILE echo "{ERROR = 24; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE echo "if (S_ISREG(__b2c__buf.st_mode)) return 1; if (S_ISDIR(__b2c__buf.st_mode)) return 2;" >> $g_HFILE echo "if (S_ISCHR(__b2c__buf.st_mode)) return 3; if (S_ISBLK(__b2c__buf.st_mode)) return 4; if (S_ISFIFO(__b2c__buf.st_mode)) return 5;" >> $g_HFILE echo "if (S_ISLNK(__b2c__buf.st_mode)) return 6; if (S_ISSOCK(__b2c__buf.st_mode)) return 7; return 0;}" >> $g_HFILE echo "#define FILETYPE(x) __b2c__filetype(x)" >> $g_HFILE echo "long __b2c__search(FILE* __b2c__x, char* __b2c__y){long __b2c__off; long __b2c__pos; char* __b2c__ptr;" >> $g_HFILE echo "if(__b2c__x == NULL && !__b2c__trap){ERROR = 2; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE echo "if(__b2c__y == NULL && !__b2c__trap){ERROR = 25; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE echo "__b2c__pos = ftell(__b2c__x); __b2c__ptr = (char*)malloc((strlen(__b2c__y)+1)*sizeof(char)); __b2c__off = 0; do {" >> $g_HFILE echo "fseek(__b2c__x, __b2c__off, SEEK_SET);memset(__b2c__ptr, 0, sizeof(char)*(strlen(__b2c__y)+1));" >> $g_HFILE echo "fread(__b2c__ptr, sizeof(char), strlen(__b2c__y), __b2c__x);__b2c__off+=1;" >> $g_HFILE echo "} while(!feof(__b2c__x) && strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y)));" >> $g_HFILE echo "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_HFILE echo "#define SEARCH(x, y) __b2c__search(x, y)" >> $g_HFILE echo "char *__b2c__exec(char *__b2c__x){int __b2c__r, __b2c__len, __b2c__i, __b2c__page;int __b2c__wpipe[2], __b2c__rpipe[2];char *__b2c__ans = NULL;" >> $g_HFILE echo "if (pipe (__b2c__rpipe) < 0 || pipe (__b2c__wpipe) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}}" >> $g_HFILE echo "if ((__b2c__r = fork ()) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}} else if (__b2c__r == 0){" >> $g_HFILE echo "close(__b2c__wpipe[1]);close (__b2c__rpipe[0]);dup2 (__b2c__wpipe[0], 0);close (__b2c__wpipe[0]);dup2 (__b2c__rpipe[1], 1);close (__b2c__rpipe[1]);system (__b2c__x);exit(EXIT_SUCCESS);}" >> $g_HFILE echo "else{close (__b2c__wpipe[0]);close (__b2c__rpipe[1]);__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE*sizeof(char) + 1);__b2c__ans = (char *) malloc ($g_BUFFER_SIZE * sizeof (char));" >> $g_HFILE echo "__b2c__len = 0;__b2c__page = 0;do{__b2c__i = read (__b2c__rpipe[0], __b2c__ans, $g_BUFFER_SIZE);if (__b2c__i == -1 && !__b2c__trap){ERROR=30;fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE echo "if (__b2c__i == 0)break;if (__b2c__len + __b2c__i > $g_BUFFER_SIZE * __b2c__page + 1){__b2c__page++;__b2c__sbuffer[__b2c__sbuffer_ptr] = realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE * __b2c__page + 1);" >> $g_HFILE echo "if (__b2c__sbuffer[__b2c__sbuffer_ptr] == NULL && !__b2c__trap){ERROR=6; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len, __b2c__ans, __b2c__i);" >> $g_HFILE echo " __b2c__len += __b2c__i;}while (__b2c__i == $g_BUFFER_SIZE || __b2c__i == 1); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\0';close (__b2c__wpipe[1]);" >> $g_HFILE echo "close (__b2c__rpipe[0]);free (__b2c__ans);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define EXEC${g_STRINGSIGN}(x) __b2c__exec(x)" >> $g_HFILE echo "#define ENDFILE(x) feof(x)" >> $g_HFILE echo "#define TELL(x) ftell(x)" >> $g_HFILE echo "#define HEX${g_STRINGSIGN}(x) __b2c__dec2hex(x)" >> $g_HFILE echo "#define DEC(x) __b2c__hex2dec(x)" >> $g_HFILE echo "#define ASC(x) __b2c__char2asc(x)" >> $g_HFILE echo "#define CHR${g_STRINGSIGN}(__b2c__x) __b2c__asc2char(__b2c__x)" >> $g_HFILE echo "#define MEMTELL(x) (long)x" >> $g_HFILE echo >> $g_HFILE echo "/* Dynamic loading, errors */" >> $g_HFILE echo "#include " >> $g_HFILE echo "#include " >> $g_HFILE echo >> $g_HFILE echo "/* GETKEY */" >> $g_HFILE echo "#include " >> $g_HFILE echo "long __b2c__getch(){long __b2c__ch; struct termios __b2c__oldt, __b2c__newt; tcgetattr(0, &__b2c__oldt);" >> $g_HFILE echo "__b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(0, TCSANOW, &__b2c__newt);" >> $g_HFILE echo "__b2c__ch = getchar(); tcsetattr(0, TCSANOW, &__b2c__oldt); return __b2c__ch;} " >> $g_HFILE echo "#define GETKEY __b2c__getch()" >> $g_HFILE echo >> $g_HFILE echo "/* Constants, logical stuff */" >> $g_HFILE echo "#define PI 3.14159265" >> $g_HFILE echo "#define NOT(x) (!(x))" >> $g_HFILE echo "#define AND &&" >> $g_HFILE echo "#define OR ||" >> $g_HFILE echo "#define EQ ==" >> $g_HFILE echo "#define IS ==" >> $g_HFILE echo "#define NE !=" >> $g_HFILE echo "#define ISNOT !=" >> $g_HFILE echo "#define TRUE 1" >> $g_HFILE echo "#define FALSE 0" >> $g_HFILE echo "#define NL${g_STRINGSIGN} \"\n\"" >> $g_HFILE echo "#define STRING char*" >> $g_HFILE echo "#define NUMBER long" >> $g_HFILE echo "#define FLOATING double" >> $g_HFILE echo "#define ISTRUE(x) (x!=0)" >> $g_HFILE echo "#define ISFALSE(x) (x==0)" >> $g_HFILE echo >> $g_HFILE echo "/* Date and time */" >> $g_HFILE echo "#include " >> $g_HFILE echo "#define NOW (long)time(NULL)" >> $g_HFILE echo "long __b2c__time(time_t __b2c__now, int __b2c__which){struct tm *ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS); ts = localtime(&__b2c__now); switch(__b2c__which) { case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%d\", ts); break;" >> $g_HFILE echo "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%m\", ts); break; case 3: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%Y\", ts); break;" >> $g_HFILE echo "case 4: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%H\", ts); break; case 5: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%M\", ts); break;" >> $g_HFILE echo "case 6: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%S\", ts); break; case 7: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%W\", ts); break;}" >> $g_HFILE echo "return(atol(__b2c__sbuffer[__b2c__sbuffer_ptr]));}" >> $g_HFILE echo "#define DAY(x) __b2c__time(x, 1)" >> $g_HFILE echo "#define MONTH(x) __b2c__time(x, 2)" >> $g_HFILE echo "#define YEAR(x) __b2c__time(x, 3)" >> $g_HFILE echo "#define HOUR(x) __b2c__time(x, 4)" >> $g_HFILE echo "#define MINUTE(x) __b2c__time(x, 5)" >> $g_HFILE echo "#define SECOND(x) __b2c__time(x, 6)" >> $g_HFILE echo "#define WEEK(x) __b2c__time(x, 7)" >> $g_HFILE echo "char * __b2c__datename(time_t __b2c__now, int __b2c__which){struct tm *ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS); ts = localtime(&__b2c__now); switch(__b2c__which){case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%A\", ts); break;" >> $g_HFILE echo "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%B\", ts); break;} return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define WEEKDAY${g_STRINGSIGN}(x) __b2c__datename(x, 1)" >> $g_HFILE echo "#define MONTH${g_STRINGSIGN}(x) __b2c__datename(x, 2)" >> $g_HFILE echo "unsigned long __b2c__epoch(int __b2c__year, int __b2c__month, int __b2c__day, int __b2c__hour, int __b2c__minute, int __b2c__second){" >> $g_HFILE echo "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_HFILE echo "tm.tm_hour = __b2c__hour; tm.tm_min = __b2c__minute; tm.tm_sec = __b2c__second;" >> $g_HFILE echo "tm.tm_isdst = -1; __b2c__t = mktime(&tm); if (__b2c__t == -1) return (0); return(long) __b2c__t; }" >> $g_HFILE echo "#define TIMEVALUE(x,y,z,a,b,c) __b2c__epoch(x,y,z,a,b,c)" >> $g_HFILE echo "char* __b2c__os(void){struct utsname __b2c__buf; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE);" >> $g_HFILE echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_BUFFER_SIZE); if(uname(&__b2c__buf) < 0 && !__b2c__trap) {ERROR = 26; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE echo "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.sysname); strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], \" \");" >> $g_HFILE echo "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.machine); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE echo "#define OS${g_STRINGSIGN} __b2c__os()" >> $g_HFILE echo >> $g_HFILE echo "/* Peek and Poke */" >> $g_HFILE echo "struct stat __b2c__sb;" >> $g_HFILE echo "void __b2c__memory__check(char* __b2c__x) {if (stat(__b2c__x, &__b2c__sb) == -1 && errno == EFAULT) {ERROR = 1;} }" >> $g_HFILE echo "long __b2c__malloc(long __b2c__x) {void *__b2c__mem; if(__b2c__x==0) return(0); __b2c__mem = calloc(__b2c__x+1, sizeof(char));" >> $g_HFILE echo "if(__b2c__mem == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} return(long)__b2c__mem;}" >> $g_HFILE echo "#define MEMORY(__b2c__x) __b2c__malloc(__b2c__x)" >> $g_HFILE echo "void *__b2c__realloc(void* __b2c__x, long __b2c__y) {if(__b2c__x == NULL) return (NULL); if(!__b2c__trap) {__b2c__memory__check((char*)__b2c__x);" >> $g_HFILE echo "if(ERROR) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } __b2c__x = realloc((void*)__b2c__x, sizeof(char)*(__b2c__y+1));" >> $g_HFILE echo "if(__b2c__x == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} }" >> $g_HFILE echo "#define RESIZE(__b2c__x, __b2c__y) __b2c__realloc((void*)__b2c__x, __b2c__y)" >> $g_HFILE echo "void __b2c__poke(char* __b2c__x, unsigned char __b2c__y) {if (!__b2c__trap){__b2c__memory__check((char*)__b2c__x); if(ERROR) {" >> $g_HFILE echo "fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } *__b2c__x = (unsigned char)__b2c__y;}" >> $g_HFILE echo "#define POKE(__b2c__x, __b2c__y) __b2c__poke((char*)(__b2c__x), (unsigned char)(__b2c__y))" >> $g_HFILE echo "unsigned char __b2c__peek(char* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((char*) __b2c__x); if(ERROR) {" >> $g_HFILE echo "fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } return((unsigned char)*__b2c__x);}" >> $g_HFILE echo "#define PEEK(__b2c__x) __b2c__peek((char*)(__b2c__x))" >> $g_HFILE echo "#define ADDRESS(__b2c__x) (long)(&__b2c__x)" >> $g_HFILE echo >> $g_HFILE echo "/* Network variables and functions */" >> $g_HFILE echo "struct timeval __b2c__to; struct hostent *__b2c__he; char __b2c__data[$g_BUFFER_SIZE]; char *__b2c__host; char *__b2c__port; int __b2c__yes = 1; struct sockaddr_in __b2c__addr; int __b2c__result; /* Declarations for OPEN */" >> $g_HFILE echo "long __b2c__netpeek(int __b2c__fd, int __b2c__usec){fd_set __b2c__rfds;struct timeval __b2c__tv;long __b2c__retval;" >> $g_HFILE echo "FD_ZERO(&__b2c__rfds); FD_SET(__b2c__fd, &__b2c__rfds);__b2c__tv.tv_usec = __b2c__usec*1000;__b2c__tv.tv_sec = 0;" >> $g_HFILE echo "__b2c__retval = select(__b2c__fd + 1, &__b2c__rfds, NULL, NULL, &__b2c__tv);" >> $g_HFILE echo "if (__b2c__retval == -1 && !__b2c__trap) {ERROR = 16; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} return(__b2c__retval);}" >> $g_HFILE echo "#define WAIT(x, y) __b2c__netpeek(x, y)" >> $g_HFILE echo >> $g_HFILE echo "/* Regex */" >> $g_HFILE echo "#include " >> $g_HFILE echo "long __b2c__regex(char* __b2c__x, char* __b2c__y){regex_t __b2c__reg; int __b2c__reti; char __b2c__buf[100]; __b2c__reti = regcomp(&__b2c__reg, __b2c__y, REG_EXTENDED|REG_NOSUB);" >> $g_HFILE echo "if(!__b2c__trap && __b2c__reti){ERROR=27; fprintf(stderr, \"%s: \", ERR${g_STRINGSIGN}(ERROR)); regerror(__b2c__reti, &__b2c__reg, __b2c__buf, sizeof(__b2c__buf)); fprintf(stderr, \"%s\n\", __b2c__buf);" >> $g_HFILE echo "exit(ERROR);} __b2c__reti = regexec(&__b2c__reg, __b2c__x, 0, NULL, 0);" >> $g_HFILE echo "regfree(&__b2c__reg); if( !__b2c__reti ) return (1); else return (0);}" >> $g_HFILE echo "#define REGEX(x, y) __b2c__regex(x, y)" >> $g_HFILE echo >> $g_HFILE echo "/* Declare reserved variable 'ARGUMENT' */" >> $g_HFILE echo "int __b2c__counter;" >> $g_HFILE echo "int __b2c__arglen = 0;" >> $g_HFILE echo "char *ARGUMENT${g_STRINGSIGN};" >> $g_HFILE echo >> $g_HFILE echo "/* Initialize stack arrays and pointer */" >> $g_HFILE echo "char **__b2c__stringstack = NULL; double *__b2c__doublestack = NULL;" >> $g_HFILE echo "long *__b2c__longstack = NULL; int *__b2c__typestack = NULL;" >> $g_HFILE echo "int __b2c__stackptr = 0;" >> $g_HFILE # Signal function echo "/* Signal trapping activated with TRAP */" >> $g_HFILE echo "void __b2c__catch_signal(int sig){" >> $g_HFILE echo "switch (sig) {case SIGABRT: fprintf(stderr, \"ERROR: signal ABORT received - internal error. Try to compile the program with TRAP LOCAL to find the cause.\n\"); break;" >> $g_HFILE echo "case SIGFPE: fprintf(stderr, \"ERROR: signal for FPE received - division by zero? Examine the calculations in the program.\n\"); break;" >> $g_HFILE echo "case SIGSEGV: fprintf(stderr, \"ERROR: signal for SEGMENTATION FAULT received - memory invalid or array out of bounds? Try to compile the program with TRAP LOCAL to find the cause.\n\"); break;" >> $g_HFILE echo "case SIGILL: fprintf(stderr, \"ERROR: signal for ILLEGAL INSTRUCTION received - executing the program on other hardware? Try to recompile the program from scratch.\n\"); break;} exit(sig);}" >> $g_HFILE # Makedir function echo "int __b2c__makedir(char* __b2c__dir){char *__b2c__i; __b2c__i = __b2c__dir; do { __b2c__i++; while(*__b2c__i != '/' && *__b2c__i != '\0') __b2c__i++; if(*__b2c__i == '/') {" >> $g_HFILE echo "*__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_HFILE echo "if(errno != EEXIST && errno != 0) return errno;} while (*__b2c__i != '\0'); return 0;}" >> $g_HFILE # Add error function echo >> $g_HFILE echo "/* Initialize error function */" >> $g_HFILE echo "char *ERR${g_STRINGSIGN}(int __b2c__nr){static char __b2c__warn[$g_BUFFER_SIZE];" >> $g_HFILE echo "switch(__b2c__nr){" >> $g_HFILE echo "case 0: strcpy(__b2c__warn,\"Success\"); break;" >> $g_HFILE echo "case 1: strcpy(__b2c__warn,\"Trying to access illegal memory: \"); strncat(__b2c__warn,strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 2: strcpy(__b2c__warn,\"Error opening file: \"); strncat(__b2c__warn,strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 3: strcpy(__b2c__warn, \"Could not open library \"); strncat(__b2c__warn, dlerror(), $g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 4: strcpy(__b2c__warn, \"Symbol not found in library \"); strncat(__b2c__warn, dlerror(), $g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 5: strcpy(__b2c__warn, \"Wrong hexvalue: \"); strncat(__b2c__warn, strerror(errno), $g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 6: strcpy(__b2c__warn, \"Unable to claim memory.\"); break;" >> $g_HFILE echo "case 7: strcpy(__b2c__warn, \"Unable to delete file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 8: strcpy(__b2c__warn, \"Could not open directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 9: strcpy(__b2c__warn, \"Unable to rename file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 10: strcpy(__b2c__warn, \"NETWORK argument should contain colon with port number\"); break;" >> $g_HFILE echo "case 11: strcpy(__b2c__warn, \"Could not resolve hostname: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 12: strcpy(__b2c__warn, \"Socket error: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 13: strcpy(__b2c__warn, \"Unable to open address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 14: strcpy(__b2c__warn, \"Error reading from socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 15: strcpy(__b2c__warn, \"Error sending to socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 16: strcpy(__b2c__warn, \"Error checking socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 17: strcpy(__b2c__warn, \"Unable to bind the specified socket address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 18: strcpy(__b2c__warn, \"Unable to listen to socket address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 19: strcpy(__b2c__warn, \"Cannot accept incoming connection: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 20: strcpy(__b2c__warn, \"Unable to remove directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 21: strcpy(__b2c__warn, \"Unable to create directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 22: strcpy(__b2c__warn, \"Unable to change to directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 23: strcpy(__b2c__warn, \"GETENVIRON argument does not exist as environment variable\"); break;" >> $g_HFILE echo "case 24: strcpy(__b2c__warn, \"Unable to stat file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 25: strcpy(__b2c__warn, \"Search contains illegal string\"); break;" >> $g_HFILE echo "case 26: strcpy(__b2c__warn, \"Cannot return OS name: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 27: strcpy(__b2c__warn, \"Illegal regex expression\"); break;" >> $g_HFILE echo "case 28: strcpy(__b2c__warn, \"Unable to create bidirectional pipes: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 29: strcpy(__b2c__warn, \"Unable to fork process: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "case 30: strcpy(__b2c__warn, \"Cannot read from pipe: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE echo "}; ERROR = 0; return(__b2c__warn);}" >> $g_HFILE echo >> $g_HFILE echo "/* User program definitions */" >> $g_HFILE # Initialize the arrayfiles for DATA statement echo "char *__b2c__stringarray[] = {" > $STRINGARRAYFILE echo "int __b2c__intarray[] = {" > $INTARRAYFILE echo "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 $SOURCEFILE $SOURCEFILE.cpp FEED="${SOURCEFILE}.cpp" g_TMP_FILES="$g_TMP_FILES ${SOURCEFILE}.cpp" else echo -e "ERROR: the C Preprocessor 'cpp' not found on this system! Exiting..." exit 1 fi else FEED=${SOURCEFILE} fi g_CURFILE=${SOURCEFILE##*/} # Initialize LEN= TOTAL= SEQ= g_COUNTER=1 # Start walking through program while read -r LINE do echo -e -n "\rStarting conversion... $g_COUNTER " # Line is not empty? if [[ -n "$LINE" ]] then if [[ "$LINE" = +(* \\) && "$LINE" != +(REM*) && "$LINE" != +(\'*) ]] then let LEN="${#LINE}"-2 SEQ="${LINE:0:$LEN}" TOTAL=$TOTAL$SEQ else Parse_Line "$TOTAL$LINE" TOTAL= fi fi ((g_COUNTER+=1)) done < $FEED # Check if enclosed IF/ELIF/ELSE needs to be closed if [[ $g_IF_PARSE -eq 1 ]] then echo "}" >> $g_CFILE fi # Finalize main C-file echo "__B2C__PROGRAM__EXIT:" >> $g_CFILE echo "return 0;" >> $g_CFILE echo "}" >> $g_CFILE # Finalize INT ARRAY file for DATA echo " \"\" };" >> $STRINGARRAYFILE # Finalize STRING ARRAY file for DATA echo " 0};" >> $INTARRAYFILE # Finalize FLOAT ARRAY file for DATA echo " 0.0};" >> $FLOATARRAYFILE # Include functions and subs for i in $g_INCLUDE_FILES do echo "#include \"${i}\"" >> $g_HFILE done echo -e "\rStarting conversion... done. " # Indentation only when files are preserved if [[ $g_TMP_PRESERVE -eq 1 ]] then if [[ -n `which indent 2>/dev/null` ]] then echo -n "Applying indentation... " for i in $g_TMP_FILES do if [[ $i != +(*.cpp) ]] then if [[ `uname` = "Darwin" || `uname` = +(*BSD*) ]] then mv ${i} "${i}.BAK" indent "${i}.BAK" ${i} rm "${i}.BAK" else indent $i rm $i~ fi fi done echo "done." else echo "WARNING: 'indent' not found on this system!" echo "Generated source code cannot be beautified." fi fi # Start compilation if [[ $g_NO_COMPILE -eq 0 ]] then echo -n "Starting compilation... " $g_CCNAME $g_CCFLAGS -o ${SOURCEFILE%.*}$g_BINEXT $g_CFILE $g_LDFLAGS > $g_TEMPDIR/${SOURCEFILE##*/}.log 2>&1 g_TMP_FILES="$g_TMP_FILES $g_TEMPDIR/${SOURCEFILE##*/}.log" if [[ -z `cat $g_TEMPDIR/${SOURCEFILE##*/}.log` ]] then echo "done." echo "Program '${SOURCEFILE%.*}$g_BINEXT' ready." else # Only print first error echo -e "Compiler emits messages!" while read -r g_ERROR do if [[ $g_ERROR != +(-*) && -n `echo "${g_ERROR}" | grep -E "\:[0-9]+\: error\:"` ]] then echo -e "\n${g_ERROR}" break fi done < $g_TEMPDIR/${SOURCEFILE##*/}.log # Non-gcc if [[ -z $g_ERROR || $g_CCFLAGS = +(*Wall*) ]] then echo cat $g_TEMPDIR/${SOURCEFILE##*/}.log echo else # Get the error string from the logfile g_FILE_LINE=${g_ERROR%%: *} g_COUNTER=1 while read -r LINE do if [[ $g_COUNTER -eq ${g_FILE_LINE##*:} ]] then echo -e " ---> ${LINE} <---\n" break fi ((g_COUNTER+=1)) done < ${g_FILE_LINE%%:*} 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 rm $i done elif [[ $g_CPP -eq 1 ]] then mv ${SOURCEFILE}.cpp $g_TEMPDIR/${SOURCEFILE##*/}.cpp fi exit 0