#!/usr/bin/env ksh # # KornShell BASIC-to-C converter --= BACON =-- # # Peter van Eerten - March/November 2009. License: GPL version 2. # # 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 #--------------------------------------------------------------------------------------------------------------------- # Make sure GCC uses English localization export LC_CTYPE="C" export LANG="C" # Version of BACON g_VERSION="1.0 rc 1" # 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 print "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 typeset -rx g_PARSEVAR=`print "\001"` #----------------------------------------------------------- function Print_Element { typeset -R1 DQ="${1}" typeset -u -L3 FUNC="${1}" # 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 print -r "fprintf(stdout, \"%.10g\", (double)($1));" >> $g_CFILE # String function? elif [[ "$1" = +(*\$*) && "$1" = +(*\(*\)*) ]] then print -r "fprintf(stdout, \"%s\", $1);" >> $g_CFILE # Is there a "$" symbol? Then it is always a string, or stringvariable elif [[ "$1" = +(*\$*) ]] then print -r "if($1 != NULL) fprintf(stdout, \"%s\", $1);" >> $g_CFILE print -r "else fprintf(stdout, \"\");" >> $g_CFILE # Check if it is a normal string elif [[ $DQ = "\"" ]] then print -r "fprintf(stdout, \"%s\", $1);" >> $g_CFILE # Other numeric variable else print -r "fprintf(stdout, \"%.10g\", (double)($1));" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Print { typeset 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 typeset -L$LEN EXP="$1" else EXP="${1}" fi # If there is FORMAT/format argument if [[ "$EXP" = +(* FORMAT *) ]] then FORMAT=${EXP##* FORMAT} print -r "fprintf(stdout, ${FORMAT%%;*}, ${EXP%%FORMAT *});" >> $g_CFILE else # Start miniparser, convert spaces LINE=`print -r "${EXP}" | tr " " "\001"` TOKEN= LEN=${#LINE} # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${LINE}" case $CHAR in ",") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then 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 typeset -R$LEN LINE="${LINE}" done Print_Element "${TOKEN}" # If line ends with ';' then skip newline if [[ -n ${1##*;} ]] then print -r "fprintf(stdout, \"\n\");" >> $g_CFILE fi fi else print -r "fprintf(stdout, \"\n\");" >> $g_CFILE fi # Flush buffer print -r "fflush(stdout);" >> $g_CFILE } #----------------------------------------------------------- function Handle_Input { # Local variables typeset CHECK VAR TARGET STR LINE LEN IN_STRING IN_FUNC CHAR ESCAPED IN_FUNC=0 # Check if we have an argument at all if [[ "$1" = "INPUT" ]] then print "\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=`print -r "${1}" | tr " " "\001"` VAR= LEN=${#LINE} # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${LINE}" case $CHAR in ",") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then 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 typeset -R$LEN LINE="${LINE}" done # Check type of var, string? if [[ "${VAR}" = +(*\$) ]] then STR=${VAR%\$*} CHECK=`grep -E "char \*${STR}\\\\$ = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi # Translate function to C function print -r "fgets(__b2c__input__buffer, $g_BUFFER_SIZE, stdin);" >> $g_CFILE # Always realloc VAR to correct size, maybe it was resized somewhere else print -r "$VAR = (char*)realloc($VAR, $g_BUFFER_SIZE*sizeof(char));" >> $g_CFILE # Make sure internal var is copied to var of program print -r "strncpy($VAR, __b2c__input__buffer, $g_BUFFER_SIZE);" >> $g_CFILE # Get rid of the terminating newline print -r "$VAR[strlen(__b2c__input__buffer)-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 "\/\*record\*\/"` if [[ -z $CHECK ]] then print -r "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 "\/\*record\*\/"` fi # Translate function to C function print -r "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 print -r "$VAR = atof(__b2c__input__buffer);" >> $g_CFILE elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*NUMBER *) ]] then print -r "$VAR = atol(__b2c__input__buffer);" >> $g_CFILE elif [[ "$CHECK" = +(*int *) || "$CHECK" = +(*NUMBER *) ]] then print -r "$VAR = atoi(__b2c__input__buffer);" >> $g_CFILE else print -r "$VAR = (char*)realloc($VAR, $g_BUFFER_SIZE*sizeof(char));" >> $g_CFILE print -r "strncpy($VAR, __b2c__input__buffer, $g_BUFFER_SIZE);" >> $g_CFILE print -r "$VAR[strlen(__b2c__input__buffer)-1] = '\0';" >> $g_CFILE fi fi } #----------------------------------------------------------- function Handle_For { # Local variables typeset FROM TO TMP VAR STEP CHECK TARGET # Get the variablename without (surrounding) spaces VAR=`print -r "${1%%=*}" | tr -d "\040"`; TMP=`print -r "${1#*=}"` # Do we have a STRING var? if [[ "${VAR}" = +(*\$*) ]] then print "\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 print "\nERROR: missing TO in FOR statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the starting and ending value FROM=`print -r "${TMP%% TO *}"` TO=`print -r "${TMP##* TO }"` # Check if there is a STEP if [[ "$TO" = +(* STEP *) ]] then STEP="${TO##* STEP }" TO="${TO%% STEP *}" else STEP=1 fi # 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 "\/\*record\*\/"` if [[ -z $CHECK ]] then print -r "long $VAR;" >> $g_HFILE fi fi # Translate function to C function if [[ "${STEP}" = +(*-*) ]] then print -r "for($VAR=$FROM; $VAR >= $TO; $VAR+=$STEP){" >> $g_CFILE else print -r "for($VAR=$FROM; $VAR <= $TO; $VAR+=$STEP){" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_If { # Check if THEN is available if [[ "$1" != +(* THEN) ]] then print "\nERROR: Missing THEN in IF statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Translate function to C function print -r "if(${1% *}){" >> $g_CFILE } #----------------------------------------------------------- function Handle_Elif { # Check if THEN is available if [[ "$1" != +(* THEN) ]] then print "\nERROR: Missing THEN in ELIF statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Translate function to C function print -r "} else if(${1% *}){" >> $g_CFILE } #----------------------------------------------------------- function Handle_While { # Check if DO is available if [[ "$1" != +(* DO) ]] then print "\nERROR: Missing DO in WHILE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi print -r "while(${1% *}){" >> $g_CFILE } #----------------------------------------------------------- function Handle_Let { # Local variables typeset VAR CHECK TMP TARGET LEN STR # Check if there is an asignment at all, if not exit if [[ "$1" != +(*=*) ]] then print "\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=`print ${1%%=*}`; TMP=${1#*=} # Check if var is string var, exclude RECORD elements if [[ "${VAR}" = +(*\$) && "$VAR" != +(*.*) ]] then STR=${VAR%\$*} CHECK=`grep -E "char \*${STR}\\\\$ = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi # Assume number, exclude RECORD elements elif [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) && "$VAR" != "ERROR" ]] 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 "\/\*record\*\/"` if [[ -z $CHECK ]] then if [[ "$TMP" = +(*.*) ]] then print -r "double $VAR;" >> $g_HFILE else print -r "long $VAR;" >> $g_HFILE fi fi fi # Do we have a STRING variable? if [[ "${VAR}" = +(*\$*) ]] then print -r "__b2c__assign = (char*) strdup ($TMP); ${g_WITHVAR}${VAR} = (char*)realloc(${g_WITHVAR}${VAR}, (strlen(__b2c__assign)+1)*sizeof(char));" >> $g_CFILE print -r " strcpy(${g_WITHVAR}${VAR}, __b2c__assign); free(__b2c__assign);" >> $g_CFILE else print -r "${g_WITHVAR}${1};" >> $g_CFILE fi } #----------------------------------------------------------- function Handle_Open { # Local variables typeset FILE MODE HANDLE TMP CHECK TARGET LABEL # Check if FOR is available if [[ "$1" != +(* FOR *) ]] then print "\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 print "\nERROR: Missing AS in OPEN statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the file, mode and handle FILE=`print "${1%% FOR *}"` TMP=`print "${1##* FOR }"` MODE=`print "${TMP%% AS *}"` HANDLE=`print "${TMP##* AS }"` # Check if var is string var if [[ "${HANDLE}" = +(*\$) ]] then print "\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 "\/\*record\*\/"` fi # File or dir? if [[ $MODE = "DIRECTORY" ]] then if [[ -z $CHECK ]] then print -r "DIR* $HANDLE;" >> $g_HFILE fi elif [[ $MODE = "MEMORY" ]] then if [[ -z $CHECK ]] then print -r "char* $HANDLE;" >> $g_HFILE fi elif [[ $MODE = "NETWORK" || $MODE = "SERVER" ]] then if [[ -z $CHECK ]] then print -r "int $HANDLE;" >> $g_HFILE fi else if [[ -z $CHECK ]] then print -r "FILE* $HANDLE;" >> $g_HFILE fi fi # Convert to C syntax case $MODE in @(READING) ) print -r "$HANDLE = fopen($FILE, \"r\");" >> $g_CFILE print -r "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(WRITING) ) print -r "$HANDLE = fopen($FILE, \"w\");" >> $g_CFILE print -r "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(APPENDING) ) print -r "$HANDLE = fopen($FILE, \"a\");" >> $g_CFILE print -r "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(READWRITE) ) print -r "$HANDLE = fopen($FILE, \"r+\");" >> $g_CFILE print -r "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(DIRECTORY) ) print -r "$HANDLE = opendir($FILE);" >> $g_CFILE print -r "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(MEMORY) ) print -r "$HANDLE = (char*)$FILE; long __b2c_mem_$HANDLE; __b2c_mem_$HANDLE = $FILE;" >> $g_CFILE print -r "if(!__b2c__trap){__b2c__memory__check($HANDLE); if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(NETWORK) ) # Network code print -r "if (strstr($FILE, \":\") == NULL) {if(!__b2c__trap){ERROR = 10;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "strncpy(__b2c__data, $FILE, $g_BUFFER_SIZE); __b2c__host = strtok(__b2c__data, \":\"); __b2c__port = strtok(NULL, \":\"); __b2c__he = gethostbyname(__b2c__host);" >> $g_CFILE print -r "if (__b2c__he == NULL){if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "$HANDLE = socket(PF_INET, SOCK_STREAM, 0);" >> $g_CFILE print -r "if ($HANDLE == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "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 print -r "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr); memset(&(__b2c__addr.sin_zero), '\0', sizeof(__b2c__addr.sin_zero));" >> $g_CFILE print -r "__b2c__result = connect($HANDLE, (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" >> $g_CFILE print -r "if(__b2c__result == -1) {if(!__b2c__trap){ERROR = 13;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; @(SERVER) ) # Network code print -r "if (strstr($FILE, \":\") == NULL){if(!__b2c__trap){ERROR = 10;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "strncpy(__b2c__data, $FILE, $g_BUFFER_SIZE); __b2c__host = strtok(__b2c__data, \":\"); __b2c__port = strtok(NULL, \":\"); __b2c__he = gethostbyname(__b2c__host);" >> $g_CFILE print -r "if (__b2c__he == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "$HANDLE = socket(AF_INET, SOCK_STREAM, 0);" >> $g_CFILE print -r "if ($HANDLE == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "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 print -r "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr); memset(&(__b2c__addr.sin_zero), '\0', sizeof(__b2c__addr.sin_zero));" >> $g_CFILE print -r "__b2c__result = bind($HANDLE, (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" >> $g_CFILE print -r "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 17;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "__b2c__result = listen($HANDLE, $g_MAX_BACKLOG);" >> $g_CFILE print -r "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 18;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "__b2c__result = accept($HANDLE, NULL, 0);" >> $g_CFILE print -r "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 19;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "$HANDLE= __b2c__result;" >> $g_CFILE;; esac } #----------------------------------------------------------- function Handle_Readln { # Local variables typeset CHECK VAR FROM TARGET STR # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\nERROR: Missing FROM in READLN statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`print ${1%% FROM *}` # Get filedescriptor FROM=`print ${1##* FROM }` # Check if var is string var if [[ "${VAR}" != +(*\$*) ]] then print "\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%\$*} CHECK=`grep -E "char \*${STR}\\\\$ = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi fi # Translate function to C function print -r "fgets(__b2c__input__buffer, $g_BUFFER_SIZE, $FROM);" >> $g_CFILE # Make sure internal var is copied to var of program print -r "$VAR = (char*)realloc($VAR, $g_BUFFER_SIZE*sizeof(char));" >> $g_CFILE print -r "strncpy($VAR, __b2c__input__buffer, $g_BUFFER_SIZE);" >> $g_CFILE # Make sure to end the string print -r "$VAR[strlen(__b2c__input__buffer)-1] = '\0';" >> $g_CFILE } #----------------------------------------------------------- function Handle_Writeln { # Local variables typeset VAR TO LINE LEN CHAR IN_STRING IN_FUNC # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nERROR: Missing TO in WRITELN statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get filedescriptor TO=`print -r ${1##* TO }` # Start miniparser to see if we need to print something, convert spaces LINE=`print -r "${1%% TO *}" | tr " " "\001"` VAR= LEN=${#LINE} IN_STRING=0 # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${LINE}" case $CHAR in ",") if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] then # Check if var is string var if [[ "${VAR}" = +(*\$*) || "${VAR}" != `print -r "${VAR}" | tr -d "\042"` ]] then print -r "fprintf($TO, \"%s\", ${VAR});" >> $g_CFILE VAR= CHAR= ESCAPED=0 else print "\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 typeset -R$LEN LINE="${LINE}" done # Check if var is string var if [[ "${VAR}" = +(*\$*) || "${VAR}" != `print -r "${VAR}" | tr -d "\042"` ]] then print -r "fprintf($TO, \"%s\n\", ${VAR});" >> $g_CFILE print -r "fflush($TO);" >> $g_CFILE else print "\nERROR: Argument for WRITELN at line $g_COUNTER in file $g_CURFILE must be string!" exit 1 fi } #----------------------------------------------------------- function Handle_Getbyte { # Local variables typeset POS FROM SIZE TARGET CHECK # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\nERROR: Missing FROM in GETBYTE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces POS=`print ${1%% FROM *}` # Get filedescriptor FROM=`print ${1##* FROM }` 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 "\/\*record\*\/"` if [[ -z $CHECK ]] then print -r "long $POS;" >> $g_HFILE fi fi # Translate function to C function print -r "if(!__b2c__trap){__b2c__memory__check((char *)$POS); if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "fread((void*)$POS, sizeof(char), $SIZE, $FROM);" >> $g_CFILE } #----------------------------------------------------------- function Handle_Putbyte { # Local variables typeset VAR TO SIZE POS # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nERROR: Missing TO in PUTBYTE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces POS=`print ${1%% TO *}`; # Get filedescriptor TO=`print ${1##* TO }` 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 print -r "if(!__b2c__trap){__b2c__memory__check((char *)$POS); if(ERROR){if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE print -r "fwrite((void*)$POS, sizeof(char), $SIZE, $TO);" >> $g_CFILE } #----------------------------------------------------------- function Handle_Getfile { # Local variables typeset VAR FROM SIZE TARGET STR # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\nERROR: Missing FROM in GETFILE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`print ${1%% FROM *}` # Get dirdescriptor FROM=`print ${1##* FROM }` # Determine target if [[ -n $g_FUNCNAME ]] then TARGET="$g_CFILE $g_HFILE" else TARGET=$g_HFILE fi touch $TARGET # Translate function to C function print -r "__b2c__dir = readdir($FROM);" >> $g_CFILE # Check if variable is declared STR=${VAR%\$*} CHECK=`grep -E "char \*${STR}\\\\$ = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi # Always realloc VAR to correct size, maybe it was resized somewhere else print -r "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 print -r "strcpy($VAR, __b2c__dir->d_name); $VAR[strlen(__b2c__dir->d_name)] = '\0';}" >> $g_CFILE print -r "else {$VAR[0] = '\0';}" >> $g_CFILE } #----------------------------------------------------------- function Handle_Receive { # Local variables typeset CHECK VAR FROM TARGET STR # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\nERROR: Missing FROM in RECEIVE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`print ${1%% FROM *}` # Get filedescriptor FROM=`print ${1##* FROM }` # Check if var is string var if [[ "${VAR}" != +(*\$) ]] then print "\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%\$*} CHECK=`grep -E "char \*${STR}\\\\$ = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi # Translate function to C function print -r "$VAR = (char*)realloc($VAR, ($g_BUFFER_SIZE+1)*sizeof(char));" >> $g_CFILE print -r "memset($VAR, '\0', $g_BUFFER_SIZE+1);" >> $g_CFILE print -r "if(recv($FROM, $VAR, $g_BUFFER_SIZE, 0) < 0) {if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Send { # Local variables typeset VAR TO # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nERROR: Missing TO in SEND statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`print -r ${1%% TO *}`; # Get filedescriptor TO=`print -r ${1##* TO }` # Check if var is string var if [[ "${VAR}" != +(*\$*) && "$VAR" = `print -r "$VAR" | tr -d "\042"` ]] then print "\nERROR: Variable for SEND at line $g_COUNTER in file $g_CURFILE must be string!" exit 1 fi # Translate function to C function print -r "if(send($TO, $VAR, strlen($VAR), 0) < 0) {if(!__b2c__trap){ERROR = 15; if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Getline { # Local variables typeset CHECK VAR FROM TARGET STR # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\nERROR: Missing FROM in GETLINE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`print -r ${1%% FROM *}` # Get filedescriptor FROM=`print -r ${1##* FROM }` # Check if var is string var if [[ "${VAR}" != +(*\$*) ]] then print "\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%\$*} CHECK=`grep -E "char \*${STR}\\\\$ = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$VAR = NULL;" >> $g_HFILE fi fi # Translate function to C function print -r "if ($FROM == NULL || *$FROM == '\0') {$VAR = (char*)realloc($VAR, 2*sizeof(char)); strcpy($VAR, \"\");}" >> $g_CFILE print -r "else { __b2c__assign = $FROM; while(*$FROM != '\0' && *$FROM != '\n') $FROM++;" >> $g_CFILE # Make sure internal var is copied to var of program print -r "$VAR = (char*)realloc($VAR, ($FROM-__b2c__assign+1)*sizeof(char));" >> $g_CFILE print -r "strncpy($VAR, __b2c__assign, $FROM-__b2c__assign);" >> $g_CFILE # Make sure to end the string print -r "$VAR[($FROM-__b2c__assign)] = '\0'; $FROM++;}" >> $g_CFILE } #----------------------------------------------------------- function Handle_Putline { # Local variables typeset VAR TO # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nERROR: Missing TO in PUTLINE statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces VAR=`print -r ${1%% TO *}`; # Get memorydescriptor TO=`print -r ${1##* TO }` # Check if var is string var if [[ "${VAR}" != +(*\$*) && "$VAR" = `print -r "$VAR" | tr -d "\042"` ]] then print "\nERROR: Variable for PUTLINE at line $g_COUNTER in file $g_CURFILE must be string!" exit 1 fi # Translate function to C function print -r "strcat($TO, $VAR); strcat($TO, \"\n\"); $TO+=strlen($VAR)+1;" >> $g_CFILE } #----------------------------------------------------------- function Handle_Import { # Local variables typeset TMP SYM LIB CHECK TOKEN PTR TYPE # Check if FROM is available if [[ "$1" != +(* FROM *) ]] then print "\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=`print ${1%%\(*} | tr -d "\042"`; TMP=${1#* FROM } TOKEN=`print ${1%%\)*}` else SYM=`print ${1%% FROM *} | tr -d "\042"`; TMP=${1#* FROM } TOKEN= fi # Check if TYPE is available if [[ "$1" != +(* TYPE *) ]] then print "\nERROR: missing TYPE in IMPORT statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get library and type LIB=`print ${TMP%% TYPE *}` TYPE=`print ${TMP##* TYPE }` # 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=`print $LIB | tr -d [:punct:]` # Check if variable was declared CHECK=`grep -i "void\* __b2c__dlopen__pointer_$PTR;" $g_HFILE` if [[ -z $CHECK ]] then print -r "void* __b2c__dlopen__pointer_$PTR;" >> $g_HFILE print -r "__b2c__dlopen__pointer_$PTR = dlopen($LIB, RTLD_GLOBAL|RTLD_LAZY);" >> $g_CFILE print -r "if(__b2c__dlopen__pointer_$PTR == NULL){if(!__b2c__trap){ERROR = 3;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(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 print -r "$TYPE (*$SYM)(${TOKEN##*\(});" >> $g_HFILE fi # Translate to C function print -r "*($TYPE **) (&$SYM) = dlsym(__b2c__dlopen__pointer_$PTR, \"$SYM\");" >> $g_CFILE print -r "if($SYM == NULL) {if(!__b2c__trap){ERROR = 4;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(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 typeset VAR TYPE CHECK # Get the variablename and type if [[ "$1" = +(* TYPE *) ]] then VAR=`print ${1%% TYPE *}` TYPE=`print ${1##* TYPE }` else VAR=`print ${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 "\/\*record\*\/"` fi if [[ -n $CHECK ]] then print "\nERROR: variable in DECLARE or GLOBAL statement at line $g_COUNTER in file $g_CURFILE was defined previously!" exit 1 fi # Check if var is string var if [[ "${VAR}" = +(*\$*) ]] then STR=${VAR%\$*} CHECK=`grep -E "char \*${STR}\\\\$ = NULL;" $g_HFILE` if [[ -z $CHECK ]] then STR=`print ${VAR} | tr ',' ' '` for i in $STR do if [[ "${i}" = +(*\[*\]*) ]] then print -r "char *$i = { NULL };" >> $g_HFILE else print -r "char *$i = NULL;" >> $g_HFILE fi done fi # Assume number else print -r "$TYPE $VAR;" >> $g_HFILE fi } #----------------------------------------------------------- function Handle_Local { # Local variables typeset VAR TYPE CHECK TARGET DIM # Get the variablename and type if [[ "$1" = +(* TYPE *) ]] then VAR=`print ${1%% TYPE *}` TYPE=`print ${1##* TYPE }` else VAR=`print ${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 "\/\*record\*\/"` fi if [[ -n $CHECK ]] then print "\nERROR: variable in LOCAL statement at line $g_COUNTER in file '$g_CURFILE' was defined previously!" exit 1 fi # Check if var is string var and not an argument in an array itself if [[ "${VAR}" = +(*\$*) && "${VAR}" != +(*\[*\$*\]*) ]] then STR=${VAR%\$*} CHECK=`grep -E "char \*${STR}\\\\$ = " ${TARGET}` if [[ -z $CHECK ]] then STR=`print ${VAR} | tr ',' ' '` for i in $STR do # Check on multidimensional stringarrays if [[ "${i}" = +(*\[*\]*\]*) ]] then print "\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 print -r "char *$i;" >> $g_CFILE DIM=${i##*\[}; DIM=${DIM%%\]*} g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++)if($g_RECORDVAR.${i%%\[*}[__b2c__ctr]!=NULL){free($g_RECORDVAR.${i%%\[*}[__b2c__ctr]);}" else print -r "char *$i; /*record*/" >> $g_CFILE fi else if [[ "${i}" = +(*\[*\]*) ]] then print -r "char *$i = { NULL };" >> $g_CFILE DIM=${i##*\[}; DIM=${DIM%%\]*} g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++)if(${i%%\[*}[__b2c__ctr]!=NULL){free(${i%%\[*}[__b2c__ctr]);}" else print -r "char *$i = NULL;" >> $g_CFILE g_LOCALSTRINGS="$g_LOCALSTRINGS ${i}" fi fi # We are in the mainprogram else if [[ -n $g_RECORDNAME ]] then print -r "char *$i; /*record*/" >> $g_HFILE else if [[ "${i}" = +(*\[*\]*) ]] then print -r "char *$i = { NULL };" >> $g_CFILE else print -r "char *$i = NULL;" >> $g_HFILE fi fi fi done fi # Assume number else if [[ -n $g_FUNCNAME ]] then if [[ -n $g_RECORDNAME ]] then print -r "$TYPE $VAR; /*record*/" >> $g_CFILE else print -r "$TYPE $VAR;" >> $g_CFILE fi else if [[ -n $g_RECORDNAME ]] then print -r "$TYPE $VAR; /*record*/" >> $g_HFILE else print -r "$TYPE $VAR;" >> $g_HFILE fi fi fi } #----------------------------------------------------------- function Handle_Read { # Local variables typeset CHECK TARGET STR # Check if we have an argument at all if [[ "$1" = "READ" ]] then print "\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}" = +(*\$) ]] then STR=${1%\$*} CHECK=`grep -E "char \*${STR}\\\\$ = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$1 = NULL;" >> $g_HFILE fi # Convert to C print -r "$1 = (char*)realloc($1, (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" >> $g_CFILE print -r "strcpy($1, __b2c__stringarray[__b2c__stringarray_ptr]);" >> $g_CFILE print -r "__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 "\/\*record\*\/"` if [[ -z $CHECK ]] then print -r "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 "\/\*record\*\/"` fi # Convert to C if [[ "$CHECK" = +(*double *) || "$CHECK" = +(*float *) || "$CHECK" = +(*FLOATING *) ]] then print -r "${1} = __b2c__floatarray[__b2c__floatarray_ptr];" >> $g_CFILE print -r "__b2c__floatarray_ptr++;" >> $g_CFILE elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*int *) || "$CHECK" = +(*NUMBER *) ]] then print -r "${1} = __b2c__intarray[__b2c__intarray_ptr];" >> $g_CFILE print -r "__b2c__intarray_ptr++;" >> $g_CFILE else print -r "${1} = (char*)realloc($1, (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" >> $g_CFILE print -r "strcpy(${1}, __b2c__stringarray[__b2c__stringarray_ptr]);" >> $g_CFILE print -r "__b2c__stringarray_ptr++;" >> $g_CFILE fi fi } #----------------------------------------------------------- function Handle_Endfunction { # Check if return was found if [[ -z $g_FUNCTYPE ]] then print "\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 print -r "$g_FUNCTYPE $g_ORIGFUNCNAME(void) {" > ${g_COPY_CFILE%.*}.$g_FUNCNAME.h else print -r "$g_FUNCTYPE $g_ORIGFUNCNAME {" > ${g_COPY_CFILE%.*}.$g_FUNCNAME.h fi # Add function body print -r "${g_STRINGARGS}" >> ${g_COPY_CFILE%.*}.$g_FUNCNAME.h cat $g_CFILE >> ${g_COPY_CFILE%.*}.$g_FUNCNAME.h print -r "__B2C__PROGRAM__EXIT: ;" >> ${g_COPY_CFILE%.*}.$g_FUNCNAME.h print -r "}" >> ${g_COPY_CFILE%.*}.$g_FUNCNAME.h # Include header file if [[ ${g_INCLUDE_FILES} != +(*${g_COPY_CFILE%\.*}.$g_FUNCNAME.h*) ]] then g_INCLUDE_FILES="$g_INCLUDE_FILES ${g_COPY_CFILE%\.*}.$g_FUNCNAME.h" fi # Add to total filelist g_TMP_FILES="$g_TMP_FILES ${g_COPY_CFILE%.*}.$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 typeset CHECK STR DQ FUNC ARG # Check if we have an argument at all if [[ "$1" = "RETURN" ]] then print "\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 "\/\*record\*\/"` # Determine if argument ends with Double Quote typeset -R1 DQ="$1" typeset -u -L3 FUNC="${1}" # 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}" = +(*\$*) || "$DQ" = "\"" || "$DQ" = "\"" ]] then g_FUNCTYPE="char * " print -r "__b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= $g_MAX_RBUFFERS) __b2c__rbuffer_ptr=0; if($1 != NULL)" >> $g_CFILE print -r " {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen($1)+1)*sizeof(char));" >> $g_CFILE print -r "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], $1);}" >> $g_CFILE print -r "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], 2*sizeof(char));" >> $g_CFILE print -r "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 print -r "if($STR != NULL) free($STR);" >> $g_CFILE done print -r "${g_STRINGARRAYS}" >> $g_CFILE # The actual return value print -r "return (${ARG});" >> $g_CFILE } #----------------------------------------------------------- function Handle_Push { # Local variables typeset CHECK TARGET # Check if we have an argument at all if [[ "$1" = "PUSH" ]] then print "\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 "\/\*record\*\/"` fi # Check type of var, string? if [[ "${1}" = +(*\$*) ]] then print -r "if(__b2c__stringstack[__b2c__stackptr] == NULL){__b2c__stringstack[__b2c__stackptr] = (char*)realloc(__b2c__stringstack[__b2c__stackptr], (strlen($1)+1)*sizeof(char));}" >> $g_CFILE print -r "strcpy(__b2c__stringstack[__b2c__stackptr], $1);" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 1;" >> $g_CFILE # Check if it is a normal string elif [[ "$1" != `print -r "$1" | tr -d "\042"` ]] then print -r "if(__b2c__stringstack[__b2c__stackptr] == NULL){__b2c__stringstack[__b2c__stackptr] = (char*)realloc(__b2c__stringstack[__b2c__stackptr], (strlen($1)+1)*sizeof(char));}" >> $g_CFILE print -r "strcpy(__b2c__stringstack[__b2c__stackptr], $1);" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 1;" >> $g_CFILE # Check if float elif [[ "$1" = +(*.*) ]] then print -r "__b2c__doublestack[__b2c__stackptr] = $1;" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 2;" >> $g_CFILE # Check if no alpha chars (then integer value) elif [[ "$1" = +(![a-zA-Z]) ]] then print -r "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE # Assume variable, check if declared before elif [[ -n $CHECK ]] then if [[ $CHECK = +(double*) ]] then print -r "__b2c__doublestack[__b2c__stackptr] = $1;" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 2;" >> $g_CFILE else print -r "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE fi # Not declared, assume integer variable else print -r "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE print -r "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE fi # Increase stackpointer print -r "__b2c__stackptr++;" >> $g_CFILE print -r "if(__b2c__stackptr == $g_STACK_DEPTH) __b2c__stackptr=$g_STACK_DEPTH-1;" >> $g_CFILE } #----------------------------------------------------------- function Handle_Pull { typeset CHECK TARGET STR # Check if we have an argument at all if [[ "$1" = "PULL" ]] then print "\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 print "\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 print -r "__b2c__stackptr--;" >> $g_CFILE print -r "if(__b2c__stackptr < 0) __b2c__stackptr=0;" >> $g_CFILE # Get the last value from stack if [[ "${1}" = +(*\$) ]] then STR=${1%\$*} CHECK=`grep -E "char \*${STR}\\\\$ = NULL;" ${TARGET}` if [[ -z $CHECK ]] then print -r "char *$1 = NULL;" >> $g_HFILE fi print -r "if(__b2c__typestack[__b2c__stackptr] == 1) {" >> $g_CFILE print -r "$1 = (char*)realloc($1, (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" >> $g_CFILE print -r "strcpy($1, __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 "\/\*record\*\/"` if [[ -z $CHECK ]] then print -r "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 "\/\*record\*\/"` fi # Make sure internal var is copied to var of program if [[ "$CHECK" = +(*double *) || "$CHECK" = +(*float *) || "$CHECK" = +(*FLOATING *) ]] then print -r "if(__b2c__typestack[__b2c__stackptr] == 2) $1=__b2c__doublestack[__b2c__stackptr];" >> $g_CFILE elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*int *) || "$CHECK" = +(*NUMBER *) ]] then print -r "if(__b2c__typestack[__b2c__stackptr] == 3) $1=__b2c__longstack[__b2c__stackptr];" >> $g_CFILE else print -r "if(__b2c__typestack[__b2c__stackptr] == 1) {" >> $g_CFILE print -r "$1 = (char*)realloc($1, (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" >> $g_CFILE print -r "strcpy($1, __b2c__stringstack[__b2c__stackptr]);}" >> $g_CFILE fi fi } #----------------------------------------------------------- function Handle_SubFunc { typeset ARGS TOKEN LEN CHAR # Check argument if [[ "${1}" = "SUB" ]] then print "\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 print "\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=`print ${1%%\(*}"("` # Start miniparser to duplicate string arguments, convert spaces ARGS=`print -r "${1##*\(}" | tr " " "\001"` TOKEN= LEN=${#ARGS} # Get the characters until [[ $LEN -eq 0 ]] do typeset -L1 CHAR="${ARGS}" if [[ $CHAR = "," ]] then if [[ ${TOKEN} = +(*STRING*) || ${TOKEN} = +(*char\**) ]] then 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 typeset -R$LEN ARGS="${ARGS}" 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 )" fi # Get original function name if [[ "$g_ORIGFUNCNAME" = +(* \(*\)*) ]] then g_FUNCNAME=`print ${g_ORIGFUNCNAME%% *}` elif [[ "$g_ORIGFUNCNAME" = +(*\(*\)*) ]] then g_FUNCNAME=`print ${g_ORIGFUNCNAME%%\(*}` else g_FUNCNAME=`print $g_ORIGFUNCNAME` fi # 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 print -r "void ${g_ORIGFUNCNAME} {" > ${g_COPY_CFILE%.*}.$g_FUNCNAME.h elif [[ "$g_ORIGFUNCNAME" = +(*\(*\)*) ]] then print -r "void ${g_ORIGFUNCNAME} {" > ${g_COPY_CFILE%.*}.$g_FUNCNAME.h else print -r "void ${g_FUNCNAME}(void) {" > ${g_COPY_CFILE%.*}.$g_FUNCNAME.h fi # Finalize sub print -r "${g_STRINGARGS}" >> ${g_COPY_CFILE%.*}.$g_FUNCNAME.h cat $g_CFILE >> ${g_COPY_CFILE%.*}.$g_FUNCNAME.h # Free strings variables if there are any for STR in $g_LOCALSTRINGS do print -r "if($STR != NULL) free(${STR});" >> ${g_COPY_CFILE%.*}.$g_FUNCNAME.h done print -r "${g_STRINGARRAYS}" >> ${g_COPY_CFILE%.*}.$g_FUNCNAME.h print -r "__B2C__PROGRAM__EXIT: ;" >> ${g_COPY_CFILE%.*}.$g_FUNCNAME.h print -r "}" >> ${g_COPY_CFILE%.*}.$g_FUNCNAME.h # Include header file if [[ ${g_INCLUDE_FILES} != +(*${g_COPY_CFILE%\.*}.$g_FUNCNAME.h*) ]] then g_INCLUDE_FILES="$g_INCLUDE_FILES ${g_COPY_CFILE%\.*}.$g_FUNCNAME.h" fi # Add to total filelist g_TMP_FILES="$g_TMP_FILES ${g_COPY_CFILE%.*}.$g_FUNCNAME.h" # Delete temp funcfile rm $g_CFILE # Restore mainfile g_CFILE=$g_COPY_CFILE # Restore CATCH routine g_CATCHGOTO="$g_ORIGCATCHGOTO" # Reset variables g_ORIGFUNCNAME= g_FUNCNAME= g_LOCALSTRINGS= g_STRINGARRAYS= g_STRINGARGS= } #----------------------------------------------------------- function Handle_Deffn { typeset SYM # Check if we have an argument at all if [[ "$1" = "DEF" ]] then print "\nERROR: empty DEF FN at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Translate to C macro SYM=${1#* } print -r "#define ${SYM%%=*} ${SYM#*=}" >> $g_HFILE # Make symbol known to parser g_IMPORTED="${SYM%%\(*} $g_IMPORTED" } #----------------------------------------------------------- function Handle_Const { # Check if we have an argument at all if [[ "$1" = "CONST" ]] then print "\nERROR: empty CONST at line $g_COUNTER in file $g_CURFILE!" exit 1 fi print -r "#define ${1%%=*} (${1#*=})" >> $g_HFILE } #----------------------------------------------------------- function Handle_Seek { typeset FILE OFFSET WHENCE # Check if we have an argument at all if [[ "$1" = "SEEK" ]] then print "\nERROR: empty SEEK at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if TO is available if [[ "$1" != +(* OFFSET *) ]] then print "\nERROR: Missing OFFSET in SEEK statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the variablename without surrounding spaces FILE=`print ${1%% OFFSET *}`; # Get filedescriptor OFFSET=`print ${1##* OFFSET }` WHENCE= # Check if WHENCE is available if [[ "$1" = +(* WHENCE *) ]] then WHENCE=${OFFSET##* WHENCE } OFFSET=${OFFSET%% WHENCE *} fi # Convert to C function case $WHENCE in +(START) ) print -r "fseek($FILE, $OFFSET, SEEK_SET);" >> $g_CFILE;; +(CURRENT) ) print -r "fseek($FILE, $OFFSET, SEEK_CUR);" >> $g_CFILE;; +(END) ) print -r "fseek($FILE, $OFFSET, SEEK_END);" >> $g_CFILE;; *) print -r "fseek($FILE, $OFFSET, SEEK_SET);" >> $g_CFILE;; esac } #----------------------------------------------------------- function Handle_Copy { typeset FROM TO # Check if we have an argument at all if [[ "$1" = "COPY" ]] then print "\nERROR: empty COPY at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nERROR: Missing TO in COPY statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the filename and copyname FROM=`print ${1%% TO *}` TO=`print ${1##* TO }` # Translate to C function print -r "__b2c__inFile = fopen($FROM, \"r\"); __b2c__outFile = fopen($TO, \"w\"); __b2c__Byte = 0;" >> $g_CFILE print -r "if (__b2c__inFile != NULL && __b2c__outFile != NULL){while(__b2c__Byte!=EOF){" >> $g_CFILE print -r "__b2c__Byte=fgetc(__b2c__inFile); if(__b2c__Byte!=EOF){" >> $g_CFILE print -r "fputc(__b2c__Byte,__b2c__outFile); }}}" >> $g_CFILE print -r "fclose(__b2c__inFile); fclose(__b2c__outFile);" >> $g_CFILE } #----------------------------------------------------------- function Handle_Rename { typeset FROM TO # Check if we have an argument at all if [[ "$1" = "RENAME" ]] then print "\nERROR: empty RENAME at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if TO is available if [[ "$1" != +(* TO *) ]] then print "\nERROR: Missing TO in RENAME statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the filename and copyname FROM=`print ${1%% TO *}` TO=`print ${1##* TO }` # Translate to C function print -r "if(rename($FROM, $TO) < 0) {if(!__b2c__trap){ERROR = 9; if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE } #----------------------------------------------------------- function Handle_Color { typeset -u TO FROM # Check if we have an argument at all if [[ "$1" = "COLOR" ]] then print "\nERROR: empty COLOR at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if we need to reset if [[ "$1" = +(*RESET*) ]] then print -r "printf(\"\033[0m\");" >> $g_CFILE elif [[ "$1" = +(*INTENSE*) ]] then print -r "printf(\"\033[1m\");" >> $g_CFILE elif [[ "$1" = +(*INVERSE*) ]] then print -r "printf(\"\033[7m\");" >> $g_CFILE elif [[ "$1" = +(*NORMAL*) ]] then print -r "printf(\"\033[22m\");" >> $g_CFILE # Check if TO is available elif [[ "$1" != +(* TO *) ]] then print "\nERROR: Missing TO in COLOR statement at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Get the target and colorname FROM=`print ${1%% TO *}` TO=`print ${1##* TO }` # Now select color if [[ $FROM = +(*FG*) ]] then case $TO in "BLACK") print -r "printf(\"\033[30m\");" >> $g_CFILE;; "RED") print -r "printf(\"\033[31m\");" >> $g_CFILE;; "GREEN") print -r "printf(\"\033[32m\");" >> $g_CFILE;; "YELLOW") print -r "printf(\"\033[33m\");" >> $g_CFILE;; "BLUE") print -r "printf(\"\033[34m\");" >> $g_CFILE;; "MAGENTA") print -r "printf(\"\033[35m\");" >> $g_CFILE;; "CYAN") print -r "printf(\"\033[36m\");" >> $g_CFILE;; "WHITE") print -r "printf(\"\033[37m\");" >> $g_CFILE;; esac elif [[ $FROM = +(*BG*) ]] then case $TO in "BLACK") print -r "printf(\"\033[40m\");" >> $g_CFILE;; "RED") print -r "printf(\"\033[41m\");" >> $g_CFILE;; "GREEN") print -r "printf(\"\033[42m\");" >> $g_CFILE;; "YELLOW") print -r "printf(\"\033[43m\");" >> $g_CFILE;; "BLUE") print -r "printf(\"\033[44m\");" >> $g_CFILE;; "MAGENTA") print -r "printf(\"\033[45m\");" >> $g_CFILE;; "CYAN") print -r "printf(\"\033[46m\");" >> $g_CFILE;; "WHITE") print -r "printf(\"\033[47m\");" >> $g_CFILE;; esac fi fi } #----------------------------------------------------------- function Handle_Gotoxy { typeset X Y # Check if we have an argument at all if [[ "$1" = "GOTOXY" ]] then print "\nERROR: empty GOTOXY at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the target and colorname if [[ "$1" = +(*,*) ]] then X=`print ${1%%,*}` Y=`print ${1##*,}` else print "\nERROR: missing coordinate in GOTOXY at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Translate to C print -r "printf(\"\033[${Y};${X}H\");" >> $g_CFILE } #----------------------------------------------------------- function Handle_Split { typeset SOURCE REST BY TO SIZE TARGET CHECK # Check if we have an argument at all if [[ "$1" = "SPLIT" ]] then print "\nERROR: empty SPLIT at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Check if BY is available if [[ "$1" != +(* BY *) ]] then print "\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 print "\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 print "\nERROR: Missing SIZE in SPLIT statement at line $g_COUNTER in file $g_CURFILE!" exit 1 fi # Get the source string SOURCE=`print ${1%% BY *}` REST=`print ${1##* BY }` BY=`print ${REST%% TO *}` REST=`print ${REST##* TO }` TO=`print ${REST%% SIZE *}` SIZE=`print ${REST##* SIZE }` # 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 "\/\*record\*\/"` if [[ -z $CHECK ]] then print -r "long $SIZE;" >> $g_HFILE fi fi # Translate to C code if [[ -n $g_FUNCNAME ]] then if [[ $g_STRINGARGS != +(*\*\*$TO*) ]] then g_STRINGARGS="$g_STRINGARGS char **$TO = NULL; int __b2c__split__$TO = 0;" fi else if [[ -z `grep "$TO = NULL;" $g_HFILE` ]] then print -r "char **$TO = NULL; int __b2c__split__$TO = 0;" >> $g_HFILE fi fi # If the split array was used before in a loop, clear it print -r "if($TO != NULL) {for(__b2c__ctr=0; __b2c__ctr<=__b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr]!=NULL)" >> $g_CFILE print -r "{free($TO[__b2c__ctr]);} free($TO); $TO = NULL; __b2c__split__$TO = 0;}" >> $g_CFILE # Run the SPLIT code print -r "if ($SOURCE != NULL && $BY != NULL && strlen($BY) > 0) {__b2c__split_tmp = strdup($SOURCE); __b2c__split = strtok(__b2c__split_tmp, $BY);" >> $g_CFILE print -r "if (__b2c__split != NULL) {$TO = (char **)realloc($TO, (__b2c__split__$TO + 1) * sizeof(char*)); $TO[__b2c__split__$TO++] = strdup(__b2c__split);" >> $g_CFILE print -r "while((__b2c__split = strtok(NULL, $BY)) != NULL) {$TO = (char **)realloc($TO, (__b2c__split__$TO + 1) * sizeof(char*));" >> $g_CFILE print -r "$TO[__b2c__split__$TO++] = strdup(__b2c__split);} } free(__b2c__split_tmp);} $SIZE = __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=0; __b2c__ctr<=__b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr]!=NULL){free($TO[__b2c__ctr]);} free($TO);}" fi } #----------------------------------------------------------- # # Simple parser to tokenize line. # # Each line should begin with a statement. # The rest of the line may contain functions, these are # converted using C macros. # #----------------------------------------------------------- function Parse_Line { typeset FOUND SYM INC COPY_COUNTER COPY_CURFILE STATEMENT typeset LEN SEQ TOTAL EXP # Get statement without spaces STATEMENT=`print -r "${1%% *}"` if [[ $g_USE_C -eq 1 ]] then if [[ "$STATEMENT" = "END" || "$STATEMENT" = "ENDUSEC" ]] then let g_USE_C=0 else print -r "${1}" >> $g_CFILE fi else case "$STATEMENT" in "USEC") let g_USE_C=1;; "PRINT") Handle_Print "${1#* }";; "INPUT") Handle_Input "${1#* }";; "FOR") Handle_For "${1#* }";; "NEXT") print -r "}" >> $g_CFILE;; "IF") Handle_If "${1#* }";; "ELIF") Handle_Elif "${1#* }";; "ELSE") print -r "} else {" >> $g_CFILE;; "ENDIF") print -r "}" >> $g_CFILE;; "WHILE") Handle_While "${1#* }";; "WEND") print -r "}" >> $g_CFILE;; "BREAK") print -r "break;" >> $g_CFILE;; "REPEAT") print -r "do{" >> $g_CFILE;; "UNTIL") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty UNTIL at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Convert to legal C code print -r "} while(!(${1#* }));" >> $g_CFILE fi;; "LET") Handle_Let "${1#* }";; +(REM*) ) ;; +(\'*) ) ;; "SYSTEM") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty SYSTEM at line $g_COUNTER in file $g_CURFILE!" exit 1 else print -r "SYSTEM (${1#* });" >> $g_CFILE fi;; "SLEEP") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty SLEEP at line $g_COUNTER in file $g_CURFILE!" exit 1 else print -r "usleep(${1#* }*1000);" >> $g_CFILE fi;; "OPEN") Handle_Open "${1#* }";; "CLOSE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty CLOSE at line $g_COUNTER in file $g_CURFILE!" exit 1 else SYM="${1#* }" if [[ "$SYM" = +(*FILE*) ]] then print -r "fclose(${1##* });" >> $g_CFILE elif [[ "$SYM" = +(*DIRECTORY*) ]] then print -r "closedir(${1##* });" >> $g_CFILE elif [[ "$SYM" = +(*MEMORY*) ]] then print -r "${1##* } = NULL;" >> $g_CFILE elif [[ "$SYM" = +(*NETWORK*) || "$SYM" = +(*SERVER*) ]] then print -r "close(${1##* });" >> $g_CFILE else print "\nERROR: erronuous CLOSE argument at line $g_COUNTER in file $g_CURFILE!" exit 1 fi fi;; "REWIND") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty REWIND at line $g_COUNTER in file $g_CURFILE!" exit 1 else print -r "rewind(${1#* });" >> $g_CFILE fi;; "MEMREWIND") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty MEMREWIND at line $g_COUNTER in file $g_CURFILE!" exit 1 else print -r "${1#* } = (char*)__b2c_mem_${1#* };" >> $g_CFILE fi;; "SEEK") Handle_Seek "${1#* }";; "READLN") Handle_Readln "${1#* }";; "WRITELN") Handle_Writeln "${1#* }";; "GETBYTE") Handle_Getbyte "${1#* }";; "PUTBYTE") Handle_Putbyte "${1#* }";; "GETFILE") Handle_Getfile "${1#* }";; "GETLINE") Handle_Getline "${1#* }";; "PUTLINE") Handle_Putline "${1#* }";; "END") if [[ "${1#* }" = +(*IF*) ]] then print -r "}" >> $g_CFILE elif [[ "${1#* }" = +(*RECORD*) ]] then if [[ -n $g_FUNCNAME ]] then print -r "};" >> $g_CFILE print -r "struct $g_RECORDNAME $g_RECORDVAR = { } ;" >> $g_CFILE else print -r "};" >> $g_HFILE print -r "struct $g_RECORDNAME $g_RECORDVAR = { } ;" >> $g_HFILE fi g_RECORDNAME= g_RECORDVAR= elif [[ "${1#* }" = +(*FUNCTION*) ]] then Handle_Endfunction elif [[ "${1#* }" = +(*SUB*) ]] then Handle_Endsub elif [[ "${1#* }" = +(*WITH*) ]] then g_WITHVAR= elif [[ "${1#* }" = +(*SELECT*) ]] then print -r "}" >> $g_CFILE g_SELECTVAR= g_IN_CASE= elif [[ "${1#* }" != "END" ]] then print -r "exit(${1#* });" >> $g_CFILE else print -r "exit(EXIT_SUCCESS);" >> $g_CFILE fi;; "SUB") Handle_SubFunc "${1#* }";; "ENDSUB") Handle_Endsub;; "ENDWITH") g_WITHVAR=;; "ENDSELECT") print -r "}" >> $g_CFILE g_SELECTVAR= g_IN_CASE=;; "CALL") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty CALL at line $g_COUNTER in file $g_CURFILE!" exit 1 else SYM=`print "${1#* }"` if [[ "$SYM" = +(* TO *) ]] then print -r -n "${SYM##*TO } = " >> $g_CFILE if [[ "${SYM%% TO*}" = +(*\(*\)*) ]] then print -r "${SYM%% TO*};" >> $g_CFILE EXP="${SYM%% TO*}" else print -r "${SYM%% TO*}();" >> $g_CFILE EXP="${SYM%% TO*}()" fi if [[ ${g_INCLUDE_FILES} != +(*$g_TEMPDIR/$SOURCEFILE.${EXP%%\(*}.h*) ]] then g_INCLUDE_FILES="$g_TEMPDIR/$SOURCEFILE.${EXP%%\(*}.h ${g_INCLUDE_FILES}" fi else if [[ "$SYM" = +(*\(*\)*) ]] then print -r "$SYM;" >> $g_CFILE EXP="${SYM}" else print -r "$SYM();" >> $g_CFILE EXP="${SYM}()" fi if [[ ${g_INCLUDE_FILES} != +(*$g_TEMPDIR/$SOURCEFILE.${EXP%%\(*}.h*) ]] then g_INCLUDE_FILES="$g_TEMPDIR/$SOURCEFILE.${EXP%%\(*}.h ${g_INCLUDE_FILES}" fi fi fi;; "FUNCTION") Handle_SubFunc "${1#* }";; "ENDFUNCTION") Handle_Endfunction;; "RETURN") Handle_Return "${1#* }";; "IMPORT") Handle_Import "${1#* }";; "DECLARE") Handle_Declare "${1#* }";; "GLOBAL") Handle_Declare "${1#* }";; "LOCAL") Handle_Local "${1#* }";; "DATA") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty DATA at line $g_COUNTER in file $g_CURFILE!" exit 1 else if [[ "${1#* }" != `print -r "${1#* }" | tr -d "\042"` ]] then print -r "${1#* }, " >> $STRINGARRAYFILE else # Check if float if [[ "${1#* }" = +(*.*) ]] then print -r "${1#* }, " >> $FLOATARRAYFILE else print -r "${1#* }, " >> $INTARRAYFILE fi fi fi;; "RESTORE") print -r "if(__b2c__intarray_ptr > 0) __b2c__intarray_ptr = 0;" >> $g_CFILE print -r "if(__b2c__floatarray_ptr > 0) __b2c__floatarray_ptr = 0;" >> $g_CFILE print -r "if(__b2c__stringarray_ptr > 0) __b2c__stringarray_ptr = 0;" >> $g_CFILE;; "READ") Handle_Read "${1#* }";; "PUSH") Handle_Push "${1#* }";; "PULL") Handle_Pull "${1#* }";; "SEED") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty SEED at line $g_COUNTER in file $g_CURFILE!" exit 1 else print -r "srandom((unsigned int)${1#* });" >> $g_CFILE fi;; "DEF") Handle_Deffn "${1#* }";; "CONST") Handle_Const "${1#* }";; "INCLUDE") # Get rid of doublequotes if they are there INC=`print ${1#* } | tr -d "\042"` # Check argument if [[ ! -f $INC || "${1%% *}" = "${1#* }" ]] then print "\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 g_CURFILE=$INC while read -r LINE do print -n "\rStarting conversion... $g_COUNTER" # Line is not empty? if [[ -n "$LINE" ]] then if [[ "$LINE" = +(* \\) ]] then let LEN="${#LINE}"-1 typeset -L$LEN SEQ="${LINE}" 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 [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty POKE at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Resolve this with C macro because of casting to (char) print -r "POKE(${1#* });" >> $g_CFILE fi;; "RESIZE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty RESIZE at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Resolve this with C macro because of casting to (char) print -r "RESIZE(${1#* });" >> $g_CFILE fi;; "COPY") Handle_Copy "${1#* }";; "DELETE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty DELETE at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C function if [[ "${1#* }" = +(*FILE*) ]] then print -r "if (unlink(${1#*FILE })==-1){if(!__b2c__trap){ERROR = 7;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE elif [[ "${1#* }" = +(*DIRECTORY*) ]] then print -r "if (rmdir(${1#*DIRECTORY }) == -1){if(!__b2c__trap){ERROR = 20;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE else print "\nERROR: erronuous argument for DELETE at line $g_COUNTER in file $g_CURFILE!" exit 1 fi fi;; "RENAME") Handle_Rename "${1#* }";; "MAKEDIR") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty MAKEDIR at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C function print -r "if (mkdir(${1#* }, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == -1){if(!__b2c__trap){ERROR = 21;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE fi;; "CHANGEDIR") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty CHANGEDIR at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C function print -r "if (chdir(${1#* }) == -1){if(!__b2c__trap) {ERROR = 22;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE fi;; "FREE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty FREE at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C function print -r "if(!__b2c__trap){__b2c__memory__check((char *)${1#* });" >> $g_CFILE print -r "if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} } free((void*)${1#* });" >> $g_CFILE fi;; "GOTO") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty GOTO at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C label print -r "goto ${1#* };" >> $g_CFILE fi;; "LABEL") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty LABEL at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Translate to C label print -r "${1#* }:" >> $g_CFILE print -r ";" >> $g_CFILE fi;; "TRAP") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty TRAP at line $g_COUNTER in file $g_CURFILE!" exit 1 else if [[ "${1#* }" = "SYSTEM" ]] then print -r "/* Error trapping by OS */" >> $g_CFILE print -r "__b2c__trap = 1;" >> $g_CFILE print -r "signal(SIGILL, __b2c__catch_signal);" >> $g_CFILE print -r "signal(SIGABRT, __b2c__catch_signal);" >> $g_CFILE print -r "signal(SIGFPE, __b2c__catch_signal);" >> $g_CFILE print -r "signal(SIGSEGV, __b2c__catch_signal);" >> $g_CFILE elif [[ "${1#* }" = "LOCAL" ]] then print -r "/* Error trapping by BaCon */" >> $g_CFILE print -r "__b2c__trap = 0;" >> $g_CFILE print -r "signal(SIGILL, SIG_DFL);" >> $g_CFILE print -r "signal(SIGABRT, SIG_DFL);" >> $g_CFILE print -r "signal(SIGFPE, SIG_DFL);" >> $g_CFILE print -r "signal(SIGSEGV, SIG_DFL);" >> $g_CFILE else print "\nERROR: invalid argument for TRAP at line $g_COUNTER in file $g_CURFILE!" exit 1 fi fi;; "CATCH") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty CATCH at line $g_COUNTER in file $g_CURFILE!" exit 1 elif [[ "${1#* }" = +(*GOTO*) ]] then print -r "__b2c__catch_set = 1;" >> $g_CFILE g_CATCHGOTO="${1##* GOTO }" elif [[ "${1#* }" = +(*RESET*) ]] then print -r "__b2c__catch_set = 0;" >> $g_CFILE else print "\nERROR: CATCH without GOTO or RESET at line $g_COUNTER in file $g_CURFILE!" exit 1 fi;; "RESUME") print -r "longjmp(__b2c__jump, 1);" >> $g_CFILE;; "CLEAR") print -r "printf(\"\033[2J\"); printf(\"\033[0;0f\");" >> $g_CFILE;; "COLOR") Handle_Color "${1#* }";; "GOTOXY") Handle_Gotoxy "${1#* }";; "RECEIVE") Handle_Receive "${1#* }";; "SEND") Handle_Send "${1#* }";; "RECORD") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty RECORD at line $g_COUNTER in file $g_CURFILE!" exit 1 elif [[ -n $g_RECORDNAME ]] then print "\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}" print -r "struct $g_RECORDNAME{" >> $g_CFILE else g_RECORDNAME="RECORD_${g_COUNTER}" print -r "struct $g_RECORDNAME{" >> $g_HFILE fi g_RECORDVAR=${1#* } fi;; "WITH") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty WITH at line $g_COUNTER in file $g_CURFILE!" exit 1 elif [[ -n $g_RECORDNAME ]] then print "\nERROR: cannot define a WITH within a WITH!" exit 1 else g_WITHVAR=${1#* } fi;; "SPLIT") Handle_Split "${1#* }";; "SELECT") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty SELECT at line $g_COUNTER in file $g_CURFILE!" exit 1 elif [[ -n $g_SELECTVAR ]] then print "\nERROR: cannot define a SELECT within a SELECT!" exit 1 else g_SELECTVAR=${1#* } g_IN_CASE= g_CASE_FALL= fi;; "CASE") # Check argument if [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty CASE at line $g_COUNTER in file $g_CURFILE!" exit 1 else if [[ -n $g_IN_CASE ]] then if [[ ${g_SELECTVAR} = +(*\$*) ]] then # Get expression without ; if [[ -z ${1##*;} ]] then let LEN="${#1}"-1; typeset -L$LEN EXP="${1}" g_CASE_FALL="|| !strcmp(${g_SELECTVAR}, ${EXP#* }) ${g_CASE_FALL}" else print -r "} else if (!strcmp(${g_SELECTVAR}, ${1#* }) ${g_CASE_FALL}){" >> $g_CFILE fi else # Get expression without ; if [[ -z ${1##*;} ]] then let LEN="${#1}"-1; typeset -L$LEN EXP="${1}" g_CASE_FALL="|| ${g_SELECTVAR} == (${EXP#* }) ${g_CASE_FALL}" else print -r "} else if (${g_SELECTVAR} == (${1#* }) ${g_CASE_FALL}){" >> $g_CFILE fi fi else if [[ ${g_SELECTVAR} = +(*\$*) ]] then # Get expression without ; if [[ -z ${1##*;} ]] then let LEN="${#1}"-1; typeset -L$LEN EXP="${1}" g_CASE_FALL="|| !strcmp(${g_SELECTVAR}, ${EXP#* }) ${g_CASE_FALL}" else print -r "if (!strcmp(${g_SELECTVAR}, ${1#* }) ${g_CASE_FALL}){" >> $g_CFILE fi else # Get expression without ; if [[ -z ${1##*;} ]] then let LEN="${#1}"-1; typeset -L$LEN EXP="${1}" g_CASE_FALL="|| ${g_SELECTVAR} == (${EXP#* }) ${g_CASE_FALL}" else print -r "if (${g_SELECTVAR} == (${1#* }) ${g_CASE_FALL}){" >> $g_CFILE fi fi fi g_IN_CASE=1 fi;; "DEFAULT") if [[ -n $g_IN_CASE ]] then print -r "} else {" >> $g_CFILE else print "\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 [[ "${1%% *}" = "${1#* }" ]] then print "\nERROR: empty SETENVIRON at line $g_COUNTER in file $g_CURFILE!" exit 1 else # Resolve this with C macro print -r "SETENVIRON(${1#* });" >> $g_CFILE fi;; *) # Check on imported symbols first FOUND=0 for SYM in $g_IMPORTED do if [[ "$SYM" = ${1%%\(*} || "$SYM" = ${1%% *} ]] then FOUND=1 if [[ "$1" != +(*\(*\)*) ]] then print -r "$SYM();" >> $g_CFILE else print -r "$SYM(${1#*\(};" >> $g_CFILE fi fi done # Not an imported symbol? Check if assignment if [[ $FOUND -eq 0 ]] then Handle_Let "$1" fi;; esac fi } #----------------------------------------------------------- # # 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_STACK_DEPTH=8 let g_TMP_PRESERVE=0 let g_USE_C=0 let g_MAX_BACKLOG=4 g_TEMPDIR=. g_CCNAME=cc g_CCFLAGS= g_INCFILES= g_INCLUDE_FILES= # Some global declarations g_CURFILE= g_FUNCNAME= g_FUNCTYPE= g_TMP_FILES= g_LOCALSTRINGS= g_STRINGARRAYS= g_STRINGARGS= # Always create a final label g_CATCHGOTO="__B2C__PROGRAM__EXIT" # Records g_RECORDNAME= g_RECORDVAR= g_WITHVAR= # Get arguments while getopts ":m:c:s:d:i:l:awognpv" OPT do case $OPT in m) g_MAX_BUFFERS=$OPTARG;; c) g_CCNAME=$OPTARG;; s) g_STACK_DEPTH=$OPTARG;; d) g_TEMPDIR=$OPTARG;; i) g_INCFILES="$g_INCFILES $OPTARG";; l) g_LDFLAGS="$g_LDFLAGS -l$OPTARG";; n) g_NO_COMPILE=1;; g) g_CCFLAGS="$g_CCFLAGS -g";; w) g_CCFLAGS="$g_CCFLAGS -Wall";; o) g_CCFLAGS="$g_CCFLAGS -mtune=native";; p) let g_TMP_PRESERVE=1;; a) g_CCFLAGS="$g_CCFLAGS -m32";; v) print print "BaCon version $g_VERSION - (c) Peter van Eerten - GPL v2." print exit 0;; \?|h) print print "USAGE: bacon [options] program[.bac]" print print "OPTIONS:" print print " -c \tCompiler to use (default: $g_CCNAME)" print " -i \tAdd include file to C code" print " -l \tPass library to linker" print " -m \tMax temporary buffers (default: $g_MAX_BUFFERS)" print " -s \tDepth of stack (default: $g_STACK_DEPTH)" print " -d \tTemporary directory (default: $g_TEMPDIR)" print " -n \t\tDo not compile automatically" print " -p \t\tPreserve temporary files" print " -o \t\tOptimize binary for current platform" print " -a \t\tForce 32bit compilation" print " -g \t\tCompile with debug info" print " -w \t\tShow all warnings during compilation" print " -v \t\tShow version" print " -h \t\tShow help" print exit 0;; esac done shift $(($OPTIND-1)) # Check if a filename was entered, if so get it if [[ $# -eq 0 ]] then print "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 print "ERROR: file not found!" exit 1 fi print -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 print -r "/* Created with BaCon $g_VERSION - Peter van Eerten 2009 */" > $g_CFILE print -r "#include \"${SOURCEFILE}.h\"" >> $g_CFILE print -r "int main(int argc, const char **argv)" >> $g_CFILE print -r "{" >> $g_CFILE print -r "/* Default is: system traps signals */" >> $g_CFILE print -r "signal(SIGILL, __b2c__catch_signal);" >> $g_CFILE print -r "signal(SIGABRT, __b2c__catch_signal);" >> $g_CFILE print -r "signal(SIGFPE, __b2c__catch_signal);" >> $g_CFILE print -r "signal(SIGSEGV, __b2c__catch_signal);" >> $g_CFILE print -r "/* Make sure internal string buffers are empty */" >> $g_CFILE print -r "for(__b2c__sbuffer_ptr=0; __b2c__sbuffer_ptr < $g_MAX_BUFFERS; __b2c__sbuffer_ptr++) __b2c__sbuffer[__b2c__sbuffer_ptr] = NULL;" >> $g_CFILE print -r "__b2c__sbuffer_ptr=0;" >> $g_CFILE print -r "for(__b2c__stackptr=0; __b2c__stackptr < $g_STACK_DEPTH; __b2c__stackptr++) __b2c__stringstack[__b2c__stackptr] = NULL;" >> $g_CFILE print -r "__b2c__stackptr=0;" >> $g_CFILE print -r "for(__b2c__rbuffer_ptr=0; __b2c__rbuffer_ptr < $g_MAX_RBUFFERS; __b2c__rbuffer_ptr++) __b2c__rbuffer[__b2c__rbuffer_ptr] = NULL;" >> $g_CFILE print -r "__b2c__rbuffer_ptr=0;" >> $g_CFILE # Put arguments into reserved variable ARGUMENT print -r "/* Setup the reserved variable 'ARGUMENT' */" >> $g_CFILE print -r "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" >> $g_CFILE print -r "{__b2c__arglen += strlen(argv[__b2c__counter]) + 1;} __b2c__arglen++;" >> $g_CFILE print -r "ARGUMENT\$ = (char*)malloc(__b2c__arglen*sizeof(char)); strcpy(ARGUMENT\$, \"\");" >> $g_CFILE print -r "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" >> $g_CFILE print -r "{strcat(ARGUMENT\$, argv[__b2c__counter]); if(__b2c__counter != argc - 1) strcat(ARGUMENT\$, \" \");}" >> $g_CFILE print -r "/* Rest of the program */" >> $g_CFILE # Create basic H file, functions are converted using macros print -r "/* Created with BaCon $g_VERSION - Peter van Eerten 2009 */" > $g_HFILE print >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE if [[ `uname` = +(*BSD*) ]] then print -r "#include " >> $g_HFILE fi print -r "#include " >> $g_HFILE print -r "static jmp_buf __b2c__jump;" >> $g_HFILE print -r "static int __b2c__trap = 1;" >> $g_HFILE print -r "static int __b2c__catch_set = 0;" >> $g_HFILE print -r "static int ERROR = 0;" >> $g_HFILE print -r "const char VERSION\$[] = \"$g_VERSION\";" >> $g_HFILE print >> $g_HFILE # Add user include files print -r "/* User include files */" >> $g_HFILE for i in $g_INCFILES do if [[ "$i" = +(*<*) ]] then print -r "#include $i" >> $g_HFILE else print -r "#include \"$i\"" >> $g_HFILE fi done print -r "/* READ/DATA include files */" >> $g_HFILE print -r "int __b2c__stringarray_ptr = 0;" >> $g_HFILE print -r "#include \"${SOURCEFILE}.string.h\"" >> $g_HFILE print -r "int __b2c__intarray_ptr = 0;" >> $g_HFILE print -r "#include \"${SOURCEFILE}.int.h\"" >> $g_HFILE print -r "int __b2c__floatarray_ptr = 0;" >> $g_HFILE print -r "#include \"${SOURCEFILE}.float.h\"" >> $g_HFILE print -r "int __b2c__ctr;" >> $g_HFILE print >> $g_HFILE print -r "/* Math functions */" >> $g_HFILE print -r "extern double round(double __b2c__x);" >> $g_HFILE print -r "extern long int lrint(double __b2c__x);" >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#define SQR(__b2c__x) sqrt(__b2c__x)" >> $g_HFILE print -r "#define POW(__b2c__x, __b2c__y) pow(__b2c__x, __b2c__y)" >> $g_HFILE print -r "#define SIN(__b2c__x) sin(__b2c__x)" >> $g_HFILE print -r "#define COS(__b2c__x) cos(__b2c__x)" >> $g_HFILE print -r "#define TAN(__b2c__x) tan(__b2c__x)" >> $g_HFILE print -r "#define ROUND(__b2c__x) lrint(__b2c__x)" >> $g_HFILE print -r "#define INT(__b2c__x) lrint(__b2c__x)" >> $g_HFILE print -r "#define MOD(__b2c__x, __b2c__y) (__b2c__x % __b2c__y)" >> $g_HFILE print -r "#define EVEN(__b2c__x) ((__b2c__x % 2 == 0) ? 1 : 0)" >> $g_HFILE print -r "#define ODD(__b2c__x) ((__b2c__x % 2 != 0) ? 1 : 0)" >> $g_HFILE print -r "#define FLOOR(__b2c__x) (long)floor(__b2c__x)" >> $g_HFILE print -r "#define ABS(__b2c__x) abs(__b2c__x)" >> $g_HFILE print -r "#define RND random()" >> $g_HFILE print -r "#define MAXRANDOM RAND_MAX" >> $g_HFILE print >> $g_HFILE print -r "/* Other functions */" >> $g_HFILE print -r "#define VAL(__b2c__x) ((__b2c__x != NULL) ? atof(__b2c__x) : 0)" >> $g_HFILE print >> $g_HFILE print -r "/* Unix functions */" >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#define SYSTEM(__b2c__x) ((__b2c__x != NULL) ? system(__b2c__x) : 0)" >> $g_HFILE print -r "#define CURDIR\$ getcwd(__b2c__input__buffer, $g_BUFFER_SIZE)" >> $g_HFILE print >> $g_HFILE print -r "/* String functions */" >> $g_HFILE print -r "#include " >> $g_HFILE print -r "char __b2c__input__buffer[$g_BUFFER_SIZE];" >> $g_HFILE print -r "char* __b2c__sbuffer[$g_MAX_BUFFERS];" >> $g_HFILE print -r "int __b2c__sbuffer_ptr;" >> $g_HFILE print -r "char* __b2c__rbuffer[$g_MAX_RBUFFERS];" >> $g_HFILE print -r "int __b2c__rbuffer_ptr;" >> $g_HFILE print -r "/* Temporary pointer to perform assignments */" >> $g_HFILE print -r "char *__b2c__assign = NULL;" >> $g_HFILE print -r "char *__b2c__split = NULL; char *__b2c__split_tmp = NULL;" >> $g_HFILE print -r "char *ERR\$(int);" >> $g_HFILE print -r "/* Actual functions */" >> $g_HFILE print -r "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 print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__s)+2)*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)+1);" >> $g_HFILE print -r "for(__b2c__i=0;__b2c__i> $g_HFILE print -r "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define REVERSE\$(x) ((x != NULL) ? __b2c__reverse(x) : \"null\")" >> $g_HFILE print -r "char* __b2c__str(double d){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS);" >> $g_HFILE print -r "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 print -r "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define STR\$(x) __b2c__str(x)" >> $g_HFILE print -r "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 print -r "if(__b2c__first != NULL) { __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__first)+1)*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first);}" >> $g_HFILE print -r "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 print -r "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 print -r "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__tmp);} va_end(__b2c__ap); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define CONCAT\$(...) __b2c__concat(__VA_ARGS__, (char*)NULL)" >> $g_HFILE print -r "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 print -r "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE print -r "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 print -r "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define LEFT\$(__b2c__x, __b2c__y) __b2c__left(__b2c__x, __b2c__y)" >> $g_HFILE print -r "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 print -r "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE print -r "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 print -r "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define RIGHT\$(__b2c__x, __b2c__y) __b2c__right(__b2c__x, __b2c__y)" >> $g_HFILE print -r "char* __b2c__mid(char *__b2c__src, ...){ va_list __b2c__ap; int __b2c__start, __b2c__end; if(__b2c__src == NULL) return(\"\");" >> $g_HFILE print -r "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); va_start(__b2c__ap, __b2c__src);" >> $g_HFILE print -r "__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 print -r "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 print -r "#define MID\$(__b2c__string, ...) __b2c__mid(__b2c__string, __VA_ARGS__, -1)" >> $g_HFILE print -r "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 print -r "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 print -r "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" >> $g_HFILE print -r "__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 print -r "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 print -r "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" >> $g_HFILE print -r "#define INSTR(...) __b2c__instr(__VA_ARGS__, -1)" >> $g_HFILE print -r "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 print -r "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 print -r "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" >> $g_HFILE print -r "__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 print -r "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 print -r "__b2c__res = strstr(__b2c__sbuffer[__b2c__sbuffer_ptr] + strlen(__b2c__sbuffer[__b2c__sbuffer_ptr]) - __b2c__pos + 1, __b2c__tmp); __b2c__pos+=1;}" >> $g_HFILE print -r "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" >> $g_HFILE print -r "#define INSTRREV(...) __b2c__instrrev(__VA_ARGS__, -1)" >> $g_HFILE print -r "char* __b2c__spc(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 32, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define SPC\$(x) ((x > -1) ? __b2c__spc(x) : \"\")" >> $g_HFILE print -r "char* __b2c__tab(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 9, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define TAB\$(x) ((x > -1) ? __b2c__tab(x) : \"\")" >> $g_HFILE print -r "char* __b2c__fill(unsigned long __b2c__x, unsigned char __b2c__y){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__y, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define FILL\$(x, y) ((y > -1 && y < 256) ? __b2c__fill(x, y) : \"\")" >> $g_HFILE print -r "char* __b2c__chop(char *__b2c__src){char *__b2c__tmp; int __b2c__i; if(strlen(__b2c__src) == 0) return(__b2c__src);" >> $g_HFILE print -r "while ((*__b2c__src == 10 || *__b2c__src == 13 || *__b2c__src == 9 || *__b2c__src == 32) && *__b2c__src != '\0') __b2c__src++;" >> $g_HFILE print -r "if (*__b2c__src == '\0') return(\"\"); __b2c__tmp = __b2c__src + strlen(__b2c__src) - 1;" >> $g_HFILE print -r "while ((*__b2c__tmp == 10 || *__b2c__tmp == 13 || *__b2c__tmp == 9 || *__b2c__tmp == 32) && *__b2c__src != '\0') __b2c__tmp--;" >> $g_HFILE print -r "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE print -r "for(__b2c__i = 0; __b2c__i <= __b2c__tmp - __b2c__src; __b2c__i++) __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__src[__b2c__i];" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i] = '\0'; return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define CHOP\$(x) ((x != NULL) ? __b2c__chop(x) : 0)" >> $g_HFILE print -r "char* __b2c__replace(char* __b2c__x, char* __b2c__y, char* __b2c__z){" >> $g_HFILE print -r "char *__b2c__tmp, *__b2c__buf, *__b2c__haystack, *__b2c__dup = NULL; __b2c__sbuffer_ptr++;" >> $g_HFILE print -r "if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0; __b2c__haystack = strdup(__b2c__x); __b2c__dup = __b2c__haystack;" >> $g_HFILE print -r "__b2c__buf = strdup(\"\"); while((__b2c__tmp = strstr(__b2c__haystack, __b2c__y)) != NULL) {*__b2c__tmp = '\0';" >> $g_HFILE print -r "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + strlen(__b2c__z) + 1)*sizeof(char));" >> $g_HFILE print -r "strcat(__b2c__buf, __b2c__haystack);strcat(__b2c__buf, __b2c__z);__b2c__haystack = __b2c__tmp+strlen(__b2c__y);}" >> $g_HFILE print -r "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + 1)*sizeof(char));strcat(__b2c__buf, __b2c__haystack);" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__buf)+1)*sizeof(char));" >> $g_HFILE print -r "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf);free(__b2c__buf);free(__b2c__dup);return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define REPLACE\$(x, y, z)((x!=NULL && y!=NULL && z!= NULL) ? __b2c__replace(x, y, z) : 0)" >> $g_HFILE print -r "#define LEN(x) ((x != NULL) ? strlen(x) : 0)" >> $g_HFILE print -r "#define EQUAL(__b2c__x, __b2c__y) ((__b2c__x != NULL && __b2c__y != NULL) ? !strcmp(__b2c__x, __b2c__y) : 0)" >> $g_HFILE print -r "char * __b2c__getenv(char *__b2c__env){static char * __b2c__tmp; __b2c__tmp = getenv(__b2c__env); if (__b2c__tmp == NULL)" >> $g_HFILE print -r "{return \"\";} return __b2c__tmp;}" >> $g_HFILE print -r "#define GETENVIRON\$(x) ((x != NULL) ? __b2c__getenv(x) : \"null\")" >> $g_HFILE print -r "#define SETENVIRON(x, y) if(x != NULL && y != NULL) setenv(x, y, 1)" >> $g_HFILE print >> $g_HFILE print -r "/* CHAR functions */" >> $g_HFILE print -r "#include " >> $g_HFILE print -r "char* __b2c__ucase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE print -r "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=toupper(__b2c__s[__b2c__i]);}" >> $g_HFILE print -r "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define UCASE\$(x) ((x != NULL) ? __b2c__ucase(x) : \"null\")" >> $g_HFILE print -r "char* __b2c__lcase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE print -r "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=tolower(__b2c__s[__b2c__i]);}" >> $g_HFILE print -r "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define LCASE\$(x) ((x != NULL) ? __b2c__lcase(x) : \"null\")" >> $g_HFILE print >> $g_HFILE print -r "/* I/O functions */" >> $g_HFILE print -r "FILE *__b2c__inFile; FILE *__b2c__outFile; int __b2c__Byte; struct dirent *__b2c__dir;" >> $g_HFILE print -r "char* __b2c__dec2hex(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS);" >> $g_HFILE print -r "snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%X\", __b2c__i); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "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 print -r "fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} return(int)(__b2c__i);}" >> $g_HFILE print -r "unsigned char __b2c__char2asc(char *__b2c__c){return (unsigned char)*__b2c__c;}" >> $g_HFILE print -r "char* __b2c__asc2char(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char));" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, 2*sizeof(char)); snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], 2, \"%c\", __b2c__i);" >> $g_HFILE print -r "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "long __b2c__filelen(const char *__b2c__x) {struct stat __b2c__buf; if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0) return -1;" >> $g_HFILE print -r "if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} return(long)(__b2c__buf.st_size);}" >> $g_HFILE print -r "#define FILELEN(x) __b2c__filelen(x)" >> $g_HFILE print -r "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 print -r "{ERROR = 24; fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);}" >> $g_HFILE print -r "if (S_ISREG(__b2c__buf.st_mode)) return 1; if (S_ISDIR(__b2c__buf.st_mode)) return 2;" >> $g_HFILE print -r "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 print -r "if (S_ISLNK(__b2c__buf.st_mode)) return 6; if (S_ISSOCK(__b2c__buf.st_mode)) return 7; return 0;}" >> $g_HFILE print -r "#define FILETYPE(x) __b2c__filetype(x)" >> $g_HFILE print -r "long __b2c__search(FILE* __b2c__x, char* __b2c__y){long __b2c__off; long __b2c__pos; char* __b2c__ptr;" >> $g_HFILE print -r "if(__b2c__x == NULL && !__b2c__trap){ERROR = 2; fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);}" >> $g_HFILE print -r "if(__b2c__y == NULL && !__b2c__trap){ERROR = 25; fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);}" >> $g_HFILE print -r "__b2c__pos = ftell(__b2c__x); __b2c__ptr = (char*)malloc((strlen(__b2c__y)+1)*sizeof(char)); __b2c__off = 0; do {" >> $g_HFILE print -r "fseek(__b2c__x, __b2c__off, SEEK_SET);memset(__b2c__ptr, 0, sizeof(char)*(strlen(__b2c__y)+1));" >> $g_HFILE print -r "fread(__b2c__ptr, sizeof(char), strlen(__b2c__y), __b2c__x);__b2c__off+=1;" >> $g_HFILE print -r "} while(!feof(__b2c__x) && strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y)));" >> $g_HFILE print -r "if(strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y))) __b2c__off = 0; fseek(__b2c__x, __b2c__pos, SEEK_SET); free(__b2c__ptr); return (--__b2c__off);}" >> $g_HFILE print -r "#define SEARCH(x, y) __b2c__search(x, y)" >> $g_HFILE print -r "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 print -r "if (pipe (__b2c__rpipe) < 0 || pipe (__b2c__wpipe) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);}}" >> $g_HFILE print -r "if ((__b2c__r = fork ()) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);}} else if (__b2c__r == 0){" >> $g_HFILE print -r "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 print -r "else{close (__b2c__wpipe[0]);close (__b2c__rpipe[1]);__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__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 print -r "__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\$(ERROR)); exit(ERROR);}" >> $g_HFILE print -r "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 print -r "if (__b2c__sbuffer[__b2c__sbuffer_ptr] == NULL && !__b2c__trap){ERROR=6; fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} } memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len, __b2c__ans, __b2c__i);" >> $g_HFILE print -r " __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 print -r "close (__b2c__rpipe[0]);free (__b2c__ans);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define EXEC\$(x) __b2c__exec(x)" >> $g_HFILE print -r "#define ENDFILE(x) feof(x)" >> $g_HFILE print -r "#define TELL(x) ftell(x)" >> $g_HFILE print -r "#define HEX\$(x) __b2c__dec2hex(x)" >> $g_HFILE print -r "#define DEC(x) __b2c__hex2dec(x)" >> $g_HFILE print -r "#define ASC(x) __b2c__char2asc(x)" >> $g_HFILE print -r "#define CHR\$(__b2c__x) __b2c__asc2char(__b2c__x)" >> $g_HFILE print >> $g_HFILE print -r "/* Dynamic loading, errors */" >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#include " >> $g_HFILE print >> $g_HFILE print -r "/* GETKEY */" >> $g_HFILE print -r "#include " >> $g_HFILE print -r "long __b2c__getch(){long __b2c__ch; struct termios __b2c__oldt, __b2c__newt; tcgetattr(0, &__b2c__oldt);" >> $g_HFILE print -r "__b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(0, TCSANOW, &__b2c__newt);" >> $g_HFILE print -r "__b2c__ch = getchar(); tcsetattr(0, TCSANOW, &__b2c__oldt); return __b2c__ch;} " >> $g_HFILE print -r "#define GETKEY __b2c__getch()" >> $g_HFILE print >> $g_HFILE print -r "/* Constants, logical stuff */" >> $g_HFILE print -r "#define PI 3.14159265" >> $g_HFILE print -r "#define NOT(x) (!(x))" >> $g_HFILE print -r "#define AND &&" >> $g_HFILE print -r "#define OR ||" >> $g_HFILE print -r "#define EQ ==" >> $g_HFILE print -r "#define NE !=" >> $g_HFILE print -r "#define TRUE 1" >> $g_HFILE print -r "#define FALSE 0" >> $g_HFILE print -r "#define NL\$ \"\n\"" >> $g_HFILE print -r "#define STRING char*" >> $g_HFILE print -r "#define NUMBER long" >> $g_HFILE print -r "#define FLOATING double" >> $g_HFILE print -r "#define ISTRUE(x) (x!=0)" >> $g_HFILE print -r "#define ISFALSE(x) (x==0)" >> $g_HFILE print >> $g_HFILE print -r "/* Date and time */" >> $g_HFILE print -r "#include " >> $g_HFILE print -r "#define NOW (long)time(NULL)" >> $g_HFILE print -r "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 print -r "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_HFILE print -r "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 print -r "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 print -r "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 print -r "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 print -r "return(atol(__b2c__sbuffer[__b2c__sbuffer_ptr]));}" >> $g_HFILE print -r "#define DAY(x) __b2c__time(x, 1)" >> $g_HFILE print -r "#define MONTH(x) __b2c__time(x, 2)" >> $g_HFILE print -r "#define YEAR(x) __b2c__time(x, 3)" >> $g_HFILE print -r "#define HOUR(x) __b2c__time(x, 4)" >> $g_HFILE print -r "#define MINUTE(x) __b2c__time(x, 5)" >> $g_HFILE print -r "#define SECOND(x) __b2c__time(x, 6)" >> $g_HFILE print -r "#define WEEK(x) __b2c__time(x, 7)" >> $g_HFILE print -r "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 print -r "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_HFILE print -r "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 print -r "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%B\", ts); break;} return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define WEEKDAY\$(x) __b2c__datename(x, 1)" >> $g_HFILE print -r "#define MONTH\$(x) __b2c__datename(x, 2)" >> $g_HFILE print -r "unsigned long __b2c__epoch(int __b2c__year, int __b2c__month, int __b2c__day, int __b2c__hour, int __b2c__minute, int __b2c__second){" >> $g_HFILE print -r "struct tm tm; time_t __b2c__t; tm.tm_year = __b2c__year - 1900; tm.tm_mon = __b2c__month - 1; tm.tm_mday = __b2c__day;" >> $g_HFILE print -r "tm.tm_hour = __b2c__hour; tm.tm_min = __b2c__minute; tm.tm_sec = __b2c__second;" >> $g_HFILE print -r "tm.tm_isdst = -1; __b2c__t = mktime(&tm); if (__b2c__t == -1) return (0); return(long) __b2c__t; }" >> $g_HFILE print -r "#define TIMEVALUE(x,y,z,a,b,c) __b2c__epoch(x,y,z,a,b,c)" >> $g_HFILE print -r "char* __b2c__os(void){struct utsname __b2c__buf; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE print -r "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE);" >> $g_HFILE print -r "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_BUFFER_SIZE); if(uname(&__b2c__buf) < 0 && !__b2c__trap) {ERROR = 26; fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);}" >> $g_HFILE print -r "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.sysname); strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], \" \");" >> $g_HFILE print -r "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.machine); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE print -r "#define OS\$ __b2c__os()" >> $g_HFILE print >> $g_HFILE print -r "/* Peek and Poke */" >> $g_HFILE print -r "struct stat __b2c__sb;" >> $g_HFILE print -r "void __b2c__memory__check(char* __b2c__x) {if (stat(__b2c__x, &__b2c__sb) == -1 && errno == EFAULT) {ERROR = 1;} }" >> $g_HFILE print -r "long __b2c__malloc(long __b2c__x) {void *__b2c__mem; if(__b2c__x==0) return(0); __b2c__mem = malloc(sizeof(char)*(__b2c__x));" >> $g_HFILE print -r "if(__b2c__mem == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} memset(__b2c__mem, 0, sizeof(char)*(__b2c__x));return(long)__b2c__mem;}" >> $g_HFILE print -r "#define MEMORY(__b2c__x) __b2c__malloc(__b2c__x)" >> $g_HFILE print -r "void __b2c__realloc(void* __b2c__x, long __b2c__y) {if(__b2c__x == NULL) return; if(!__b2c__trap) {__b2c__memory__check((char*)__b2c__x);" >> $g_HFILE print -r "if(ERROR) {fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} } else {__b2c__x = realloc((void*)__b2c__x, sizeof(char)*(__b2c__y));" >> $g_HFILE print -r "if(__b2c__x == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} return;} }" >> $g_HFILE print -r "#define RESIZE(__b2c__x, __b2c__y) __b2c__realloc((void*)__b2c__x, __b2c__y)" >> $g_HFILE print -r "void __b2c__poke(char* __b2c__x, unsigned char __b2c__y) {if (!__b2c__trap){__b2c__memory__check((char*)__b2c__x); if(ERROR) {" >> $g_HFILE print -r "fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} } *__b2c__x = (unsigned char)__b2c__y;}" >> $g_HFILE print -r "#define POKE(__b2c__x, __b2c__y) __b2c__poke((char*)(__b2c__x), (unsigned char)(__b2c__y))" >> $g_HFILE print -r "unsigned char __b2c__peek(char* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((char*) __b2c__x); if(ERROR) {" >> $g_HFILE print -r "fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} } return((unsigned char)*__b2c__x);}" >> $g_HFILE print -r "#define PEEK(__b2c__x) __b2c__peek((char*)(__b2c__x))" >> $g_HFILE print -r "#define ADDRESS(__b2c__x) (long)(&__b2c__x)" >> $g_HFILE print >> $g_HFILE print -r "/* Network variables and functions */" >> $g_HFILE print -r "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 print -r "long __b2c__netpeek(int __b2c__fd, int __b2c__usec){fd_set __b2c__rfds;struct timeval __b2c__tv;long __b2c__retval;" >> $g_HFILE print -r "FD_ZERO(&__b2c__rfds); FD_SET(__b2c__fd, &__b2c__rfds);__b2c__tv.tv_usec = __b2c__usec*1000;__b2c__tv.tv_sec = 0;" >> $g_HFILE print -r "__b2c__retval = select(__b2c__fd + 1, &__b2c__rfds, NULL, NULL, &__b2c__tv);" >> $g_HFILE print -r "if (__b2c__retval == -1 && !__b2c__trap) {ERROR = 16; fprintf(stderr, \"%s\n\", ERR\$(ERROR)); exit(ERROR);} return(__b2c__retval);}" >> $g_HFILE print -r "#define WAIT(x, y) __b2c__netpeek(x, y)" >> $g_HFILE print >> $g_HFILE print -r "/* Regex */" >> $g_HFILE print -r "#include " >> $g_HFILE print -r "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 print -r "if(!__b2c__trap && __b2c__reti){ERROR=27; fprintf(stderr, \"%s: \", ERR\$(ERROR)); regerror(__b2c__reti, &__b2c__reg, __b2c__buf, sizeof(__b2c__buf)); fprintf(stderr, \"%s\n\", __b2c__buf);" >> $g_HFILE print -r "exit(ERROR);} __b2c__reti = regexec(&__b2c__reg, __b2c__x, 0, NULL, 0);" >> $g_HFILE print -r "regfree(&__b2c__reg); if( !__b2c__reti ) return (1); else return (0);}" >> $g_HFILE print -r "#define REGEX(x, y) __b2c__regex(x, y)" >> $g_HFILE print >> $g_HFILE print -r "/* Declare reserved variable 'ARGUMENT\$' */" >> $g_HFILE print -r "int __b2c__counter;" >> $g_HFILE print -r "int __b2c__arglen = 0;" >> $g_HFILE print -r "char *ARGUMENT\$;" >> $g_HFILE print >> $g_HFILE print -r "/* Initialize stack arrays and pointer */" >> $g_HFILE print -r "char *__b2c__stringstack[$g_STACK_DEPTH];" >> $g_HFILE print -r "double __b2c__doublestack[$g_STACK_DEPTH];" >> $g_HFILE print -r "long __b2c__longstack[$g_STACK_DEPTH];" >> $g_HFILE print -r "int __b2c__typestack[$g_STACK_DEPTH];" >> $g_HFILE print -r "int __b2c__stackptr;" >> $g_HFILE # Signal function print -r "/* Signal trapping activated with TRAP */" >> $g_HFILE print -r "void __b2c__catch_signal(int sig){" >> $g_HFILE print -r "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 print -r "case SIGFPE: fprintf(stderr, \"ERROR: signal for FPE received - division by zero? Examine the calculations in the program.\n\"); break;" >> $g_HFILE print -r "case SIGSEGV: fprintf(stderr, \"ERROR: signal for SEGMENTATION FAULT received - memory invalid or array out of bounds? Try to compile the program with TRAP LOCAL to find the cause.\n\"); break;" >> $g_HFILE print -r "case SIGILL: fprintf(stderr, \"ERROR: signal for ILLEGAL INSTRUCTION received - executing the program on other hardware? Try to recompile the program from scratch.\n\"); break;} exit(sig);}" >> $g_HFILE # Add error function print >> $g_HFILE print -r "/* Initialize error function */" >> $g_HFILE print -r "char *ERR\$(int __b2c__nr){static char __b2c__warn[$g_BUFFER_SIZE];" >> $g_HFILE print -r "switch(__b2c__nr){" >> $g_HFILE print -r "case 0: strcpy(__b2c__warn,\"Success\"); break;" >> $g_HFILE print -r "case 1: strcpy(__b2c__warn,\"Trying to access illegal memory: \"); strncat(__b2c__warn,strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 2: strcpy(__b2c__warn,\"Error opening file: \"); strncat(__b2c__warn,strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 3: strcpy(__b2c__warn, \"Could not open library \"); strncat(__b2c__warn, dlerror(), $g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 4: strcpy(__b2c__warn, \"Symbol not found in library \"); strncat(__b2c__warn, dlerror(), $g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 5: strcpy(__b2c__warn, \"Wrong hexvalue: \"); strncat(__b2c__warn, strerror(errno), $g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 6: strcpy(__b2c__warn, \"Unable to claim memory.\"); break;" >> $g_HFILE print -r "case 7: strcpy(__b2c__warn, \"Unable to delete file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 8: strcpy(__b2c__warn, \"Could not open directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 9: strcpy(__b2c__warn, \"Unable to rename file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 10: strcpy(__b2c__warn, \"NETWORK argument should contain colon with port number\"); break;" >> $g_HFILE print -r "case 11: strcpy(__b2c__warn, \"Could not resolve hostname: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 12: strcpy(__b2c__warn, \"Socket error: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 13: strcpy(__b2c__warn, \"Unable to open address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 14: strcpy(__b2c__warn, \"Error reading from socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 15: strcpy(__b2c__warn, \"Error sending to socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 16: strcpy(__b2c__warn, \"Error checking socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 17: strcpy(__b2c__warn, \"Unable to bind the specified socket address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 18: strcpy(__b2c__warn, \"Unable to listen to socket address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 19: strcpy(__b2c__warn, \"Cannot accept incoming connection: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 20: strcpy(__b2c__warn, \"Unable to remove directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 21: strcpy(__b2c__warn, \"Unable to create directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 22: strcpy(__b2c__warn, \"Unable to change to directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 23: strcpy(__b2c__warn, \"GETENVIRON argument does not exist as environment variable\"); break;" >> $g_HFILE print -r "case 24: strcpy(__b2c__warn, \"Unable to stat file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 25: strcpy(__b2c__warn, \"Search contains illegal string\"); break;" >> $g_HFILE print -r "case 26: strcpy(__b2c__warn, \"Cannot return OS name: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 27: strcpy(__b2c__warn, \"Illegal regex expression\"); break;" >> $g_HFILE print -r "case 28: strcpy(__b2c__warn, \"Unable to create bidirectional pipes: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 29: strcpy(__b2c__warn, \"Unable to fork process: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "case 30: strcpy(__b2c__warn, \"Cannot read from pipe: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE print -r "}; ERROR = 0; return(__b2c__warn);}" >> $g_HFILE print >> $g_HFILE print -r "/* User program definitions */" >> $g_HFILE # Initialize the arrayfiles for DATA statement print -r "char *__b2c__stringarray[] = {" > $STRINGARRAYFILE print -r "int __b2c__intarray[] = {" > $INTARRAYFILE print -r "double __b2c__floatarray[] = {" > $FLOATARRAYFILE # There are no imported symbols yet g_IMPORTED= # This is the current file we are parsing g_CURFILE=$SOURCEFILE # Initialize LEN= TOTAL= SEQ= g_COUNTER=1 # Start walking through program while read -r LINE do print -n "\rStarting conversion... $g_COUNTER" # Line is not empty? if [[ -n "$LINE" ]] then if [[ "$LINE" = +(* \\) && "$LINE" != +(REM*) && "$LINE" != +(\'*) ]] then let LEN="${#LINE}"-2 typeset -L$LEN SEQ="${LINE}" TOTAL=$TOTAL$SEQ else Parse_Line "$TOTAL$LINE" TOTAL= fi fi ((g_COUNTER+=1)) done < $SOURCEFILE # Finalize main C-file print -r "__B2C__PROGRAM__EXIT:" >> $g_CFILE print -r "return 0;" >> $g_CFILE print -r "}" >> $g_CFILE # Finalize INT ARRAY file for DATA print -r " \"\" };" >> $STRINGARRAYFILE # Finalize STRING ARRAY file for DATA print -r " 0};" >> $INTARRAYFILE # Finalize FLOAT ARRAY file for DATA print -r " 0.0};" >> $FLOATARRAYFILE # Include functions and subs for i in $g_INCLUDE_FILES do if [[ -n $g_TEMPDIR ]] then let LEN=${#i}-${#g_TEMPDIR}-1 # KSH88 need a typeset twice when variable TOTAL gets bigger (bug?) typeset -R$LEN TOTAL="${i}" typeset -R$LEN TOTAL="${i}" print "#include \"${TOTAL}\"" >> $g_HFILE else print "#include \"${i}\"" >> $g_HFILE fi done print "\rStarting conversion... done. " # Indentation only when files are preserved if [[ $g_TMP_PRESERVE -eq 1 ]] then if [[ -n `which indent 2>/dev/null` ]] then print -n "Applying indentation... " for i in $g_TMP_FILES do indent $i if [[ `uname` = "Darwin" || `uname` = +(*BSD*) ]] then rm `basename $i`.BAK else rm $i~ fi done print "done." else print "WARNING: 'indent' not found on this system!" print "Generated source code cannot be beautified." fi fi # Start compilation if [[ $g_NO_COMPILE -eq 0 ]] then print -n "Starting compilation... " $g_CCNAME $g_CCFLAGS -o ${SOURCEFILE%.*} $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 print "done." print "Program '${SOURCEFILE%.*}' ready." else # Only print first error print "Compiler emits messages!" while read -r g_ERROR do if [[ $g_ERROR != +(-*) && -n `print "${g_ERROR}" | grep -E "\:[0-9]+\: error\:"` ]] then print "\n${g_ERROR}" break fi done < $g_TEMPDIR/${SOURCEFILE}.log # Non-gcc if [[ -z $g_ERROR || $g_CCFLAGS = +(*Wall*) ]] then print cat $g_TEMPDIR/${SOURCEFILE}.log print 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 print " ---> ${LINE} <---\n" break fi ((g_COUNTER+=1)) done < ${g_FILE_LINE%%:*} fi fi fi # Cleanup if [[ $g_TMP_PRESERVE -eq 0 ]] then for i in $g_TMP_FILES do rm $i done fi exit 0