diff options
author | dsomero <xgizzmo@slackbuilds.org> | 2011-05-31 19:34:15 -0400 |
---|---|---|
committer | Robby Workman <rworkman@slackbuilds.org> | 2011-06-13 01:31:20 -0400 |
commit | d7e4da4608734eeeec045a46c9846c7b60b264e5 (patch) | |
tree | b02844782f8277f34f9439cf2f44c67042a18dfd | |
parent | ff341d37de1ea397fe67875da7683d5be3abb4aa (diff) |
development/bacon: Updated for version 1.0_build_22.
Signed-off-by: dsomero <xgizzmo@slackbuilds.org>
-rw-r--r-- | development/bacon/README | 3 | ||||
-rw-r--r-- | development/bacon/bacon.SlackBuild | 23 | ||||
-rw-r--r-- | development/bacon/bacon.bac | 4895 | ||||
-rw-r--r-- | development/bacon/bacon.bash | 5351 | ||||
-rw-r--r-- | development/bacon/bacon.info | 6 |
5 files changed, 10264 insertions, 14 deletions
diff --git a/development/bacon/README b/development/bacon/README index a784a287b4f5b..d769c6dc98f92 100644 --- a/development/bacon/README +++ b/development/bacon/README @@ -5,5 +5,8 @@ The following design goals were followed: * Must resemble genuine BASIC with implicit variable declarations * Spoken language constructs are preferred +Code converted by BaCon can be compiled by GCC, the Compaq C Compiler or TCC. +This SlackBuild uses gcc by default, you can change that with the COMPILER variable. + Note: When a new version of BaCon is released, the downloads will change and the md5sums won't match. diff --git a/development/bacon/bacon.SlackBuild b/development/bacon/bacon.SlackBuild index 94f09d02291d5..c09ec33002ea3 100644 --- a/development/bacon/bacon.SlackBuild +++ b/development/bacon/bacon.SlackBuild @@ -1,11 +1,11 @@ #!/bin/sh -# Slackware build script for bacon +# Slackware build script for bacon # Written by Steve Pledger <spledger91@yahoo.com> PRGNAM=bacon -VERSION=${VERSION:-1.0_build_21} +VERSION=${VERSION:-1.0_build_22} BUILD=${BUILD:-1} TAG=${TAG:-_SBo} @@ -22,8 +22,11 @@ TMP=${TMP:-/tmp/SBo} PKG=$TMP/package-$PRGNAM OUTPUT=${OUTPUT:-/tmp} +# which C compiler to use: +COMPILER="${COMPILER:-gcc}" # supported compilers: gcc, tcc, and HP's Compaq C Compiler + # Version number may change, so figure out the real version -SRCVER="$(bash $CWD/bacon.bash -v | grep version | cut -d' ' -f3-5 | tr ' ' _)" +SRCVER="$(/bin/bash $CWD/bacon.bash -v | grep version | cut -d' ' -f3-5 | tr ' ' _)" # suggested by Niels Horn: if [ "$VERSION" != "$SRCVER" ]; then @@ -53,7 +56,7 @@ else LIBDIRSUFFIX="" fi -set -e +set -e rm -rf $PKG mkdir -p $TMP $PKG $OUTPUT @@ -62,8 +65,8 @@ rm -rf $PRGNAM-$VERSION mkdir $PRGNAM-$VERSION cd $PRGNAM-$VERSION -# Bacon creates a binary in the same location as the source, so copy the source file here. -cat $CWD/bacon.bac > bacon.bac +# Bacon creates a binary in the same location as the source, so copy the source files here. +cp $CWD/bacon.bash $CWD/bacon.bac . chown -R root:root . find . \ @@ -73,14 +76,12 @@ find . \ -exec chmod 644 {} \; # Use the Bash version of BaCon to convert and compile the BASIC version, which is much faster. -# (Note: Not using sh because this requires Bash 4.x and sh may be a symlink to another shell) -bash $CWD/bacon.bash -p -o $(echo $SLKCFLAGS | sed -e 's: : -o :g') bacon.bac +# (Note: Not using sh because this requires Bash >=3.2 and sh may be a symlink to another shell) +/bin/bash bacon.bash -c $COMPILER -p -o $(echo $SLKCFLAGS | sed -e 's: : -o :g') bacon.bac mkdir -p $PKG/usr/bin install -m 0755 bacon $PKG/usr/bin - -find $PKG | xargs file | grep -e "executable" -e "shared object" | grep ELF \ - | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true +strip --strip-unneeded $PKG/usr/bin/* 2>/dev/null || true mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild diff --git a/development/bacon/bacon.bac b/development/bacon/bacon.bac new file mode 100644 index 0000000000000..416a981af0f4f --- /dev/null +++ b/development/bacon/bacon.bac @@ -0,0 +1,4895 @@ +' ____ ____ +' | __ ) __ _ / ___|___ _ __ +' | _ \ / _` | | / _ \| '_ \ +' | |_) | (_| | |__| (_) | | | | --= A BaCon BASIC-to-C converter =-- +' |____/ \__,_|\____\___/|_| |_| +' +' Peter van Eerten - March 2009/April 2011. License: GPL version 3. +' +'---------------------------------------------------------------------------------------------- +' CREDITS: +' - James C. Fuller for endless testing and patiently pointing to many issues +' - John Spikowksi for giving some hints to improve the language +' - Vovchik for providing ideas, programs and hints +' +'---------------------------------------------------------------------------------------------- +' +' Though BaCon is much more powerful than KSH or BASH, this program follows the same structure +' and approach as the existing shell script implementations where possible. +' +' The reason for this is maintainability and consistency: a bug should show up in all versions +' and should be solved in all versions. +' +'---------------------------------------------------------------------------------------------- +' GLOBAL INITIALIZATIONS +'---------------------------------------------------------------------------------------------- + +TRAP LOCAL + +' Lower bound of array starts with 1 +OPTION BASE 1 + +' Prevent parse errors +OPTION COLLAPSE TRUE + +' Version of BACON +CONST g_VERSION$ = "1.0 build 22" + +' Link flags +IF INSTR(OS$, "OSF1") OR INSTR(OS$, "BSD") THEN g_LDFLAGS$ = "-lm" +ELSE g_LDFLAGS$ = "-lm -ldl" + +' Solaris +IF INSTR(OS$, "SunOS" ) THEN g_LDFLAGS$ = CONCAT$(g_LDFLAGS$, " -lnsl -lsocket") + +' Global to define '$'-replacement +CONST g_STRINGSIGN$ = "__b2c__string_var" + +'---------------------------------------------------------------------------------------------- + +FUNCTION Check_Declared(STRING filename$, STRING v$, NUMBER position) + + LOCAL txt$, needle$ + LOCAL expr + LOCAL thefile TYPE FILE* + + needle$ = REPLACE$(v$, "*", "\\*") + + OPEN filename$ FOR READING AS thefile + + SEEK thefile OFFSET position + + WHILE NOT(ENDFILE(thefile)) DO + + READLN txt$ FROM thefile + IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN + expr = REGEX(txt$, "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING") + IF ISTRUE(expr) THEN + IF INSTR(needle$, "[") THEN + expr = REGEX(txt$, CONCAT$(" ", LEFT$(needle$, INSTR(needle$, "[")-1), "\\[|,", LEFT$(needle$, INSTR(needle$, "[")-1), "\\[" )) + ELSE + expr = REGEX(txt$, CONCAT$(" ", needle$, ",| ", needle$, ";|\\*", needle$, " |,", needle$, ",|,", needle$, ";| ", needle$, " +=")) + END IF + IF ISTRUE(expr) THEN BREAK + ENDIF + ENDIF + WEND + + CLOSE FILE thefile + + RETURN expr + +END FUNCTION + +'---------------------------------------------------------------------------------------------- + +FUNCTION Check_Type$(STRING filename$, STRING v$, NUMBER position) + + LOCAL txt$, needle$ + LOCAL expr + LOCAL thefile TYPE FILE* + + needle$ = CHOP$(REPLACE$(v$, "*", "\\*")) + + OPEN filename$ FOR READING AS thefile + + SEEK thefile OFFSET position + + WHILE NOT(ENDFILE(thefile)) DO + + READLN txt$ FROM thefile + IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN + expr = REGEX(txt$, "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING") + IF ISTRUE(expr) THEN + IF INSTR(needle$, "[") THEN + IF INSTR(needle$, g_STRINGSIGN$) THEN + expr = REGEX(txt$, CONCAT$(" *", LEFT$(needle$, INSTR(needle$, "[")-1), "\\[")) + ELSE + expr = REGEX(txt$, CONCAT$(" ", LEFT$(needle$, INSTR(needle$, "[")-1), "\\[")) + ENDIF + ELSE + expr = REGEX(txt$, CONCAT$(" ", needle$, ",| ", needle$, ";|,", needle$, ",|,", needle$, ";| ", needle$, " +=")) + END IF + IF ISTRUE(expr) THEN BREAK + ENDIF + ENDIF + WEND + + CLOSE FILE thefile + + IF ISTRUE(expr) THEN RETURN txt$ + + RETURN "" + +END FUNCTION + +'---------------------------------------------------------------------------------------------- + +FUNCTION Search(STRING file$, STRING line$, NUMBER position) + + LOCAL found + LOCAL txt$ + LOCAL handle TYPE FILE* + + found = -1 + + OPEN file$ FOR READING AS handle + + SEEK handle OFFSET position + + WHILE NOT(ENDFILE(handle)) DO + READLN txt$ FROM handle + IF INSTR(txt$, line$) THEN + found = TRUE + BREAK + ENDIF + WEND + CLOSE FILE handle + + RETURN found + +END FUNCTION + +'---------------------------------------------------------------------------------------------- + +SUB Print_Element (STRING arg$) + + LOCAL len, check + + ' Get part just before '(' + len = INSTR(arg$, "(")-1 + IF len < 0 THEN len = LEN(arg$) + + ' Check on string by reference variable + check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0) + ENDIF + + ' Check if var is string var + IF INSTR(MID$(arg$, 1, len), g_STRINGSIGN$) OR INSTR(MID$(arg$, 1, len), CHR$(34)) OR REGEX(MID$(arg$, 1, len), "gettext|ngettext") OR check >= 0 THEN + WRITELN "__b2c__assign = ", arg$, "; if(__b2c__assign != NULL) fprintf(stdout, \"%s\", __b2c__assign);" TO g_CFILE + ELSE + WRITELN "fprintf(stdout, \"%s\", STR", g_STRINGSIGN$, "(", arg$, "));" TO g_CFILE + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Print(STRING arg$) + + LOCAL exp$, form$ + LOCAL x, in_string, in_func, pos, escaped + + ' Check if argument + IF ISTRUE(LEN(arg$)) THEN + + ' Omit semicolon if there is one + IF EQUAL(RIGHT$(arg$, 1), ";") THEN + exp$ = LEFT$(arg$, LEN(arg$) - 1) + ELSE + exp$ = arg$ + END IF + + ' If there is a FORMAT argument + IF INSTR(exp$, " FORMAT ") THEN + form$ = MID$(exp$, INSTR(exp$, " FORMAT ") + 8) + WRITELN "fprintf(stdout, ", form$, ", ", LEFT$(exp$, INSTR(exp$, " FORMAT ")), ");" TO g_CFILE + ELSE + ' Start miniparser + in_string = FALSE + in_func = 0 + pos = 1 + escaped = 0 + + FOR x = 1 TO LEN(exp$) + IF EQUAL(MID$(exp$, x, 1), ",") THEN + IF ISFALSE(in_string) AND ISFALSE(in_func) THEN + Print_Element(CHOP$(MID$(exp$, pos, x-pos))) + pos = x + 1 + escaped = FALSE + END IF + ELIF EQUAL(MID$(exp$, x, 1), "\\") THEN + escaped = TRUE + ELIF EQUAL(MID$(exp$, x, 1), CHR$(34)) THEN + IF ISFALSE(escaped) THEN + in_string = NOT(in_string) + END IF + escaped = FALSE + ELIF EQUAL(MID$(exp$, x, 1), "(") THEN + IF ISFALSE(in_string) THEN + INCR in_func + END IF + escaped = FALSE + ELIF EQUAL(MID$(exp$, x, 1), ")") THEN + IF ISFALSE(in_string) THEN + DECR in_func + END IF + escaped = FALSE + ELSE + escaped = FALSE + ENDIF + NEXT + Print_Element(CHOP$(MID$(exp$, pos))) + + ' If line ends with ';' then skip newline + IF ISFALSE(EQUAL(RIGHT$(arg$, 1), ";")) THEN + WRITELN "fprintf(stdout, \"\\n\");" TO g_CFILE + END IF + END IF + + ELSE + WRITELN "fprintf(stdout, \"\\n\");" TO g_CFILE + END IF + + ' Flush print buffer + WRITELN "fflush(stdout);" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Input(STRING arg$) + + LOCAL x, in_string, in_func, pos, check, escaped + LOCAL type$ + + ' Check if we have an argument at all + IF ISFALSE(LEN(arg$)) THEN + PRINT NL$, "ERROR: empty INPUT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Start miniparser + in_string = FALSE + in_func = 0 + pos = 1 + escaped = 0 + + FOR x = 1 TO LEN(arg$) + IF ISTRUE(EQUAL(MID$(arg$, x, 1), ",")) THEN + IF ISFALSE(in_string) AND ISFALSE(in_func) THEN + Print_Element(CHOP$(MID$(arg$, pos, x-pos))) + pos = x+1 + escaped = FALSE + END IF + ELIF EQUAL(MID$(arg$, x, 1), "\\") THEN + escaped = TRUE + ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), CHR$(34))) THEN + IF ISFALSE(escaped) THEN + in_string = NOT(in_string) + END IF + escaped = FALSE + ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), "(")) THEN + IF ISFALSE(in_string) THEN + INCR in_func + END IF + escaped = FALSE + ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), ")")) THEN + IF ISFALSE(in_string) THEN + DECR in_func + END IF + escaped = FALSE + ELSE + escaped = FALSE + ENDIF + NEXT + arg$ = CHOP$(MID$(arg$, pos)) + + ' Check type of var, string? + IF INSTR(arg$, g_STRINGSIGN$) THEN + + IF NOT(REGEX(arg$, "\\[.*\\]")) THEN + ' Is variable declared already? + check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0) + ENDIF + IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE + END IF + + ' Translate function to C function + WRITELN "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, ");" TO g_CFILE + WRITELN "__b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", stdin);" TO g_CFILE + + ' Make sure internal var is copied to var of program + WRITELN arg$, " = (char*)realloc(", arg$, ", (", g_BUFFER_SIZE, "+1)*__b2c__counter*sizeof(char));" TO g_CFILE + WRITELN "if(__b2c__counter == 1) strncpy(", arg$, ", __b2c__input__buffer, ", g_BUFFER_SIZE, ");" TO g_CFILE + WRITELN "else strncat(", arg$, ", __b2c__input__buffer, ", g_BUFFER_SIZE, "); __b2c__counter++;" TO g_CFILE + WRITELN "} while (!strstr(__b2c__input__buffer, \"\\n\") && strlen(__b2c__input__buffer));" TO g_CFILE + ' Cut off last newline + WRITELN "if (strlen(__b2c__input__buffer))", arg$, "[strlen(", arg$, ")-1] = '\\0';" TO g_CFILE + ' Var is numeric or stringarray + ELSE + ' Variable may not be array, these should be defined with DECLARE + IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN + + ' Is variable declared already? + check = Check_Declared(g_HFILE$, arg$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$, 0) + + IF ISFALSE(check) THEN WRITELN "long ", arg$, ";" TO g_HFILE + END IF + + ' Get the type + type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN + type$ = Check_Type$(g_CFILE$, arg$, 0) + END IF + + ' Translate function to C function - we do not need endless buffer here because numbers never can have more than 10 digits anyway + WRITELN "memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, "); __b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", stdin);" TO g_CFILE + + ' Make sure internal var is copied to var of program + IF INSTR(type$, "double ") OR INSTR(type$, "float ") OR INSTR(type$, "FLOATING ") THEN + WRITELN arg$, " = atof(__b2c__input__buffer);" TO g_CFILE + ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN + WRITELN arg$, " = atol(__b2c__input__buffer);" TO g_CFILE + ELSE + WRITELN arg$, " = atoi(__b2c__input__buffer);" TO g_CFILE + END IF + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_For(STRING arg$) + + LOCAL var$, tmp$, from$, to$, step$ + LOCAL check + + ' Get the variablename without (surrounding) spaces + var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "=") - 1)) + tmp$ = CHOP$(MID$(arg$, INSTR(arg$, "=") + 1)) + + ' Do we have a STRING var? + IF INSTR(var$, g_STRINGSIGN$) THEN + PRINT NL$, "ERROR: variable in FOR statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' cannot be string!" + END 1 + END IF + + ' Check if TO is available + IF NOT(INSTR(tmp$, " TO ")) THEN + PRINT NL$, "ERROR: missing TO in FOR statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the starting and ending value + from$ = CHOP$(LEFT$(tmp$, INSTR(tmp$, " TO ") - 1)) + to$ = CHOP$(MID$(tmp$, INSTR(tmp$, " TO ") + 3)) + + ' Check if there is a STEP + IF ISTRUE(INSTR(to$, " STEP ")) THEN + step$ = CHOP$(MID$(to$, INSTR(to$, " STEP ") + 5)) + to$ = CHOP$(LEFT$(to$, INSTR(to$, " STEP ") - 1)) + ELSE + step$ = "1" + END IF + + ' Variable may not be array, these should be defined with DECLARE + IF NOT(REGEX(var$, "\\[.*\\]")) AND ISFALSE(INSTR(var$, ".")) THEN + + ' Is variable declared already? + check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0) + + IF ISFALSE(check) THEN WRITELN "long ", var$, ";" TO g_HFILE + END IF + + ' Translate function to C function + IF VAL(step$) < 0 THEN + WRITELN "for(", var$," = ", from$, "; ", var$, " >= ", to$, ";", var$, " += ", step$, "){" TO g_CFILE + ELSE + WRITELN "for(", var$," = ", from$, "; ", var$, " <= ", to$, ";", var$, " += ", step$, "){" TO g_CFILE + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_While (STRING arg$) + + ' Check if DO is available + IF ISFALSE(INSTRREV(arg$, " DO")) THEN + WRITELN "while(", Parse_Equation$(arg$), "){" TO g_CFILE + ELSE + WRITELN "while(", Parse_Equation$(LEFT$(arg$, INSTRREV(arg$, " DO"))), "){" TO g_CFILE + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- +' $1: name of ASSOC variable +' $2: name of index +' $3: actual value to assign +' $4: recursion level + +SUB Relate_Recurse(STRING var$, STRING str$, STRING tmp$, NUMBER lvl) + + LOCAL rel$ + LOCAL ctr + + ' Check endless recursion + INCR lvl + IF lvl > g_RELATE_CTR THEN + PRINT NL$, "ERROR: Endless recursion in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Now add relation + FOR ctr = 0 TO g_RELATE_CTR + IF EQUAL(LEFT$(g_RELATE$[ctr], LEN(var$)), var$) THEN + rel$ = MID$(g_RELATE$[ctr], INSTR(g_RELATE$[ctr], " ")+1) + WRITELN "if(__b2c__", rel$, "_exist (", str$, " == NULL) __b2c__", rel$, "__add(", str$, ";" TO g_CFILE + IF INSTR(rel$, g_STRINGSIGN$) THEN + WRITELN "__b2c__", rel$, "_exist(", str$, "->value = realloc(__b2c__", rel$, "_exist(", str$, "->value, (strlen(", tmp$, ")+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(__b2c__", rel$, "_exist(", str$, "->value, ", tmp$, ");" TO g_CFILE + ELSE + WRITELN "__b2c__", rel$, "_exist(", str$, "->value = ", tmp$, ";" TO g_CFILE + END IF + Relate_Recurse(rel$, str$, tmp$, lvl) + END IF + NEXT + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Let(STRING arg$) + + LOCAL check, ctr + LOCAL var$, tmp$, str$, lft$, rel$, ptr$ + + ' Check if we have an argument at all + IF NOT(INSTR(arg$, "=")) THEN + PRINT NL$, "ERROR: could not parse line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the variablename without surrounding spaces + var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "=") - 1)) + tmp$ = CHOP$(MID$(arg$, INSTR(arg$, "=") + 1)) + + ' Check if var is string var, exclude RECORD elements + IF REGEX(var$, CONCAT$(g_STRINGSIGN$, "$")) AND NOT(INSTR(var$, ".")) THEN + ' Is variable declared already? + check = Search(g_HFILE$, CONCAT$("char *", var$, " = NULL;"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", var$, " = NULL;"), 0) + ENDIF + + IF check < 0 AND NOT(REGEX(g_PROTOTYPE$, CONCAT$(".* ", var$, "[ ,)]+"))) THEN + WRITELN "char *", var$, " = NULL;" TO g_HFILE + END IF + + ' Assume number, exclude RECORD elements + ELIF NOT(REGEX(var$, "\\[.*\\]")) AND NOT(INSTR(var$, ".")) AND NOT(EQUAL(var$, "ERROR")) AND NOT(REGEX(var$, "\\(.*\\)")) THEN + + ' Is variable declared already? + check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0) + + IF ISFALSE(check) AND NOT(REGEX(g_PROTOTYPE$, CONCAT$(".* ", var$, "[ ,)]+"))) THEN + IF INSTR(tmp$, ".") AND NOT(INSTR(tmp$, CHR$(34))) THEN WRITELN "double ", var$, ";" TO g_HFILE + ELSE WRITELN "long ", var$, ";" TO g_HFILE + END IF + END IF + + ' Check if there is associative array assignment + IF REGEX(var$, "\\(.*\\)$") THEN + lft$ = LEFT$(var$, INSTR(var$, "(") - 1) + str$ = MID$(var$, INSTR(var$, "(") + 1) + WRITELN "if(__b2c__", lft$, "_exist (", str$, " == NULL) __b2c__", lft$, "__add(", str$, ";" TO g_CFILE + IF INSTR(lft$, g_STRINGSIGN$) THEN + WRITELN "__b2c__", lft$, "_exist(", str$, "->value = realloc(__b2c__", lft$, "_exist(", str$, "->value, (strlen(", tmp$, ")+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(__b2c__", lft$, "_exist(", str$, "->value, ", tmp$, ");" TO g_CFILE + ELSE + WRITELN "__b2c__", lft$, "_exist(", str$, "->value = ", tmp$, ";" TO g_CFILE + END IF + ' Check for relations + Relate_Recurse(lft$, str$, tmp$, -1) + + ' Do we have a STRING variable not STRING array? + ELIF INSTR(var$, g_STRINGSIGN$) AND NOT(REGEX(var$, CONCAT$(".*\\[.*", g_STRINGSIGN$, ".*\\].*"))) THEN + WRITELN "__b2c__assign = (char*) strdup (", tmp$, "); ", g_WITHVAR$, var$, " = (char*)realloc(", g_WITHVAR$, var$, ", (strlen(__b2c__assign)+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(", g_WITHVAR$, var$, ", __b2c__assign); free(__b2c__assign);" TO g_CFILE + ' Also check if string var already is used for IMPORT, if so, perform dlopen again + ptr$ = REPLACE$(REPLACE$(var$, CHR$(34), ""), "-", "") + ptr$ = REPLACE$(REPLACE$(REPLACE$(ptr$, ".", ""), "/", ""), "_", "") + check = Search(g_CFILE$, CONCAT$("void* __b2c__dlopen__pointer_", ptr$, ";"), 0) + IF check >= 0 THEN + WRITELN "__b2c__dlopen__pointer_", ptr$, " = dlopen(", var$, ", RTLD_LAZY);" TO g_CFILE + END IF + + ELSE + WRITELN g_WITHVAR$, arg$, ";" TO g_CFILE + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Open(STRING arg$) + + LOCAL check + LOCAL file$, tmp$, mode$, handle$ + + ' Check if FOR is available + IF NOT(INSTR(arg$, " FOR ")) THEN + PRINT NL$, "ERROR: missing FOR in OPEN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if AS is available + IF NOT(INSTR(arg$, " AS ")) THEN + PRINT NL$, "ERROR: missing AS in OPEN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the file, mode and handle + file$ = CHOP$(LEFT$(arg$, INSTR(arg$, " FOR ") - 1)) + tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FOR ") + 5)) + + mode$ = CHOP$(LEFT$(tmp$, INSTR(tmp$, " AS ") - 1)) + handle$ = CHOP$(MID$(tmp$, INSTR(tmp$, " AS ") + 4)) + + ' Check if var is string var + IF INSTR(handle$, g_STRINGSIGN$) AND NOT(EQUAL(mode$, "MEMORY")) THEN + PRINT NL$, "ERROR: variable for OPEN at line ", g_COUNTER, " in file '", g_CURFILE$, "' cannot be string!" + END 1 + END IF + + ' Check if variable was declared + IF NOT(INSTR(handle$, ".")) THEN + check = Check_Declared(g_HFILE$, handle$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, handle$, 0) + END IF + + ' File or dir? + IF EQUAL(mode$, "DIRECTORY") THEN + IF ISFALSE(check) THEN + WRITELN "DIR* ", handle$, ";" TO g_HFILE + END IF + ELIF EQUAL(mode$, "MEMORY") THEN + IF ISFALSE(check) THEN + WRITELN "char* ", handle$, ";" TO g_HFILE + END IF + check = Check_Declared(g_HFILE$, CONCAT$("__b2c_mem_", handle$, ";"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, CONCAT$("__b2c_mem_", handle$, ";"), 0) + IF ISFALSE(check) THEN + WRITELN "long __b2c_mem_", handle$, ";" TO g_HFILE + END IF + ELIF EQUAL(mode$, "NETWORK") OR EQUAL(mode$, "SERVER") THEN + IF ISFALSE(check) THEN + WRITELN "int ", handle$, ";" TO g_HFILE + END IF + ELSE + IF ISFALSE(check) THEN + WRITELN "FILE* ", handle$, ";" TO g_HFILE + END IF + END IF + + ' Convert to C syntax + IF EQUAL(mode$, "READING") THEN + WRITELN handle$, " = fopen(", file$, ", \"r\");" TO g_CFILE + WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELIF EQUAL(mode$, "WRITING") THEN + WRITELN handle$, " = fopen(", file$, ", \"w\");" TO g_CFILE + WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELIF EQUAL(mode$, "APPENDING") THEN + WRITELN handle$, " = fopen(", file$, ", \"a\");" TO g_CFILE + WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELIF EQUAL(mode$, "READWRITE") THEN + WRITELN handle$, " = fopen(", file$, ", \"r+\");" TO g_CFILE + WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELIF EQUAL(mode$, "DIRECTORY") THEN + WRITELN handle$, " = opendir(", file$, ");" TO g_CFILE + WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELIF EQUAL(mode$, "MEMORY") THEN + WRITELN handle$, " = (char*)", file$, "; __b2c_mem_", handle$, " = ", file$, ";" TO g_CFILE + WRITELN "if(!__b2c__trap){__b2c__memory__check(", handle$, "); if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELIF EQUAL(mode$, "NETWORK") THEN + ' Network code + WRITELN "if (strstr(", file$, ", \":\") == NULL){ERROR = 10; fprintf(stderr, \"ERROR: %s: '%s'\\n\", ERR", g_STRINGSIGN$, "(ERROR), ", file$, "); exit(ERROR);}" TO g_CFILE + WRITELN "strncpy(__b2c__data_client, ", file$, ", ", g_BUFFER_SIZE, ");__b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\");__b2c__he = gethostbyname(__b2c__host);" TO g_CFILE + WRITELN "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN handle$, " = socket(PF_INET, SOCK_STREAM, 0);" TO g_CFILE + WRITELN "if (", handle$, " == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN "__b2c__to.tv_sec = ", g_OPTION_SOCKET, "; __b2c__to.tv_usec = 0; setsockopt(", handle$, ", SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" TO g_CFILE + WRITELN "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));" TO g_CFILE + WRITELN "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr); memset(&(__b2c__addr.sin_zero), '\\0', sizeof(__b2c__addr.sin_zero));" TO g_CFILE + WRITELN "__b2c__result = connect(", handle$, ", (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" TO g_CFILE + WRITELN "if(__b2c__result == -1) {if(!__b2c__trap){ERROR = 13;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELIF EQUAL(mode$, "SERVER") THEN + ' Network code + WRITELN "if (strstr(", file$, ", \":\") == NULL){ERROR = 10; fprintf(stderr, \"ERROR: %s: '%s'\\n\", ERR", g_STRINGSIGN$, "(ERROR), ", file$, "); exit(ERROR);}" TO g_CFILE + WRITELN "if(strcmp(__b2c__data_server, ", file$, ")) {strncpy(__b2c__data_server, ", file$, ", ", g_BUFFER_SIZE, ");__b2c__host = strtok(__b2c__data_server, \":\"); __b2c__port = strtok(NULL, \":\");__b2c__he = gethostbyname(__b2c__host);" TO g_CFILE + WRITELN "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN "__b2c__handle = socket(AF_INET, SOCK_STREAM, 0);" TO g_CFILE + WRITELN "if (__b2c__handle == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN "__b2c__to.tv_sec = ", g_OPTION_SOCKET, "; __b2c__to.tv_usec = 0; setsockopt(__b2c__handle, SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" TO g_CFILE + WRITELN "setsockopt(__b2c__handle, SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int));__b2c__addr.sin_family = AF_INET; __b2c__addr.sin_port = htons((long)atol(__b2c__port));" TO g_CFILE + WRITELN "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr);memset(&(__b2c__addr.sin_zero), '\\0', sizeof(__b2c__addr.sin_zero));" TO g_CFILE + WRITELN "__b2c__result = bind(__b2c__handle, (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" TO g_CFILE + WRITELN "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 17;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN "__b2c__result = listen(__b2c__handle, ", g_MAX_BACKLOG, ");" TO g_CFILE + WRITELN "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 18;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN "strncpy(__b2c__data_server, ", file$, ", ", g_BUFFER_SIZE, "); /* Restore data because of strtok */} __b2c__result = accept(__b2c__handle, NULL, 0);" TO g_CFILE + WRITELN "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 19;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN handle$, "= __b2c__result;" TO g_CFILE + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Seek(STRING arg$) + + LOCAL dim + + ' Check if we have an argument at all + IF ISFALSE(LEN(arg$)) THEN + PRINT NL$, "ERROR: empty SEEK at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if OFFSET is available + IF NOT(INSTR(arg$, " OFFSET ")) THEN + PRINT NL$, "ERROR: missing OFFSET in SEEK statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the variablename, filedescriptor + SPLIT arg$ BY " " TO element$ SIZE dim + + ' Convert to C function + IF dim EQ 3 THEN + WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_SET);" TO g_CFILE + ELIF dim EQ 5 THEN + IF EQUAL(element$[5], "START") THEN + WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_SET);" TO g_CFILE + ELIF EQUAL(element$[4], "CURRENT") THEN + WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_CUR);" TO g_CFILE + ELIF EQUAL(element$[4], "END") THEN + WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_END);" TO g_CFILE + END IF + ELSE + PRINT NL$, "ERROR: erroneous SEEK statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Copy(STRING arg$) + + LOCAL from$, to$ + + ' Check if we have an argument at all + IF ISFALSE(LEN(arg$)) THEN + PRINT NL$, "ERROR: empty COPY at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if TO is available + IF NOT(INSTR(arg$, " TO ")) THEN + PRINT NL$, "ERROR: Missing TO in COPY statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the filename and copyname + from$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TO ") - 1)) + to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4)) + + ' Translate to C function + WRITELN "__b2c__inFile = fopen(", from$, ", \"r\"); __b2c__outFile = fopen(", to$, ", \"w\"); __b2c__Byte = 0;" TO g_CFILE + WRITELN "if (__b2c__inFile != NULL && __b2c__outFile != NULL){while(__b2c__Byte!=EOF){" TO g_CFILE + WRITELN "__b2c__Byte=fgetc(__b2c__inFile); if(__b2c__Byte!=EOF){" TO g_CFILE + WRITELN "fputc(__b2c__Byte,__b2c__outFile); }}" TO g_CFILE + WRITELN "fclose(__b2c__inFile); fclose(__b2c__outFile);}" TO g_CFILE + WRITELN "else { if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Rename(STRING arg$) + + LOCAL from$, to$ + + ' Check if we have an argument at all + IF ISFALSE(LEN(arg$)) THEN + PRINT NL$, "ERROR: empty RENAME at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if TO is available + IF NOT(INSTR(arg$, " TO ")) THEN + PRINT NL$, "ERROR: Missing TO in RENAME statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the filename and copyname + from$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TO ") - 1)) + to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4)) + + ' Translate to C function + WRITELN "if(rename(", from$, ", ", to$, ") < 0) {if(!__b2c__trap){ERROR = 9; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Readln(STRING arg$) + + LOCAL dim, check + + ' Check if FROM is available + IF NOT(INSTR(arg$, " FROM ")) THEN + PRINT NL$, "ERROR: missing FROM in READLN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the variablename, filedescriptor + SPLIT arg$ BY " " TO element$ SIZE dim + + ' Check if var is string var + IF NOT(INSTR(element$[1], g_STRINGSIGN$)) THEN + PRINT NL$, "ERROR: variable for READLN at line ", g_COUNTER, " in file '", g_CURFILE$, "' must be string!" + END 1 + END IF + + ' Check if var is string var, exclude RECORD elements + IF NOT(REGEX(element$[1], "\\[.*\\]")) THEN + ' Is variable declared already? + check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0) + ENDIF + + IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE + END IF + + ' Translate function to C function + WRITELN "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, ");" TO g_CFILE + WRITELN "__b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", ", element$[3], ");" TO g_CFILE + + ' Make sure internal var is copied to var of program + WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", g_BUFFER_SIZE, "+1)*__b2c__counter*sizeof(char));" TO g_CFILE + WRITELN "if(__b2c__counter == 1) strncpy(", element$[1], ", __b2c__input__buffer, ", g_BUFFER_SIZE, ");" TO g_CFILE + WRITELN "else strncat(", element$[1], ", __b2c__input__buffer, ", g_BUFFER_SIZE, "); __b2c__counter++;" TO g_CFILE + WRITELN "} while (!strstr(__b2c__input__buffer, \"\\n\") && strlen(__b2c__input__buffer));" TO g_CFILE + ' Cut off last newline + WRITELN "if (strlen(__b2c__input__buffer))", element$[1], "[strlen(", element$[1], ")-1]='\\0';" TO g_CFILE + ' Cut off CR if available + WRITELN "if(strlen(", element$[1], ")>0 && ", element$[1], "[strlen(", element$[1], ")-1]=='\\r') ", element$[1], "[strlen(", element$[1], ")-1]='\\0';" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Writeln(STRING arg$) + + LOCAL in_string, in_func, pos, escaped, x, len + LOCAL var$, to$ + + ' Check if FROM is available + IF NOT(INSTR(arg$, " TO ")) THEN + PRINT NL$, "ERROR: missing TO in WRITELN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the variablename, filedescriptor + var$ = LEFT$(arg$, INSTRREV(arg$, " TO ")) + to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " TO ") + 4)) + + ' Start miniparser + in_string = FALSE + in_func = 0 + pos = 1 + escaped = 0 + + FOR x = 1 TO LEN(var$) + IF ISTRUE(EQUAL(MID$(var$, x, 1), ",")) THEN + IF ISFALSE(in_string) AND ISFALSE(in_func) THEN + len = INSTR(MID$(var$, pos, x-pos), "(")-1 + IF len < 0 THEN len = x-pos + IF INSTR(MID$(var$, pos, len), g_STRINGSIGN$) OR INSTR(MID$(var$, pos, len), CHR$(34)) THEN + WRITELN "fprintf(", to$, ", \"%s\", ", MID$(var$, pos, x-pos), ");" TO g_CFILE + ELSE + WRITELN "fprintf(", to$, ", \"%s\", STR", g_STRINGSIGN$, "(", MID$(var$, pos, x-pos), "));" TO g_CFILE + END IF + pos = x+1 + escaped = FALSE + END IF + ELIF EQUAL(MID$(var$, x, 1), "\\") THEN + escaped = TRUE + ELIF ISTRUE(EQUAL(MID$(var$, x, 1), CHR$(34))) THEN + IF ISFALSE(escaped) THEN + in_string = NOT(in_string) + END IF + escaped = FALSE + ELIF ISTRUE(EQUAL(MID$(var$, x, 1), "(")) THEN + IF ISFALSE(in_string) THEN + INCR in_func + END IF + escaped = FALSE + ELIF ISTRUE(EQUAL(MID$(var$, x, 1), ")")) THEN + IF ISFALSE(in_string) THEN + DECR in_func + END IF + escaped = FALSE + ELSE + escaped = FALSE + ENDIF + NEXT + var$ = MID$(var$, pos) + + ' Write last element to file + len = INSTR(var$, "(")-1 + IF len < 0 THEN len = LEN(var$) + IF INSTR(LEFT$(var$, len), g_STRINGSIGN$) OR INSTR(LEFT$(var$, len), CHR$(34)) THEN + WRITELN "fprintf(", to$, ", \"%s\\n\", ", var$, ");" TO g_CFILE + ELSE + WRITELN "fprintf(", to$, ", \"%s\\n\", STR", g_STRINGSIGN$, "(", var$, "));" TO g_CFILE + END IF + WRITELN "fflush(", to$, ");" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Getbyte(STRING arg$) + + LOCAL dim, check + LOCAL var$, to$, size$ + + ' Check if FROM is available + IF NOT(INSTR(arg$, " FROM ")) THEN + PRINT NL$, "ERROR: missing FROM in GETBYTE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the variablename, filedescriptor + var$ = CHOP$(LEFT$(arg$, INSTRREV(arg$, " FROM "))) + to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " FROM ") + 6)) + + ' Check if SIZE is available + IF INSTR(to$, " SIZE ") THEN + size$ = MID$(to$, INSTR(to$, " SIZE ") + 6) + to$ = MID$(to$, 1, INSTR(to$, " SIZE ")) + ELSE + size$ = "1" + END IF + + ' Declare variable if not done yet, assuming long + IF NOT(INSTR(var$, ".")) THEN + check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0) + + IF ISFALSE(check) THEN WRITELN "long ", var$, ";" TO g_HFILE + END IF + + ' Translate function to C function + WRITELN "if(!__b2c__trap){__b2c__memory__check((char *)", var$, "); if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN "__b2c__counter = fread((void*)", var$, ", sizeof(", g_OPTION_MEMTYPE$, "), ", size$, ", ", to$, ");" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Putbyte(STRING arg$) + + LOCAL dim + LOCAL var$, to$, size$ + + ' Check if FROM is available + IF NOT(INSTR(arg$, " TO ")) THEN + PRINT NL$, "ERROR: missing TO in PUTBYTE statement at line at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the variablename, filedescriptor + var$ = LEFT$(arg$, INSTRREV(arg$, " TO ")) + to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " TO ") + 4)) + + ' Check if SIZE is available + IF INSTR(to$, " SIZE ") THEN + size$ = MID$(to$, INSTR(to$, " SIZE ") + 6) + to$ = MID$(to$, 1, INSTR(to$, " SIZE ")) + ELSE + size$ = "1" + END IF + + ' Translate function to C function + WRITELN "if(!__b2c__trap){__b2c__memory__check((char *)", var$, "); if(ERROR){if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN "__b2c__counter = fwrite((void*)", var$, ", sizeof(", g_OPTION_MEMTYPE$, "), ", size$, ", ", to$, ");" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Getfile(STRING arg$) + + LOCAL dim, check + + ' Check if FROM is available + IF NOT(INSTR(arg$, " FROM ")) THEN + PRINT NL$, "ERROR: missing FROM in GETFILE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the variablename, filedescriptor + SPLIT arg$ BY " " TO element$ SIZE dim + + ' Translate function to C function + WRITELN "__b2c__dir = readdir(", element$[3], ");" TO g_CFILE + + ' Check if variable is declared + IF NOT(INSTR(element$[1], "[")) AND NOT(INSTR(element$[1], "]")) THEN + check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0) + ENDIF + END IF + + IF check < 0 AND NOT(REGEX(element$[1], "\\[.*\\]")) AND NOT(INSTR(element$[1], ".")) THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE + + ' Always realloc VAR to correct size, maybe it was resized somewhere else + WRITELN "if(__b2c__dir != NULL) {", element$[1], " = realloc(", element$[1], ", (strlen(__b2c__dir->d_name)+1)*sizeof(char));" TO g_CFILE + ' Make sure internal var is copied to var of program + WRITELN "strcpy(", element$[1], ", __b2c__dir->d_name); ", element$[1], "[strlen(__b2c__dir->d_name)] = '\\0';}" TO g_CFILE + WRITELN "else {", element$[1], " = realloc(", element$[1], ", sizeof(char)); ", element$[1], "[0] = '\\0';}" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Receive(STRING arg$) + + LOCAL dim, check + LOCAL size$, chunk$ + + ' Check if FROM is available + IF NOT(INSTR(arg$, " FROM ")) THEN + PRINT NL$, "ERROR: Missing FROM in RECEIVE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get filedescriptor + SPLIT CHOP$(arg$) BY " " TO element$ SIZE dim + + ' Check for optional chunksize + SELECT dim + CASE 5 + chunk$ = element$[5] + size$ = "" + CASE 7 + chunk$ = element$[5] + size$ = element$[7] + DEFAULT + chunk$ = STR$(g_BUFFER_SIZE) + size$ = "" + END SELECT + + ' Variable may not be array, these should be defined with DECLARE + IF LEN(size$) > 0 AND NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) THEN + check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$, 0) + + IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE + END IF + + ' Check if variable is declared + IF INSTR(element$[1], g_STRINGSIGN$) THEN + check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0) + ENDIF + + IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE + WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", chunk$, "+1)*sizeof(char)); memset(", element$[1], ", '\\0', sizeof(char)*(", chunk$, "+1));" TO g_CFILE + END IF + + ' Translate function to C function + IF LEN(size$) EQ 0 THEN + WRITELN "if(recv(", element$[3], ", (void*)", element$[1], ", ", chunk$, ", 0) < 0) {if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELSE + WRITELN "if((", size$, " = recv(", element$[3], ", (void*)", element$[1], ", ", chunk$,", 0)) < 0) {if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Send(STRING arg$) + + LOCAL to$, var$, chunk$ + + ' Check if TO is available + IF NOT(INSTR(arg$, " TO ")) THEN + PRINT NL$, "ERROR: Missing TO in SEND statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the variablename without surrounding spaces + var$ = LEFT$(arg$, INSTR(arg$, " TO ")) + + ' Get filedescriptor + to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4)) + + IF INSTR(to$, " CHUNK ") THEN + chunk$ = MID$(to$, INSTR(to$, " CHUNK ") + 7) + to$ = MID$(to$, 1, INSTR(to$, " CHUNK ") - 1) + ELSE + chunk$ = CONCAT$("strlen(", var$, ")") + END IF + + ' Translate function to C function + WRITELN "if(send(", to$, ", (void*)", var$, ", ", chunk$, ", 0) < 0) {if(!__b2c__trap){ERROR = 15; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Getline(STRING arg$) + + LOCAL dim, check + + ' Check if FROM is available + IF NOT(INSTR(arg$, " FROM ")) THEN + PRINT NL$, "ERROR: missing FROM in GETLINE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the variablename, filedescriptor + SPLIT arg$ BY " " TO element$ SIZE dim + + ' Check if var is string var + IF NOT(INSTR(element$[1], g_STRINGSIGN$)) THEN + PRINT NL$, "ERROR: variable for GETLINE at line $g_COUNTER in file ", g_COUNTER, " in file '", g_CURFILE$, "' must be string!" + END 1 + END IF + + ' Check if variable is declared + IF NOT(INSTR(element$[1], "[")) AND NOT(INSTR(element$[1], "]")) THEN + ' Is variable declared already? + check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0) + ENDIF + + IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE + END IF + + ' Translate function to C function + WRITELN "if (", element$[3], " == NULL ||", CONCAT$("*", element$[3]) , " == '\\0') {", element$[1], " = (char*)realloc(", element$[1], ", 2*sizeof(char)); strcpy(", element$[1], ", \"\");}" TO g_CFILE + WRITELN "else { __b2c__assign = ", element$[3], "; while(*", element$[3], " != '\\0' && *", element$[3], " != '\\n') ", element$[3], "++;" TO g_CFILE + + ' Make sure internal var is copied to var of program + WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", element$[3], "-__b2c__assign+1)*sizeof(char));" TO g_CFILE + WRITELN "strncpy(", element$[1], ", __b2c__assign, ", element$[3], "-__b2c__assign);" TO g_CFILE + + ' Make sure to end the string + WRITELN element$[1], "[(", element$[3], "-__b2c__assign)] = '\\0'; ", element$[3], "++;}" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Putline(STRING arg$) + + LOCAL in_string, in_func, pos, escaped, x, len + LOCAL var$, to$ + + ' Check if TO is available + IF NOT(INSTR(arg$, " TO ")) THEN + PRINT NL$, "ERROR: missing TO in PUTLINE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the variablename, filedescriptor + var$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO "))) + to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4)) + + ' Start miniparser + in_string = FALSE + in_func = 0 + pos = 1 + escaped = 0 + + FOR x = 1 TO LEN(var$) + IF ISTRUE(EQUAL(MID$(var$, x, 1), ",")) THEN + IF ISFALSE(in_string) AND ISFALSE(in_func) THEN + len = INSTR(MID$(var$, pos, x-pos), "(")-1 + IF len < 0 THEN len = x-pos + IF INSTR(MID$(var$, pos, len), g_STRINGSIGN$) OR INSTR(MID$(var$, pos, len), CHR$(34)) THEN + WRITELN "strcat(", to$, ", ", CHOP$(MID$(var$, pos, x-pos)), ");", to$, "+=strlen(", CHOP$(MID$(var$, pos, x-pos)), ");" TO g_CFILE + ELSE + WRITELN "strcat(", to$, ", STR", g_STRINGSIGN$, "(", CHOP$(MID$(var$, pos, x-pos)), "));", to$, "+=strlen(STR", g_STRINGSIGN$, "(", CHOP$(MID$(var$, pos, x-pos)), "));" TO g_CFILE + END IF + pos = x+1 + escaped = FALSE + END IF + ELIF EQUAL(MID$(var$, x, 1), "\\") THEN + escaped = TRUE + ELIF ISTRUE(EQUAL(MID$(var$, x, 1), CHR$(34))) THEN + IF ISFALSE(escaped) THEN + in_string = NOT(in_string) + END IF + escaped = FALSE + ELIF ISTRUE(EQUAL(MID$(var$, x, 1), "(")) THEN + IF ISFALSE(in_string) THEN + INCR in_func + END IF + escaped = FALSE + ELIF ISTRUE(EQUAL(MID$(var$, x, 1), ")")) THEN + IF ISFALSE(in_string) THEN + DECR in_func + END IF + escaped = FALSE + ELSE + escaped = FALSE + ENDIF + NEXT + var$ = MID$(var$, pos) + + ' Check if var is string var + len = INSTR(MID$(var$, pos, x-pos), "(")-1 + IF len < 0 THEN len = x-pos + IF INSTR(LEFT$(var$, len), g_STRINGSIGN$) OR INSTR(LEFT$(var$, len), CHR$(34)) THEN + WRITELN "strcat(", to$, ", ", var$, "); strcat(", to$, ", \"\\n\"); ", to$, "+=strlen(", var$, ")+1;" TO g_CFILE + ELSE + WRITELN "strcat(", to$, ", STR", g_STRINGSIGN$, "(", var$, ")); strcat(", to$, ", \"\\n\"); ", to$, "+=strlen(STR", g_STRINGSIGN$, "(", var$, "))+1;" TO g_CFILE + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_SubFunc(STRING arg$) + + LOCAL x, dim, check + LOCAL arg_s$, dim$, arr$, size$ + + ' Check argument + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty SUB/FUNCTION at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if we are in a sub already + IF LEN(g_FUNCNAME$) > 0 THEN + PRINT NL$, "ERROR: cannot define a SUB/FUNCTION within a SUB/FUNCTION at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the funcname + IF INSTR(arg$, "(") THEN + g_ORIGFUNCNAME$ = CHOP$(LEFT$(arg$, INSTR(arg$, "("))) + g_PROTOTYPE$ = CHOP$(LEFT$(arg$, INSTR(arg$, "("))) + ELSE + g_ORIGFUNCNAME$ = CHOP$(CONCAT$(arg$, "(")) + g_PROTOTYPE$ = CHOP$(CONCAT$(arg$, "(")) + END IF + + ' Start miniparser to duplicate string arguments + arg_s$ = CHOP$(MID$(arg$, INSTR(arg$, "(") + 1)) + + SPLIT arg_s$ BY "," TO element$ SIZE dim + + x = 1 + WHILE dim > 1 DO + IF INSTR(element$[x], "STRING ") OR INSTR(element$[x], "char* ") THEN + element$[x] = CHOP$(element$[x]) + arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ")-1) + dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1) + IF NOT(INSTR(element$[x], g_STRINGSIGN$)) AND REGEX(element$[x], ".*\\[.*\\].*") THEN + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"],") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char** ", arr$, " = __b2c_", arr$, ";") + g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ",") + ELIF NOT(INSTR(element$[x], g_STRINGSIGN$)) THEN + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ",") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = __b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ";") + g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ",") + ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"],") + IF LEN(dim$) < 1 THEN + PRINT NL$, "ERROR: cannot pass string array without dimension at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"] = { NULL };") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){if(__b2c_", arr$, "[__b2c__ctr]!=NULL) ", arr$, "[__b2c__ctr] = strdup(__b2c_", arr$, "[__b2c__ctr]);}") + g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++)if(", arr$, "[__b2c__ctr]!=NULL){free(", arr$, "[__b2c__ctr]);}") + g_PROTOTYPE$=CONCAT$(g_PROTOTYPE$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ",") + ELSE + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ",") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = strdup(__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ");") + g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", CHOP$(MID$(element$[x], INSTR(element$[x], " ")))) + g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ",") + END IF + ELSE + element$[x] = CHOP$(element$[x]) + IF REGEX(element$[x], ".*\\[.*\\].*\\].*") THEN + PRINT NL$, "ERROR: cannot pass multidimensional numeric array at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELIF REGEX(element$[x], ".*\\[\\].*") THEN + g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ",")) + ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN + dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1) + IF LEN(dim$) < 1 THEN + PRINT NL$, "ERROR: cannot pass numeric array without dimension at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ") - 1) + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, MID$(element$[x], 1, INSTR(element$[x], " "))," __b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"],") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, MID$(element$[x], 1, INSTR(element$[x], " ")), " ", arr$, "[", dim$, "+", STR$(g_OPTION_BASE), "] = { 0 };") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){", arr$, "[__b2c__ctr] = __b2c_", arr$, "[__b2c__ctr];}") + ELIF INSTR(element$[x], "VAR ") THEN + PRINT NL$, "ERROR: variable argument list cannot be followed by other arguments at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ",")) + END IF + g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", CHOP$(element$[x]), ",") + END IF + INCR x + DECR dim + WEND + + ' Last token in the sequence of arguments + IF ISTRUE(dim) THEN + element$[x] = CHOP$(LEFT$(element$[x], INSTR(element$[x], ")") - 1)) + IF INSTR(element$[x], "STRING ") OR INSTR(element$[x], "char* ") THEN + arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ")-1) + dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1) + IF NOT(INSTR(element$[x], g_STRINGSIGN$)) AND REGEX(element$[x], ".*\\[.*\\].*") THEN + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"])") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char** ", arr$, " = __b2c_", arr$, ";") + g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")") + ELIF NOT(INSTR(element$[x], g_STRINGSIGN$)) THEN + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ")") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = __b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ";") + g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")") + ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"])") + IF LEN(dim$) < 1 THEN + PRINT NL$, "ERROR: cannot pass string array without dimension at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"] = { NULL };") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){if(__b2c_", arr$, "[__b2c__ctr]!=NULL) ", arr$, "[__b2c__ctr] = strdup(__b2c_", arr$, "[__b2c__ctr]);}") + g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++)if(", arr$, "[__b2c__ctr]!=NULL){free(", arr$, "[__b2c__ctr]);}") + g_PROTOTYPE$=CONCAT$(g_PROTOTYPE$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ")") + ELSE + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ")") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = strdup(__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ");") + g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", CHOP$(MID$(element$[x], INSTR(element$[x], " ")))) + g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")") + END IF + ELSE + IF INSTR(g_ORIGFUNCNAME$, element$[x]) OR LEN(element$[x]) EQ 0 THEN element$[x] = "void " + IF REGEX(element$[x], ".*\\[.*\\].*\\].*") THEN + PRINT NL$, "ERROR: cannot pass multidimensional numeric array at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELIF REGEX(element$[x], ".*\\[\\].*") THEN + g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ")")) + ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN + dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1) + IF LEN(dim$) < 1 THEN + PRINT NL$, "ERROR: cannot pass numeric array without dimension at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ") - 1) + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, MID$(element$[x], 1, INSTR(element$[x], " "))," __b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"])") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, MID$(element$[x], 1, INSTR(element$[x], " ")), " ", arr$, "[", dim$, "+", STR$(g_OPTION_BASE), "] = { 0 };") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){", arr$, "[__b2c__ctr] = __b2c_", arr$, "[__b2c__ctr];}") + ELIF INSTR(element$[x], "VAR ") THEN + IF INSTR(g_PROTOTYPE$, ",") THEN + PRINT NL$, "ERROR: variable argument list cannot be preceded by other arguments at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + IF NOT(INSTR(element$[x], " SIZE ")) THEN + PRINT NL$, "ERROR: variable argument list lacks SIZE argument at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + arr$ = MID$(element$[x], INSTR(element$[x], " ") + 1):arr$ = CHOP$(LEFT$(arr$, INSTR(arr$, "SIZE ")-1)):size$ = CHOP$(MID$(element$[x], INSTR(element$[x], "SIZE ") + 5)) + IF NOT(INSTR(arr$, g_STRINGSIGN$)) THEN + PRINT NL$, "ERROR: variable argument list is not string at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS) + IF ISFALSE(check) THEN g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " long ", size$, ";") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "long __b2c__var_", arr$, " = ", STR$(g_OPTION_BASE), "; va_list __b2c__ap; char **", arr$, " = NULL; char* __b2c__va = NULL; ", arr$, " = (char **)realloc(", arr$, ", (__b2c__var_", arr$, "+1) * sizeof(char*));") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "va_start(__b2c__ap, __b2c__name); ", arr$, "[__b2c__var_", arr$, "] = strdup(__b2c__name); while (", arr$, "[__b2c__var_", arr$, "] != NULL) {__b2c__var_", arr$, "++; ", arr$, " = (char **)realloc(", arr$, ", (__b2c__var_", arr$, "+1) * sizeof(char*));") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "__b2c__va = va_arg(__b2c__ap, char*); if(__b2c__va != NULL) ", arr$, "[__b2c__var_", arr$, "] = strdup(__b2c__va); else ", arr$, "[__b2c__var_", arr$, "] = NULL; }") + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "va_end(__b2c__ap); ", size$, " = __b2c__var_", arr$, " - ", STR$(g_OPTION_BASE), "; if(__b2c__var_", arr$, " > 0) __b2c__var_", arr$, "--;") + g_PROTOTYPE$ = CONCAT$("__", g_PROTOTYPE$) + g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c__name, ...)") + element$[x] = "char*, ..." + g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, "if(", arr$, " != NULL) {for(__b2c__ctr=", STR$(g_OPTION_BASE), "; __b2c__ctr<=__b2c__var_", arr$, "; __b2c__ctr++) if(", arr$, "[__b2c__ctr]!=NULL){free(", arr$, "[__b2c__ctr]);} free(", arr$, ");}") + ELSE + g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ")")) + END IF + g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")") + END IF + END IF + + ' Get original function name + IF INSTR(g_ORIGFUNCNAME$, " (") THEN + g_FUNCNAME$ = LEFT$(g_ORIGFUNCNAME$, INSTR(g_ORIGFUNCNAME$, " (") - 1) + ELIF INSTR(g_ORIGFUNCNAME$, "(") THEN + g_FUNCNAME$ = LEFT$(g_ORIGFUNCNAME$, INSTR(g_ORIGFUNCNAME$, "(") - 1) + ELSE + g_FUNCNAME$ = g_ORIGFUNCNAME$ + END IF + + ' Close the current C file + CLOSE FILE g_CFILE + + ' Add macro in case of VAR argument + IF INSTR(element$[x], " ...") THEN + WRITELN "#define ", g_FUNCNAME$, "(...) __", g_FUNCNAME$, "(\"", g_FUNCNAME$, "\", __VA_ARGS__, NULL)" TO g_HFILE + g_ORIGFUNCNAME$ = CONCAT$("__", g_ORIGFUNCNAME$) + END IF + + ' Make symbol known to parser + g_IMPORTED$ = CONCAT$(g_FUNCNAME$, " ", g_IMPORTED$) + + ' Switch to header file + g_COPY_CFILE$ = g_CFILE$ + g_CFILE$ = CONCAT$(LEFT$(g_CFILE$, INSTR(g_CFILE$, ".c")), g_FUNCNAME$, ".tmp") + + ' Save CATCH routine + g_ORIGCATCHGOTO$ = g_CATCHGOTO$ + g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" + + ' Open temp C file + OPEN g_CFILE$ FOR WRITING AS g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Endsub() + + LOCAL tmp_HFILE TYPE FILE* + LOCAL line$ + LOCAL dim, x + + ' Close the current C file + CLOSE FILE g_CFILE + + ' Put prototype to header file + WRITELN "void ", g_PROTOTYPE$, "; /* noparse */" TO g_HFILE + g_PROTOTYPE$ = "" + + ' Open temporary header file + OPEN CONCAT$(g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h") FOR WRITING AS tmp_HFILE + + ' Get original function name + WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO tmp_HFILE + WRITELN "/* noparse ", g_CURFILE$, " BACON LINE ", g_COUNTER, " */" TO tmp_HFILE + IF INSTR(g_ORIGFUNCNAME$, " (") THEN + WRITELN "void ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE + ELIF INSTR(g_ORIGFUNCNAME$, "(") THEN + WRITELN "void ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE + ELSE + WRITELN "void ", g_FUNCNAME$, "(void) {" TO tmp_HFILE + END IF + + ' Finalize sub + WRITELN g_STRINGARGS$ TO tmp_HFILE + OPEN g_CFILE$ FOR READING AS g_CFILE + WHILE NOT(ENDFILE(g_CFILE)) DO + READLN line$ FROM g_CFILE + IF NOT(ENDFILE(g_CFILE)) THEN WRITELN line$ TO tmp_HFILE + WEND + CLOSE FILE g_CFILE + + ' Free strings variables if there are any + SPLIT g_LOCALSTRINGS$ BY " " TO element$ SIZE dim + FOR x = 1 TO dim + IF LEN(element$[x]) > 0 THEN WRITELN "if(", element$[x], " != NULL) free(", element$[x], ");" TO tmp_HFILE + NEXT + WRITELN g_STRINGARRAYS$ TO tmp_HFILE + WRITELN "__B2C__PROGRAM__EXIT: ;" TO tmp_HFILE + WRITELN "}" TO tmp_HFILE + + CLOSE FILE tmp_HFILE + + ' Include header file + IF NOT(INSTR(g_INCLUDE_FILES$, CONCAT$(LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h"))) THEN + g_INCLUDE_FILES$ = CONCAT$(g_INCLUDE_FILES$, " ", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h") + END IF + + ' Add to total filelist + g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h") + + ' Delete temp funcfile + DELETE FILE g_CFILE$ + + ' Restore mainfile + g_CFILE$ = g_COPY_CFILE$ + OPEN g_CFILE$ FOR APPENDING AS g_CFILE + + ' Restore CATCH routine + g_CATCHGOTO$ = g_ORIGCATCHGOTO$ + + ' Reset variables + g_ORIGFUNCNAME$ = "" + g_FUNCNAME$ = "" + g_LOCALSTRINGS$ = "" + g_STRINGARRAYS$ = "" + g_STRINGARGS$ = "" + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Endfunction() + + IF ISFALSE(LEN(g_FUNCTYPE$)) THEN + PRINT NL$, "ERROR: function '", g_FUNCNAME$, "' was defined without returning a value or string!" + END 1 + END IF + + ' Close the current C file + CLOSE FILE g_CFILE + + ' Put prototype to header file + WRITELN g_FUNCTYPE$, " ", g_PROTOTYPE$, "; /* noparse */" TO g_HFILE + g_PROTOTYPE$ = "" + + ' Open temporary header file + OPEN CONCAT$(g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h") FOR WRITING AS tmp_HFILE + + ' Get original function name + WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO tmp_HFILE + WRITELN "/* noparse ", g_CURFILE$, " BACON LINE ", g_COUNTER, " */" TO tmp_HFILE + IF NOT(INSTR(g_ORIGFUNCNAME$, "(")) THEN + WRITELN g_FUNCTYPE$, " ", g_FUNCNAME$, "(void) {" TO tmp_HFILE + ELSE + WRITELN g_FUNCTYPE$, " ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE + END IF + + ' Add function body + WRITELN g_STRINGARGS$ TO tmp_HFILE + OPEN g_CFILE$ FOR READING AS g_CFILE + WHILE NOT(ENDFILE(g_CFILE)) DO + READLN line$ FROM g_CFILE + IF NOT(ENDFILE(g_CFILE)) THEN WRITELN line$ TO tmp_HFILE + WEND + CLOSE FILE g_CFILE + + WRITELN "__B2C__PROGRAM__EXIT: ;" TO tmp_HFILE + + ' Make sure the function always returns something + IF INSTR(g_FUNCTYPE$, "char*") THEN WRITELN "return (\"\");}" TO tmp_HFILE + ELSE WRITELN "return (0);}" TO tmp_HFILE + + CLOSE FILE tmp_HFILE + + ' Include header file + IF NOT(INSTR(g_INCLUDE_FILES$, CONCAT$(LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h"))) THEN + g_INCLUDE_FILES$ = CONCAT$(g_INCLUDE_FILES$, " ", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h") + END IF + + ' Add to total filelist + g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h") + + ' Delete temp funcfile + DELETE FILE g_CFILE$ + + ' Restore mainfile + g_CFILE$ = g_COPY_CFILE$ + OPEN g_CFILE$ FOR APPENDING AS g_CFILE + + ' Restore CATCH routine + g_CATCHGOTO$ = g_ORIGCATCHGOTO$ + + ' Clear function variables + g_ORIGFUNCNAME$ = "" + g_FUNCNAME$ = "" + g_FUNCTYPE$ = "" + g_LOCALSTRINGS$ = "" + g_STRINGARRAYS$ = "" + g_STRINGARGS$ = "" + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Return(STRING arg$) + + LOCAL type$, thearg$ + LOCAL dim, x + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty RETURN at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + type$ = Check_Type$(g_CFILE$, arg$, 0) + + ' Check type of var, func using string but returning a value? See also PRINT miniparser + IF REGEX(arg$, "^VAL *\\(|^INSTR *\\(|^LEN *\\(|^SEARCH *\\(|^ASC *\\(|^FILE *\\(|^REGEX *\\(|^INSTRREV *\\(") THEN + g_FUNCTYPE$ = "double " + thearg$ = arg$ + + ' Check type of var, string or normal string? + ELIF INSTR(arg$, g_STRINGSIGN$) OR INSTR(arg$, CHR$(34)) OR INSTR(g_FUNCNAME$, g_STRINGSIGN$) THEN + g_FUNCTYPE$ = "char* " + WRITELN "__b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= ", g_MAX_RBUFFERS, ") __b2c__rbuffer_ptr=0; if(", arg$, " != NULL)" TO g_CFILE + WRITELN " {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], ", arg$, ");}" TO g_CFILE + WRITELN "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], 2*sizeof(char));" TO g_CFILE + WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], \"\");}" TO g_CFILE + thearg$ = "__b2c__rbuffer[__b2c__rbuffer_ptr]" + + ' Check if float + ELIF INSTR(arg$, ".") THEN + g_FUNCTYPE$ = "double " + thearg$ = arg$ + + ' Check if no alpha chars (then integer value) + ELIF REGEX(arg$, "[0-9]") THEN + g_FUNCTYPE$ = "long " + thearg$ = arg$ + + ' Assume variable, check if declared before + ELIF ISTRUE(LEN(type$)) THEN + IF INSTR(type$, "DIR* ") THEN + g_FUNCTYPE$ = "DIR* " + ELIF INSTR(type$, "FILE ") THEN + g_FUNCTYPE$ = "FILE* " + ELIF INSTR(type$, "int* ") THEN + g_FUNCTYPE$ = "int* " + ELIF INSTR(type$, "float* ") THEN + g_FUNCTYPE$ = "float* " + ELIF INSTR(type$, "double* ") THEN + g_FUNCTYPE$ = "double* " + ELIF INSTR(type$, "char* ") OR INSTR(type$, "STRING ") THEN + g_FUNCTYPE$ = "char* " + ELIF INSTR(type$, "long* ") THEN + g_FUNCTYPE$ = "long* " + ELIF INSTR(type$, "void* ") THEN + g_FUNCTYPE$ = "void* " + ELIF INSTR(type$, "int ") THEN + g_FUNCTYPE$ = "int " + ELIF INSTR(type$, "float ") THEN + g_FUNCTYPE$ = "float " + ELIF INSTR(type$, "double ") OR INSTR(type$, "FLOATING ") THEN + g_FUNCTYPE$ = "double " + ELIF INSTR(type$, "char ") THEN + g_FUNCTYPE$ = "char " + ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN + g_FUNCTYPE$ = "long " + ELIF INSTR(type$, "void ") THEN + g_FUNCTYPE$ = "void " + END IF + thearg$ = arg$ + + ' Not declared, assume integer variable + ELSE + g_FUNCTYPE$ = "long " + thearg$ = arg$ + END IF + + ' Free strings variables if there are any + SPLIT g_LOCALSTRINGS$ BY " " TO element$ SIZE dim + FOR x = 1 TO dim + IF LEN(element$[x]) > 0 THEN WRITELN "if(", element$[x], " != NULL) free(", element$[x], ");" TO g_CFILE + NEXT + WRITELN g_STRINGARRAYS$ TO g_CFILE + + ' The actual return value + WRITELN "return (", thearg$, ");" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Deffn(STRING arg$) + + LOCAL sym$ + + ' Check if we have an argument at all + IF ISFALSE(LEN(arg$)) THEN + PRINT NL$, "ERROR: empty DEF FN at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Translate to C macro + sym$ = CHOP$(MID$(arg$, INSTR(arg$, " "))) + + WRITELN "#define ", LEFT$(sym$, INSTR(sym$, "=") -1), " (", MID$(sym$, INSTR(sym$, "=") + 1), ")" TO g_HFILE + + ' Make symbol known to parser + g_IMPORTED$ = CONCAT$(LEFT$(sym$, INSTR(sym$, "(") - 1), " ", g_IMPORTED$) + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Const(STRING arg$) + + ' Check if we have an argument at all + IF ISFALSE(LEN(arg$)) THEN + PRINT NL$, "ERROR: empty CONST at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + WRITELN "#define ", LEFT$(arg$, INSTR(arg$, "=") - 1), " (", MID$(arg$, INSTR(arg$, "=") + 1), ")" TO g_HFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Push(STRING arg$) + + LOCAL type$ + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty PUSH at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + IF NOT(INSTR(arg$, ".")) THEN + type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN + type$ = Check_Type$(g_CFILE$, arg$, 0) + END IF + END IF + + ' Allocate space for type + WRITELN "__b2c__typestack = (int*)realloc(__b2c__typestack, (__b2c__stackptr+1)*sizeof(int));" TO g_CFILE + + ' Check type of var, string? + IF INSTR(arg$, g_STRINGSIGN$) THEN + WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" TO g_CFILE + WRITELN "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(__b2c__stringstack[__b2c__stackptr], ", arg$, ");} else __b2c__stringstack[__b2c__stackptr] = strdup(", arg$, ");" TO g_CFILE + WRITELN "__b2c__typestack[__b2c__stackptr] = 1;" TO g_CFILE + ' Check if it is a normal string + ELIF INSTR(arg$, CHR$(34)) THEN + WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" TO g_CFILE + WRITELN "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(__b2c__stringstack[__b2c__stackptr], ", arg$, ");} else __b2c__stringstack[__b2c__stackptr] = strdup(", arg$, ");" TO g_CFILE + WRITELN "__b2c__typestack[__b2c__stackptr] = 1;" TO g_CFILE + ' Check if float + ELIF INSTR(arg$, ".") THEN + WRITELN "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" TO g_CFILE + WRITELN "__b2c__doublestack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE + WRITELN "__b2c__typestack[__b2c__stackptr] = 2;" TO g_CFILE + ' Check if no alpha chars (then integer value) + ELIF NOT(REGEX(arg$, "[a-zA-Z]")) THEN + WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE + WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE + WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE + ' Assume variable, check if declared before + ELIF ISTRUE(LEN(type$)) THEN + IF REGEX(type$, "double .*") THEN + WRITELN "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" TO g_CFILE + WRITELN "__b2c__doublestack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE + WRITELN "__b2c__typestack[__b2c__stackptr] = 2;" TO g_CFILE + ELSE + WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE + WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE + WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE + END IF + ' Not declared, assume integer variable + ELSE + WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE + WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE + WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE + END IF + + ' Increase stackpointer + WRITELN "__b2c__stackptr++;" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Pull(STRING arg$) + + LOCAL check + LOCAL type$ + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty PULL at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Argument must be a variable + IF NOT(REGEX(arg$, "[a-zA-Z]+.*")) THEN + PRINT NL$, "ERROR: argument in PULL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' is not a variable!" + END 1 + END IF + + ' Decrease stackpointer again + WRITELN "__b2c__stackptr--;" TO g_CFILE + WRITELN "if(__b2c__stackptr < 0) __b2c__stackptr=0;" TO g_CFILE + + ' Get the last value from stack + IF INSTR(arg$, g_STRINGSIGN$) THEN + check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0) + ENDIF + + IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE + + WRITELN "if(__b2c__typestack[__b2c__stackptr] == 1) {" TO g_CFILE + WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(", arg$, ", __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" TO g_CFILE + ELSE + ' Variable may not be array, these should be defined with DECLARE + IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN + ' Not declared? Assume long + check = Check_Declared(g_HFILE$, arg$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$, 0) + + IF ISFALSE(check) THEN WRITELN "long ", arg$, "; /* pull */" TO g_HFILE + END IF + + ' See how var was declared + type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN + type$ = Check_Type$(g_CFILE$, arg$, 0) + END IF + + ' Make sure internal var is copied to var of program + IF INSTR(type$, "double ") OR INSTR(type$, "float ") OR INSTR(type$, "FLOATING ") THEN + WRITELN "if(__b2c__typestack[__b2c__stackptr] == 2) ", arg$, "=__b2c__doublestack[__b2c__stackptr];" TO g_CFILE + ELIF INSTR(type$, "long ") OR INSTR(type$, "int ") OR INSTR(type$, "NUMBER ") THEN + WRITELN "if(__b2c__typestack[__b2c__stackptr] == 3) ", arg$, "=__b2c__longstack[__b2c__stackptr];" TO g_CFILE + ELSE + WRITELN "if(__b2c__typestack[__b2c__stackptr] == 1) {" TO g_CFILE + WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(", arg$, ", __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" TO g_CFILE + END IF + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Import(STRING arg$) + + LOCAL lib$, type$, sym$, tmp$, token$, alias$ + LOCAL check + + ' Check if FROM is available + IF NOT(INSTR(arg$, " FROM ")) THEN + PRINT NL$, "ERROR: missing FROM in IMPORT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the symbolname without surrounding spaces and doublequotes + IF INSTR(arg$, "(") THEN + sym$ = REPLACE$((CHOP$(LEFT$(arg$, INSTR(arg$, "(") - 1))), CHR$(34), "") + tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6)) + token$ = CHOP$(MID$(arg$, 1, INSTRREV(arg$, ")") - 1)) + ELSE + sym$ = REPLACE$((CHOP$(MID$(arg$, 1, INSTR(arg$, " FROM ") - 1))), CHR$(34), "") + tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6)) + token$ = "" + END IF + + ' Check if TYPE is available + IF NOT(INSTR(arg$, " TYPE ")) THEN + PRINT NL$, "ERROR: missing TYPE in IMPORT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get library and type + lib$ = CHOP$(MID$(tmp$, 1, INSTR(tmp$, " TYPE "))) + type$ = CHOP$(MID$(tmp$, INSTR(tmp$, " TYPE ") + 6)) + + ' Check if ALIAS is there + IF INSTR(type$, " ALIAS ") THEN + alias$ = REPLACE$(MID$(type$, INSTR(type$, " ALIAS ") + 7), CHR$(34), "") + WRITELN "#define ", alias$, " ", sym$ TO g_HFILE + g_IMPORTED$ = CONCAT$(alias$, " ", g_IMPORTED$) + type$ = LEFT$(type$, INSTR(type$, " ALIAS ") - 1) + ENDIF + + ptr$ = REPLACE$(REPLACE$(lib$, CHR$(34), ""), "-", "") + ptr$ = REPLACE$(REPLACE$(REPLACE$(ptr$, ".", ""), "/", ""), "_", "") + + ' If library is libm or libc, skip dlopen as we're linking with those anyway + IF NOT(INSTR(lib$, "libc.so") ) AND NOT(INSTR(lib$, "libm.so")) THEN + + ' Check if variable was declared + check = Search(g_CFILE$, CONCAT$("void* __b2c__dlopen__pointer_", ptr$, ";"), 0) + IF check < 0 THEN + WRITELN "void* __b2c__dlopen__pointer_", ptr$, ";" TO g_CFILE + WRITELN "__b2c__dlopen__pointer_", ptr$, " = dlopen(", lib$, ", RTLD_LAZY);" TO g_CFILE + END IF + WRITELN "if(__b2c__dlopen__pointer_", ptr$, " == NULL){if(!__b2c__trap){ERROR = 3;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + + ' Check if token was declared + check = Search(g_HFILE$, CONCAT$(type$, "(\\*", sym$, ")"), g_HEADER_SEARCHPOS) + IF check < 0 THEN + WRITELN type$, "(*", sym$, ")(", MID$(token$, INSTR(token$, "(") + 1), ");" TO g_HFILE + END IF + + ' Translate to C function + WRITELN "*(", type$, "**) (&", sym$, ") = dlsym(__b2c__dlopen__pointer_", ptr$, ", \"", sym$, "\");" TO g_CFILE + WRITELN "if(", sym$, " == NULL) {if(!__b2c__trap){ERROR = 4;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + END IF + + ' Make symbol known to parser + g_IMPORTED$ = CONCAT$(sym$, " ", g_IMPORTED$) + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Declare(STRING arg$) + + LOCAL var$, type$, new$, value$ + LOCAL i, dim, check, option + + ' Check on a GLOBAL RECORD + IF INSTR(arg$, "RECORD ") THEN + ' Translate to C typedef struct + g_RECORDNAME$ = CONCAT$("RECORD_", STR$(g_COUNTER)) + WRITELN "struct ", g_RECORDNAME$, "{" TO g_HFILE + g_RECORDVAR$ = MID$(CHOP$(arg$), INSTR(CHOP$(arg$), " ") + 1) + ' Store current function name + IF LEN(g_FUNCNAME$) > 0 THEN + g_RECORDCACHE$ = g_FUNCNAME$ + g_FUNCNAME$ = "" + END IF + ELSE + ' Get the variablename and type + IF INSTR(arg$, " TYPE ") THEN + var$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TYPE "))) + type$ = CHOP$(MID$(arg$, INSTR(arg$, " TYPE ") + 6)) + ELIF INSTR(arg$, " ASSOC ") THEN + var$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " ASSOC "))) + type$ = CHOP$(MID$(arg$, INSTR(arg$, " ASSOC ") + 7)) + ELSE + var$ = CHOP$(arg$) + type$ = "long" + END IF + + ' Check if variable was already declared + IF NOT(INSTR(var$, ".")) THEN check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS) + ELSE check = FALSE + + IF ISTRUE(check) THEN + PRINT NL$, "ERROR: variable in DECLARE or GLOBAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!" + END 1 + END IF + + ' If array, increase dimensions when OPTION BASE is set + IF REGEX(var$, "\\[.*\\]") AND NOT(INSTR(var$, "=")) THEN + new$ = "" + REPEAT + new$ = CONCAT$(new$, LEFT$(var$, INSTR(var$, "[") - 1), "[") + value$ = MID$(var$, INSTR(var$, "[") + 1) + new$ = CONCAT$(new$, MID$(value$, 1, INSTR(value$, "]") - 1), "+", STR$(g_OPTION_BASE), "]") + var$ = MID$(var$, INSTR(var$, "]") + 1) + UNTIL NOT(REGEX(var$, "\\[.*\\]")) + var$ = new$ + END IF + + ' Check for associative array + IF INSTR(arg$, " ASSOC ") THEN + SPLIT var$ BY "," TO str$ SIZE dim + FOR i = 1 TO dim + WRITELN "struct __b2c__", CHOP$(str$[i]), "_type {char *key; /* noparse */ ", type$, " value; /* noparse */ };" TO g_HFILE + WRITELN "struct __b2c__", CHOP$(str$[i]), "_type *__b2c__", CHOP$(str$[i]), " = { NULL }; long __b2c__", CHOP$(str$[i]), "_idx = 0;" TO g_HFILE + + WRITELN "static int __b2c__", CHOP$(str$[i]), "_comp(const void *__b2c__m1, const void *__b2c__m2){ " TO g_HFILE + WRITELN "struct __b2c__", CHOP$(str$[i]), "_type *__b2c__mi1 = (struct __b2c__", CHOP$(str$[i]), "_type *) __b2c__m1;" TO g_HFILE + WRITELN "struct __b2c__", CHOP$(str$[i]), "_type *__b2c__mi2 = (struct __b2c__", CHOP$(str$[i]), "_type *) __b2c__m2;" TO g_HFILE + WRITELN "if(__b2c__mi1->key == NULL && __b2c__mi2->key == NULL) return 0;" TO g_HFILE + WRITELN "if(__b2c__mi1->key == NULL && __b2c__mi2->key != NULL) return -1;" TO g_HFILE + WRITELN "if(__b2c__mi1->key != NULL && __b2c__mi2->key == NULL) return 1;" TO g_HFILE + WRITELN "return strcmp(__b2c__mi1->key, __b2c__mi2->key); }" TO g_HFILE + + WRITELN "struct __b2c__", CHOP$(str$[i]), "_type * __b2c__", CHOP$(str$[i]), "_exist (char *__b2c__index){struct __b2c__", CHOP$(str$[i]), "_type __b2c__", CHOP$(str$[i]), "_key, *__b2c__", CHOP$(str$[i]), "__result;" TO g_HFILE + WRITELN "qsort(__b2c__", CHOP$(str$[i]), ", __b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE + WRITELN "__b2c__", CHOP$(str$[i]), "_key.key = __b2c__index; __b2c__", CHOP$(str$[i]), "__result = bsearch(&__b2c__", CHOP$(str$[i]), "_key, __b2c__", CHOP$(str$[i]), "," TO g_HFILE + WRITELN "__b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE + WRITELN "return(__b2c__", CHOP$(str$[i]), "__result); }" TO g_HFILE + + WRITELN "void __b2c__", CHOP$(str$[i]), "__add(char *__b2c__index){__b2c__", CHOP$(str$[i]), "_idx++;" TO g_HFILE + WRITELN "__b2c__", CHOP$(str$[i]), " = (struct __b2c__", CHOP$(str$[i]), "_type *) realloc (__b2c__", CHOP$(str$[i]), ", __b2c__", CHOP$(str$[i]), "_idx * sizeof (struct __b2c__", CHOP$(str$[i]), "_type));" TO g_HFILE + WRITELN "__b2c__", CHOP$(str$[i]), "[__b2c__", CHOP$(str$[i]), "_idx - 1].key = strdup (__b2c__index); __b2c__", CHOP$(str$[i]), "[__b2c__", CHOP$(str$[i]), "_idx-1].value = 0;}" TO g_HFILE + + WRITELN "void __b2c__", CHOP$(str$[i]), "__del(char *__b2c__index){struct __b2c__", CHOP$(str$[i]), "_type *__b2c__", CHOP$(str$[i]), "__location = __b2c__", CHOP$(str$[i]), "_exist(__b2c__index);" TO g_HFILE + WRITELN "if(__b2c__", CHOP$(str$[i]), "__location != NULL) {free(__b2c__", CHOP$(str$[i]), "__location->key); __b2c__", CHOP$(str$[i]), "__location->key = NULL;} }" TO g_HFILE + + WRITELN type$, " ", CHOP$(str$[i]), "(char *__b2c__index){struct __b2c__", CHOP$(str$[i]), "_type __b2c__", CHOP$(str$[i]), "_key, *__b2c__", CHOP$(str$[i]), "__result;" TO g_HFILE + WRITELN "qsort(__b2c__", CHOP$(str$[i]), ", __b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE + WRITELN "__b2c__", CHOP$(str$[i]), "_key.key = __b2c__index; __b2c__", CHOP$(str$[i]), "__result = bsearch(&__b2c__", CHOP$(str$[i]), "_key, __b2c__", CHOP$(str$[i]), "," TO g_HFILE + WRITELN "__b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE + IF INSTR(str$[i], g_STRINGSIGN$) OR INSTR(type$, "STRING") OR INSTR(type$, "char*") THEN + WRITELN "if(__b2c__", CHOP$(str$[i]), "__result == NULL) return(\"\"); return __b2c__", CHOP$(str$[i]), "__result->value;}" TO g_HFILE + ELSE + WRITELN "if(__b2c__", CHOP$(str$[i]), "__result == NULL) return(0); return __b2c__", CHOP$(str$[i]), "__result->value;}" TO g_HFILE + END IF + NEXT + + ' Check if var is string var + ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND NOT(INSTR(var$, "=")) THEN + check = Search(g_HFILE$, CONCAT$("char *", var$, " = NULL;"), g_HEADER_SEARCHPOS) + IF check < 0 THEN + SPLIT CHOP$(var$) BY "," TO str$ SIZE dim + FOR i = 1 TO dim + IF INSTR(str$[i], "[") THEN + WRITELN "char *", CHOP$(str$[i]), " = { NULL };" TO g_HFILE + ELSE + WRITELN "char *", CHOP$(str$[i]), " = NULL; " TO g_HFILE + ' Pointer var should not be initialized + IF INSTR(var$, g_STRINGSIGN$) THEN WRITELN CHOP$(str$[i]), " = calloc(1, sizeof(char));" TO g_CFILE + END IF + NEXT + END IF + ' Var is string array assignment + ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND INSTR(var$, "=") THEN + WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE + option = g_OPTION_BASE + WHILE option > 0 + WRITELN " \"\", " TO g_HFILE + DECR option + WEND + WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE + + ' Assume char assignment or number + ELSE + IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN + SPLIT var$ BY "," TO str$ SIZE dim + FOR i = 1 TO dim + WRITELN type$, " ", str$[i], " = { 0 };" TO g_HFILE + NEXT + ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN + WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE + option = g_OPTION_BASE + WHILE option > 0 + WRITELN " 0, " TO g_HFILE + DECR option + WEND + WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE + ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN + WRITELN type$, " ", var$, ";" TO g_HFILE + WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE + ELSE + WRITELN type$, " ", var$, ";" TO g_HFILE + END IF + ENDIF + ENDIF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Local(STRING arg$) + + LOCAL var$, type$, new$, value$, dim$ + LOCAL check, i, dim, option + + ' Get the variablename and type + IF INSTR(arg$, " TYPE ") THEN + var$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TYPE "))) + type$ = CHOP$(MID$(arg$, INSTR(arg$, " TYPE ") + 6)) + ELSE + var$ = CHOP$(arg$) + IF INSTR(var$, g_STRINGSIGN$) THEN + type$ = "char*" + ELSE + type$ = "long" + END IF + END IF + + check = 0 + + ' Check if variable was already declared + IF NOT(INSTR(var$, ".")) THEN + IF LEN(g_FUNCNAME$) > 0 THEN check = Check_Declared(g_CFILE$, var$, 0) + ELSE check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS) + END IF + + IF ISTRUE(check) THEN + PRINT NL$, "ERROR: variable in LOCAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!" + END 1 + END IF + + ' If array, increase dimensions when OPTION BASE is set + IF REGEX(var$, "\\[.*\\]") AND NOT(INSTR(var$, "=")) THEN + new$ = "" + REPEAT + new$ = CONCAT$(new$, LEFT$(var$, INSTR(var$, "[") - 1), "[") + value$ = MID$(var$, INSTR(var$, "[") + 1) + new$ = CONCAT$(new$, MID$(value$, 1, INSTR(value$, "]") - 1), "+", STR$(g_OPTION_BASE), "]") + var$ = MID$(var$, INSTR(var$, "]") + 1) + UNTIL NOT(REGEX(var$, "\\[.*\\]")) + var$ = new$ + END IF + + ' Check if var is string var + IF ( REGEX(type$, "STRING|char\\*$") OR INSTR(var$, g_STRINGSIGN$) ) AND NOT(INSTR(var$, "=")) AND NOT(REGEX(type$, ".+\\[.+\\$\\]")) THEN + check = Search(g_HFILE$, CONCAT$("char *", var$, " = NULL;"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", var$, " = NULL;"), 0) + ENDIF + + IF check < 0 THEN + SPLIT var$ BY "," TO str$ SIZE dim + FOR i = 1 TO dim + ' Check on multidimensional stringarrays + IF REGEX(str$[i], "\\[.*\\]\\[") THEN + PRINT NL$, "ERROR: multidimensional stringarrays at line ", g_COUNTER, " in file '", g_CURFILE$, "' are not supported!" + END 1 + END IF + + ' Are we in a function? + IF ISTRUE(LEN(g_FUNCNAME$)) THEN + IF ISTRUE(LEN(g_RECORDNAME$)) THEN + IF REGEX(str$[i], "\\[.*\\]") THEN + WRITELN "char *", CHOP$(str$[i]), ";" TO g_CFILE + dim$ = MID$(str$[i], INSTR(str$[i], "[") + 1) + g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " for(__b2c__ctr=0; __b2c__ctr<", LEFT$(dim$, INSTR(dim$, "]") - 1), "; __b2c__ctr++)if(", g_RECORDVAR$, ".", LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]!=NULL){free(", g_RECORDVAR$, ".", LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]);}") + ELSE + WRITELN "char *", CHOP$(str$[i]), "; /* noparse */" TO g_CFILE + END IF + ELSE + IF REGEX(str$[i], "\\[.*\\]") THEN + WRITELN "char *", CHOP$(str$[i]), " = { NULL};" TO g_CFILE + dim$ = MID$(str$[i], INSTR(str$[i], "[") + 1) + g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " for(__b2c__ctr=0; __b2c__ctr<", LEFT$(dim$, INSTR(dim$, "]") - 1), "; __b2c__ctr++)if(", g_WITHVAR$, LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]!=NULL){free(", g_WITHVAR$, LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]);}") + ELSE + WRITELN "char *", CHOP$(str$[i]), " = NULL;" TO g_CFILE + ' Pointer var should not be initialized + IF INSTR(var$, g_STRINGSIGN$) THEN + WRITELN CHOP$(str$[i]), " = calloc(1, sizeof(char));" TO g_CFILE + g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", CHOP$(str$[i])) + END IF + END IF + END IF + ' We are in the mainprogram + ELSE + IF ISTRUE(LEN(g_RECORDNAME$)) THEN + WRITELN "char *", CHOP$(str$[i]), "; /* noparse */" TO g_HFILE + ELSE + IF REGEX(str$[i], "\\[.*\\]") THEN + WRITELN "char *", CHOP$(str$[i]), " = { NULL };" TO g_CFILE + ELSE + WRITELN "char *", CHOP$(str$[i]), " = NULL; " TO g_HFILE + ' Pointer var should not be initialized + IF INSTR(var$, g_STRINGSIGN$) THEN WRITELN CHOP$(str$[i]), " = calloc(1, sizeof(char));" TO g_CFILE + END IF + END IF + END IF + NEXT + END IF + ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND INSTR(var$, "=") THEN + IF ISTRUE(LEN(g_FUNCNAME$)) THEN + ' String array assignment + WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_CFILE + option = g_OPTION_BASE + WHILE option > 0 + WRITELN " \"\", " TO g_CFILE + DECR option + WEND + WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_CFILE + ELSE + ' String array assignment + WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE + option = g_OPTION_BASE + WHILE option > 0 + WRITELN " \"\", " TO g_HFILE + DECR option + WEND + WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE + END IF + ' Assume number + ELSE + IF ISTRUE(LEN(g_FUNCNAME$)) THEN + IF ISTRUE(LEN(g_RECORDNAME$)) THEN + WRITELN type$, " ", var$, "; /* noparse */" TO g_CFILE + ELSE + IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN + SPLIT var$ BY "," TO str$ SIZE dim + FOR i = 1 TO dim + WRITELN type$, " ", str$[i], " = { 0 };" TO g_CFILE + NEXT + ELIF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN + ' Numeric array assignment + WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_CFILE + option = g_OPTION_BASE + WHILE option > 0 + WRITELN " 0, " TO g_CFILE + DECR option + WEND + WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_CFILE + ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN + WRITELN type$, " ", var$, ";" TO g_CFILE + WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE + ELSE + WRITELN type$, " ", var$, ";" TO g_CFILE + END IF + END IF + ELSE + IF ISTRUE(LEN(g_RECORDNAME$)) THEN + WRITELN type$, " ", var$, "; /* noparse */" TO g_HFILE + ELSE + IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN + SPLIT var$ BY "," TO str$ SIZE dim + FOR i = 1 TO dim + WRITELN type$, " ", str$[i], " = { 0 };" TO g_HFILE + NEXT + ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN + ' Numeric array assignment + WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE + option = g_OPTION_BASE + WHILE option > 0 + WRITELN " 0, " TO g_HFILE + DECR option + WEND + WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE + ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN + WRITELN type$, " ", var$, ";" TO g_HFILE + WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE + ELSE + WRITELN type$, " ", var$, ";" TO g_HFILE + END IF + END IF + END IF + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Read(STRING arg$) + + LOCAL check + LOCAL type$ + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty READ at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check type of var, string? + IF EQUAL(RIGHT$(arg$, LEN(g_STRINGSIGN$)), g_STRINGSIGN$) THEN + check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0) + ENDIF + + IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE + + ' Convert to C + WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(", arg$, ", __b2c__stringarray[__b2c__stringarray_ptr]);" TO g_CFILE + WRITELN "__b2c__stringarray_ptr++;" TO g_CFILE + ELSE + ' Variable may not be array, these should be defined with DECLARE + IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN + ' Not declared? Assume long + check = Check_Declared(g_HFILE$, arg$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$, 0) + + IF ISFALSE(check) THEN WRITELN "long ", arg$, ";" TO g_HFILE + END IF + + ' See how var was declared + type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN + type$ = Check_Type$(g_CFILE$, arg$, 0) + END IF + + ' Convert to C + IF INSTR(type$, "double ") OR INSTR(type$, "FLOATING ") THEN + WRITELN arg$, " = __b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE + WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE + ELIF INSTR(type$, "float ") THEN + WRITELN arg$, " = (float)__b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE + WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE + ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN + WRITELN arg$, " = __b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE + WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE + ELIF INSTR(type$, "int ") THEN + WRITELN arg$, " = (int)__b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE + WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE + ELSE + WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(", arg$, ", __b2c__stringarray[__b2c__stringarray_ptr]);" TO g_CFILE + WRITELN "__b2c__stringarray_ptr++;" TO g_CFILE + END IF + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Color(STRING arg$) + + LOCAL dim + LOCAL BFG$, COL$ + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty COLOR at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + SPLIT arg$ BY " " TO element$ SIZE dim + + ' Check if we need to reset + IF EQUAL(element$[1], "RESET") THEN + WRITELN "fprintf(stdout,\"\\033[0m\");" TO g_CFILE + ELIF EQUAL(element$[1], "INTENSE") THEN + WRITELN "fprintf(stdout,\"\\033[1m\");" TO g_CFILE + ELIF EQUAL(element$[1], "INVERSE") THEN + WRITELN "fprintf(stdout,\"\\033[7m\");" TO g_CFILE + ELIF EQUAL(element$[1], "NORMAL") THEN + WRITELN "fprintf(stdout,\"\\033[22m\");" TO g_CFILE + ' Check if TO is available + ELIF NOT(INSTR(arg$, " TO ")) THEN + PRINT NL$, "ERROR: Missing TO in COLOR statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Get the target and colorname + SELECT element$[1] + CASE "FG" + BFG$ = "3" + CASE "BG" + BFG$ = "4" + DEFAULT + IF REGEX(element$[1], "0|1") THEN BFG$ = STR$(VAL(element$[1]) + 3) + ELSE BFG$ = element$[1] + END SELECT + + SELECT element$[3] + CASE "BLACK" + COL$ = "0" + CASE "RED" + COL$ = "1" + CASE "GREEN" + COL$ = "2" + CASE "YELLOW" + COL$ = "3" + CASE "BLUE" + COL$ = "4" + CASE "MAGENTA" + COL$ = "5" + CASE "CYAN" + COL$ = "6" + CASE "WHITE" + COL$ = "7" + DEFAULT + COL$ = element$[3] + END SELECT + + ' Now select color + WRITELN "fprintf(stdout,\"\\033[%ld%ldm\", (long)", BFG$, ", (long)", COL$, ");" TO g_CFILE + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Gotoxy(STRING arg$) + + LOCAL dim + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty GOTOXY at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the target and colorname + SPLIT arg$ BY "," TO element$ SIZE dim + + IF dim EQ 1 THEN + PRINT NL$, "ERROR: missing coordinate in GOTOXY at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Translate to C + WRITELN "fprintf(stdout, \"\\033[%ld;%ldH\",(long)(", CHOP$(element$[2]), "), (long)(", CHOP$(element$[1]), ")); fflush(stdout);" TO g_CFILE + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Split(STRING arg$) + + LOCAL source$, rest$, by$, to$, size$ + LOCAL check + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty SPLIT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if BY is available + IF NOT(INSTR(arg$, " BY ")) THEN + PRINT NL$, "ERROR: Missing BY in SPLIT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if TO is available + IF NOT(INSTR(arg$, " TO ")) THEN + PRINT NL$, "ERROR: Missing TO in SPLIT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if SIZE is available + IF NOT(INSTR(arg$, " SIZE ")) THEN + PRINT NL$, "ERROR: Missing SIZE in SPLIT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the source string + source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " BY ") - 1)) + rest$ = MID$(arg$, INSTR(arg$, " BY ") + 4) + + by$ = CHOP$(LEFT$(rest$, INSTR(rest$, " TO ") - 1)) + rest$ = MID$(rest$, INSTR(rest$, " TO ") + 4) + + to$ = CHOP$(LEFT$(rest$, INSTR(rest$, " SIZE ") - 1)) + size$ = CHOP$(MID$(rest$, INSTR(rest$, " SIZE ") + 6)) + + ' Variable may not be array, these should be defined with DECLARE + IF NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) THEN + check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$, 0) + + IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE + END IF + + ' Translate to C code + IF ISTRUE(LEN(g_FUNCNAME$)) THEN + IF NOT(INSTR(g_STRINGARGS$, CONCAT$("**", to$))) THEN + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char **", to$, " = NULL; int __b2c__split__", to$, " = ", STR$(g_OPTION_BASE), ";") + END IF + ELSE + check = Search(g_HFILE$, CONCAT$(to$, " = NULL;"), g_HEADER_SEARCHPOS) + IF check < 0 THEN + WRITELN "char **", to$, " = NULL; int __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_HFILE + END IF + END IF + + ' If the split array was used before in a loop, clear it + WRITELN "if(", to$, " != NULL) {for(__b2c__ctr=", g_OPTION_BASE, "; __b2c__ctr<=__b2c__split__", to$, "; __b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL)" TO g_CFILE + WRITELN "{free(", to$, "[__b2c__ctr]);} free(", to$, "); ", to$, " = NULL;} __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_CFILE + + ' Run the SPLIT code + WRITELN "if (", source$, " != NULL && strlen(", source$, ") > 0 && ", by$, " != NULL && strlen(", by$, ")>0){__b2c__split_tmp = strdup(", source$, "); __b2c__split_ptr = __b2c__split_tmp; while((__b2c__split = strstr(__b2c__split_tmp, ", by$, ")) != NULL)" TO g_CFILE + WRITELN "{if(__b2c__split-__b2c__split_tmp >= 0) {", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*)); if(__b2c__split-__b2c__split_tmp == 0) {", to$, "[__b2c__split__", to$, "] = calloc(1, sizeof(char)); if (__b2c__collapse == 0)" TO g_CFILE + WRITELN "__b2c__split__", to$, "++; else free(", to$, "[__b2c__split__", to$, "]);} else ", to$, "[__b2c__split__", to$, "++] = __b2c__strndup(__b2c__split_tmp, __b2c__split-__b2c__split_tmp);}" TO g_CFILE + WRITELN "__b2c__split_tmp = __b2c__split + strlen(", by$, ");} if(strlen(__b2c__split_tmp) >= 0) {", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*)); if(strlen(__b2c__split_tmp) == 0) {" TO g_CFILE + WRITELN to$, "[__b2c__split__", to$, "] = calloc(1, sizeof(char)); if (__b2c__collapse == 0) __b2c__split__", to$, "++; else free(", to$, "[__b2c__split__", to$, "]);}" TO g_CFILE + WRITELN "else ", to$, "[__b2c__split__", to$, "++] = strdup(__b2c__split_tmp);} free(__b2c__split_ptr);} ", size$, " = __b2c__split__", to$, " - ", g_OPTION_BASE, "; if(__b2c__split__", to$, " > 0) __b2c__split__", to$, "--;" TO g_CFILE + + ' Add declared array to array list if we are in a function + IF ISTRUE(LEN(g_FUNCNAME$)) AND NOT(INSTR(g_STRINGARRAYS$, CONCAT$(to$, "["))) THEN + g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " if(", to$, "!= NULL){for(__b2c__ctr=", STR$(g_OPTION_BASE), ";__b2c__ctr<=__b2c__split__", to$, ";__b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL){free(", to$, "[__b2c__ctr]);}free(", to$, ");}") + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Sort(STRING arg$) + + LOCAL dim$, type$, var$, down$ + LOCAL check + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty SORT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check on SIZE argument + IF INSTR(arg$, "SIZE") THEN + dim$ = CHOP$(MID$(arg$, INSTR(arg$, "SIZE") + 5)) + var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "SIZE") - 1)) + ELSE + var$ = arg$ + END IF + + ' Check on DOWN argument + IF INSTR(arg$, "DOWN") THEN + IF LEN(dim$) > 0 THEN dim$ = CHOP$(LEFT$(dim$, INSTR(dim$, "DOWN") - 1)) + var$ = CHOP$(LEFT$(var$, INSTR(var$, "DOWN") - 1)) + down$ = "_down" + ELSE + down$ = "" + END IF + + ' Declared before? + IF INSTR(var$, g_STRINGSIGN$) THEN + check = Search(g_HFILE$, CONCAT$("char *", var$, "["), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("char *", var$, "["), 0) + ENDIF + ELSE + check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0) + END IF + + ' Verify if the array was declared at SPLIT + IF check < 0 THEN + check = Search(g_HFILE$, CONCAT$("__b2c__split__", var$), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN + check = Search(g_CFILE$, CONCAT$("__b2c__split__", var$), 0) + ENDIF + IF ISFALSE(check) THEN + PRINT NL$, "ERROR: argument to SORT not an array at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELIF LEN(dim$) IS 0 THEN + dim$ = CONCAT$("__b2c__split__", var$, "+1") + END IF + ELIF LEN(dim$) IS 0 THEN + ' See how var was declared + type$ = Check_Type$(g_HFILE$, CONCAT$(var$, "["), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN + type$ = Check_Type$(g_CFILE$, CONCAT$(var$, "["), 0) + ENDIF + dim$ = MID$(type$, INSTR(type$, "[") + 1, INSTR(type$, "]") - INSTR(type$, "[") - 1) + END IF + + ' Check if we have a string + IF INSTR(var$, g_STRINGSIGN$) THEN + WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(char*), __b2c__sortstr", down$, ");" TO g_CFILE + ' It is a value + ELSE + ' See how var was declared + type$ = Check_Type$(g_HFILE$, CONCAT$(var$, "["), g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, CONCAT$(var$, "["), 0) + + IF INSTR(type$, "double ") OR INSTR(type$, "FLOATING ") THEN + WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(double), __b2c__sortnrd", down$, ");" TO g_CFILE + ELIF INSTR(type$, "float ") THEN + WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(float), __b2c__sortnrf", down$, ");" TO g_CFILE + ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN + WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(long), __b2c__sortnrl", down$, ");" TO g_CFILE + ELSE + WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(int), __b2c__sortnri", down$, ");" TO g_CFILE + END IF + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Alias(STRING arg$) + + LOCAL dim + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty ALIAS at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the target and colorname + SPLIT REPLACE$(arg$, CHR$(34), "") BY "TO" TO element$ SIZE dim + + IF dim EQ 1 THEN + PRINT NL$, "ERROR: missing TO in ALIAS statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Translate to C + WRITELN "#define ", element$[2], " ", element$[1] TO g_HFILE + g_IMPORTED$ = CONCAT$(element$[2], " ", g_IMPORTED$) + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Lookup(STRING arg$) + + LOCAL source$, rest$, to$, size$ + LOCAL check + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty LOOKUP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if TO is available + IF NOT(INSTR(arg$, " TO ")) THEN + PRINT NL$, "ERROR: Missing TO in LOOKUP statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if SIZE is available + IF NOT(INSTR(arg$, " SIZE ")) THEN + PRINT NL$, "ERROR: Missing SIZE in LOOKUP statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the source string + source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ") - 1)) + rest$ = MID$(arg$, INSTR(arg$, " TO ") + 4) + + to$ = CHOP$(LEFT$(rest$, INSTR(rest$, " SIZE ") - 1)) + size$ = CHOP$(MID$(rest$, INSTR(rest$, " SIZE ") + 6)) + + ' Variable may not be array, these should be defined with DECLARE + IF NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) THEN + check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS) + IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$, 0) + + IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE + END IF + + ' Translate to C code + IF ISTRUE(LEN(g_FUNCNAME$)) THEN + IF NOT(INSTR(g_STRINGARGS$, CONCAT$("**", to$))) THEN + g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char **", to$, " = NULL; int __b2c__split__", to$, " = ", STR$(g_OPTION_BASE), ";") + END IF + ELSE + check = Search(g_HFILE$, CONCAT$(to$, " = NULL;"), g_HEADER_SEARCHPOS) + IF check < 0 THEN + WRITELN "char **", to$, " = NULL; int __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_HFILE + END IF + END IF + + ' If the split array was used before in a loop, clear it + WRITELN "if(", to$, " != NULL) {for(__b2c__ctr=", g_OPTION_BASE, "; __b2c__ctr <= __b2c__split__", to$, "; __b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL)" TO g_CFILE + WRITELN "{free(", to$, "[__b2c__ctr]);} free(", to$, "); ", to$, " = NULL;} __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_CFILE + + ' Run the LOOKUP code + WRITELN "for(__b2c__ctr = ", g_OPTION_BASE, "; __b2c__ctr < __b2c__", source$, "_idx + ", g_OPTION_BASE, "; __b2c__ctr++)" TO g_CFILE + WRITELN "{", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*));" TO g_CFILE + WRITELN to$, "[__b2c__split__", to$, "++] = strdup(__b2c__", source$, "[__b2c__ctr-", g_OPTION_BASE, "].key);} ", size$, " = __b2c__split__", to$, " - ", g_OPTION_BASE, ";if(__b2c__split__", to$, " > 0) __b2c__split__", to$, "--;" TO g_CFILE + + ' Add declared array to array list if we are in a function + IF ISTRUE(LEN(g_FUNCNAME$)) AND NOT(INSTR(g_STRINGARRAYS$, CONCAT$(to$, "["))) THEN + g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " if(", to$, "!= NULL){for(__b2c__ctr=", STR$(g_OPTION_BASE), ";__b2c__ctr<=__b2c__split__", to$, ";__b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL){free(", to$, "[__b2c__ctr]);}free(", to$, ");}") + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Relate(STRING arg$) + + LOCAL source$, to$, txt$ + LOCAL declared, dim, i + LOCAL thefile TYPE FILE* + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty RELATE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Check if TO is available + IF NOT(INSTR(arg$, " TO ")) THEN + PRINT NL$, "ERROR: Missing TO in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Get the source string + source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ") - 1)) + to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4)) + + ' CHeck if declared as ASSOC + OPEN g_HFILE$ FOR READING AS thefile + SEEK thefile OFFSET g_HEADER_SEARCHPOS + + WHILE NOT(ENDFILE(thefile)) DO + READLN txt$ FROM thefile + IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN + declared = REGEX(txt$, CONCAT$("__b2c__", source$, "_type")) + IF ISTRUE(declared) THEN BREAK + END IF + WEND + IF NOT(declared) THEN + PRINT NL$, "ERROR: Variable ", source$, " not declared in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Assign relations + SPLIT to$ BY "," TO str$ SIZE dim + + FOR i = 1 TO dim + + SEEK thefile OFFSET g_HEADER_SEARCHPOS + WHILE NOT(ENDFILE(thefile)) DO + READLN txt$ FROM thefile + IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN + declared = REGEX(txt$, CONCAT$("__b2c__", CHOP$(str$[i]), "_type")) + IF ISTRUE(declared) THEN BREAK + END IF + WEND + IF NOT(declared) THEN + PRINT NL$, "ERROR: Variable ", CHOP$(str$[i]), " not declared in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + g_RELATE$[g_RELATE_CTR] = CONCAT$(source$, " ", CHOP$(str$[i])) + INCR g_RELATE_CTR + + NEXT + + CLOSE FILE thefile + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Handle_Data(STRING arg$) + + LOCAL in_string, pos, escaped, x + + ' Check if we have an argument at all + IF ISFALSE(LEN(CHOP$(arg$))) THEN + PRINT NL$, "ERROR: empty DATA at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + ' Start miniparser + in_string = FALSE + pos = 1 + escaped = 0 + + FOR x = 1 TO LEN(arg$) + IF ISTRUE(EQUAL(MID$(arg$, x, 1), ",")) THEN + IF ISFALSE(in_string) THEN + IF INSTR(MID$(arg$, pos, x-pos), CHR$(34)) THEN + WRITELN MID$(arg$, pos, x-pos), ", " TO STRINGARRAYFILE + ELSE + WRITELN MID$(arg$, pos, x-pos), ", " TO FLOATARRAYFILE + END IF + pos = x+1 + escaped = FALSE + END IF + ELIF EQUAL(MID$(arg$, x, 1), "\\") THEN + escaped = TRUE + ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), CHR$(34))) THEN + IF ISFALSE(escaped) THEN + in_string = NOT(in_string) + END IF + escaped = FALSE + ELSE + escaped = FALSE + ENDIF + NEXT + arg$ = MID$(arg$, pos) + + ' Write last element to file + IF INSTR(arg$, CHR$(34)) THEN + WRITELN arg$, ", " TO STRINGARRAYFILE + ELSE + WRITELN arg$, ", " TO FLOATARRAYFILE + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- +' +' 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. +' +'---------------------------------------------------------------------------------------------- + +SUB Parse_Line(STRING statement$) + + LOCAL inc$, copy_curfile$, total$, txt$, exp$ + LOCAL dim, i, found, copy_counter, to_parse, size + LOCAL newfile TYPE FILE* + + SPLIT statement$ BY " " TO element$ SIZE dim + + IF dim > 0 THEN + + ' Check if enclosed IF/ELIF/ELSE needs to be closed + IF g_IF_PARSE IS 1 THEN + IF NOT(EQUAL(element$[1], "ELIF")) AND NOT(EQUAL(element$[1], "ELSE")) THEN + WRITELN "}" TO g_CFILE + g_IF_PARSE = 0 + END IF + END IF + + ' In TRACE MODE show linenr and code + IF g_TRACE IS 1 AND NOT(INSTR(statement$, "FUNCTION ")) AND NOT(INSTR(statement$, "SUB ")) THEN + WRITELN "if(__b2c__getch() == 27) exit(EXIT_SUCCESS); /* noparse */" TO g_CFILE + txt$ = REPLACE$(statement$, CHR$(34), "'") + WRITELN "fprintf(stderr, \"", g_CURFILE$, " %d: ", txt$, "\\n\", ", g_COUNTER, "); /* noparse */" TO g_CFILE + END IF + + ' See if we need to pass C code + IF ISTRUE(g_USE_C) THEN + IF EQUAL(LEFT$(statement$, 8), "END USEC") OR EQUAL(element$[1], "ENDUSEC") THEN + g_USE_C = 0 + ELSE + WRITELN statement$ TO g_CFILE + END IF + + ELIF EQUAL(LEFT$(element$[1], 2), "#!") THEN + 'Do nothing + + ELIF EQUAL(LEFT$(element$[1], 1), "'") THEN + 'Do nothing + + ELIF EQUAL(LEFT$(element$[1], 3), "REM") THEN + 'Do nothing + + ELSE + SELECT element$[1] + CASE "USEC" + g_USE_C = 1 + + CASE "PRINT" + Handle_Print(MID$(statement$, INSTR(statement$, "PRINT") + 5)) + + CASE "INPUT" + Handle_Input(MID$(statement$, INSTR(statement$, "INPUT") + 5)) + + CASE "FOR" + INCR g_LOOPCTR + Handle_For(MID$(statement$, INSTR(statement$, "FOR") + 3)) + + CASE "NEXT" + WRITELN "}" TO g_CFILE + IF g_LOOPCTR > 0 THEN + DECR g_LOOPCTR + IF g_LOOPCTR > 0 THEN + WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE + END IF + END IF + + CASE "IF" + ' Check if THEN is available + g_IF_PARSE = 0 + IF ISFALSE(INSTRREV(statement$, " THEN")) THEN + PRINT NL$, "ERROR: missing THEN in IF statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Translate function to C function + exp$ = Parse_Equation$(MID$(statement$, INSTR(statement$, "IF") + 2, INSTRREV(statement$, " THEN") - (INSTR(statement$, "IF") + 2))) + WRITELN "if(", exp$, "){" TO g_CFILE + IF LEN(CHOP$(MID$(statement$, INSTRREV(statement$, " THEN") + 5))) > 0 THEN + CALL Tokenize(MID$(statement$, INSTRREV(statement$, " THEN") + 5)) + g_IF_PARSE = 1 + END IF + ENDIF + + CASE "ELIF" + ' Check if THEN is available + g_IF_PARSE = 0 + IF ISFALSE(INSTRREV(statement$, " THEN")) THEN + PRINT NL$, "ERROR: missing THEN in ELIF statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Translate function to C function + exp$ = Parse_Equation$(MID$(statement$, INSTR(statement$, "ELIF") + 4, INSTRREV(statement$, " THEN") - (INSTR(statement$, "ELIF") + 4))) + WRITELN "} else if(", exp$, "){" TO g_CFILE + IF LEN(CHOP$(MID$(statement$, INSTRREV(statement$, " THEN") + 5))) > 0 THEN + CALL Tokenize(MID$(statement$, INSTRREV(statement$, " THEN") + 5)) + g_IF_PARSE = 1 + END IF + END IF + + CASE "ELSE" + ' Translate function to C function + g_IF_PARSE = 0 + WRITELN "} else {" TO g_CFILE + IF LEN(CHOP$(MID$(statement$, INSTR(statement$, " ELSE") + 5))) > 0 THEN + CALL Tokenize(MID$(statement$, INSTR(statement$, " ELSE") + 5)) + g_IF_PARSE = 1 + END IF + + CASE "ENDIF" + WRITELN "}" TO g_CFILE + + CASE "WHILE" + INCR g_LOOPCTR + Handle_While(MID$(statement$, INSTR(statement$, "WHILE") + 5)) + + CASE "WEND" + WRITELN "}" TO g_CFILE + IF g_LOOPCTR > 0 THEN + DECR g_LOOPCTR + IF g_LOOPCTR > 0 THEN + WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE + END IF + END IF + + CASE "BREAK" + ' Check argument + IF dim > 1 AND VAL(MID$(statement$, INSTR(statement$, "BREAK") + 5)) NE 0 THEN + WRITELN "__b2c__break_ctr = ", MID$(statement$, INSTR(statement$, "BREAK") + 5), "-1; __b2c__break_flag = 1;" TO g_CFILE + END IF + + WRITELN "break;" TO g_CFILE + + CASE "CONTINUE" + ' Check argument + IF dim > 1 AND VAL(MID$(statement$, INSTR(statement$, "CONTINUE") + 8)) NE 0 THEN + WRITELN "__b2c__break_ctr = ", MID$(statement$, INSTR(statement$, "CONTINUE") + 8), "-1; __b2c__break_flag = 2;" TO g_CFILE + END IF + IF VAL(MID$(statement$, INSTR(statement$, "CONTINUE") + 8)) > 1 THEN + WRITELN "break;" TO g_CFILE + ELSE + WRITELN "continue;" TO g_CFILE + END IF + + CASE "REPEAT" + INCR g_LOOPCTR + WRITELN "do{" TO g_CFILE + + CASE "UNTIL" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty UNTIL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Convert to legal C code + exp$ = Parse_Equation$(MID$(statement$, INSTR(statement$, "UNTIL") + 5) ) + WRITELN "} while(!(", exp$, "));" TO g_CFILE + IF g_LOOPCTR > 0 THEN + DECR g_LOOPCTR + IF g_LOOPCTR > 0 THEN + WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE + END IF + END IF + END IF + + CASE "LET" + Handle_Let(MID$(statement$, INSTR(statement$, "LET") + 3)) + + CASE "SYSTEM" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty SYSTEM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + WRITELN "SYSTEM (", MID$(statement$, INSTR(statement$, "SYSTEM") + 6), ");" TO g_CFILE + END IF + + CASE "SLEEP" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty SLEEP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + WRITELN "usleep(", MID$(statement$, INSTR(statement$, "SLEEP") + 5), "*1000);" TO g_CFILE + END IF + + CASE "OPEN" + Handle_Open(MID$(statement$, INSTR(statement$, "OPEN") + 4)) + + CASE "CLOSE" + ' Check argument + IF dim NE 3 THEN + PRINT NL$, "ERROR: erroneous CLOSE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + SELECT element$[2] + CASE "FILE" + WRITELN "fclose(", element$[3], ");" TO g_CFILE + CASE "DIRECTORY" + WRITELN "closedir(", element$[3], ");" TO g_CFILE + CASE "MEMORY" + WRITELN element$[3], " = NULL;" TO g_CFILE + CASE "NETWORK"; + CASE "SERVER" + WRITELN "close(", element$[3], ");" TO g_CFILE + END SELECT + END IF + + CASE "REWIND" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty REWIND at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + WRITELN "rewind(", element$[2], ");" TO g_CFILE + END IF + + CASE "MEMREWIND" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty MEMREWIND at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + WRITELN element$[2], " = (char*)__b2c_mem_", element$[2], ";" TO g_CFILE + END IF + + CASE "SEEK" + Handle_Seek(CHOP$(MID$(statement$, INSTR(statement$, "SEEK") + 4))) + + CASE "READLN" + Handle_Readln(CHOP$(MID$(statement$, INSTR(statement$, "READLN") + 6))) + + CASE "WRITELN" + Handle_Writeln(MID$(statement$, INSTR(statement$, "WRITELN") + 7)) + + CASE "GETBYTE" + Handle_Getbyte(CHOP$(MID$(statement$, INSTR(statement$, "GETBYTE") + 7))) + + CASE "PUTBYTE" + Handle_Putbyte(CHOP$(MID$(statement$, INSTR(statement$, "PUTBYTE") + 7))) + + CASE "GETFILE" + Handle_Getfile(CHOP$(MID$(statement$, INSTR(statement$, "GETFILE") + 7))) + + CASE "GETLINE" + Handle_Getline(CHOP$(MID$(statement$, INSTR(statement$, "GETLINE") + 7))) + + CASE "PUTLINE" + Handle_Putline(MID$(statement$, INSTR(statement$, "PUTLINE") + 7)) + + CASE "END" + IF dim > 1 THEN + SELECT element$[2] + CASE "IF" + WRITELN "}" TO g_CFILE + CASE "RECORD" + IF LEN(g_FUNCNAME$) > 0 THEN + WRITELN "};" TO g_CFILE + WRITELN "struct ", g_RECORDNAME$, " ", g_RECORDVAR$, " = { } ;" TO g_CFILE + ELSE + WRITELN "};" TO g_HFILE + WRITELN "struct ", g_RECORDNAME$, " ", g_RECORDVAR$, " = { } ;" TO g_HFILE + END IF + g_RECORDNAME$ = "" + g_RECORDVAR$ = "" + ' Restore function name if GLOBAL was used + IF LEN(g_RECORDCACHE$) > 0 THEN + g_FUNCNAME$ = g_RECORDCACHE$ + g_RECORDCACHE$ = "" + ENDIF + CASE "FUNCTION" + Handle_Endfunction + CASE "SUB" + Handle_Endsub + CASE "WITH" + g_WITHVAR$ = "" + CASE "SELECT" + IF g_SELECTVAR_CTR IS 0 THEN + PRINT NL$, "ERROR: invalid END SELECT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + WRITELN "}" TO g_CFILE + g_SELECTVAR$[g_SELECTVAR_CTR] = "" + g_IN_CASE[g_SELECTVAR_CTR] = 0 + g_CASE_FALL$ = "" + DECR g_SELECTVAR_CTR + END IF + DEFAULT + WRITELN "exit(", element$[2], ");" TO g_CFILE + END SELECT + ELSE + WRITELN "exit(EXIT_SUCCESS);" TO g_CFILE + END IF + + CASE "SUB" + Handle_SubFunc(MID$(statement$, INSTR(statement$, "SUB") + 3)) + + CASE "ENDSUB" + Handle_Endsub + + CASE "ENDWITH" + g_WITHVAR$ = "" + + CASE "ENDSELECT" + IF g_SELECTVAR_CTR IS 0 THEN + PRINT NL$, "ERROR: invalid END SELECT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + WRITELN "}" TO g_CFILE + g_SELECTVAR$[g_SELECTVAR_CTR] = "" + g_IN_CASE[g_SELECTVAR_CTR] = 0 + g_CASE_FALL$ = "" + DECR g_SELECTVAR_CTR + END IF + + CASE "CALL" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty CALL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + exp$ = MID$(statement$, INSTR(statement$, "CALL ") + 5) + IF INSTR(statement$, " TO ") THEN + IF INSTR(MID$(exp$, INSTR(exp$, " TO ") + 4), g_STRINGSIGN$) THEN + WRITELN MID$(exp$, INSTR(exp$, " TO ") + 4), " = realloc(", MID$(exp$, INSTR(exp$, " TO ") + 4), ", (strlen(", MID$(exp$, 1, INSTR(exp$, " TO ") - 1), ")+1)*sizeof(char));" TO g_CFILE + WRITELN "strcpy(", MID$(exp$, INSTR(exp$, " TO ") + 4), "," TO g_CFILE + ELSE + WRITELN MID$(exp$, INSTR(exp$, " TO") + 3), "=" TO g_CFILE + END IF + IF INSTR(exp$, "(") THEN + WRITELN MID$(exp$, 1, INSTR(exp$, " TO ") - 1) TO g_CFILE + ELSE + WRITELN MID$(exp$, 1, INSTR(exp$, " TO ") - 1), "()" TO g_CFILE + END IF + IF INSTR(MID$(exp$, INSTR(exp$, " TO ") + 4), g_STRINGSIGN$) THEN + WRITELN ");" TO g_CFILE + ELSE + WRITELN ";" TO g_CFILE + END IF + ELSE + IF INSTR(exp$, "(") THEN + WRITELN exp$, ";" TO g_CFILE + ELSE + WRITELN exp$, "();" TO g_CFILE + END IF + END IF + END IF + + CASE "FUNCTION" + Handle_SubFunc(MID$(statement$, INSTR(statement$, "FUNCTION") + 8)) + + CASE "ENDFUNCTION" + Handle_Endfunction + + CASE "RETURN" + Handle_Return(MID$(statement$, INSTR(statement$, "RETURN") + 6)) + + CASE "IMPORT" + Handle_Import(MID$(statement$, INSTR(statement$, "IMPORT") + 6)) + + CASE "DECLARE" + Handle_Declare(MID$(statement$, INSTR(statement$, "DECLARE") + 7)) + + CASE "GLOBAL" + Handle_Declare(MID$(statement$, INSTR(statement$, "GLOBAL") + 6)) + + CASE "LOCAL" + Handle_Local(MID$(statement$, INSTR(statement$, "LOCAL") + 5)) + + CASE "DATA" + Handle_Data(MID$(statement$, INSTR(statement$, "DATA") + 4)) + + CASE "RESTORE" + WRITELN "if(__b2c__floatarray_ptr > 0) __b2c__floatarray_ptr = 0;" TO g_CFILE + WRITELN "if(__b2c__stringarray_ptr > 0) __b2c__stringarray_ptr = 0;" TO g_CFILE + + CASE "READ" + Handle_Read(CHOP$(MID$(statement$, INSTR(statement$, "READ") + 4))) + + CASE "PUSH" + Handle_Push(CHOP$(MID$(statement$, INSTR(statement$, "PUSH") + 4))) + + CASE "PULL" + Handle_Pull(CHOP$(MID$(statement$, INSTR(statement$, "PULL") + 4))) + + CASE "SEED" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty DATA at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + WRITELN "srandom((unsigned int)", element$[2], ");" TO g_CFILE + END IF + + CASE "DEF" + Handle_Deffn(CHOP$(MID$(statement$, INSTR(statement$, "DEF") + 3))) + + CASE "CONST" + Handle_Const(CHOP$(MID$(statement$, INSTR(statement$, "CONST") + 5))) + + CASE "INCLUDE" + ' Get rid of doublequotes if they are there + inc$ = REPLACE$((CHOP$(MID$(statement$, INSTR(statement$, " ") + 1))), CHR$(34), "") + ' See if there are arguments + IF INSTR(inc$, ",") THEN + SPLIT MID$(inc$, INSTR(inc$, ",")+1) BY "," TO element$ SIZE size + FOR i = 1 TO size + element$[i] = REPLACE$(element$[i], g_STRINGSIGN$, "") + NEXT + inc$ = MID$(inc$, 1, INSTR(inc$, ",")-1) + ELSE + to_parse = 2 + END IF + + ' Check argument + IF NOT(FILEEXISTS(inc$)) OR dim EQ 1 OR FILETYPE(inc$) != 1 THEN + PRINT NL$, "ERROR: missing file '", inc$, "' for INCLUDE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Start walking through program + copy_counter = g_COUNTER + g_COUNTER = 1 + ' Assign new file + copy_curfile$ = g_CURFILE$ + ' Get rid of absolute path + g_CURFILE$ = MID$(inc$, INSTRREV(inc$, "/") + 1) + OPEN inc$ FOR READING AS newfile + + WHILE NOT(ENDFILE(newfile)) DO + PRINT "\rStarting conversion... ", g_COUNTER, " "; + READLN txt$ FROM newfile + ' See if we need to enable flag + IF size > 0 THEN + FOR i = 1 TO size + IF ( to_parse = 0 AND REGEX(CHOP$(MID$(txt$, INSTR(txt$, " "))), CONCAT$("^", CHOP$(element$[i]))) AND REGEX(txt$, "SUB|FUNCTION") ) OR REGEX(txt$, "INCLUDE$") THEN + to_parse = 1 + BREAK + END IF + NEXT + END IF + ' Line is not empty? + IF NOT(ENDFILE(newfile)) AND LEN(txt$) > 0 AND to_parse > 0 THEN + IF EQUAL(RIGHT$(txt$, 2), CONCAT$(" ", CHR$(92))) AND NOT(EQUAL(LEFT$(txt$, 3), "REM")) AND NOT(EQUAL(LEFT$(txt$, 1), CHR$(39))) THEN + total$ = CONCAT$(total$, LEFT$(txt$, LEN(txt$)-2)) + ELSE + WRITELN "/* noparse ", inc$, " BACON LINE ", g_COUNTER, " */" TO g_HFILE + WRITELN "/* noparse ", inc$, " BACON LINE ", g_COUNTER, " */" TO g_CFILE + total$ = CHOP$(CONCAT$(total$, txt$)) + IF NOT(EQUAL(LEFT$(total$, 3), "REM")) AND NOT(EQUAL( LEFT$(total$, 1), CHR$(39) )) THEN + CALL Tokenize(total$) + END IF + LET total$ = "" + END IF + ENDIF + ' See if we need to stop parsing + IF to_parse = 1 AND INSTR(txt$, "END") AND REGEX(txt$, "SUB|FUNCTION") THEN to_parse = 0 + ' Increase line number + INCR g_COUNTER + WEND + CLOSE FILE newfile + + ' Restore original counter + g_COUNTER = copy_counter + ' Restore original file + g_CURFILE$ = copy_curfile$ + END IF + + CASE "POKE" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty POKE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + exp$ = MID$(statement$, INSTR(statement$, "POKE") + 4) + WRITELN "if (!__b2c__trap){__b2c__memory__check((char*)", MID$(exp$, 1, INSTR(exp$, ",")-1), "); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} }" TO g_CFILE + WRITELN "*(", g_OPTION_MEMTYPE$, "*)(", MID$(exp$, 1, INSTR(exp$, ",")-1), ") = ( ", g_OPTION_MEMTYPE$, ")", MID$(exp$, INSTR(exp$, ",")+1), ";" TO g_CFILE + END IF + + CASE "RESIZE" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty RESIZE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Resolve this with C macro because of casting to (char) + exp$ = MID$(statement$, INSTR(statement$, "RESIZE") + 6) + WRITELN MID$(exp$, 1, INSTR(exp$, ",") - 1), " = (long)RESIZE(", exp$, ");" TO g_CFILE + END IF + + CASE "COPY" + Handle_Copy(MID$(statement$, INSTR(statement$, "COPY") + 4)) + + CASE "DELETE" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty DELETE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Translate to C function + IF EQUAL(element$[2], "FILE") THEN + WRITELN "if (unlink(", MID$(statement$, INSTR(statement$, " FILE ") + 6), ")==-1){if(!__b2c__trap){ERROR = 7;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELIF EQUAL(element$[2], "DIRECTORY") THEN + WRITELN "if (rmdir(", MID$(statement$, INSTR(statement$, " DIRECTORY ") + 11), ") == -1){if(!__b2c__trap){ERROR = 20;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELSE + PRINT NL$, "ERROR: erronuous argument for DELETE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + END IF + + CASE "RENAME" + Handle_Rename(MID$(statement$, INSTR(statement$, "RENAME") + 6)) + + CASE "MAKEDIR" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty MAKEDIR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Translate to C function + WRITELN "if(__b2c__makedir(", MID$(statement$, INSTR(statement$, "MAKEDIR") + 7), ") != 0){if(!__b2c__trap){ERROR = 21;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + END IF + + CASE "CHANGEDIR" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty CHANGEDIR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Translate to C function + WRITELN "if(chdir(", MID$(statement$, INSTR(statement$, "CHANGEDIR") + 9), ") == -1){if(!__b2c__trap) {ERROR = 22;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + END IF + + CASE "FREE" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty FREE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Translate to C function + IF REGEX(element$[2], "\\(.*\\)") THEN + exp$ = MID$(element$[2], INSTR(element$[2], " ")+1) + IF INSTR(exp$, g_STRINGSIGN$) THEN + WRITELN "if(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1)," != NULL) {free(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1), "->value);" TO g_CFILE + WRITELN " __b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1), "->value = NULL; __b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__del(", MID$(element$[2], INSTR(element$[2], "(")+1), "; }" TO g_CFILE + ELSE + WRITELN "if(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1)," != NULL) {__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1), "->value = 0;" TO g_CFILE + WRITELN "__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__del(", MID$(element$[2], INSTR(element$[2], "(")+1), ";}" TO g_CFILE + ENDIF + ELSE + WRITELN "if(!__b2c__trap){__b2c__memory__check((char *)", element$[2], ");" TO g_CFILE + WRITELN "if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} } free((void*)", element$[2], ");" TO g_CFILE + END IF + END IF + + CASE "GOTO" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty GOTO at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Translate to C label + WRITELN "goto ", element$[2], ";" TO g_CFILE + END IF + + CASE "LABEL" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty LABEL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Translate to C label + WRITELN element$[2], ":" TO g_CFILE + WRITELN ";" TO g_CFILE + END IF + + CASE "TRAP" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty TRAP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + IF EQUAL(element$[2], "SYSTEM") THEN + WRITELN "/* Error catching is enabled */" TO g_CFILE + WRITELN "__b2c__trap = 1;" TO g_CFILE + WRITELN "signal(SIGILL, __b2c__catch_signal);" TO g_CFILE + WRITELN "signal(SIGABRT, __b2c__catch_signal);" TO g_CFILE + WRITELN "signal(SIGFPE, __b2c__catch_signal);" TO g_CFILE + WRITELN "signal(SIGSEGV, __b2c__catch_signal);" TO g_CFILE + ELIF EQUAL(element$[2], "LOCAL") THEN + WRITELN "/* Error catching is disabled */" TO g_CFILE + WRITELN "__b2c__trap = 0;" TO g_CFILE + WRITELN "signal(SIGILL, SIG_DFL);" TO g_CFILE + WRITELN "signal(SIGABRT, SIG_DFL);" TO g_CFILE + WRITELN "signal(SIGFPE, SIG_DFL);" TO g_CFILE + WRITELN "signal(SIGSEGV, SIG_DFL);" TO g_CFILE + ELSE + PRINT NL$, "ERROR: invalid argument for TRAP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + END IF + + CASE "CATCH" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty CATCH at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELIF EQUAL(element$[2], "GOTO") THEN + WRITELN "__b2c__catch_set = 1;" TO g_CFILE + g_CATCHGOTO$ = element$[3] + ELIF EQUAL(element$[2], "RESET") THEN + WRITELN "__b2c__catch_set = 0;" TO g_CFILE + g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" + ELSE + PRINT NL$, "ERROR: CATCH without GOTO or RESET at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + + CASE "RESUME" + WRITELN "longjmp(__b2c__jump, 1);" TO g_CFILE + + CASE "CLEAR" + WRITELN "fprintf(stdout,\"\\033[2J\"); fprintf(stdout,\"\\033[0;0f\");fflush(stdout);" TO g_CFILE + + CASE "COLOR" + Handle_Color(CHOP$(MID$(statement$, INSTR(statement$, "COLOR") + 5))) + + CASE "GOTOXY" + Handle_Gotoxy(CHOP$(MID$(statement$, INSTR(statement$, "GOTOXY") + 6))) + + CASE "RECEIVE" + Handle_Receive(CHOP$(MID$(statement$, INSTR(statement$, "RECEIVE") + 7))) + + CASE "SEND" + Handle_Send(MID$(statement$, INSTR(statement$, "SEND") + 4)) + + CASE "RECORD" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty RECORD at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELIF ISTRUE(LEN(g_RECORDNAME$)) THEN + PRINT NL$, "ERROR: cannot define a record within a record!" + END 1 + ELSE + ' Translate to C typedef struct + IF ISTRUE(LEN(g_FUNCNAME$)) THEN + g_RECORDNAME$ = CONCAT$("RECORD_", g_FUNCNAME$, "_", STR$(g_COUNTER)) + WRITELN "struct ", g_RECORDNAME$, "{" TO g_CFILE + ELSE + g_RECORDNAME$ = CONCAT$("RECORD_", STR$(g_COUNTER)) + WRITELN "struct ", g_RECORDNAME$, "{" TO g_HFILE + END IF + g_RECORDVAR$ = element$[2] + END IF + + CASE "WITH" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty WITH at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELIF ISTRUE(LEN(g_RECORDNAME$)) THEN + PRINT NL$, "ERROR: cannot define a WITH within a WITH!" + END 1 + ELSE + g_WITHVAR$ = element$[2] + END IF + + CASE "SPLIT" + Handle_Split(MID$(statement$, INSTR(statement$, "SPLIT") + 5)) + + CASE "SELECT" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty SELECT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + INCR g_SELECTVAR_CTR + g_SELECTVAR$[g_SELECTVAR_CTR] = MID$(statement$, INSTR(statement$, "SELECT") + 6) + g_IN_CASE[g_SELECTVAR_CTR] = 0 + g_CASE_FALL$ = "" + END IF + + CASE "CASE" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty CASE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + IF ISTRUE(g_IN_CASE[g_SELECTVAR_CTR]) THEN + IF INSTR(g_SELECTVAR$[g_SELECTVAR_CTR], g_STRINGSIGN$) THEN + IF EQUAL(RIGHT$(statement$, 1), ";") THEN + exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4) + g_CASE_FALL$ = CONCAT$("|| !strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", LEFT$(exp$, LEN(exp$)-1), ") ", g_CASE_FALL$) + ELSE + WRITELN "} else if (!strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE + g_CASE_FALL$ = "" + END IF + ELSE + IF EQUAL(RIGHT$(statement$, 1), ";") THEN + exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4) + g_CASE_FALL$ = CONCAT$("|| ", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", LEFT$(exp$, LEN(exp$)-1), ")", g_CASE_FALL$) + ELSE + WRITELN "} else if (", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE + g_CASE_FALL$ = "" + END IF + END IF + ELSE + IF INSTR(g_SELECTVAR$[g_SELECTVAR_CTR], g_STRINGSIGN$) THEN + IF EQUAL(RIGHT$(statement$, 1), ";") THEN + exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4) + g_CASE_FALL$ = CONCAT$("|| !strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", LEFT$(exp$, LEN(exp$)-1), ") ", g_CASE_FALL$) + ELSE + WRITELN "if (!strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", MID$(statement$, INSTR(statement$, "CASE") + 4),") ", g_CASE_FALL$, "){" TO g_CFILE + g_IN_CASE[g_SELECTVAR_CTR] = 1 + g_CASE_FALL$ = "" + END IF + ELSE + IF EQUAL(RIGHT$(statement$, 1), ";") THEN + exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4) + g_CASE_FALL$ = CONCAT$("|| ", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", LEFT$(exp$, LEN(exp$)-1), ")", g_CASE_FALL$) + ELSE + WRITELN "if (", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE + g_IN_CASE[g_SELECTVAR_CTR] = 1 + g_CASE_FALL$ = "" + END IF + END IF + END IF + END IF + + CASE "DEFAULT" + IF ISTRUE(g_IN_CASE[g_SELECTVAR_CTR]) THEN + WRITELN "} else {" TO g_CFILE + ELSE + PRINT NL$, "ERROR: cannot use DEFAULT without previous CASE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + g_IN_CASE[g_SELECTVAR_CTR] = 0 + g_CASE_FALL$ = "" + + CASE "SETENVIRON" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty SETENVIRON at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Resolve this with C macro + WRITELN "SETENVIRON(", MID$(statement$, INSTR(statement$, "SETENVIRON") + 10), ");" TO g_CFILE + END IF + + CASE "SORT" + Handle_Sort(CHOP$(MID$(statement$, INSTR(statement$, "SORT") + 4))) + + CASE "STOP" + WRITELN "kill(getpid(), SIGSTOP);" TO g_CFILE + + CASE "TRACE" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty TRACE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + IF EQUAL(element$[2], "ON") THEN g_TRACE = 1 + ELIF EQUAL(element$[2], "OFF") THEN g_TRACE =0 + ENDIF + + CASE "OPTION" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty OPTION at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + IF EQUAL(element$[2], "BASE") AND dim IS 3 THEN + IF REGEX(element$[3], "[0-9]") THEN + g_OPTION_BASE = VAL(element$[3]) + ELSE + PRINT NL$, "ERROR: invalid argument to OPTION BASE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + ELIF EQUAL(element$[2], "COMPARE") AND dim IS 3 THEN + IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN + WRITELN "__b2c__option_compare = ", element$[3], ";" TO g_CFILE + ELSE + PRINT NL$, "ERROR: invalid argument to OPTION COMPARE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + ELIF EQUAL(element$[2], "SOCKET") AND dim IS 3 THEN + IF REGEX(element$[3], "[0-9]") THEN + g_OPTION_SOCKET = VAL(element$[3]) + ELSE + PRINT NL$, "ERROR: invalid argument to OPTION SOCKET at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + ELIF EQUAL(element$[2], "MEMSTREAM") AND dim IS 3 THEN + IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN + WRITELN "__b2c__option_memstream = ", element$[3], ";" TO g_CFILE + ELSE + PRINT NL$, "ERROR: invalid argument to OPTION MEMSTREAM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + ELIF EQUAL(element$[2], "MEMTYPE") AND dim IS 3 THEN + IF REGEX(statement$, ".*short.*") THEN + WRITELN "__b2c__memtype = 2;" TO g_CFILE + g_OPTION_MEMTYPE$ = "short" + ELIF REGEX(statement$, ".*int.*") THEN + WRITELN "__b2c__memtype = 3;" TO g_CFILE + g_OPTION_MEMTYPE$ = "int" + ELIF REGEX(statement$, ".*long.*|.*NUMBER.*") THEN + WRITELN "__b2c__memtype = 4;" TO g_CFILE + g_OPTION_MEMTYPE$ = "long" + ELIF REGEX(statement$, ".*float.*") THEN + WRITELN "__b2c__memtype = 5;" TO g_CFILE + g_OPTION_MEMTYPE$ = "float" + ELIF REGEX(statement$, ".*double.*|.*FLOATING.*") THEN + WRITELN "__b2c__memtype = 6;" TO g_CFILE + g_OPTION_MEMTYPE$ = "double" + ELIF REGEX(statement$, ".*void.*|.*char\\*.*|.*STRING.*") THEN + WRITELN "__b2c__memtype = 7;" TO g_CFILE + g_OPTION_MEMTYPE$ = "char*" + ELIF REGEX(statement$, ".*char.*") THEN + WRITELN "__b2c__memtype = 1;" TO g_CFILE + g_OPTION_MEMTYPE$ = "char" + ELSE + PRINT NL$, "ERROR: invalid argument to OPTION MEMTYPE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + ELIF EQUAL(element$[2], "COLLAPSE") AND dim IS 3 THEN + IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN + WRITELN "__b2c__collapse = ", element$[3], ";" TO g_CFILE + ELSE + PRINT NL$, "ERROR: invalid argument to OPTION COLLAPSE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + ELIF EQUAL(element$[2], "INTERNATIONAL") AND dim IS 3 THEN + IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN + WRITELN "#include <libintl.h>" TO g_HFILE + WRITELN "#include <locale.h>" TO g_HFILE + WRITELN "setlocale(LC_ALL, \"\");" TO g_CFILE + WRITELN "if(bindtextdomain(\"", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), "\",\"/usr/share/locale\")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN "if(textdomain(\"", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), "\")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELSE + PRINT NL$, "ERROR: invalid argument to OPTION INTERNATIONAL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + ELSE + PRINT NL$, "ERROR: argument to OPTION at line ", g_COUNTER, " in file '", g_CURFILE$, "' not recognized!" + END 1 + END IF + END IF + + CASE "PROTO" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty PROTO at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + exp$ = MID$(REPLACE$(statement$, CHR$(34), ""), INSTR(statement$, "PROTO") + 5) + ' Check if ALIAS is there + IF INSTR(exp$, " ALIAS ") THEN + WRITELN "#define ", MID$(exp$, INSTR(exp$, " ALIAS ") + 7), " ", MID$(exp$, 1, INSTR(exp$, " ALIAS ")) TO g_HFILE + g_IMPORTED$ = CONCAT$(MID$(exp$, INSTR(exp$, " ALIAS ") + 7), " ", g_IMPORTED$) + g_IMPORTED$ = CONCAT$(MID$(exp$, 1, INSTR(exp$, " ALIAS ")), " ", g_IMPORTED$) + ELSE + g_IMPORTED$ = CONCAT$(REPLACE$(exp$, ",", " "), " ", g_IMPORTED$) + END IF + END IF + + CASE "INCR" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty INC at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Walk through commas + SPLIT CHOP$(MID$(statement$, INSTR(statement$, "INCR") + 4)) BY "," TO sym$ SIZE dim + IF dim IS 1 THEN + WRITELN sym$[1], " = ", sym$[1], " + 1;" TO g_CFILE + ELSE + WRITELN sym$[1], " = ", sym$[1], " + (", CHOP$(MID$(statement$, INSTR(statement$, ",") + 1)), ");" TO g_CFILE + END IF + END IF + + CASE "DECR" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty INC at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Walk through commas + SPLIT CHOP$(MID$(statement$, INSTR(statement$, "DECR") + 4)) BY "," TO sym$ SIZE dim + IF dim IS 1 THEN + WRITELN sym$[1], " = ", sym$[1], " - 1;" TO g_CFILE + ELSE + WRITELN sym$[1], " = ", sym$[1], " - (", CHOP$(MID$(statement$, INSTR(statement$, ",") + 1)), ");" TO g_CFILE + END IF + END IF + + CASE "ALARM" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty ALARM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Walk through commas + SPLIT CHOP$(MID$(statement$, INSTR(statement$, "ALARM") + 5)) BY "," TO sym$ SIZE dim + IF dim IS 2 THEN + WRITELN "signal(SIGALRM, (void*)", sym$[1], ");" TO g_CFILE + WRITELN "alarm(", sym$[2], ");" TO g_CFILE + ELSE + PRINT NL$, "ERROR: missing argument in ALARM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + END IF + + CASE "CURSOR" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty CURSOR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + IF EQUAL(element$[2], "ON") THEN WRITELN "fprintf(stdout,\"\\033[?25h\"); fflush(stdout);" TO g_CFILE + ELIF EQUAL(element$[2], "OFF") THEN WRITELN "fprintf(stdout,\"\\033[?25l\"); fflush(stdout);" TO g_CFILE + ENDIF + + CASE "ALIAS" + Handle_Alias(CHOP$(MID$(statement$, INSTR(statement$, "ALIAS") + 5))) + + CASE "LOOKUP" + Handle_Lookup(CHOP$(MID$(statement$, INSTR(statement$, "LOOKUP") + 6))) + + CASE "RELATE" + Handle_Relate(CHOP$(MID$(statement$, INSTR(statement$, "RELATE") + 6))) + + CASE "TEXTDOMAIN" + ' Check argument + IF dim EQ 1 THEN + PRINT NL$, "ERROR: empty TEXTDOMAIN at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + ELSE + ' Walk through commas + SPLIT CHOP$(MID$(statement$, INSTR(statement$, "TEXTDOMAIN") + 10)) BY "," TO sym$ SIZE dim + IF dim IS 2 THEN + WRITELN "if(bindtextdomain(", sym$[1], ",", sym$[2], ")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + WRITELN "if(textdomain(", sym$[1], ")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE + ELSE + PRINT NL$, "ERROR: missing argument in TEXTDOMAIN at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" + END 1 + END IF + END IF + + DEFAULT + ' Check on imported symbols first + IF INSTR(element$[1], "(") THEN element$[1] = LEFT$(element$[1], INSTR(element$[1], "(") - 1) + + SPLIT CHOP$(g_IMPORTED$) BY " " TO sym$ SIZE dim + found = FALSE + + FOR i = 1 TO dim + IF EQUAL(sym$[i], element$[1]) THEN + IF REGEX(statement$, "\\(.*\\)") THEN WRITELN statement$, ";" TO g_CFILE + ELSE WRITELN statement$, "();" TO g_CFILE + found = TRUE + BREAK + END IF + NEXT + ' Not an imported symbol? Check if assignment + IF NOT(found) THEN Handle_Let(statement$) + END SELECT + END IF + END IF + +END SUB + +'---------------------------------------------------------------------------------------------- + +SUB Tokenize (STRING current$) + + LOCAL dim, i, is_string, is_escaped + LOCAL token$ + + ' Initialize parser + is_string = FALSE + is_escaped = FALSE + token$ = "" + + ' See if there are colons + FOR i = 1 TO LEN(current$) + IF EQUAL(MID$(current$, i, 5), "INTL$") THEN + IF ISFALSE(is_string) THEN + token$ = CONCAT$(token$, "gettext") + INCR i, 5 + END IF + ELIF EQUAL(MID$(current$, i, 5), "NNTL$") THEN + IF ISFALSE(is_string) THEN + token$ = CONCAT$(token$, "ngettext") + INCR i, 5 + END IF + END IF + SELECT MID$(current$, i, 1) + ' Separator + CASE ":" + IF ISFALSE(is_string) THEN + token$ = CONCAT$(token$, CHR$(10)) + ELSE + token$ = CONCAT$(token$, ":") + END IF + ' String symbol + CASE "$" + IF ISFALSE(is_string) OR REGEX(current$, "IMPORT.*FROM.*TYPE.*") THEN + token$ = CONCAT$(token$, g_STRINGSIGN$) + is_escaped = FALSE + ELSE + token$ = CONCAT$(token$, "$") + END IF + ' Escape symbol + CASE CHR$(92) + token$ = CONCAT$(token$, CHR$(92)) + is_escaped = NOT(is_escaped) + ' Quote symbol + CASE CHR$(34) + token$ = CONCAT$(token$, CHR$(34)) + IF ISFALSE(is_escaped) THEN is_string = NOT(is_string) + is_escaped = FALSE + DEFAULT + token$ = CONCAT$(token$, MID$(current$, i, 1)) + is_escaped = FALSE + END SELECT + NEXT + ' Split into separate statements + SPLIT token$ BY CHR$(10) TO element$ SIZE dim + ' Start parsing + FOR i = 1 TO dim + Parse_Line(CHOP$(element$[i])) + NEXT + +END SUB + +'---------------------------------------------------------------------------------------------- + +FUNCTION Parse_Equation$(STRING current$) + + LOCAL dim, i, j, is_string, is_escaped, is_equation, opctr + LOCAL token$, term$, eq$, total$, type$ + LOCAL logop$[32] + + ' Initialize parser + is_string = FALSE + is_escaped = FALSE + opctr = 1 + + ' First split into separate chunks OR/AND + FOR i = 1 TO LEN(current$) + IF EQUAL(MID$(current$, i, 5), " AND ") THEN + IF ISFALSE(is_string) THEN + token$ = CONCAT$(token$, CHR$(10)) + logop$[opctr] = " AND " + INCR opctr : INCR i, 4 + ELSE + token$ = CONCAT$(token$, " ") + END IF + ELIF EQUAL(MID$(current$, i, 4), " OR ") THEN + IF ISFALSE(is_string) THEN + token$ = CONCAT$(token$, CHR$(10)) + logop$[opctr] = " OR " + INCR opctr : INCR i, 3 + ELSE + token$ = CONCAT$(token$, " ") + END IF + ELIF EQUAL(MID$(current$, i, 1), CHR$(92)) THEN + token$ = CONCAT$(token$, CHR$(92)) + is_escaped = NOT(is_escaped) + ELIF EQUAL(MID$(current$, i, 1), CHR$(34)) THEN + token$ = CONCAT$(token$, CHR$(34)) + IF ISFALSE(is_escaped) THEN is_string = NOT(is_string) + is_escaped = FALSE + ELSE + token$ = CONCAT$(token$, MID$(current$, i, 1)) + is_escaped = FALSE + END IF + NEXT + logop$[opctr] = "" + opctr = 1 + + ' Split into separate chunks + SPLIT token$ BY CHR$(10) TO element$ SIZE dim + + ' Start parsing + FOR j = 1 TO dim + + eq$ = "!" + token$ = "" + + ' Check if this is a string + IF INSTR(element$[j], "(") THEN + type$ = MID$(element$[j], 1, INSTR(element$[j], "(")) + ELSE + type$ = element$[j] + END IF + + ' See if there are equal signs + FOR i = 1 TO LEN(element$[j]) + + SELECT MID$(element$[j], i, 1) + ' Separator + CASE "=" + IF ISFALSE(is_string) THEN + IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN + term$ = token$ + token$ = "" + ELIF NOT(is_equation) THEN + token$ = CONCAT$(token$, "==") + ELSE + token$ = CONCAT$(token$, "=") + is_equation = 0 + END IF + ELSE + token$ = CONCAT$(token$, "=") + END IF + ' Negation + CASE "!" + IF ISFALSE(is_string) THEN + IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN + eq$ = "" + ELIF NOT(is_equation) THEN + token$ = CONCAT$(token$, "!=") + INCR i + ELSE + token$ = CONCAT$(token$, "!") + is_equation = 0 + END IF + ELSE + token$ = CONCAT$(token$, "!") + END IF + ' Comparison symbols + CASE "<" + token$ = CONCAT$(token$, "<") + is_equation = 1 + CASE ">" + token$ = CONCAT$(token$, ">") + is_equation = 1 + CASE "#" + token$ = CONCAT$(token$, "#") + is_equation = 1 + ' Escape symbol + CASE CHR$(92) + token$ = CONCAT$(token$, CHR$(92)) + is_escaped = NOT(is_escaped) + ' Quote symbol + CASE CHR$(34) + token$ = CONCAT$(token$, CHR$(34)) + IF ISFALSE(is_escaped) THEN is_string = NOT(is_string) + is_escaped = FALSE + DEFAULT + token$ = CONCAT$(token$, MID$(element$[j], i, 1)) + is_escaped = FALSE + END SELECT + NEXT + + ' Construct string equation + IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN token$ = CONCAT$("((__b2c__option_compare == 0) ? ", eq$, "strcmp(", term$, ",", token$, ") : ", eq$, "strcasecmp(", term$, ",", token$, "))") + + total$ = CONCAT$(total$, token$) + + ' Restore logical operator + total$ = CONCAT$(total$, logop$[opctr]) + INCR opctr + NEXT + + RETURN total$ + +END FUNCTION + +'---------------------------------------------------------------------------------------------- + +SUB Download_File(STRING name$) + + LOCAL total$, dat$ + LOCAL length, mynet + LOCAL baconfile TYPE FILE* + + PRINT "Fetching file... "; + + OPEN CONCAT$(LEFT$(name$, INSTR(name$, "/")-1), ":80") FOR NETWORK AS mynet + SEND CONCAT$("GET /", MID$(name$, INSTR(name$, "/")+1), " HTTP/1.1\r\nHost: ", LEFT$(name$, INSTR(name$, "/")-1), "\r\n\r\n") TO mynet + + RECEIVE dat$ FROM mynet + + ' Get the filesize from the HTTP header + IF NOT(INSTR(dat$, "Content-Length:")) THEN + PRINT "ERROR: file not found! Check URL and try again." + END 1 + END IF + + dat$ = MID$(dat$, INSTR(dat$, "Content-Length:")+15) + length = VAL(LEFT$(dat$, INSTR(dat$, NL$))) + + ' As long as there is data, get it + WHILE WAIT(mynet, 1000) + total$ = CONCAT$(total$, dat$) + RECEIVE dat$ FROM mynet + IF LEN(dat$) = 0 THEN BREAK + WEND + total$ = CONCAT$(total$, dat$) + + CLOSE NETWORK mynet + + ' Write to file + OPEN MID$(name$, INSTR(name$, "/")+1) FOR WRITING AS baconfile + WRITELN MID$(total$, INSTR(total$, "\r\n\r\n")+4) TO baconfile + CLOSE FILE baconfile + + IF FILELEN(MID$(name$, INSTR(name$, "/")+1)) != length+1 THEN + PRINT "ERROR: file could not be downloaded. Try again later." + END 1 + END IF + + PRINT "done." + +END SUB + +'---------------------------------------------------------------------------------------------- +' +' 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 = 32 + +LET g_NO_COMPILE = 0 +LET g_TMP_PRESERVE = 0 +LET g_USE_C = 0 +LET g_MAX_BACKLOG = 4 +LET g_CPP = 0 +LET g_SHEBANG = FALSE +LET g_XGETTEXT = 0 + +g_TEMPDIR$ = "." +g_CCNAME$ = "cc" +g_CCFLAGS$ = "" +g_INCFILES$ = "" +g_INCLUDE_FILES$ = "" +LET g_TRACE = 0 +LET g_OPTION_BASE = 0 +LET g_OPTION_SOCKET = 5 +LET g_OPTION_MEMTYPE$ = "char" +LET g_IF_PARSE = 0 + +' Some global declarations +g_CURFILE$ = "" +g_FUNCNAME$ = "" +g_FUNCTYPE$ = "" +g_PROTOTYPE$ = "" +g_TMP_FILES$ = "" +g_LOCALSTRINGS$ = "" +g_STRINGARRAYS$ = "" +g_STRINGARGS$ = "" +g_BINEXT$ = "" +g_RECORDCACHE$ = "" +LET g_LOOPCTR = 0 +g_ERRORTXT$ = "" + +' Always create a final label +g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" + +' Records +g_RECORDNAME$ = "" +g_RECORDVAR$ = "" +g_WITHVAR$ = "" + +' Select/Case currently 16 levels deep +DECLARE g_SELECTVAR$[16] +DECLARE g_IN_CASE[16] +g_SELECTVAR_CTR = 0 + +' Relate currently 256 +DECLARE g_RELATE$[256] +g_RELATE_CTR = 0 + +SPLIT CHOP$(ARGUMENT$) BY " " TO args$ SIZE amount + +IF amount < 2 THEN + PRINT "ERROR: no filename? Run with '-h' to see usage." + END +ENDIF + +i = 1 + +WHILE i <= amount DO + + SELECT LEFT$(args$[i], 2) + + ' Compiler option + CASE "-c" + INCR i + IF LEN(args$[i]) > 0 THEN g_CCNAME$ = args$[i] + + ' Include option + CASE "-i" + INCR i + IF NOT(FILEEXISTS(args$[i])) AND NOT(FILEEXISTS(CONCAT$("/usr/include/", args$[i]))) THEN + PRINT NL$, "ERROR: included C header file from -i option not found!" + END 1 + END IF + IF LEN(args$[i]) > 0 THEN + IF NOT(FILEEXISTS(CONCAT$("/usr/include/", args$[i]))) THEN + g_INCFILES$ = CONCAT$("#include \"", args$[i], "\"", NL$, g_INCFILES$) + ELSE + g_INCFILES$ = CONCAT$("#include <", args$[i], ">", NL$, g_INCFILES$) + END IF + END IF + + ' Library flags + CASE "-l" + IF LEN(args$[i]) > 2 THEN + g_LDFLAGS$ = CONCAT$(g_LDFLAGS$, " -l", MID$(args$[i], 3)) + ELSE + INCR i + IF i <= amount THEN g_LDFLAGS$ = CONCAT$(g_LDFLAGS$, " -l", args$[i]) + END IF + + ' Compiler flags + CASE "-o" + INCR i + IF LEN(args$[i]) > 0 THEN g_CCFLAGS$ = CONCAT$(g_CCFLAGS$, " ", args$[i]) + + ' Temporary directory + CASE "-d" + INCR i + IF LEN(args$[i]) > 0 THEN + IF NOT(FILEEXISTS(args$[i])) THEN MAKEDIR args$[i] + g_TEMPDIR$ = args$[i] + END IF + + ' Help option + CASE "-h"; + CASE "-?" + PRINT NL$, "USAGE: bacon [options] program[.bac]" + PRINT NL$, "OPTIONS:" + PRINT NL$, " -c <compiler>", TAB$(1), "Compiler to use (default: ", g_CCNAME$, ")" + PRINT " -l <flags>", TAB$(1), "Pass libraries to linker" + PRINT " -o <options>", TAB$(1), "Pass compiler options" + PRINT " -i <include>", TAB$(1), "Add include file to C code" + PRINT " -d <tmpdir>", TAB$(1), "Temporary directory (default: ", g_TEMPDIR$, ")" + PRINT " -x ", TAB$(2), "Extract gettext strings" + PRINT " -f ", TAB$(2), "Create Shared Object" + PRINT " -n ", TAB$(2), "Do not compile, only convert" + PRINT " -j ", TAB$(2), "Invoke C Preprocessor" + PRINT " -p ", TAB$(2), "Preserve temporary files" + PRINT " -b ", TAB$(2), "Execute from shebang" + PRINT " -v ", TAB$(2), "Show version" + PRINT " -h ", TAB$(2), "Show help", NL$ + END + + ' Version option + CASE "-v" + PRINT NL$, "BaCon version ", g_VERSION$, " - (c) Peter van Eerten - GPL v3.", NL$ + END + + ' Preserve option + CASE "-p" + g_TMP_PRESERVE = 1 + + ' Gettext option + CASE "-x" + g_XGETTEXT = 1 + + ' No compile option + CASE "-n" + g_NO_COMPILE = 1 + + ' Invoke C Preprocessor + CASE "-j" + g_CPP = 1 + + ' Shared library + CASE "-f" + g_CCFLAGS$ = CONCAT$(g_CCFLAGS$, " -shared -rdynamic") + IF INSTR(OS$, "x86_64") THEN g_CCFLAGS$ = CONCAT$(g_CCFLAGS$, " -fPIC") + g_BINEXT$ = ".so" + + ' use shebang + CASE "-b" + g_SHEBANG = TRUE + g_TEMPDIR$ = "/tmp" + + ' This is the sourcefile + DEFAULT + g_SOURCEFILE$ = args$[i] + + END SELECT + + INCR i + +WEND + +IF LEFT$(g_SOURCEFILE$, 7) = "http://" THEN + g_SOURCEFILE$ = MID$(g_SOURCEFILE$, 8) + Download_File(g_SOURCEFILE$) + g_SOURCEFILE$ = MID$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, "/")+1) +ELIF NOT(EQUAL(RIGHT$(g_SOURCEFILE$, 4), ".bac")) THEN + g_SOURCEFILE$ = CONCAT$(g_SOURCEFILE$, ".bac") +END IF + +IF ISFALSE(FILEEXISTS(g_SOURCEFILE$)) THEN + PRINT "ERROR: file not found!" + END ERROR +END IF + +' Change the working directory +IF INSTR(g_SOURCEFILE$, "/") THEN CHANGEDIR MID$(g_SOURCEFILE$, 1, INSTRREV(g_SOURCEFILE$, "/")-1) + +' Now create the global filenames where to write to +g_CFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".c") +g_HFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".h") +STRINGARRAYFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".string.h") +FLOATARRAYFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".float.h") + +' Check to overwrite +IF FILEEXISTS(g_CFILE$) OR FILEEXISTS(g_HFILE$) THEN + IF FILEEXISTS(g_CFILE$) THEN DELETE FILE g_CFILE$ + IF FILEEXISTS(g_HFILE$) THEN DELETE FILE g_HFILE$ + IF FILEEXISTS(STRINGARRAYFILE$) THEN DELETE FILE STRINGARRAYFILE$ + IF FILEEXISTS(FLOATARRAYFILE$) THEN DELETE FILE FLOATARRAYFILE$ +END IF + +IF NOT(g_SHEBANG) THEN PRINT "Starting conversion..."; + +' Add to total file list +g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_CFILE$) +g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_HFILE$) +g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", STRINGARRAYFILE$) +g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", FLOATARRAYFILE$) + +' Create new sourcefile +OPEN g_CFILE$ FOR WRITING AS g_CFILE + +' Create basic C file +WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO g_CFILE +WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".h\"" TO g_CFILE +WRITELN "int main(int argc, const char **argv)" TO g_CFILE +WRITELN "{" TO g_CFILE +WRITELN "/* Default is: system traps signals */" TO g_CFILE +WRITELN "signal(SIGILL, __b2c__catch_signal);" TO g_CFILE +WRITELN "signal(SIGABRT, __b2c__catch_signal);" TO g_CFILE +WRITELN "signal(SIGFPE, __b2c__catch_signal);" TO g_CFILE +WRITELN "signal(SIGSEGV, __b2c__catch_signal);" TO g_CFILE +WRITELN "/* Make sure internal string buffers are empty */" TO g_CFILE +WRITELN "__b2c__sbuffer_ptr=0;" TO g_CFILE +WRITELN "__b2c__rbuffer_ptr=0;" TO g_CFILE + +' Put arguments into reserved variable ARGUMENT +WRITELN "/* Setup the reserved variable 'ARGUMENT' */" TO g_CFILE +WRITELN "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" TO g_CFILE +WRITELN "{__b2c__arglen += strlen(argv[__b2c__counter]) + 1;} __b2c__arglen++;" TO g_CFILE +WRITELN "ARGUMENT", g_STRINGSIGN$, " = (char*)calloc(__b2c__arglen, sizeof(char));" TO g_CFILE +WRITELN "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" TO g_CFILE +WRITELN "{strcat(ARGUMENT", g_STRINGSIGN$, ", argv[__b2c__counter]); if(__b2c__counter != argc - 1) strcat(ARGUMENT", g_STRINGSIGN$, ", \" \");}" TO g_CFILE +WRITELN "/* By default seed random generator */" TO g_CFILE +WRITELN "srandom((unsigned int)time(NULL));" TO g_CFILE +WRITELN "/* Initialize internal stackpointer */" TO g_CFILE +WRITELN "__b2c__typestack = (int*)calloc(1, sizeof(int));" TO g_CFILE +WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, sizeof(char*)); __b2c__stringstack[0] = calloc(1, sizeof(char));" TO g_CFILE +WRITELN "/* Rest of the program */" TO g_CFILE + +' Create new headerfile +OPEN g_HFILE$ FOR WRITING AS g_HFILE + +' Create basic H file, functions are converted using macros +WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO g_HFILE +WRITELN "#include <stdio.h>" TO g_HFILE +WRITELN "#include <stdlib.h>" TO g_HFILE +WRITELN "#include <stdarg.h>" TO g_HFILE +WRITELN "#include <sys/time.h>" TO g_HFILE +WRITELN "#include <sys/stat.h>" TO g_HFILE +WRITELN "#include <sys/types.h>" TO g_HFILE +WRITELN "#include <sys/wait.h>" TO g_HFILE +WRITELN "#include <sys/socket.h>" TO g_HFILE +WRITELN "#include <sys/utsname.h>" TO g_HFILE +WRITELN "#include <dirent.h>" TO g_HFILE +WRITELN "#include <setjmp.h>" TO g_HFILE +WRITELN "#include <netdb.h>" TO g_HFILE +IF INSTR(OS$, "BSD") THEN + WRITELN "#include <netinet/in.h>" TO g_HFILE +END IF +WRITELN "#include <arpa/inet.h>" TO g_HFILE +WRITELN "#include <signal.h>" TO g_HFILE +WRITELN "static jmp_buf __b2c__jump;" TO g_HFILE +WRITELN "static int __b2c__trap = 1;" TO g_HFILE +WRITELN "static int __b2c__catch_set = 0;" TO g_HFILE +WRITELN "static int ERROR = 0;" TO g_HFILE +WRITELN "static int __b2c__option_compare = 0;" TO g_HFILE +WRITELN "static int __b2c__option_memstream = 0;" TO g_HFILE +WRITELN "static int __b2c__memtype = 1;" TO g_HFILE +WRITELN "static int __b2c__collapse = 0;" TO g_HFILE +WRITELN "int __b2c__break_ctr = 0;" TO g_HFILE +WRITELN "int __b2c__break_flag = 0;" TO g_HFILE +WRITELN "int RETVAL = 0;" TO g_HFILE +WRITELN "char __b2c__chop_default[] = \"\\r\\n\\t \";" TO g_HFILE +WRITELN "char VERSION", g_STRINGSIGN$, "[] = \"", g_VERSION$, "\";" TO g_HFILE + +' Add user include files +WRITELN "/* User include files */" TO g_HFILE +WRITELN g_INCFILES$ TO g_HFILE + +WRITELN "/* READ/DATA include files */" TO g_HFILE +WRITELN "int __b2c__stringarray_ptr = 0;" TO g_HFILE +WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".string.h\"" TO g_HFILE +WRITELN "int __b2c__floatarray_ptr = 0;" TO g_HFILE +WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".float.h\"" TO g_HFILE +WRITELN "int __b2c__ctr;" TO g_HFILE + +WRITELN "/* Math functions */" TO g_HFILE +WRITELN "extern double round(double __b2c__x);" TO g_HFILE +WRITELN "extern long int lrint(double __b2c__x);" TO g_HFILE +WRITELN "#include <math.h>" TO g_HFILE +WRITELN "#define SQR(__b2c__x) sqrt(__b2c__x)" TO g_HFILE +WRITELN "#define POW(__b2c__x, __b2c__y) pow(__b2c__x, __b2c__y)" TO g_HFILE +WRITELN "#define SIN(__b2c__x) sin(__b2c__x)" TO g_HFILE +WRITELN "#define COS(__b2c__x) cos(__b2c__x)" TO g_HFILE +WRITELN "#define TAN(__b2c__x) tan(__b2c__x)" TO g_HFILE +WRITELN "#define ATN(__b2c__x) atan(__b2c__x)" TO g_HFILE +WRITELN "#define LOG(__b2c__x) log(__b2c__x)" TO g_HFILE +WRITELN "#define EXP(__b2c__x) exp(__b2c__x)" TO g_HFILE +WRITELN "#define SGN(__b2c__x) (__b2c__x == 0 ? 0 : (__b2c__x < 0 ? -1 : 1))" TO g_HFILE +WRITELN "#define ROUND(__b2c__x) lrint(__b2c__x)" TO g_HFILE +WRITELN "#define INT(__b2c__x) lrint(__b2c__x)" TO g_HFILE +WRITELN "#define MOD(__b2c__x, __b2c__y) ((long)__b2c__x % (long)__b2c__y)" TO g_HFILE +WRITELN "#define EVEN(__b2c__x) ((__b2c__x % 2 == 0) ? 1 : 0)" TO g_HFILE +WRITELN "#define ODD(__b2c__x) ((__b2c__x % 2 != 0) ? 1 : 0)" TO g_HFILE +WRITELN "#define FLOOR(__b2c__x) (long)floor(__b2c__x)" TO g_HFILE +WRITELN "#define ABS(__b2c__x) (long)abs(__b2c__x)" TO g_HFILE +WRITELN "#define RND random()" TO g_HFILE +IF INSTR(OS$, "SunOS") THEN + WRITELN "#define MAXRANDOM 2147483647" TO g_HFILE +ELSE + WRITELN "#define MAXRANDOM RAND_MAX" TO g_HFILE +END IF +WRITELN "#define RANDOM(__b2c__x) ((__b2c__x != 0) ? random()/(MAXRANDOM/__b2c__x) : 0)" TO g_HFILE +WRITELN "/* Other functions */" TO g_HFILE +WRITELN "#define VAL(__b2c__x) ((__b2c__x != NULL) ? atof(__b2c__x) : 0)" TO g_HFILE +WRITELN "/* Unix functions */" TO g_HFILE +WRITELN "#include <unistd.h>" TO g_HFILE +WRITELN "#define SYSTEM(__b2c__x) do {if (__b2c__x != NULL) {RETVAL = system(__b2c__x); if(WIFEXITED(RETVAL)) RETVAL = WEXITSTATUS(RETVAL);} else RETVAL=0;} while(0)" TO g_HFILE +WRITELN "/* String functions */" TO g_HFILE +WRITELN "#include <string.h>" TO g_HFILE +WRITELN "char *__b2c__strndup(const char *__b2c__s, size_t __b2c__n){size_t __b2c__avail;" TO g_HFILE +WRITELN "char *__b2c__p; if (!__b2c__s) return 0; __b2c__avail = strlen(__b2c__s) + 1;" TO g_HFILE +WRITELN "if (__b2c__avail > __b2c__n + 1) __b2c__avail = __b2c__n + 1; __b2c__p = malloc(__b2c__avail);" TO g_HFILE +WRITELN "memcpy(__b2c__p, __b2c__s, __b2c__avail); __b2c__p[__b2c__avail - 1] = '\\0'; return __b2c__p;}" TO g_HFILE +WRITELN "char __b2c__input__buffer[", g_BUFFER_SIZE, "];" TO g_HFILE +WRITELN "char* __b2c__sbuffer[", g_MAX_BUFFERS, "] = { NULL };" TO g_HFILE +WRITELN "int __b2c__sbuffer_ptr;" TO g_HFILE +WRITELN "char* __b2c__rbuffer[", g_MAX_RBUFFERS, "] = { NULL };" TO g_HFILE +WRITELN "int __b2c__rbuffer_ptr;" TO g_HFILE +WRITELN "/* Temporary pointer to perform assignments */" TO g_HFILE +WRITELN "char *__b2c__assign = NULL;" TO g_HFILE +WRITELN "char *__b2c__split = NULL; char *__b2c__split_tmp = NULL; char *__b2c__split_ptr = NULL;" TO g_HFILE +WRITELN "char *ERR", g_STRINGSIGN$, "(int);" TO g_HFILE +WRITELN "/* Functions for sort */" TO g_HFILE +WRITELN "int __b2c__sortnrd(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE +WRITELN "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return -1; else return 1;}" TO g_HFILE +WRITELN "int __b2c__sortnrd_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE +WRITELN "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return 1; else return -1;}" TO g_HFILE +WRITELN "int __b2c__sortnrf(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE +WRITELN "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return -1; else return 1;}" TO g_HFILE +WRITELN "int __b2c__sortnrf_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE +WRITELN "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return 1; else return -1;}" TO g_HFILE +WRITELN "int __b2c__sortnrl(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE +WRITELN "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return -1; else return 1;}" TO g_HFILE +WRITELN "int __b2c__sortnrl_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE +WRITELN "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return 1; else return -1;}" TO g_HFILE +WRITELN "int __b2c__sortnri(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE +WRITELN "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return -1; else return 1;}" TO g_HFILE +WRITELN "int __b2c__sortnri_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE +WRITELN "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return 1; else return -1;}" TO g_HFILE +WRITELN "int __b2c__sortstr(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE +WRITELN "{return strcmp(*(char **) __b2c__a, *(char **) __b2c__b);}" TO g_HFILE +WRITELN "int __b2c__sortstr_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE +WRITELN "{return strcmp(*(char **) __b2c__b, *(char **) __b2c__a);}" TO g_HFILE +WRITELN "/* Actual functions */" TO g_HFILE +WRITELN "char* __b2c__curdir(void){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "*sizeof(char));" TO g_HFILE +WRITELN "return (getcwd(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "));}" TO g_HFILE +WRITELN "#define CURDIR", g_STRINGSIGN$, " __b2c__curdir()" TO g_HFILE +WRITELN "char* __b2c__reverse(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__s)+2)*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)+1);" TO g_HFILE +WRITELN "for(__b2c__i=0;__b2c__i<strlen(__b2c__s);__b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__s[strlen(__b2c__s)-1-__b2c__i];}" TO g_HFILE +WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define REVERSE", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__reverse(x) : \"null\")" TO g_HFILE +WRITELN "char* __b2c__str(double d){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, "*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, ");" TO g_HFILE +WRITELN "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, ", \"%.10g\", d);" TO g_HFILE +WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define STR", g_STRINGSIGN$, "(x) __b2c__str(x)" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "if(__b2c__first != NULL) { __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__first)+1)*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first);}" TO g_HFILE +WRITELN "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);" TO g_HFILE +WRITELN "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));" TO g_HFILE +WRITELN "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__tmp);} va_end(__b2c__ap); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define CONCAT", g_STRINGSIGN$, "(...) __b2c__concat(__VA_ARGS__, (char*)NULL)" TO g_HFILE +WRITELN "char* __b2c__left(char *__b2c__src, long __b2c__n){if(__b2c__src == NULL || __b2c__n > strlen(__b2c__src) || __b2c__n < 0) return(__b2c__src);" TO g_HFILE +WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src, (__b2c__n));" TO g_HFILE +WRITELN "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define LEFT", g_STRINGSIGN$, "(__b2c__x, __b2c__y) __b2c__left(__b2c__x, __b2c__y)" TO g_HFILE +WRITELN "char* __b2c__right(char *__b2c__src, long __b2c__n){if(__b2c__src == NULL || __b2c__n > strlen(__b2c__src) || __b2c__n < 0) return(__b2c__src);" TO g_HFILE +WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE +WRITELN "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);" TO g_HFILE +WRITELN "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define RIGHT", g_STRINGSIGN$, "(__b2c__x, __b2c__y) __b2c__right(__b2c__x, __b2c__y)" TO g_HFILE +WRITELN "char* __b2c__mid(char *__b2c__src, ...){ va_list __b2c__ap; long __b2c__start, __b2c__end; if(__b2c__src == NULL || strlen(__b2c__src) == 0) return(\"\");" TO g_HFILE +WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); va_start(__b2c__ap, __b2c__src);" TO g_HFILE +WRITELN "__b2c__start = va_arg(__b2c__ap, long); if(__b2c__start < 1) return(__b2c__src); if(__b2c__start > strlen(__b2c__src)) return(\"\"); __b2c__end = va_arg(__b2c__ap, long); if((__b2c__end) < 0 || (__b2c__end) > strlen (__b2c__src)) __b2c__end = strlen(__b2c__src)-__b2c__start+1;" TO g_HFILE +WRITELN "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+(long)(__b2c__start)-1, (__b2c__end)); va_end(__b2c__ap); return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define MID", g_STRINGSIGN$, "(__b2c__string, ...) __b2c__mid(__b2c__string, __VA_ARGS__, -1)" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "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));" TO g_HFILE +WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" TO g_HFILE +WRITELN "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL || strlen(__b2c__tmp) == 0) return (0);__b2c__pos = va_arg(__b2c__ap, int);" TO g_HFILE +WRITELN "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); __b2c__res = strstr(__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos - 1, __b2c__tmp);" TO g_HFILE +WRITELN "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" TO g_HFILE +WRITELN "#define INSTR(...) __b2c__instr(__VA_ARGS__, -1)" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "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));" TO g_HFILE +WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" TO g_HFILE +WRITELN "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL || strlen(__b2c__tmp) == 0) return (0);__b2c__pos = va_arg(__b2c__ap, int);" TO g_HFILE +WRITELN "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); while(__b2c__res == NULL && __b2c__pos <= strlen(__b2c__sbuffer[__b2c__sbuffer_ptr])) {" TO g_HFILE +WRITELN "__b2c__res = strstr(__b2c__sbuffer[__b2c__sbuffer_ptr] + strlen(__b2c__sbuffer[__b2c__sbuffer_ptr]) - __b2c__pos, __b2c__tmp); __b2c__pos+=1;}" TO g_HFILE +WRITELN "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" TO g_HFILE +WRITELN "#define INSTRREV(...) __b2c__instrrev(__VA_ARGS__, -1)" TO g_HFILE +WRITELN "char* __b2c__spc(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 32, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define SPC", g_STRINGSIGN$, "(x) ((x > -1) ? __b2c__spc(x) : \"\")" TO g_HFILE +WRITELN "char* __b2c__tab(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 9, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define TAB", g_STRINGSIGN$, "(x) ((x > -1) ? __b2c__tab(x) : \"\")" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__y, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define FILL", g_STRINGSIGN$, "(x, y) ((y > -1 && y < 256) ? __b2c__fill(x, y) : \"\")" TO g_HFILE +WRITELN "char* __b2c__chop(char *__b2c__src, ...){char *__b2c__tmp, *__b2c__str; int __b2c__i, __b2c__loc = 0; va_list __b2c__ap; if(strlen(__b2c__src) == 0) return(__b2c__src);" TO g_HFILE +WRITELN "va_start (__b2c__ap, __b2c__src); __b2c__str = va_arg (__b2c__ap, char*); if(__b2c__str == 0) __b2c__str = (char*)__b2c__chop_default; else __b2c__loc = va_arg (__b2c__ap, int); va_end (__b2c__ap);" TO g_HFILE +WRITELN "if(__b2c__loc == 0 || __b2c__loc == 1) {while (*__b2c__src != '\\0') {for(__b2c__i = 0; __b2c__i < strlen(__b2c__str); __b2c__i++) {if (*__b2c__src == *(__b2c__str+__b2c__i)) {__b2c__src++; break; } }" TO g_HFILE +WRITELN "if(__b2c__i == strlen(__b2c__str)) break;} if (*__b2c__src == '\\0') return(\"\");} __b2c__tmp = __b2c__src + strlen(__b2c__src) - 1;" TO g_HFILE +WRITELN "if(__b2c__loc == 0 || __b2c__loc == 2) {while (__b2c__tmp >= __b2c__src && *__b2c__tmp != '\\0') {for(__b2c__i = 0; __b2c__i < strlen(__b2c__str); __b2c__i++) {if (*__b2c__tmp == *(__b2c__str+__b2c__i))" TO g_HFILE +WRITELN "{__b2c__tmp--; break; } } if(__b2c__i == strlen(__b2c__str)) break;} } __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE +WRITELN "for(__b2c__i = 0; __b2c__i <= __b2c__tmp - __b2c__src; __b2c__i++) __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__src[__b2c__i];" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i] = '\\0'; return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define CHOP", g_STRINGSIGN$, "(...) __b2c__chop(__VA_ARGS__, 0)" TO g_HFILE +WRITELN "char* __b2c__replace(char* __b2c__x, char* __b2c__y, char* __b2c__z){" TO g_HFILE +WRITELN "char *__b2c__tmp, *__b2c__buf, *__b2c__haystack, *__b2c__dup = NULL; __b2c__sbuffer_ptr++;" TO g_HFILE +WRITELN "if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0; __b2c__haystack = strdup(__b2c__x); __b2c__dup = __b2c__haystack;" TO g_HFILE +WRITELN "__b2c__buf = calloc(1, sizeof(char)); while((__b2c__tmp = strstr(__b2c__haystack, __b2c__y)) != NULL) {*__b2c__tmp = '\\0';" TO g_HFILE +WRITELN "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + strlen(__b2c__z) + 1)*sizeof(char));" TO g_HFILE +WRITELN "strcat(__b2c__buf, __b2c__haystack);strcat(__b2c__buf, __b2c__z);__b2c__haystack = __b2c__tmp+strlen(__b2c__y);}" TO g_HFILE +WRITELN "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + 1)*sizeof(char));strcat(__b2c__buf, __b2c__haystack);" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__buf)+1)*sizeof(char));" TO g_HFILE +WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf);free(__b2c__buf);free(__b2c__dup);return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define REPLACE", g_STRINGSIGN$, "(x, y, z)((x!=NULL && y!=NULL && z!= NULL) ? __b2c__replace(x, y, z) : 0)" TO g_HFILE +WRITELN "#define LEN(x) ((x != NULL) ? strlen(x) : 0)" TO g_HFILE +WRITELN "#define EQUAL(__b2c__x, __b2c__y) ((__b2c__x != NULL && __b2c__y != NULL && __b2c__option_compare == 0) ? !strcmp(__b2c__x, __b2c__y) : ((__b2c__x != NULL && __b2c__y != NULL && __b2c__option_compare == 1) ? !strcasecmp(__b2c__x, __b2c__y) : 0) )" TO g_HFILE +WRITELN "char* __b2c__getenv(char *__b2c__env){static char* __b2c__tmp; __b2c__tmp = getenv(__b2c__env); if (__b2c__tmp == NULL)" TO g_HFILE +WRITELN "{return \"\";} return __b2c__tmp;}" TO g_HFILE +WRITELN "#define GETENVIRON", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__getenv(x) : \"null\")" TO g_HFILE +WRITELN "#define SETENVIRON(x, y) if(x != NULL && y != NULL) setenv(x, y, 1)" TO g_HFILE +WRITELN "/* CHAR functions */" TO g_HFILE +WRITELN "#include <ctype.h>" TO g_HFILE +WRITELN "char* __b2c__ucase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE +WRITELN "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=toupper(__b2c__s[__b2c__i]);}" TO g_HFILE +WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define UCASE", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__ucase(x) : \"null\")" TO g_HFILE +WRITELN "char* __b2c__lcase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE +WRITELN "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=tolower(__b2c__s[__b2c__i]);}" TO g_HFILE +WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define LCASE", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__lcase(x) : \"null\")" TO g_HFILE +WRITELN "/* I/O functions */" TO g_HFILE +WRITELN "FILE *__b2c__inFile; FILE *__b2c__outFile; int __b2c__Byte; struct dirent *__b2c__dir;" TO g_HFILE +WRITELN "char* __b2c__dec2hex(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ");" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, ");" TO g_HFILE +WRITELN "snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%X\", __b2c__i); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "long __b2c__hex2dec(char *__b2c__h){unsigned int __b2c__i; if(sscanf(__b2c__h, \"%X\", &__b2c__i) == EOF && !__b2c__trap){ERROR = 5;" TO g_HFILE +WRITELN "fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} return(long)(__b2c__i);}" TO g_HFILE +WRITELN "unsigned char __b2c__char2asc(char *__b2c__c){return (unsigned char)*__b2c__c;}" TO g_HFILE +WRITELN "char* __b2c__asc2char(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char));" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, 2*sizeof(char)); snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], 2, \"%c\", __b2c__i);" TO g_HFILE +WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "/* Function FILEEXISTS contributed by Armando Rivera */ " TO g_HFILE +WRITELN "long __b2c__fileexists(const char *__b2c__x) {struct stat __b2c__buf; if (stat(__b2c__x, &__b2c__buf) != -1) return 1; return 0;}" TO g_HFILE +WRITELN "#define FILEEXISTS(x) __b2c__fileexists(x)" TO g_HFILE +WRITELN "long __b2c__filelen(const char *__b2c__x) {struct stat __b2c__buf; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE +WRITELN "if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0) return -1; else return(long)(__b2c__buf.st_size);}" TO g_HFILE +WRITELN "#define FILELEN(x) __b2c__filelen(x)" TO g_HFILE +WRITELN "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)" TO g_HFILE +WRITELN "{ERROR = 24; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE +WRITELN "if (S_ISREG(__b2c__buf.st_mode)) return 1; if (S_ISDIR(__b2c__buf.st_mode)) return 2;" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "if (S_ISLNK(__b2c__buf.st_mode)) return 6; if (S_ISSOCK(__b2c__buf.st_mode)) return 7; return 0;}" TO g_HFILE +WRITELN "#define FILETYPE(x) __b2c__filetype(x)" TO g_HFILE +WRITELN "long __b2c__search(FILE* __b2c__x, char* __b2c__y){long __b2c__off, __b2c__pos; char* __b2c__ptr; size_t __b2c__tot;" TO g_HFILE +WRITELN "if(__b2c__x == NULL && !__b2c__trap){ERROR = 2; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE +WRITELN "if(__b2c__y == NULL && !__b2c__trap){ERROR = 25; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE +WRITELN "__b2c__pos = ftell(__b2c__x); __b2c__ptr = (char*)malloc((strlen(__b2c__y)+1)*sizeof(char)); __b2c__off = 0; do {" TO g_HFILE +WRITELN "fseek(__b2c__x, __b2c__off, SEEK_SET);memset(__b2c__ptr, 0, sizeof(char)*(strlen(__b2c__y)+1));" TO g_HFILE +WRITELN "__b2c__tot = fread(__b2c__ptr, sizeof(char), strlen(__b2c__y), __b2c__x);__b2c__off+=1;" TO g_HFILE +WRITELN "} while(!feof(__b2c__x) && strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y)));" TO g_HFILE +WRITELN "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);}" TO g_HFILE +WRITELN "#define SEARCH(x, y) __b2c__search(x, y)" TO g_HFILE +WRITELN "char *__b2c__exec(char *__b2c__x, ...){int __b2c__r, __b2c__len, __b2c__i, __b2c__page; int __b2c__wpipe[2], __b2c__rpipe[2]; char *__b2c__str, *__b2c__ans = NULL; va_list __b2c__ap;" TO g_HFILE +WRITELN "va_start(__b2c__ap, __b2c__x); __b2c__str = va_arg (__b2c__ap, char*); va_end(__b2c__ap); if (pipe (__b2c__rpipe) < 0 || pipe (__b2c__wpipe) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}}" TO g_HFILE +WRITELN "if ((__b2c__r = fork ()) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}} else if (__b2c__r == 0){" TO g_HFILE +WRITELN "close(__b2c__wpipe[1]);close (__b2c__rpipe[0]);dup2 (__b2c__wpipe[0], STDIN_FILENO);close (__b2c__wpipe[0]);dup2 (__b2c__rpipe[1], STDOUT_FILENO);close (__b2c__rpipe[1]); __b2c__r = system (__b2c__x); if(WIFEXITED(__b2c__r)) RETVAL = WEXITSTATUS(__b2c__r); else RETVAL=0; exit(RETVAL);}" TO g_HFILE +WRITELN "else{close (__b2c__wpipe[0]);close (__b2c__rpipe[1]); __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__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)); __b2c__len = 0;__b2c__page = 0;" TO g_HFILE +WRITELN "if(__b2c__str!=NULL) __b2c__i = write(__b2c__wpipe[1], __b2c__str, strlen(__b2c__str)+1); wait(&RETVAL); RETVAL = WEXITSTATUS(RETVAL); do{__b2c__i = read (__b2c__rpipe[0], __b2c__ans, ", g_BUFFER_SIZE, ");if (__b2c__i == -1 && !__b2c__trap){ERROR=30;fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE +WRITELN "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);" TO g_HFILE +WRITELN "if (__b2c__sbuffer[__b2c__sbuffer_ptr] == NULL && !__b2c__trap){ERROR=6; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len, __b2c__ans, __b2c__i);" TO g_HFILE +WRITELN " __b2c__len += __b2c__i;} while (__b2c__i > 0); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\\0';close (__b2c__wpipe[1]);" TO g_HFILE +WRITELN "close (__b2c__rpipe[0]);free (__b2c__ans);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define EXEC", g_STRINGSIGN$, "(...) __b2c__exec(__VA_ARGS__, (char*)NULL)" TO g_HFILE +WRITELN "#define ENDFILE(x) feof(x)" TO g_HFILE +WRITELN "#define TELL(x) ftell(x)" TO g_HFILE +WRITELN "#define HEX", g_STRINGSIGN$, "(x) __b2c__dec2hex(x)" TO g_HFILE +WRITELN "#define DEC(x) __b2c__hex2dec(x)" TO g_HFILE +WRITELN "#define ASC(x) __b2c__char2asc(x)" TO g_HFILE +WRITELN "#define CHR", g_STRINGSIGN$, "(__b2c__x) __b2c__asc2char(__b2c__x)" TO g_HFILE +WRITELN "#define MEMTELL(x) (long)x" TO g_HFILE +WRITELN "/* Dynamic loading, errors */" TO g_HFILE +WRITELN "#include <dlfcn.h>" TO g_HFILE +WRITELN "#include <errno.h>" TO g_HFILE +WRITELN "/* GETKEY */" TO g_HFILE +WRITELN "#include <termios.h>" TO g_HFILE +WRITELN "long __b2c__getch(){long __b2c__ch; struct termios __b2c__oldt, __b2c__newt; tcgetattr(STDIN_FILENO, &__b2c__oldt);" TO g_HFILE +WRITELN "__b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);" TO g_HFILE +WRITELN "__b2c__ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt); return __b2c__ch;} " TO g_HFILE +WRITELN "#define GETKEY __b2c__getch()" TO g_HFILE +WRITELN "long __b2c__getxy(int __b2c__type){char __b2c__asw[", g_BUFFER_SIZE, "]; struct termios __b2c__old, __b2c__new; int __b2c__len, __b2c__x, __b2c__y; ssize_t __b2c__tot;" TO g_HFILE +WRITELN "tcgetattr(STDIN_FILENO, &__b2c__old); __b2c__new = __b2c__old;__b2c__new.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__new);" TO g_HFILE +WRITELN "__b2c__tot = write(STDOUT_FILENO, \"\\033[6n\", strlen(\"\\033[6n\")); __b2c__len = read(STDIN_FILENO, __b2c__asw, ", g_BUFFER_SIZE, ");__b2c__asw[__b2c__len] = '\\0'; " TO g_HFILE +WRITELN "tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__old); sscanf(__b2c__asw, \"\\033[%d;%dR\", &__b2c__y, &__b2c__x); if (!__b2c__type) return(long)__b2c__x; return(long)__b2c__y;}" TO g_HFILE +WRITELN "#define GETX __b2c__getxy(0)" TO g_HFILE +WRITELN "#define GETY __b2c__getxy(1)" TO g_HFILE +WRITELN "long __b2c__screen(int __b2c__type){long __b2c__x; fprintf(stdout,\"\\033[s\"); fprintf(stdout,\"\\033[?25l\"); fprintf(stdout,\"\\033[999;999H\"); fflush(stdout);" TO g_HFILE +WRITELN "__b2c__x = __b2c__getxy(__b2c__type); fprintf(stdout,\"\\033[u\"); fprintf(stdout,\"\\033[?25h\"); fflush(stdout); return(__b2c__x); }" TO g_HFILE +WRITELN "#define COLUMNS __b2c__screen(0)" TO g_HFILE +WRITELN "#define ROWS __b2c__screen(1)" TO g_HFILE +WRITELN "/* Constants, logical stuff */" TO g_HFILE +WRITELN "#define PI 3.14159265" TO g_HFILE +WRITELN "#define NOT(__b2c__x) (!(__b2c__x))" TO g_HFILE +WRITELN "#define AND &&" TO g_HFILE +WRITELN "#define OR ||" TO g_HFILE +WRITELN "#define EQ ==" TO g_HFILE +WRITELN "#define IS ==" TO g_HFILE +WRITELN "#define NE !=" TO g_HFILE +WRITELN "#define ISNOT !=" TO g_HFILE +WRITELN "#define TRUE 1" TO g_HFILE +WRITELN "#define FALSE 0" TO g_HFILE +WRITELN "#define NL", g_STRINGSIGN$, " \"\\n\"" TO g_HFILE +WRITELN "#define STRING char*" TO g_HFILE +WRITELN "#define NUMBER long" TO g_HFILE +WRITELN "#define FLOATING double" TO g_HFILE +WRITELN "#define ISTRUE(__b2c__x) (__b2c__x!=0)" TO g_HFILE +WRITELN "#define ISFALSE(__b2c__x) (__b2c__x==0)" TO g_HFILE +WRITELN "#define SIZEOF(__b2c__x) sizeof(__b2c__x)" TO g_HFILE +WRITELN "/* Date and time */" TO g_HFILE +WRITELN "#include <time.h>" TO g_HFILE +WRITELN "#define NOW (long)time(NULL)" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr],", g_MAX_DIGITS, ");" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "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;}" TO g_HFILE +WRITELN "return(atol(__b2c__sbuffer[__b2c__sbuffer_ptr]));}" TO g_HFILE +WRITELN "#define DAY(x) __b2c__time(x, 1)" TO g_HFILE +WRITELN "#define MONTH(x) __b2c__time(x, 2)" TO g_HFILE +WRITELN "#define YEAR(x) __b2c__time(x, 3)" TO g_HFILE +WRITELN "#define HOUR(x) __b2c__time(x, 4)" TO g_HFILE +WRITELN "#define MINUTE(x) __b2c__time(x, 5)" TO g_HFILE +WRITELN "#define SECOND(x) __b2c__time(x, 6)" TO g_HFILE +WRITELN "#define WEEK(x) __b2c__time(x, 7)" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ");" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%B\", ts); break;} return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define WEEKDAY", g_STRINGSIGN$, "(x) __b2c__datename(x, 1)" TO g_HFILE +WRITELN "#define MONTH", g_STRINGSIGN$, "(x) __b2c__datename(x, 2)" TO g_HFILE +WRITELN "unsigned long __b2c__epoch(int __b2c__year, int __b2c__month, int __b2c__day, int __b2c__hour, int __b2c__minute, int __b2c__second){" TO g_HFILE +WRITELN "struct tm tm; time_t __b2c__t; tm.tm_year = __b2c__year - 1900; tm.tm_mon = __b2c__month - 1; tm.tm_mday = __b2c__day;" TO g_HFILE +WRITELN "tm.tm_hour = __b2c__hour; tm.tm_min = __b2c__minute; tm.tm_sec = __b2c__second;" TO g_HFILE +WRITELN "tm.tm_isdst = -1; __b2c__t = mktime(&tm); if (__b2c__t == -1) return (0); return(long) __b2c__t; }" TO g_HFILE +WRITELN "#define TIMEVALUE(x,y,z,a,b,c) __b2c__epoch(x,y,z,a,b,c)" TO g_HFILE +WRITELN "char* __b2c__os(void){struct utsname __b2c__buf; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, ");" TO g_HFILE +WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_BUFFER_SIZE, "); if(uname(&__b2c__buf) < 0 && !__b2c__trap) {ERROR = 26; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE +WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.sysname); strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], \" \");" TO g_HFILE +WRITELN "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.machine); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define OS", g_STRINGSIGN$, " __b2c__os()" TO g_HFILE +WRITELN "/* Peek and Poke */" TO g_HFILE +WRITELN "struct stat __b2c__sb;" TO g_HFILE +WRITELN "void __b2c__memory__check(void* __b2c__x) {if (stat(__b2c__x, &__b2c__sb) == -1 && errno == EFAULT) {ERROR = 1;} }" TO g_HFILE +WRITELN "long __b2c__malloc(long __b2c__x) {void *__b2c__mem; if(__b2c__x==0) return(0); switch(__b2c__memtype) {case 1: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(char)); break;" TO g_HFILE +WRITELN "case 2: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(short)); break; case 3: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(int)); break;" TO g_HFILE +WRITELN "case 4: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(long)); break; case 5: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(float)); break;" TO g_HFILE +WRITELN "case 6: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(double)); break; case 7: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(char)); break;}" TO g_HFILE +WRITELN "if(__b2c__mem == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} return(long)__b2c__mem;}" TO g_HFILE +WRITELN "#define MEMORY(__b2c__x) __b2c__malloc(__b2c__x)" TO g_HFILE +WRITELN "void *__b2c__realloc(void* __b2c__x, long __b2c__y) {if(__b2c__x == NULL) return (NULL); if(!__b2c__trap) {__b2c__memory__check((char*)__b2c__x);" TO g_HFILE +WRITELN "if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } switch(__b2c__memtype) {case 1: __b2c__x = realloc((void*)__b2c__x, sizeof(char)*(__b2c__y+1)); break;" TO g_HFILE +WRITELN "case 2: __b2c__x = realloc((void*)__b2c__x, sizeof(short)*(__b2c__y+1)); break; case 3: __b2c__x = realloc((void*)__b2c__x, sizeof(int)*(__b2c__y+1)); break;" TO g_HFILE +WRITELN "case 4: __b2c__x = realloc((void*)__b2c__x, sizeof(long)*(__b2c__y+1)); break; case 5: __b2c__x = realloc((void*)__b2c__x, sizeof(float)*(__b2c__y+1)); break;" TO g_HFILE +WRITELN "case 6: __b2c__x = realloc((void*)__b2c__x, sizeof(double)*(__b2c__y+1)); break; case 7: __b2c__x = realloc((void*)__b2c__x, sizeof(char)*(__b2c__y+1)); break;}" TO g_HFILE +WRITELN "if(__b2c__x == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} return (__b2c__x);}" TO g_HFILE +WRITELN "#define RESIZE(__b2c__x, __b2c__y) __b2c__realloc((void*)__b2c__x, __b2c__y)" TO g_HFILE +WRITELN "char __b2c__peek(char* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((char*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((char)*__b2c__x);}" TO g_HFILE +WRITELN "short __b2c__peeks(short* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((short*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((short)*__b2c__x);}" TO g_HFILE +WRITELN "int __b2c__peeki(int* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((int*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((int)*__b2c__x);}" TO g_HFILE +WRITELN "long __b2c__peekl(long* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((long*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((long)*__b2c__x);}" TO g_HFILE +WRITELN "float __b2c__peekf(float* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((float*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((float)*__b2c__x);}" TO g_HFILE +WRITELN "double __b2c__peekd(double* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((double*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((double)*__b2c__x);}" TO g_HFILE +WRITELN "char __b2c__peekv(char* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((char*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((char)*__b2c__x);}" TO g_HFILE +WRITELN "#define PEEK(__b2c__x) (__b2c__memtype==1 ? (unsigned char)__b2c__peek((char*)__b2c__x) : (__b2c__memtype==2 ? (unsigned short)__b2c__peeks((short*)__b2c__x) : (__b2c__memtype==3 ? (unsigned int)__b2c__peeki((int*)__b2c__x) : \\" TO g_HFILE +WRITELN "(__b2c__memtype==4 ? (unsigned long)__b2c__peekl((long*)__b2c__x) : ( __b2c__memtype==5 ? (float)__b2c__peekf((float*)__b2c__x) : (__b2c__memtype==6 ? (double)__b2c__peekd((double*)__b2c__x) : (unsigned char)__b2c__peekv((char*)__b2c__x) ))))))" TO g_HFILE +WRITELN "#define ADDRESS(__b2c__x) (long)(&__b2c__x)" TO g_HFILE +WRITELN "/* Network variables and functions */" TO g_HFILE +WRITELN "struct timeval __b2c__to; struct hostent *__b2c__he; char *__b2c__host; char *__b2c__port; int __b2c__yes = 1; struct sockaddr_in __b2c__addr; " TO g_HFILE +WRITELN "int __b2c__result; char __b2c__data_client[", g_BUFFER_SIZE, "] = { 0 }; char __b2c__data_server[", g_BUFFER_SIZE, "] = { 0 }; int __b2c__handle;" TO g_HFILE +WRITELN "long __b2c__netpeek(int __b2c__fd, int __b2c__usec){fd_set __b2c__rfds; struct timeval __b2c__tv; long __b2c__retval; struct termios __b2c__oldt, __b2c__newt;" TO g_HFILE +WRITELN "if(__b2c__fd == STDIN_FILENO){tcgetattr(STDIN_FILENO, &__b2c__oldt); __b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);}" TO g_HFILE +WRITELN "FD_ZERO(&__b2c__rfds); FD_SET(__b2c__fd, &__b2c__rfds);__b2c__tv.tv_usec = (__b2c__usec%1000)*1000; __b2c__tv.tv_sec = __b2c__usec/1000;" TO g_HFILE +WRITELN "__b2c__retval = select(__b2c__fd + 1, &__b2c__rfds, NULL, NULL, &__b2c__tv); if (__b2c__retval == -1 && !__b2c__trap) {ERROR = 16; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE +WRITELN "if(__b2c__fd == STDIN_FILENO){if(__b2c__retval) if(read(__b2c__fd, &__b2c__retval, 1)==0) __b2c__retval=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt);} return(__b2c__retval);}" TO g_HFILE +WRITELN "#define WAIT(x, y) __b2c__netpeek(x, y)" TO g_HFILE +WRITELN "char* __b2c__nethost(char* __b2c__host) {int __b2c__y; int __b2c__flag = 0; struct in_addr __b2c__address; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE +WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "); memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_BUFFER_SIZE, ");" TO g_HFILE +WRITELN "for(__b2c__y=0; __b2c__y < strlen(__b2c__host); __b2c__y++) {if(isalpha(*(__b2c__host+__b2c__y))) {__b2c__flag = 1; break;}} if(__b2c__flag) __b2c__he = gethostbyname(__b2c__host); " TO g_HFILE +WRITELN "else {if(inet_aton(__b2c__host, &__b2c__address)) __b2c__he = gethostbyaddr((void*)&__b2c__address, sizeof(struct in_addr), AF_INET); } if (__b2c__he == NULL || __b2c__he->h_addr == NULL || __b2c__he->h_name == NULL)" TO g_HFILE +WRITELN "{if(!__b2c__trap){ERROR = 11; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR); } else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"Host not found\", ", g_BUFFER_SIZE ,"-1); } else {if(__b2c__flag) {__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr);" TO g_HFILE +WRITELN "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], inet_ntoa(__b2c__addr.sin_addr), ", g_BUFFER_SIZE, "-1);} else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__he->h_name, ", g_BUFFER_SIZE, "-1);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE +WRITELN "#define HOST", g_STRINGSIGN$, "(__b2c__x) __b2c__nethost(__b2c__x)" TO g_HFILE +WRITELN "/* Regex */" TO g_HFILE +WRITELN "#include <regex.h>" TO g_HFILE +WRITELN "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);" TO g_HFILE +WRITELN "if(!__b2c__trap && __b2c__reti){ERROR=27; fprintf(stderr, \"%s: \", ERR", g_STRINGSIGN$, "(ERROR)); regerror(__b2c__reti, &__b2c__reg, __b2c__buf, sizeof(__b2c__buf)); fprintf(stderr, \"%s\\n\", __b2c__buf);" TO g_HFILE +WRITELN "exit(ERROR);} __b2c__reti = regexec(&__b2c__reg, __b2c__x, 0, NULL, 0);" TO g_HFILE +WRITELN "regfree(&__b2c__reg); if( !__b2c__reti ) return (1); else return (0);}" TO g_HFILE +WRITELN "#define REGEX(x, y) __b2c__regex(x, y)" TO g_HFILE +WRITELN "/* Declare reserved variable 'ARGUMENT' */" TO g_HFILE +WRITELN "int __b2c__counter;" TO g_HFILE +WRITELN "int __b2c__arglen = 0;" TO g_HFILE +WRITELN "char *ARGUMENT", g_STRINGSIGN$, ";" TO g_HFILE +WRITELN "/* Initialize stack arrays and pointer */" TO g_HFILE +WRITELN "char **__b2c__stringstack = NULL; double *__b2c__doublestack = NULL;" TO g_HFILE +WRITELN "long *__b2c__longstack = NULL; int *__b2c__typestack = NULL;" TO g_HFILE +WRITELN "int __b2c__stackptr = 0;" TO g_HFILE +' Signal function +WRITELN "/* Signal trapping activated with TRAP */" TO g_HFILE +WRITELN "void __b2c__catch_signal(int sig){" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "case SIGFPE: fprintf(stderr, \"ERROR: signal for FPE received - division by zero? Examine the calculations in the program.\\n\"); break;" TO g_HFILE +WRITELN "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;" TO g_HFILE +WRITELN "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);}" TO g_HFILE +' Makedir function +WRITELN "int __b2c__makedir(char* __b2c__in){char *__b2c__i, *__b2c__dir; if(__b2c__in == NULL || strlen(__b2c__in)==0) return 0; if(*__b2c__in != '/'){__b2c__dir = (char*)malloc((strlen(__b2c__in)+2)*sizeof(char));" TO g_HFILE +WRITELN "strncpy(__b2c__dir, \"./\", 2); __b2c__dir = strcat(__b2c__dir, __b2c__in);} else __b2c__dir = strdup(__b2c__in); __b2c__i = __b2c__dir; do { __b2c__i++; while(*__b2c__i != '/' && *__b2c__i != '\\0') __b2c__i++;" TO g_HFILE +WRITELN "if(*__b2c__i == '/') {*__b2c__i = '\\0'; mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); *__b2c__i = '/';} else if (*__b2c__i == '\\0') mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);" TO g_HFILE +WRITELN "if(errno != EEXIST && errno != 0) {free(__b2c__dir); return errno;} } while (*__b2c__i != '\\0'); free(__b2c__dir); return 0;}" TO g_HFILE +' Add error function +WRITELN "/* Initialize error function */" TO g_HFILE +WRITELN "char *ERR", g_STRINGSIGN$, "(int __b2c__nr){static char __b2c__warn[", g_BUFFER_SIZE, "] = { 0 }; const char* __b2c__err;" TO g_HFILE +WRITELN "switch(__b2c__nr){" TO g_HFILE +WRITELN "case 0: strcpy(__b2c__warn,\"Success\"); break;" TO g_HFILE +WRITELN "case 1: strcpy(__b2c__warn,\"Trying to access illegal memory: \"); strncat(__b2c__warn,strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 2: strcpy(__b2c__warn,\"Error opening file: \"); strncat(__b2c__warn,strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 3: strcpy(__b2c__warn, \"Could not open library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, ", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 4: strcpy(__b2c__warn, \"Symbol not found in library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, ", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 5: strcpy(__b2c__warn, \"Wrong hexvalue: \"); strncat(__b2c__warn, strerror(errno), ", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 6: strcpy(__b2c__warn, \"Unable to claim memory.\"); break;" TO g_HFILE +WRITELN "case 7: strcpy(__b2c__warn, \"Unable to delete file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 8: strcpy(__b2c__warn, \"Could not open directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 9: strcpy(__b2c__warn, \"Unable to rename file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 10: strcpy(__b2c__warn, \"NETWORK argument should contain colon with port number\"); break;" TO g_HFILE +WRITELN "case 11: strcpy(__b2c__warn, \"Could not resolve hostname!\"); break;" TO g_HFILE +WRITELN "case 12: strcpy(__b2c__warn, \"Socket error: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 13: strcpy(__b2c__warn, \"Unable to open address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 14: strcpy(__b2c__warn, \"Error reading from socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 15: strcpy(__b2c__warn, \"Error sending to socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 16: strcpy(__b2c__warn, \"Error checking socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 17: strcpy(__b2c__warn, \"Unable to bind the specified socket address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 18: strcpy(__b2c__warn, \"Unable to listen to socket address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 19: strcpy(__b2c__warn, \"Cannot accept incoming connection: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 20: strcpy(__b2c__warn, \"Unable to remove directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 21: strcpy(__b2c__warn, \"Unable to create directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 22: strcpy(__b2c__warn, \"Unable to change to directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 23: strcpy(__b2c__warn, \"GETENVIRON argument does not exist as environment variable\"); break;" TO g_HFILE +WRITELN "case 24: strcpy(__b2c__warn, \"Unable to stat file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 25: strcpy(__b2c__warn, \"Search contains illegal string\"); break;" TO g_HFILE +WRITELN "case 26: strcpy(__b2c__warn, \"Cannot return OS name: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 27: strcpy(__b2c__warn, \"Illegal regex expression\"); break;" TO g_HFILE +WRITELN "case 28: strcpy(__b2c__warn, \"Unable to create bidirectional pipes: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 29: strcpy(__b2c__warn, \"Unable to fork process: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "case 30: strcpy(__b2c__warn, \"Cannot read from pipe: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE +WRITELN "}; ERROR = 0; return(__b2c__warn);}" TO g_HFILE +WRITELN "/* User program definitions */" TO g_HFILE + +' Set fileposition for search in header file +g_HEADER_SEARCHPOS = FILELEN(g_HFILE$) + +' Initialize the arrayfiles for DATA statement +OPEN STRINGARRAYFILE$ FOR WRITING AS STRINGARRAYFILE +WRITELN "char* __b2c__stringarray[] = {" TO STRINGARRAYFILE +OPEN FLOATARRAYFILE$ FOR WRITING AS FLOATARRAYFILE +WRITELN "double __b2c__floatarray[] = {" TO FLOATARRAYFILE + +' There are no imported symbols yet +LET g_IMPORTED$ = "" + +' Check if the C Preprocessor needs to run +IF ISTRUE(g_CPP) THEN + IF ISTRUE(LEN(EXEC$("which cpp 2>/dev/null"))) THEN + SYSTEM CONCAT$("cpp -P -w ", g_SOURCEFILE$, " ", g_SOURCEFILE$, ".cpp") + FEED$ = CONCAT$(g_SOURCEFILE$, ".cpp") + g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_SOURCEFILE$, ".cpp") + ELSE + PRINT "ERROR: the C Preprocessor 'cpp' not found on this system! Exiting..." + END 1 + END IF +ELSE + FEED$ = g_SOURCEFILE$ +END IF +LET g_CURFILE$ = MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) + +' Initialize +LET total$ = "" +LET g_COUNTER = 1 + +' Read source program +OPEN FEED$ FOR READING AS g_SOURCEFILE + +WHILE NOT(ENDFILE(g_SOURCEFILE)) DO + + IF NOT(g_SHEBANG) THEN PRINT "\rStarting conversion... ", g_COUNTER, " "; + + READLN line$ FROM g_SOURCEFILE + + ' Line is not empty? + IF NOT(ENDFILE(g_SOURCEFILE)) AND LEN(line$) > 0 THEN + + IF EQUAL(RIGHT$(line$, 2), " \\") AND NOT(EQUAL(LEFT$(line$, 3), "REM")) AND NOT(EQUAL(LEFT$(line$, 1), CHR$(39))) THEN + total$ = CONCAT$(total$, LEFT$(line$, LEN(line$) - 2)) + ELSE + WRITELN "/* noparse ", FEED$, " BACON LINE ", g_COUNTER, " */" TO g_HFILE + WRITELN "/* noparse ", FEED$, " BACON LINE ", g_COUNTER, " */" TO g_CFILE + total$ = CHOP$(CONCAT$(total$, line$)) + IF NOT(EQUAL(LEFT$(total$, 3), "REM")) AND NOT(EQUAL( LEFT$(total$, 1), CHR$(39) )) THEN + Tokenize(total$) + END IF + LET total$ = "" + END IF + ENDIF + + INCR g_COUNTER +WEND + +CLOSE FILE g_SOURCEFILE + +' Check if enclosed IF/ELIF/ELSE needs to be closed +IF g_IF_PARSE IS 1 THEN WRITELN "}" TO g_CFILE + +' Finalize main C-file +WRITELN "__B2C__PROGRAM__EXIT:" TO g_CFILE +WRITELN "return 0;" TO g_CFILE +WRITELN "}" TO g_CFILE + +' Finalize STRING ARRAY file for DATA +WRITELN " \"\" };" TO STRINGARRAYFILE + +' Finalize FLOAT ARRAY file for DATA +WRITELN " 0.0};" TO FLOATARRAYFILE + +' Include functions and subs +SPLIT CHOP$(g_INCLUDE_FILES$) BY " " TO incfiles$ SIZE dim +FOR i = 1 TO dim + IF LEN(incfiles$[i]) > 0 THEN WRITELN "#include \"", incfiles$[i], CHR$(34) TO g_HFILE +NEXT + +' Close all filehandles +CLOSE FILE FLOATARRAYFILE +CLOSE FILE STRINGARRAYFILE +CLOSE FILE g_HFILE +CLOSE FILE g_CFILE + +IF NOT(g_SHEBANG) THEN PRINT "\rStarting conversion... done. " + +' Start indentation +IF ISTRUE(g_TMP_PRESERVE) THEN + IF ISTRUE(LEN(EXEC$("which indent 2>/dev/null"))) THEN + PRINT "Applying indentation... "; + SPLIT CHOP$(g_TMP_FILES$) BY " " TO tmpfiles$ SIZE dim + FOR i = 1 TO dim + IF NOT(REGEX(tmpfiles$[i], ".*\\.cpp")) THEN + IF ISTRUE(INSTR(OS$, "Darwin")) OR ISTRUE(INSTR(OS$, "BSD")) THEN + RENAME tmpfiles$[i] TO CONCAT$(tmpfiles$[i], ".BAK") + SYSTEM CONCAT$("indent ", tmpfiles$[i], ".BAK ", tmpfiles$[i]) + DELETE FILE CONCAT$(tmpfiles$[i], ".BAK") + ELSE + SYSTEM CONCAT$("indent ", tmpfiles$[i]) + DELETE FILE CONCAT$(tmpfiles$[i], "~") + END IF + END IF + NEXT i + PRINT "done." + ELSE + PRINT "WARNING: 'indent' not found on this system!" + PRINT "Generated source code cannot be beautified." + END IF +END IF + +' Check if we need to run xgettext +IF g_XGETTEXT THEN + IF ISTRUE(LEN(EXEC$("which xgettext 2>/dev/null"))) THEN + PRINT "Executing xgettext... "; + SYSTEM CONCAT$("xgettext -d ", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), " -s -o ", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), ".pot ", g_TMP_FILES$) + IF NOT(FILEEXISTS(CONCAT$(LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), ".pot"))) THEN + PRINT "WARNING: catalog file not created!" + ELSE + PRINT "done." + END IF + ELSE + PRINT "WARNING: 'xgettext' not found on this system!" + END IF +END IF + +' Start compilation +IF ISFALSE(g_NO_COMPILE) THEN + + IF ISFALSE(LEN(EXEC$(CONCAT$("which ", g_CCNAME$, " 2>/dev/null")))) THEN + PRINT "WARNING: '", g_CCNAME$, "' not found on this system!" + PRINT "Generated source code cannot be compiled." + END 0 + END IF + + ' Make sure GCC uses English localization + SETENVIRON "LANG", "C" + + IF NOT(g_SHEBANG) THEN + PRINT "Starting compilation... "; + SYSTEM CONCAT$(g_CCNAME$, " ", g_CCFLAGS$, " -o ", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4), g_BINEXT$, " ", g_CFILE$, " ", g_LDFLAGS$, " > ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log 2>&1") + ELSE + SYSTEM CONCAT$(g_CCNAME$, " ", g_CCFLAGS$, " -o ", CONCAT$(g_TEMPDIR$, "/", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4)), g_BINEXT$, " ", g_CFILE$, " ", g_LDFLAGS$, " > ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log 2>&1") + END IF + + ' Add temp file + g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log") + + IF ISFALSE(FILELEN(CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log"))) THEN + IF g_SHEBANG THEN + SYSTEM CONCAT$(g_TEMPDIR$, "/", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4)) + ELSE + PRINT "done." + PRINT "Program '", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4), g_BINEXT$, "' ready." + END IF + ELSE + ' Only print first error + PRINT "Compiler emits messages!" + OPEN CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log") FOR READING AS errlog + WHILE NOT(ENDFILE(errlog)) DO + READLN g_ERROR$ FROM errlog + IF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, "error:")) AND REGEX(g_ERROR$, "[0-9]+") AND REGEX(g_ERROR$, "\\: error\\:") THEN + g_ERRORTXT$ = CONCAT$("Cause:", NL$, TAB$(1), MID$(g_ERROR$, INSTR(g_ERROR$, "error:") + 6)) + g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTR(g_ERROR$, "error:") - 1) + BREAK + ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, "Error:")) AND REGEX(g_ERROR$, "[0-9]+") AND REGEX(g_ERROR$, "\\: Error\\:") THEN + g_ERRORTXT$ = CONCAT$("Cause:", NL$, TAB$(1), MID$(g_ERROR$, INSTRREV(g_ERROR$, ":") + 1)) + g_FILE_LINE$ = MID$(g_ERROR$, INSTR(g_ERROR$, "Error: ") + 7) + BREAK + ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, "warning:")) AND REGEX(g_ERROR$, "[0-9]+") AND REGEX(g_ERROR$, "\\: warning\\:") THEN + g_ERRORTXT$ = CONCAT$("Cause:", NL$, TAB$(1), MID$(g_ERROR$, INSTR(g_ERROR$, "warning:") + 8)) + g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTR(g_ERROR$, "warning:") - 1) + BREAK + ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, ":")) AND REGEX(g_ERROR$, "[0-9]+\\:") THEN + g_ERRORTXT$ = CONCAT$("Cause:", NL$, TAB$(1), MID$(g_ERROR$, INSTRREV(g_ERROR$, ":") + 1)) + g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTRREV(g_ERROR$, ":") - 1) + BREAK + END IF + WEND + CLOSE FILE errlog + + ' Restore $-symbol if there is any + g_ERRORTXT$ = REPLACE$(g_ERRORTXT$, g_STRINGSIGN$, "$") + + ' Get the file where the error is + g_FILE$ = MID$(g_FILE_LINE$, 1, INSTR(g_FILE_LINE$, ":") - 1) + ' Tru64Unix helper + g_FILE$ = MID$(g_FILE$, 1, INSTR(g_FILE$, ",") - 1) + + ' Non-gcc or parse problem (file does not exist) + IF ISFALSE(LEN(g_ERROR$)) OR ISTRUE(INSTR(g_CCFLAGS$, "Wall")) OR NOT(FILEEXISTS(g_FILE$)) THEN + PRINT + SYSTEM CONCAT$("cat ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log") + PRINT + ELSE + ' Get the error string from the logfile + IF INSTR(g_FILE_LINE$, "line") THEN + g_LINE = VAL(MID$(g_FILE_LINE$, INSTR(g_FILE_LINE$, "line") + 4)) + ELSE + g_LINE = VAL(MID$(g_FILE_LINE$, INSTR(g_FILE_LINE$, ":") + 1)) + END IF + ' Initiate error file name and error line in C code + g_FEED$ = MID$(g_FILE_LINE$, 1, INSTR(g_FILE_LINE$, ":")-1) + g_CURLINE$ = CONCAT$(STR$(g_LINE), " ") + g_COUNTER = 1 + OPEN g_FILE$ FOR READING AS errlog + WHILE NOT(ENDFILE(errlog)) DO + READLN line$ FROM errlog + IF INSTR(line$, "BACON LINE") AND INSTR(line$, "noparse") THEN + g_CURLINE$ = MID$(line$, INSTR(line$, "BACON LINE") + 10) + g_FEED$ = MID$(line$, INSTR(line$, "noparse") + 7) + g_FEED$ = CHOP$(MID$(g_FEED$, 1, INSTR(g_FEED$, " BACON LINE"))) + END IF + IF g_COUNTER IS g_LINE THEN + COUNTER = 1 + OPEN g_FEED$ FOR READING AS g_SOURCEFILE + WHILE NOT(ENDFILE(g_SOURCEFILE)) DO + READLN line$ FROM g_SOURCEFILE + IF COUNTER IS VAL(MID$(g_CURLINE$, 1, INSTRREV(g_CURLINE$, " "))) THEN + PRINT NL$, "Problem:", NL$, TAB$(1), " file '", g_FEED$, "' line ", COUNTER, ": ", CHOP$(line$) + PRINT g_ERRORTXT$, NL$ + BREAK + END IF + INCR COUNTER + WEND + CLOSE FILE g_SOURCEFILE + BREAK + END IF + INCR g_COUNTER + WEND + CLOSE FILE errlog + END IF + ' Preserve temp files + g_TMP_PRESERVE = 1 + END IF +END IF + +' Cleanup +IF ISFALSE(g_TMP_PRESERVE) THEN + SPLIT CHOP$(g_TMP_FILES$) BY " " TO tmpfiles$ SIZE dim + FOR i = 1 TO dim + SYSTEM CONCAT$("rm ", tmpfiles$[i]) + NEXT i +ELIF g_CPP IS 1 THEN + RENAME CONCAT$(g_SOURCEFILE$, ".cpp") TO CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".cpp") +END IF diff --git a/development/bacon/bacon.bash b/development/bacon/bacon.bash new file mode 100644 index 0000000000000..752885f63f2de --- /dev/null +++ b/development/bacon/bacon.bash @@ -0,0 +1,5351 @@ +#!/usr/bin/env bash +# ____ ____ +# | __ ) __ _ / ___|___ _ __ +# | _ \ / _` | | / _ \| '_ \ +# | |_) | (_| | |__| (_) | | | | --= A BASH BASIC-to-C converter =-- +# |____/ \__,_|\____\___/|_| |_| +# +# Peter van Eerten - March 2009/April 2011. License: GPL version 3. +# +#--------------------------------------------------------------------------------------------------------------------- +# CREDITS: +# - James C. Fuller for endless testing and patiently pointing to many issues +# - John Spikowksi for giving some hints to improve the language +# - Vovchik for providing ideas, programs and hints +# +#--------------------------------------------------------------------------------------------------------------------- +# GLOBAL INITIALIZATIONS +#--------------------------------------------------------------------------------------------------------------------- + +# Check BASH version +if [[ ${BASH_VERSINFO[0]}$((${BASH_VERSINFO[1]}+0)) -lt 32 ]] +then + echo "ERROR: this is BASH version ${BASH_VERSION}. BaCon needs BASH 3.2 or higher to run!" + exit 1 +fi + +# Set the extended globbing option in BASH +shopt -s extglob + +# Version of BACON +declare -rx g_VERSION="1.0 build 22" + +# Find 'grep' and other coretools +if [[ -z `which grep` || -z `which cat` || -z `which rm` || -z `which tr` || -z `which touch` || -z `which uname` ]] +then + echo "ERROR: 'grep', 'cat', 'rm', 'tr', 'touch' or 'uname' not found on this system!" + exit 1 +fi + +# Link flags +if [[ `uname` = "OSF1" || `uname` = +(*BSD*) ]] +then + g_LDFLAGS="-lm" +else + g_LDFLAGS="-lm -ldl" +fi + +# Solaris +if [[ `uname` = +(*SunOS*) ]] +then + g_LDFLAGS="$g_LDFLAGS -lnsl -lsocket" +fi + +# Global constant for miniparsing +declare -rx g_PARSEVAR=`echo -e "\001"` + +# Global to define '$'-replacement +declare -rx g_STRINGSIGN="__b2c__string_var" + +# Global to define '"'-symbol +declare -rx g_DQUOTESIGN=`echo -e "\042"` + +# Global to define '''-symbol +declare -rx g_SQUOTESIGN=`echo -e "\047"` + +#----------------------------------------------------------- + +function Print_Element +{ + local TARGET CHECK VAR + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + # Check on string by reference variable + VAR=`echo ${1%%\(*}` + CHECK=`grep -E "char \*${VAR} = NULL;" ${TARGET} 2>/dev/null` + + # Check if var is string var + if [[ "${1%%\(*}" = +(*${g_STRINGSIGN}*) || "${1%%\(*}" = +(*${g_DQUOTESIGN}*) || "${1%%\(*}" = +(*gettext*|*ngettext*) || -n ${CHECK} ]] + then + echo "__b2c__assign = ${1}; if(__b2c__assign != NULL) fprintf(stdout, \"%s\", __b2c__assign);" >> $g_CFILE + else + echo "fprintf(stdout, \"%s\", STR${g_STRINGSIGN}(${1}));" >> $g_CFILE + fi +} + +#----------------------------------------------------------- + +function Handle_Print +{ + local FORMAT EXP LEN TOKEN LINE IN_STRING IN_FUNC CHAR ESCAPED + + IN_FUNC=0 + + # If no argument, do nothing + if [[ "$1" != "PRINT" ]] + then + + # Get expression without ; + if [[ -z ${1##*;} ]] + then + let LEN="${#1}"-1 + EXP="${1:0:$LEN}" + else + EXP="${1}" + fi + + # If there is FORMAT/format argument + if [[ "$EXP" = +(* FORMAT *) ]] + then + FORMAT=${EXP##* FORMAT} + echo "fprintf(stdout, ${FORMAT%%;*}, ${EXP%%FORMAT *});" >> $g_CFILE + else + # Start miniparser, convert spaces + LINE=`echo "${EXP}" | tr " " "\001"` + TOKEN= + LEN=${#LINE} + + # Get the characters + until [[ $LEN -eq 0 ]] + do + CHAR="${LINE:0:1}" + case $CHAR in + ",") + if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] + then + Print_Element "${TOKEN}" + TOKEN= + CHAR= + ESCAPED=0 + fi;; + "\\") + ESCAPED=1;; + "\"") + if [[ $ESCAPED -eq 0 ]] + then + if [[ $IN_STRING -eq 0 ]] + then + IN_STRING=1 + else + IN_STRING=0 + fi + fi + ESCAPED=0;; + "(") + if [[ $IN_STRING -eq 0 ]] + then + ((IN_FUNC=$IN_FUNC+1)) + fi + ESCAPED=0;; + ")") + if [[ $IN_STRING -eq 0 ]] + then + ((IN_FUNC=$IN_FUNC-1)) + fi + ESCAPED=0;; + *) + ESCAPED=0;; + esac + # Convert back to space + if [[ "${CHAR}" = "${g_PARSEVAR}" ]] + then + TOKEN="${TOKEN} " + else + TOKEN="${TOKEN}${CHAR}" + fi + let LEN=${#LINE}-1 + LINE="${LINE: -$LEN}" + done + Print_Element "${TOKEN}" + + # If line ends with ';' then skip newline + if [[ -n ${1##*;} ]] + then + echo "fprintf(stdout, \"\n\");" >> $g_CFILE + fi + fi + else + echo "fprintf(stdout, \"\n\");" >> $g_CFILE + fi + + # Flush buffer + echo "fflush(stdout);" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Input +{ + # Local variables + local CHECK VAR TARGET STR LINE LEN IN_STRING IN_FUNC CHAR ESCAPED + + IN_FUNC=0 + + # Check if we have an argument at all + if [[ "$1" = "INPUT" ]] + then + echo -e "\nERROR: empty INPUT at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Start miniparser to see if we need to print something, convert spaces + LINE=`echo "${1}" | tr " " "\001"` + VAR= + LEN=${#LINE} + + # Get the characters + until [[ $LEN -eq 0 ]] + do + CHAR="${LINE:0:1}" + case $CHAR in + ",") + if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] + then + Print_Element "${VAR}" + VAR= + CHAR= + ESCAPED=0 + fi;; + "\\") + ESCAPED=1;; + "\"") + if [[ $ESCAPED -eq 0 ]] + then + if [[ $IN_STRING -eq 0 ]] + then + IN_STRING=1 + else + IN_STRING=0 + fi + fi + ESCAPED=0;; + "(") + if [[ $IN_STRING -eq 0 ]] + then + ((IN_FUNC=$IN_FUNC+1)) + fi + ESCAPED=0;; + ")") + if [[ $IN_STRING -eq 0 ]] + then + ((IN_FUNC=$IN_FUNC-1)) + fi + ESCAPED=0;; + *) + ESCAPED=0;; + esac + # Convert back to space + if [[ "${CHAR}" = "${g_PARSEVAR}" ]] + then + VAR="${VAR} " + else + VAR="${VAR}${CHAR}" + fi + let LEN=${#LINE}-1 + LINE="${LINE: -$LEN}" + done + + # Remove spaces in variable + VAR=`echo ${VAR}` + + # Check type of var, string? + if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] + then + if [[ ${VAR} != +(*\[*\]*) ]] + then + STR=${VAR%${g_STRINGSIGN}*} + CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` + if [[ -z $CHECK ]] + then + echo "char *$VAR = NULL;" >> $g_HFILE + fi + fi + + # Translate function to C function + echo "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\0', $g_BUFFER_SIZE);" >> $g_CFILE + echo "__b2c__assign = fgets(__b2c__input__buffer, $g_BUFFER_SIZE, stdin);" >> $g_CFILE + + # Make sure internal var is copied to var of program + echo "$VAR = (char*)realloc($VAR, ($g_BUFFER_SIZE+1)*__b2c__counter*sizeof(char));" >> $g_CFILE + echo "if(__b2c__counter == 1) strncpy($VAR, __b2c__input__buffer, $g_BUFFER_SIZE);" >> $g_CFILE + echo "else strncat($VAR, __b2c__input__buffer, $g_BUFFER_SIZE); __b2c__counter++;" >> $g_CFILE + echo "} while (!strstr(__b2c__input__buffer, \"\n\") && strlen(__b2c__input__buffer));" >> $g_CFILE + # Cut off last newline + echo "if (strlen(__b2c__input__buffer)) $VAR[strlen($VAR)-1]='\0';" >> $g_CFILE + # Var is numeric or stringarray + else + # Variable may not be array, these should be defined with DECLARE + if [[ "${VAR}" != +(*\[*\]*) && "${VAR}" != +(*.*) ]] + then + # Not declared? Assume long + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|,$VAR,|,$VAR;| $VAR=" | grep -v " noparse "` + if [[ -z $CHECK ]] + then + echo "long $VAR;" >> $g_HFILE + CHECK="long " + fi + else + CHECK=`grep -E "DIR |FILE |int |long |float |double |char |void |STRING |NUMBER |FLOATING " $TARGET | grep -E " ${VAR%%\[*}" | grep -v " noparse "` + fi + + # Translate function to C function + echo "memset(__b2c__input__buffer, '\0', $g_BUFFER_SIZE); __b2c__assign = fgets(__b2c__input__buffer, $g_BUFFER_SIZE, stdin);" >> $g_CFILE + + # Make sure internal var is copied to var of program + if [[ "$CHECK" = +(*double *) || "$CHECK" = +(*float *) || "$CHECK" = +(*FLOATING *) ]] + then + echo "$VAR = atof(__b2c__input__buffer);" >> $g_CFILE + elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*NUMBER *) ]] + then + echo "$VAR = atol(__b2c__input__buffer);" >> $g_CFILE + else + echo "$VAR = atoi(__b2c__input__buffer);" >> $g_CFILE + fi + fi +} + +#----------------------------------------------------------- + +function Handle_For +{ + # Local variables + local FROM TO TMP VAR STEP CHECK TARGET + + # Get the variablename without (surrounding) spaces + VAR=`echo "${1%%=*}" | tr -d "\040"`; TMP=`echo "${1#*=}"` + + # Do we have a STRING var? + if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] + then + echo -e "\nERROR: variable in FOR statement at line $g_COUNTER in file '$g_CURFILE' cannot be string!" + exit 1 + fi + + # Check if TO is available + if [[ "$TMP" != +(* TO *) ]] + then + echo -e "\nERROR: missing TO in FOR statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the starting and ending value + FROM=`echo "${TMP%% TO *}"` + TO=`echo "${TMP##* TO }"` + + # Check if there is a STEP + if [[ "$TO" = +(* STEP *) ]] + then + STEP="${TO##* STEP }" + TO="${TO%% STEP *}" + else + STEP=1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Variable may not be array, these should be defined with DECLARE + if [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) ]] + then + # Declare variable if not done yet, assuming long + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|,$VAR,|,$VAR;| $VAR=| ${VAR%%\[*}\[|,${VAR%%\[*}\[" | grep -v " noparse "` + if [[ -z $CHECK ]] + then + echo "long $VAR;" >> $g_HFILE + fi + fi + + # Translate function to C function + if [[ "${STEP}" = +(*-*) ]] + then + echo "for($VAR=$FROM; $VAR >= $TO; $VAR+=$STEP){" >> $g_CFILE + else + echo "for($VAR=$FROM; $VAR <= $TO; $VAR+=$STEP){" >> $g_CFILE + fi +} + +#----------------------------------------------------------- + +function Handle_While +{ + # Check if DO is available + if [[ "$1" != +(* DO) ]] + then + Parse_Equation "${1}" + else + Parse_Equation "${1% *}" + fi + echo "while(${g_EQUATION}){" >> $g_CFILE +} + +#----------------------------------------------------------- +# $1: name of ASSOC variable +# $2: name of index +# $3: actual value to assign +# $4: recursion level + +function Relate_Recurse +{ + local CTR REL LVL + + # Check endless recursion + LVL=$4; ((LVL+=1)) + if [[ $LVL -gt $g_RELATE_CTR ]] + then + echo -e "\nERROR: Endless recursion in RELATE statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Now add relation + CTR=0 + + while [[ $CTR -lt $g_RELATE_CTR ]] + do + if [[ ${g_RELATE[${CTR}]} = +(${1}*) ]] + then + REL=${g_RELATE[${CTR}]##* } + echo "if(__b2c__${REL}_exist(${2} == NULL) __b2c__${REL}__add(${2};" >> $g_CFILE + if [[ "${REL}" = +(*${g_STRINGSIGN}*) ]] + then + echo "__b2c__${REL}_exist(${2}->value = realloc(__b2c__${REL}_exist(${2}->value, (strlen($3)+1)*sizeof(char));" >> $g_CFILE + echo "strcpy(__b2c__${REL}_exist(${2}->value, $3);" >> $g_CFILE + else + echo "__b2c__${REL}_exist(${2}->value = $3;" >> $g_CFILE + fi + Relate_Recurse ${REL} ${2} ${3} ${LVL} + fi + ((CTR+=1)) + done +} + +#----------------------------------------------------------- + +function Handle_Let +{ + # Local variables + local VAR CHECK TMP TARGET LEN STR CTR REL PTR + + # Check if there is an asignment at all, if not exit + if [[ "$1" != +(*=*) ]] + then + echo -e "\nERROR: could not parse line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Get the variablename without surrounding spaces + VAR=`echo ${1%%=*}`; TMP=${1#*=} + + # Check if var is string var, exclude RECORD elements + if [[ "${VAR}" = +(*${g_STRINGSIGN}) && "$VAR" != +(*.*) ]] + then + STR=${VAR%${g_STRINGSIGN}*} + CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` + if [[ -z $CHECK && $g_PROTOTYPE != +(* ${STR}${g_STRINGSIGN}[ ,\)]*) ]] + then + echo "char *$VAR = NULL;" >> $g_HFILE + fi + # Assume number, exclude RECORD and ASSOC elements + elif [[ "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) && "$VAR" != "ERROR" && "$VAR" != +(*\(*\)*) ]] + then + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VAR,| $VAR;|\*$VAR |,$VAR,|,$VAR;| $VAR=| ${VAR%%\[*}\[|,${VAR%%\[*}\[" | grep -v " noparse "` + if [[ -z $CHECK && $g_PROTOTYPE != +(* ${VAR}[ ,\)]*) ]] + then + if [[ "$TMP" = +(*.*) && "$TMP" != +(*$g_DQUOTESIGN*) ]] + then + echo "double $VAR;" >> $g_HFILE + else + echo "long $VAR;" >> $g_HFILE + fi + fi + fi + + # Check if there is associative array assignment + if [[ "${VAR}" = +(*\(*\)) ]] + then + STR=${VAR#*\(} + echo "if(__b2c__${VAR%%\(*}_exist(${STR} == NULL) __b2c__${VAR%%\(*}__add(${STR};" >> $g_CFILE + if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) ]] + then + echo "__b2c__${VAR%%\(*}_exist(${STR}->value = realloc(__b2c__${VAR%%\(*}_exist(${STR}->value, (strlen($TMP)+1)*sizeof(char));" >> $g_CFILE + echo "strcpy(__b2c__${VAR%%\(*}_exist(${STR}->value, ${TMP});" >> $g_CFILE + else + echo "__b2c__${VAR%%\(*}_exist(${STR}->value = ${TMP};" >> $g_CFILE + fi + # Check for relations + Relate_Recurse "${VAR%%\(*}" "${STR}" "${TMP}" "-1" + + # Do we have a STRING variable or STRING array? + elif [[ "${VAR}" = +(*${g_STRINGSIGN}*) && "${VAR}" != +(*\[*${g_STRINGSIGN}*\]*) ]] + then + echo "__b2c__assign = (char*) strdup ($TMP); ${g_WITHVAR}${VAR} = (char*)realloc(${g_WITHVAR}${VAR}, (strlen(__b2c__assign)+1)*sizeof(char));" >> $g_CFILE + echo "strcpy(${g_WITHVAR}${VAR}, __b2c__assign); free(__b2c__assign);" >> $g_CFILE + # Also check if string var already is used for IMPORT, if so, perform dlopen again + PTR=`echo $VAR | tr -d [:punct:]` + CHECK=`grep -i "void\* __b2c__dlopen__pointer_$PTR;" $g_CFILE` + if [[ -n $CHECK ]] + then + echo "__b2c__dlopen__pointer_$PTR = dlopen($VAR, RTLD_LAZY);" >> $g_CFILE + fi + else + echo "${g_WITHVAR}${1};" >> $g_CFILE + fi +} + +#----------------------------------------------------------- + +function Handle_Open +{ + # Local variables + local FILE MODE HANDLE TMP CHECK TARGET LABEL + + # Check if FOR is available + if [[ "$1" != +(* FOR *) ]] + then + echo -e "\nERROR: Missing FOR in OPEN statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if AS is available + if [[ "$1" != +(* AS *) ]] + then + echo -e "\nERROR: Missing AS in OPEN statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the file, mode and handle + FILE=`echo "${1%% FOR *}"` + TMP=`echo "${1##* FOR }"` + + MODE=`echo "${TMP%% AS *}"` + HANDLE=`echo "${TMP##* AS }"` + + # Check if var is string var + if [[ "${HANDLE}" = +(*${g_STRINGSIGN}) && $MODE != "MEMORY" ]] + then + echo -e "\nERROR: Variable for OPEN at line $g_COUNTER in file '$g_CURFILE' cannot be string!" + exit 1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Check if variable was declared + if [[ "$HANDLE" != +(*.*) ]] + then + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $HANDLE,| $HANDLE;|,$HANDLE,|,$HANDLE;| $HANDLE=| ${HANDLE%%\[*}\[|,${HANDLE%%\[*}\[" | grep -v " noparse "` + fi + + # File or dir? + if [[ $MODE = "DIRECTORY" ]] + then + if [[ -z $CHECK ]] + then + echo "DIR *$HANDLE;" >> $g_HFILE + fi + elif [[ $MODE = "MEMORY" ]] + then + CHECK=`grep -E "char \*${HANDLE}" ${TARGET}` + if [[ -z $CHECK ]] + then + echo "char *$HANDLE;" >> $g_CFILE + fi + CHECK=`grep -E "long" $TARGET | grep "__b2c_mem_$HANDLE;" | grep -v " noparse "` + if [[ -z $CHECK ]] + then + echo "long __b2c_mem_$HANDLE;" >> $g_HFILE + fi + elif [[ $MODE = "NETWORK" || $MODE = "SERVER" ]] + then + if [[ -z $CHECK ]] + then + echo "int $HANDLE;" >> $g_HFILE + fi + else + if [[ -z $CHECK ]] + then + echo "FILE* $HANDLE;" >> $g_HFILE + fi + fi + + # Convert to C syntax + case $MODE in + @(READING) ) + echo "$HANDLE = fopen($FILE, \"r\");" >> $g_CFILE + echo "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; + @(WRITING) ) + echo "$HANDLE = fopen($FILE, \"w\");" >> $g_CFILE + echo "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; + @(APPENDING) ) + echo "$HANDLE = fopen($FILE, \"a\");" >> $g_CFILE + echo "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; + @(READWRITE) ) + echo "$HANDLE = fopen($FILE, \"r+\");" >> $g_CFILE + echo "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; + @(DIRECTORY) ) + echo "$HANDLE = opendir($FILE);" >> $g_CFILE + echo "if($HANDLE == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; + @(MEMORY) ) + echo "$HANDLE = (char*)$FILE; __b2c_mem_$HANDLE = $FILE;" >> $g_CFILE + echo "if(!__b2c__trap){__b2c__memory__check($HANDLE); if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; + @(NETWORK) ) + # Network code + echo "if (strstr($FILE, \":\") == NULL) {ERROR = 10; fprintf(stderr, \"ERROR: %s: '%s'\n\", ERR${g_STRINGSIGN}(ERROR), ${FILE}); exit(ERROR);}" >> $g_CFILE + echo "strncpy(__b2c__data_client, $FILE, $g_BUFFER_SIZE); __b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\"); __b2c__he = gethostbyname(__b2c__host);" >> $g_CFILE + echo "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + echo "$HANDLE = socket(PF_INET, SOCK_STREAM, 0);" >> $g_CFILE + echo "if ($HANDLE == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + echo "__b2c__to.tv_sec = $g_OPTION_SOCKET; __b2c__to.tv_usec = 0; setsockopt($HANDLE, SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" >> $g_CFILE + echo "setsockopt($HANDLE, SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int)); __b2c__addr.sin_family = AF_INET; __b2c__addr.sin_port = htons((long)atol(__b2c__port));" >> $g_CFILE + echo "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr); memset(&(__b2c__addr.sin_zero), '\0', sizeof(__b2c__addr.sin_zero));" >> $g_CFILE + echo "__b2c__result = connect($HANDLE, (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" >> $g_CFILE + echo "if(__b2c__result == -1) {if(!__b2c__trap){ERROR = 13;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE;; + @(SERVER) ) + # Network code + echo "if (strstr($FILE, \":\") == NULL) {ERROR = 10; fprintf(stderr, \"ERROR: %s: '%s'\n\", ERR${g_STRINGSIGN}(ERROR), ${FILE}); exit(ERROR);}" >> $g_CFILE + echo "if(strcmp(__b2c__data_server, $FILE)) {strncpy(__b2c__data_server, $FILE, $g_BUFFER_SIZE); __b2c__host = strtok(__b2c__data_server, \":\"); __b2c__port = strtok(NULL, \":\"); __b2c__he = gethostbyname(__b2c__host);" >> $g_CFILE + echo "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + echo "__b2c__handle = socket(AF_INET, SOCK_STREAM, 0);" >> $g_CFILE + echo "if (__b2c__handle == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + echo "__b2c__to.tv_sec = $g_OPTION_SOCKET; __b2c__to.tv_usec = 0; setsockopt(__b2c__handle, SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" >> $g_CFILE + echo "setsockopt(__b2c__handle, SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int)); __b2c__addr.sin_family = AF_INET; __b2c__addr.sin_port = htons((long)atol(__b2c__port));" >> $g_CFILE + echo "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr); memset(&(__b2c__addr.sin_zero), '\0', sizeof(__b2c__addr.sin_zero));" >> $g_CFILE + echo "__b2c__result = bind(__b2c__handle, (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" >> $g_CFILE + echo "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 17;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + echo "__b2c__result = listen(__b2c__handle, $g_MAX_BACKLOG);" >> $g_CFILE + echo "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 18;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + echo "strncpy(__b2c__data_server, $FILE, $g_BUFFER_SIZE); /* Restore data because of strtok */} __b2c__result = accept(__b2c__handle, NULL, 0);" >> $g_CFILE + echo "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 19;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + echo "$HANDLE= __b2c__result;" >> $g_CFILE;; + esac +} + +#----------------------------------------------------------- + +function Handle_Readln +{ + # Local variables + local CHECK VAR FROM TARGET STR + + # Check if FROM is available + if [[ "$1" != +(* FROM *) ]] + then + echo -e "\nERROR: Missing FROM in READLN statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the variablename without surrounding spaces + VAR=`echo ${1%% FROM *}` + + # Get filedescriptor + FROM=`echo ${1##* FROM }` + + # Check if var is string var + if [[ "${VAR}" != +(*${g_STRINGSIGN}*) ]] + then + echo -e "\nERROR: Variable for READLN at line $g_COUNTER in file '$g_CURFILE' must be string!" + exit 1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Check if variable is declared + if [[ ${VAR} != +(*\[*\]*) ]] + then + STR=${VAR%${g_STRINGSIGN}*} + CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` + if [[ -z $CHECK ]] + then + echo "char *$VAR = NULL;" >> $g_HFILE + fi + fi + + # Translate function to C function + echo "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\0', $g_BUFFER_SIZE);" >> $g_CFILE + echo "__b2c__assign = fgets(__b2c__input__buffer, $g_BUFFER_SIZE, $FROM);" >> $g_CFILE + + # Make sure internal var is copied to var of program + echo "$VAR = (char*)realloc($VAR, ($g_BUFFER_SIZE+1)*__b2c__counter*sizeof(char));" >> $g_CFILE + echo "if(__b2c__counter == 1) strncpy($VAR, __b2c__input__buffer, $g_BUFFER_SIZE);" >> $g_CFILE + echo "else strncat($VAR, __b2c__input__buffer, $g_BUFFER_SIZE); __b2c__counter++;" >> $g_CFILE + echo "} while (!strstr(__b2c__input__buffer, \"\n\") && strlen(__b2c__input__buffer));" >> $g_CFILE + # Cut off last newline + echo "if (strlen(__b2c__input__buffer)) $VAR[strlen($VAR)-1]='\0';" >> $g_CFILE + # Cut off CR if available + echo "if(strlen($VAR)>0 && $VAR[strlen($VAR)-1]=='\r') $VAR[strlen($VAR)-1]='\0';" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Writeln +{ + # Local variables + local VAR TO LINE LEN CHAR IN_STRING IN_FUNC ESCAPED + + # Check if TO is available + if [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: Missing TO in WRITELN statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get filedescriptor + TO=`echo ${1##* TO }` + + # Start miniparser to see if we need to print something, convert spaces + LINE=`echo "${1% TO *}" | tr " " "\001"` + VAR= + LEN=${#LINE} + IN_STRING=0 + + # Get the characters + until [[ $LEN -eq 0 ]] + do + CHAR="${LINE:0:1}" + case $CHAR in + ",") + if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] + then + # Check if var is string var + if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) || "${VAR%%\(*}" = +(*${g_DQUOTESIGN}*) ]] + then + echo "fprintf($TO, \"%s\", ${VAR});" >> $g_CFILE + else + echo "fprintf($TO, \"%s\", STR${g_STRINGSIGN}(${VAR}));" >> $g_CFILE + fi + VAR= + CHAR= + ESCAPED=0 + fi;; + "\\") + ESCAPED=1;; + "\"") + if [[ $ESCAPED -eq 0 ]] + then + if [[ $IN_STRING -eq 0 ]] + then + IN_STRING=1 + else + IN_STRING=0 + fi + fi + ESCAPED=0;; + "(") + if [[ $IN_STRING -eq 0 ]] + then + ((IN_FUNC=$IN_FUNC+1)) + fi + ESCAPED=0;; + ")") + if [[ $IN_STRING -eq 0 ]] + then + ((IN_FUNC=$IN_FUNC-1)) + fi + ESCAPED=0;; + *) + ESCAPED=0;; + esac + # Convert back to space + if [[ "${CHAR}" = "${g_PARSEVAR}" ]] + then + VAR="${VAR} " + else + VAR="${VAR}${CHAR}" + fi + let LEN=${#LINE}-1 + LINE="${LINE: -$LEN}" + done + + # Write last element to file + if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) || "${VAR%%\(*}" = +(*${g_DQUOTESIGN}*) ]] + then + echo "fprintf($TO, \"%s\n\", ${VAR});" >> $g_CFILE + else + echo "fprintf($TO, \"%s\n\", STR${g_STRINGSIGN}(${VAR}));" >> $g_CFILE + fi + echo "fflush($TO);" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Getbyte +{ + # Local variables + local POS FROM SIZE TARGET CHECK + + # Check if FROM is available + if [[ "$1" != +(* FROM *) ]] + then + echo -e "\nERROR: Missing FROM in GETBYTE statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the variablename without surrounding spaces + POS=`echo ${1%% FROM *}` + + # Get filedescriptor + FROM=`echo ${1##* FROM }` + + SIZE= + + # Check if SIZE is available + if [[ "$1" = +(* SIZE *) ]] + then + SIZE=${FROM##* SIZE } + FROM=${FROM%% SIZE *} + else + SIZE=1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Declare variable if not done yet, assuming long + if [[ "$POS" != +(*.*) ]] + then + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $POS,| $POS;|,$POS,|,$POS;| $POS=| ${POS%%\[*}\[|,${POS%%\[*}\[" | grep -v " noparse "` + if [[ -z $CHECK ]] + then + echo "long $POS;" >> $g_HFILE + fi + fi + + # Translate function to C function + echo "if(!__b2c__trap){__b2c__memory__check((char *)$POS); if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + echo "__b2c__counter = fread((void*)$POS, sizeof($g_OPTION_MEMTYPE), $SIZE, $FROM);" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Putbyte +{ + # Local variables + local VAR TO SIZE POS + + # Check if TO is available + if [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: Missing TO in PUTBYTE statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the variablename without surrounding spaces + POS=`echo ${1%% TO *}`; + + # Get filedescriptor + TO=`echo ${1##* TO }` + + SIZE= + + # Check if SIZE is available + if [[ "$1" = +(* SIZE *) ]] + then + SIZE=${TO##* SIZE } + TO=${TO%% SIZE *} + else + SIZE=1 + fi + + # Translate function to C function + echo "if(!__b2c__trap){__b2c__memory__check((char *)$POS); if(ERROR){if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + echo "__b2c__counter = fwrite((void*)$POS, sizeof($g_OPTION_MEMTYPE), $SIZE, $TO);" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Getfile +{ + # Local variables + local VAR FROM SIZE TARGET STR + + # Check if FROM is available + if [[ "$1" != +(* FROM *) ]] + then + echo -e "\nERROR: Missing FROM in GETFILE statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the variablename without surrounding spaces + VAR=`echo ${1%% FROM *}` + + # Get dirdescriptor + FROM=`echo ${1##* FROM }` + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Translate function to C function + echo "__b2c__dir = readdir($FROM);" >> $g_CFILE + + # Check if variable is declared + STR=${VAR%${g_STRINGSIGN}*} + CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` + if [[ -z $CHECK && "$VAR" != +(*\[*\]*) && "$VAR" != +(*.*) ]] + then + echo "char *$VAR = NULL;" >> $g_HFILE + fi + + # Always realloc VAR to correct size, maybe it was resized somewhere else + echo "if(__b2c__dir != NULL) {$VAR = realloc($VAR, (strlen(__b2c__dir->d_name)+1)*sizeof(char));" >> $g_CFILE + # Make sure internal var is copied to var of program + echo "strcpy($VAR, __b2c__dir->d_name); $VAR[strlen(__b2c__dir->d_name)] = '\0';}" >> $g_CFILE + echo "else {$VAR = realloc($VAR, sizeof(char)); $VAR[0] = '\0';}" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Receive +{ + # Local variables + local CHECK VAR FROM TARGET STR CHUNK SIZE + + # Check if FROM is available + if [[ "$1" != +(* FROM *) ]] + then + echo -e "\nERROR: Missing FROM in RECEIVE statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the variablename without surrounding spaces + VAR=`echo ${1%% FROM *}` + + # Get filedescriptor + FROM=`echo ${1##* FROM }` + + # Check for optional chunksize + if [[ $FROM = +(* CHUNK *) ]] + then + CHUNK=${FROM##* CHUNK } + FROM=${FROM%% CHUNK *} + else + CHUNK=$g_BUFFER_SIZE + SIZE= + fi + + # Check for optional return variable + if [[ $CHUNK = +(* SIZE *) ]] + then + SIZE=${CHUNK##* SIZE } + CHUNK=${CHUNK%% SIZE *} + else + SIZE= + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Variable may not be array, these should be defined with DECLARE + if [[ -n $SIZE && "$SIZE" != +(*\[*\]*) && "$SIZE" != +(*.*) ]] + 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%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` + if [[ -z $CHECK ]] + then + echo "long $SIZE;" >> $g_HFILE + fi + fi + + # Check if string variable, and if so, if declared + if [[ "${VAR}" = +(*${g_STRINGSIGN}) ]] + then + STR=${VAR%${g_STRINGSIGN}*} + CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` + if [[ -z $CHECK ]] + then + echo "char *$VAR = NULL;" >> $g_HFILE + fi + echo "$VAR = (char*)realloc($VAR, ($CHUNK+1)*sizeof(char)); memset($VAR, '\0', sizeof(char)*($CHUNK+1));" >> $g_CFILE + fi + + # Translate function to C function + if [[ -z $SIZE ]] + then + echo "if(recv($FROM, (void*)$VAR, $CHUNK, 0) < 0) {if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set)" >> $g_CFILE + echo "{fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + else + echo "if(($SIZE = recv($FROM, (void*)$VAR, $CHUNK, 0)) < 0) {if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set)" >> $g_CFILE + echo "{fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + fi +} +#----------------------------------------------------------- + +function Handle_Send +{ + # Local variables + local VAR TO CHUNK + + # Check if TO is available + if [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: Missing TO in SEND statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the variablename without surrounding spaces + VAR=`echo ${1%% TO *}`; + + # Get filedescriptor + TO=`echo ${1##* TO }` + + # Check for optional chunksize + if [[ $TO = +(* CHUNK *) ]] + then + CHUNK=${TO##* CHUNK } + TO=${TO%% CHUNK *} + else + CHUNK="strlen($VAR)" + fi + + # Translate function to C function + echo "if(send($TO, (void*)$VAR, $CHUNK, 0) < 0) {if(!__b2c__trap){ERROR = 15; if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Getline +{ + # Local variables + local CHECK VAR FROM TARGET STR + + # Check if FROM is available + if [[ "$1" != +(* FROM *) ]] + then + echo -e "\nERROR: Missing FROM in GETLINE statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the variablename without surrounding spaces + VAR=`echo ${1%% FROM *}` + + # Get filedescriptor + FROM=`echo ${1##* FROM }` + + # Check if var is string var + if [[ "${VAR}" != +(*${g_STRINGSIGN}*) ]] + then + echo -e "\nERROR: Variable for GETLINE at line $g_COUNTER in file '$g_CURFILE' must be string!" + exit 1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Check if variable is declared + if [[ ${VAR} != +(*\[*\]*) ]] + then + STR=${VAR%${g_STRINGSIGN}*} + CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` + if [[ -z $CHECK ]] + then + echo "char *$VAR = NULL;" >> $g_HFILE + fi + fi + + # Translate function to C function + echo "if ($FROM == NULL || *$FROM == '\0') {$VAR = (char*)realloc($VAR, 2*sizeof(char)); strcpy($VAR, \"\");}" >> $g_CFILE + echo "else { __b2c__assign = $FROM; while(*$FROM != '\0' && *$FROM != '\n') $FROM++;" >> $g_CFILE + + # Make sure internal var is copied to var of program + echo "$VAR = (char*)realloc($VAR, ($FROM-__b2c__assign+1)*sizeof(char));" >> $g_CFILE + echo "strncpy($VAR, __b2c__assign, $FROM-__b2c__assign);" >> $g_CFILE + + # Make sure to end the string + echo "$VAR[($FROM-__b2c__assign)] = '\0'; $FROM++;}" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Putline +{ + # Local variables + local VAR TO LINE LEN CHAR IN_STRING IN_FUNC + + # Check if TO is available + if [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: Missing TO in PUTLINE statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get memorydescriptor + TO=`echo ${1##* TO }` + + # Start miniparser to see if we need to print something, convert spaces + LINE=`echo "${1%% TO *}" | tr " " "\001"` + VAR= + LEN=${#LINE} + IN_STRING=0 + + # Get the characters + until [[ $LEN -eq 0 ]] + do + CHAR="${LINE:0:1}" + case $CHAR in + ",") + if [[ $IN_STRING -eq 0 && $IN_FUNC -eq 0 ]] + then + # Check if var is string var + if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) || "${VAR%%\(*}" = +(*${g_DQUOTESIGN}*) ]] + then + echo "strcat($TO, $VAR); $TO+=strlen($VAR);" >> $g_CFILE + else + echo "strcat($TO, STR${g_STRINGSIGN}($VAR)); $TO+=strlen(STR${g_STRINGSIGN}($VAR));" >> $g_CFILE + fi + VAR= + CHAR= + ESCAPED=0 + fi;; + "\\") + ESCAPED=1;; + "\"") + if [[ $ESCAPED -eq 0 ]] + then + if [[ $IN_STRING -eq 0 ]] + then + IN_STRING=1 + else + IN_STRING=0 + fi + fi + ESCAPED=0;; + "(") + if [[ $IN_STRING -eq 0 ]] + then + ((IN_FUNC=$IN_FUNC+1)) + fi + ESCAPED=0;; + ")") + if [[ $IN_STRING -eq 0 ]] + then + ((IN_FUNC=$IN_FUNC-1)) + fi + ESCAPED=0;; + *) + ESCAPED=0;; + esac + # Convert back to space + if [[ "${CHAR}" = "${g_PARSEVAR}" ]] + then + VAR="${VAR} " + else + VAR="${VAR}${CHAR}" + fi + let LEN=${#LINE}-1 + LINE="${LINE: -$LEN}" + done + + # Check if var is string var + if [[ "${VAR%%\(*}" = +(*${g_STRINGSIGN}*) || "${VAR%%\(*}" = +(*${g_DQUOTESIGN}*) ]] + then + echo "strcat($TO, $VAR); strcat($TO, \"\n\"); $TO+=strlen($VAR)+1;" >> $g_CFILE + else + echo "strcat($TO, STR${g_STRINGSIGN}($VAR)); strcat($TO, \"\n\"); $TO+=strlen(STR${g_STRINGSIGN}($VAR))+1;" >> $g_CFILE + fi +} + +#----------------------------------------------------------- + +function Handle_Import +{ + # Local variables + local TMP SYM LIB CHECK TOKEN PTR TYPE ALIAS + + # Check if FROM is available + if [[ "$1" != +(* FROM *) ]] + then + echo -e "\nERROR: missing FROM in IMPORT statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the symbolname without surrounding spaces and doublequotes + if [[ "$1" = +(*\(*) ]] + then + SYM=`echo ${1%%\(*} | tr -d "\042"`; TMP=${1#* FROM } + TOKEN=`echo ${1%\)*}` + else + SYM=`echo ${1%% FROM *} | tr -d "\042"`; TMP=${1#* FROM } + TOKEN= + fi + + # Check if TYPE is available + if [[ "$1" != +(* TYPE *) ]] + then + echo -e "\nERROR: missing TYPE in IMPORT statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get library and type + LIB=`echo ${TMP%% TYPE *}` + TYPE=`echo ${TMP##* TYPE }` + + # Check if ALIAS is there + if [[ $TYPE = +(* ALIAS *) ]] + then + ALIAS=`echo ${TYPE##* ALIAS } | tr -d "\042"` + echo "#define $ALIAS $SYM" >> $g_HFILE + g_IMPORTED="$ALIAS $g_IMPORTED" + TYPE=${TYPE%% ALIAS *} + fi + + # If library is libm or libc, skip dlopen as we're linking with those anyway + if [[ $LIB != +(*libc.so*) && $LIB != +(*libm.so*) ]] + then + # Create name from libname + PTR=`echo $LIB | tr -d [:punct:]` + + # Check if variable was declared + CHECK=`grep -i "void\* __b2c__dlopen__pointer_$PTR;" $g_CFILE` + if [[ -z $CHECK ]] + then + echo "void* __b2c__dlopen__pointer_$PTR;" >> $g_CFILE + echo "__b2c__dlopen__pointer_$PTR = dlopen($LIB, RTLD_LAZY);" >> $g_CFILE + fi + echo "if(__b2c__dlopen__pointer_$PTR == NULL){if(!__b2c__trap){ERROR = 3;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + + # Check if token was declared + CHECK=`grep -i "$TYPE (\*$SYM)" $g_HFILE` + if [[ -z $CHECK ]] + then + echo "$TYPE (*$SYM)(${TOKEN#*\(});" >> $g_HFILE + fi + + # Translate to C function + echo "*($TYPE **) (&$SYM) = dlsym(__b2c__dlopen__pointer_$PTR, \"$SYM\");" >> $g_CFILE + echo "if($SYM == NULL) {if(!__b2c__trap){ERROR = 4;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + fi + + # Make symbol known to parser + g_IMPORTED="$SYM $g_IMPORTED" +} + +#----------------------------------------------------------- + +function Handle_Declare +{ + # Local variables + local VAR TYPE CHECK NEW VALUE OPTION + + # Check on a GLOBAL RECORD + if [[ "$1" = +(*RECORD *) ]] + then + # Translate to C typedef struct + g_RECORDNAME="RECORD_${g_COUNTER}" + echo "struct $g_RECORDNAME{" >> $g_HFILE + g_RECORDVAR=${1#* } + # Store current function name + if [[ -n $g_FUNCNAME ]] + then + g_RECORDCACHE=$g_FUNCNAME + g_FUNCNAME= + fi + else + # Get the variablename and type + if [[ "$1" = +(* TYPE *) ]] + then + VAR=`echo ${1%% TYPE *} | tr -d " "` + TYPE=`echo ${1##* TYPE }` + elif [[ "$1" = +(* ASSOC *) ]] + then + VAR=`echo ${1%% ASSOC *} | tr -d " "` + TYPE=`echo ${1##* ASSOC }` + else + VAR=`echo ${1} | tr -d " "` + TYPE="long" + fi + + # Check if variable was already declared + if [[ "$VAR" != +(*.*) ]] + then + VALUE=${VAR%%\[*} + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $g_HFILE | grep -E " $VALUE,| $VALUE;|,$VALUE,|,$VALUE;| $VALUE=| $VALUE\[|,$VALUE\[" | grep -v " noparse "` + fi + + if [[ -n $CHECK ]] + then + echo -e "\nERROR: variable in DECLARE or GLOBAL statement at line $g_COUNTER in file '$g_CURFILE' was defined previously!" + exit 1 + fi + + # If array, increase dimensions when OPTION BASE is set + if [[ $VAR = +(*\[*\]*) && $VAR != +(*=*) ]] + then + NEW= + while [[ ${VAR} = +(*\[*\]*) ]] + do + NEW="$NEW${VAR%%\[*}[" + VALUE=${VAR#*\[} + NEW="$NEW${VALUE%%\]*}+$g_OPTION_BASE]" + VAR=${VAR#*\]} + done + VAR="${NEW}" + fi + + # Check for associative array + if [[ "${1}" = +(* ASSOC *) ]] + then + VAR=`echo "$VAR" | tr "," " "` + for i in $VAR + do + echo "struct __b2c__${i}_type {char *key; /* noparse */ ${TYPE} value; /* noparse */ };" >> $g_HFILE + echo "struct __b2c__${i}_type *__b2c__${i} = { NULL }; long __b2c__${i}_idx = 0;" >> $g_HFILE + + echo "static int __b2c__${i}_comp(const void *__b2c__m1, const void *__b2c__m2){ " >> $g_HFILE + echo "struct __b2c__${i}_type *__b2c__mi1 = (struct __b2c__${i}_type *) __b2c__m1;" >> $g_HFILE + echo "struct __b2c__${i}_type *__b2c__mi2 = (struct __b2c__${i}_type *) __b2c__m2;" >> $g_HFILE + echo "if(__b2c__mi1->key == NULL && __b2c__mi2->key == NULL) return 0;" >> $g_HFILE + echo "if(__b2c__mi1->key == NULL && __b2c__mi2->key != NULL) return -1;" >> $g_HFILE + echo "if(__b2c__mi1->key != NULL && __b2c__mi2->key == NULL) return 1;" >> $g_HFILE + echo "return strcmp(__b2c__mi1->key, __b2c__mi2->key); }" >> $g_HFILE + + echo "struct __b2c__${i}_type * __b2c__${i}_exist(char *__b2c__index){struct __b2c__${i}_type __b2c__${i}_key, *__b2c__${i}__result;" >> $g_HFILE + echo "qsort(__b2c__${i}, __b2c__${i}_idx, sizeof(struct __b2c__${i}_type), __b2c__${i}_comp);" >> $g_HFILE + echo "__b2c__${i}_key.key = __b2c__index; __b2c__${i}__result = bsearch(&__b2c__${i}_key, __b2c__${i}," >> $g_HFILE + echo "__b2c__${i}_idx, sizeof(struct __b2c__${i}_type), __b2c__${i}_comp);" >> $g_HFILE + echo "return(__b2c__${i}__result); }" >> $g_HFILE + + echo "void __b2c__${i}__add(char *__b2c__index){__b2c__${i}_idx++;" >> $g_HFILE + echo "__b2c__${i} = (struct __b2c__${i}_type *) realloc (__b2c__${i}, __b2c__${i}_idx * sizeof (struct __b2c__${i}_type));" >> $g_HFILE + echo "__b2c__${i}[__b2c__${i}_idx - 1].key = strdup (__b2c__index); __b2c__${i}[__b2c__${i}_idx-1].value = 0;}" >> $g_HFILE + + echo "void __b2c__${i}__del(char *__b2c__index){struct __b2c__${i}_type *__b2c__${i}__location = __b2c__${i}_exist(__b2c__index);" >> $g_HFILE + echo "if(__b2c__${i}__location != NULL) {free(__b2c__${i}__location->key); __b2c__${i}__location->key = NULL; } }" >> $g_HFILE + + echo "${TYPE} ${i}(char *__b2c__index){struct __b2c__${i}_type __b2c__${i}_key, *__b2c__${i}__result;" >> $g_HFILE + echo "qsort(__b2c__${i}, __b2c__${i}_idx, sizeof(struct __b2c__${i}_type), __b2c__${i}_comp);" >> $g_HFILE + echo "__b2c__${i}_key.key = __b2c__index; __b2c__${i}__result = bsearch(&__b2c__${i}_key, __b2c__${i}," >> $g_HFILE + echo "__b2c__${i}_idx, sizeof(struct __b2c__${i}_type), __b2c__${i}_comp);" >> $g_HFILE + if [[ ${i} = +(*${g_STRINGSIGN}*) || ${TYPE} = +(*STRING*) || ${TYPE} = +(*char\**) ]] + then + echo "if(__b2c__${i}__result == NULL) return(\"\"); return __b2c__${i}__result->value;}" >> $g_HFILE + else + echo "if(__b2c__${i}__result == NULL) return(0); return __b2c__${i}__result->value;}" >> $g_HFILE + fi + done + + # Check if var is string var + elif [[ ( "${VAR}" = +(*${g_STRINGSIGN}*) || "${TYPE}" = +(*STRING*|*char\**) ) && "${VAR}" != +(*=*) ]] + then + CHECK=`grep -E "char \*${STR} = NULL;" $g_HFILE` + if [[ -z $CHECK ]] + then + STR=`echo ${VAR} | tr ',' ' '` + for i in $STR + do + if [[ "${i}" = +(*\[*\]*) ]] + then + echo "char *$i = { NULL };" >> $g_HFILE + else + echo "char *$i = NULL;" >> $g_HFILE + # Pointer var should not be initialized + if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] + then + echo "$i = calloc(1, sizeof(char));" >> $g_CFILE + fi + fi + done + fi + # Var is string array assignment + elif [[ ( "${VAR}" = +(*${g_STRINGSIGN}*) || "${TYPE}" = +(*STRING*|*char\**) ) && "${VAR}" = +(*=*) ]] + then + echo "char* ${VAR%%\{*} {" >> $g_HFILE + OPTION=$g_OPTION_BASE + while [[ ${OPTION} -gt 0 ]] + do + echo " \"\", " >> $g_HFILE + ((OPTION-=1)) + done + echo "${VAR#*\{};" >> $g_HFILE + # Assume char assignment or number + else + if [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]] + then + VAR=`echo ${VAR} | tr "," " "` + for i in $VAR + do + echo "$TYPE $i = { 0 };" >> $g_HFILE + done + elif [[ "$VAR" = +(*\[*\]*) && "$VAR" = +(*=*) ]] + then + echo "$TYPE ${VAR%%\{*} {" >> $g_HFILE + OPTION=$g_OPTION_BASE + while [[ ${OPTION} -gt 0 ]] + do + echo " 0, " >> $g_HFILE + ((OPTION-=1)) + done + echo "${VAR#*\{};" >> $g_HFILE + elif [[ "$VAR" != +(*=*) && "$VAR" != +(*\(*\)*) && "${TYPE}" = +(*char*|*short*|*int*|*long*|*double*|*float*|*NUMBER*|*FLOATING*) ]] + then + echo "$TYPE $VAR;" >> $g_HFILE + echo "$VAR = 0;" | tr "," "=" >> $g_CFILE + else + echo "$TYPE $VAR;" >> $g_HFILE + fi + fi + fi +} + +#----------------------------------------------------------- + +function Handle_Local +{ + # Local variables + local VAR TYPE CHECK TARGET DIM NEW VALUE i OPTION + + # Get the variablename and type + if [[ "$1" = +(* TYPE *) ]] + then + VAR=`echo ${1%% TYPE *} | tr -d " "` + TYPE=`echo ${1##* TYPE }` + else + VAR=`echo ${1} | tr -d " "` + if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] + then + TYPE="char*" + else + TYPE="long" + fi + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET=$g_CFILE + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Check if variable was already declared + if [[ "$VAR" != +(*.*) ]] + then + VALUE=${VAR%%\[*} + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $VALUE,| $VALUE;|,$VALUE,|,$VALUE;| $VALUE=| $VALUE\[|,$VALUE\[" | grep -v " noparse "` + fi + + if [[ -n $CHECK ]] + then + echo -e "\nERROR: variable in LOCAL statement at line $g_COUNTER in file '$g_CURFILE' was defined previously!" + exit 1 + fi + + # If array, increase dimensions when OPTION BASE is set + if [[ $VAR = +(*\[*\]*) && $VAR != +(*=*) ]] + then + NEW= + while [[ ${VAR} = +(*\[*\]*) ]] + do + NEW="$NEW${VAR%%\[*}[" + VALUE=${VAR#*\[} + NEW="$NEW${VALUE%%\]*}+$g_OPTION_BASE]" + VAR=${VAR#*\]} + done + VAR="${NEW}" + fi + + # Check if var is string var + if [[ ( "${TYPE}" = +(*STRING*|*char\*) || "${VAR}" = +(*${g_STRINGSIGN}*) ) && "${VAR}" != +(*=*) && "${VAR}" != +(*\[*${g_STRINGSIGN}*\]*) ]] + then + STR=${VAR%${g_STRINGSIGN}*} + CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = " ${TARGET}` + if [[ -z $CHECK ]] + then + STR=`echo ${VAR} | tr ',' ' '` + for i in $STR + do + # Check on multidimensional stringarrays + if [[ "${i}" = +(*\[*\]*\]*) ]] + then + echo -e "\nERROR: multidimensional stringarrays at line $g_COUNTER in file '$g_CURFILE' are not supported!" + exit 1 + fi + # Are we in a function? + if [[ -n $g_FUNCNAME ]] + then + if [[ -n $g_RECORDNAME ]] + then + if [[ "${i}" = +(*\[*\]*) ]] + then + echo "char *$i;" >> $g_CFILE + DIM=${i##*\[}; DIM=${DIM%%\]*} + g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++)if($g_RECORDVAR.${i%%\[*}[__b2c__ctr]!=NULL){free($g_RECORDVAR.${i%%\[*}[__b2c__ctr]);}" + else + echo "char *$i; /* noparse */" >> $g_CFILE + fi + else + if [[ "${i}" = +(*\[*\]*) ]] + then + echo "char *$i = { NULL };" >> $g_CFILE + DIM=${i##*\[}; DIM=${DIM%%\]*} + g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<$DIM; __b2c__ctr++)if(${g_WITHVAR}${i%%\[*}[__b2c__ctr]!=NULL){free(${g_WITHVAR}${i%%\[*}[__b2c__ctr]);}" + else + echo "char *$i = NULL;" >> $g_CFILE + # Pointer var should not be initialized + if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] + then + echo "$i = calloc(1, sizeof(char));" >> $g_CFILE + g_LOCALSTRINGS="$g_LOCALSTRINGS ${i}" + fi + fi + fi + # We are in the mainprogram + else + if [[ -n $g_RECORDNAME ]] + then + echo "char *$i; /* noparse */" >> $g_HFILE + else + if [[ "${i}" = +(*\[*\]*) ]] + then + echo "char *$i = { NULL };" >> $g_CFILE + else + echo "char *$i = NULL;" >> $g_HFILE + # Pointer var should not be initialized + if [[ "${VAR}" = +(*${g_STRINGSIGN}*) ]] + then + echo "$i = calloc(1, sizeof(char));" >> $g_CFILE + fi + fi + fi + fi + done + fi + elif [[ ( "${VAR}" = +(*${g_STRINGSIGN}*) || "${TYPE}" = +(*STRING*|*char\**) ) && "${VAR}" = +(*=*) ]] + then + if [[ -n $g_FUNCNAME ]] + then + # String array assignment + echo "char* ${VAR%%\{*} {" >> $g_CFILE + OPTION=$g_OPTION_BASE + while [[ ${OPTION} -gt 0 ]] + do + echo " \"\", " >> $g_CFILE + ((OPTION-=1)) + done + echo "${VAR#*\{};" >> $g_CFILE + else + # String array assignment + echo "char* ${VAR%%\{*} {" >> $g_HFILE + OPTION=$g_OPTION_BASE + while [[ ${OPTION} -gt 0 ]] + do + echo " \"\", " >> $g_HFILE + ((OPTION-=1)) + done + echo "${VAR#*\{};" >> $g_HFILE + fi + # Assume number + else + if [[ -n $g_FUNCNAME ]] + then + if [[ -n $g_RECORDNAME ]] + then + echo "$TYPE $VAR; /* noparse */" >> $g_CFILE + else + if [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]] + then + VAR=`echo ${VAR} | tr "," " "` + for i in $VAR + do + echo "$TYPE $i = { 0 };" >> $g_CFILE + done + elif [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]] + then + # Numeric array assignment + echo "$TYPE ${VAR%%\{*} {" >> $g_CFILE + OPTION=$g_OPTION_BASE + while [[ ${OPTION} -gt 0 ]] + do + echo " 0, " >> $g_CFILE + ((OPTION-=1)) + done + echo "${VAR#*\{};" >> $g_CFILE + elif [[ "$VAR" != +(*=*) && "$VAR" != +(*\(*\)*) && "${TYPE}" = +(*char*|*short*|*int*|*long*|*double*|*float*|*NUMBER*|*FLOATING*) ]] + then + echo "$TYPE $VAR;" >> $g_CFILE + echo "$VAR = 0;" | tr "," "=" >> $g_CFILE + else + echo "$TYPE $VAR;" >> $g_CFILE + fi + fi + else + if [[ -n $g_RECORDNAME ]] + then + echo "$TYPE $VAR; /* noparse */" >> $g_HFILE + else + if [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]] + then + VAR=`echo ${VAR} | tr "," " "` + for i in $VAR + do + echo "$TYPE $i = { 0 };" >> $g_HFILE + done + elif [[ "$VAR" = +(*\[*\]*) && "$VAR" != +(*=*) ]] + then + # Numeric array assignment + echo "$TYPE ${VAR%%\{*} {" >> $g_HFILE + OPTION=$g_OPTION_BASE + while [[ ${OPTION} -gt 0 ]] + do + echo " 0, " >> $g_HFILE + ((OPTION-=1)) + done + echo "${VAR#*\{};" >> $g_HFILE + elif [[ "$VAR" != +(*=*) && "$VAR" != +(*\(*\)*) && "${TYPE}" = +(*char*|*short*|*int*|*long*|*double*|*float*|*NUMBER*|*FLOATING*) ]] + then + echo "$TYPE $VAR;" >> $g_HFILE + echo "$VAR = 0;" | tr "," "=" >> $g_CFILE + else + echo "$TYPE $VAR;" >> $g_HFILE + fi + fi + fi + fi +} + +#----------------------------------------------------------- + +function Handle_Read +{ + # Local variables + local CHECK TARGET STR + + # Check if we have an argument at all + if [[ "$1" = "READ" ]] + then + echo -e "\nERROR: empty READ at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Check type of var, string? + if [[ "${1}" = +(*${g_STRINGSIGN}) ]] + then + STR=${1%${g_STRINGSIGN}*} + CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` + if [[ -z $CHECK ]] + then + echo "char *$1 = NULL;" >> $g_HFILE + fi + # Convert to C + echo "$1 = (char*)realloc($1, (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" >> $g_CFILE + echo "strcpy($1, __b2c__stringarray[__b2c__stringarray_ptr]);" >> $g_CFILE + echo "__b2c__stringarray_ptr++;" >> $g_CFILE + else + # Variable may not be array, these should be defined with DECLARE + if [[ "$1" != +(*\[*\]*) && "$1" != +(*.*) ]] + then + # Not declared? Assume long + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $1,| $1;|,$1,|,$1;| $1=| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v " noparse "` + if [[ -z $CHECK ]] + then + echo "long $1;" >> $g_HFILE + CHECK="long " + fi + else + # See how var was declared + CHECK=`grep -E "DIR |FILE |int |long |float |double |char |void |STRING |NUMBER |FLOATING " $TARGET | grep -E " ${1%%\[*}" | grep -v " noparse "` + fi + # Convert to C + if [[ "$CHECK" = +(*double *) || "$CHECK" = +(*FLOATING *) ]] + then + echo "${1} = __b2c__floatarray[__b2c__floatarray_ptr];" >> $g_CFILE + echo "__b2c__floatarray_ptr++;" >> $g_CFILE + elif [[ "$CHECK" = +(*float *) ]] + then + echo "${1} = (float)__b2c__floatarray[__b2c__floatarray_ptr];" >> $g_CFILE + echo "__b2c__floatarray_ptr++;" >> $g_CFILE + elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*NUMBER *) ]] + then + echo "${1} = (long)__b2c__floatarray[__b2c__floatarray_ptr];" >> $g_CFILE + echo "__b2c__floatarray_ptr++;" >> $g_CFILE + elif [[ "$CHECK" = +(*int *) ]] + then + echo "${1} = (int)__b2c__floatarray[__b2c__floatarray_ptr];" >> $g_CFILE + echo "__b2c__floatarray_ptr++;" >> $g_CFILE + else + echo "${1} = (char*)realloc($1, (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" >> $g_CFILE + echo "strcpy(${1}, __b2c__stringarray[__b2c__stringarray_ptr]);" >> $g_CFILE + echo "__b2c__stringarray_ptr++;" >> $g_CFILE + fi + fi +} + +#----------------------------------------------------------- + +function Handle_Endfunction +{ + # Check if return was found + if [[ -z $g_FUNCTYPE ]] + then + echo -e "\nERROR: function '$g_FUNCNAME' was defined without returning a value or string!" + exit 1 + fi + + # Put prototype to header file + echo "$g_FUNCTYPE ${g_PROTOTYPE}; /* noparse */" >> $g_HFILE + g_PROTOTYPE= + + # Now setup function in main program + echo "/* Created with BASH BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + echo "/* noparse $g_CURFILE BACON LINE $g_COUNTER */" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + if [[ $g_ORIGFUNCNAME != +(*\(*\)*) ]] + then + echo "$g_FUNCTYPE $g_ORIGFUNCNAME(void) {" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + else + echo "$g_FUNCTYPE $g_ORIGFUNCNAME {" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + fi + + # Add function body + echo "${g_STRINGARGS}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + cat $g_CFILE >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + echo "__B2C__PROGRAM__EXIT: ;" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + + # Make sure the function always returns something + if [[ $g_FUNCTYPE = +(*char\**) ]] + then + echo "return (\"\");}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + else + echo "return (0);}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + fi + + # Include header file + if [[ ${g_INCLUDE_FILES} != +(*${g_CURFILE%.*}.$g_FUNCNAME.h*) ]] + then + g_INCLUDE_FILES="$g_INCLUDE_FILES ${g_CURFILE%.*}.$g_FUNCNAME.h" + fi + + # Add to total filelist + g_TMP_FILES="$g_TMP_FILES ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h" + + # Delete temp funcfile + rm $g_CFILE + + # Restore mainfile + g_CFILE=$g_COPY_CFILE + + # Restore CATCH routine + g_CATCHGOTO="$g_ORIGCATCHGOTO" + + # Clear function variables + g_ORIGFUNCNAME= + g_FUNCNAME= + g_FUNCTYPE= + g_LOCALSTRINGS= + g_STRINGARRAYS= + g_STRINGARGS= +} + +#----------------------------------------------------------- + +function Handle_Return +{ + # Local variables + local CHECK STR DQ FUNC ARG + + # Check if we have an argument at all + if [[ "$1" = "RETURN" ]] + then + echo -e "\nERROR: empty RETURN at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $g_CFILE | grep -E " $1,| $1;|,$1,|,$1;| $1=| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v " noparse "` + + # Determine if argument ends with Double Quote + DQ="${1: -1}" + FUNC="${1:0:3}" + + # Check type of var, func using string but returning a value? See also PRINT miniparser + if [[ ${FUNC} = "INS" || ${FUNC} = "VAL" || ${FUNC} = "LEN" || ${FUNC} = "SEA" || ${FUNC} = "ASC" || "${1}" = +(FILE*) || "${1}" = +(REGEX*) ]] + then + g_FUNCTYPE="double " + ARG="${1}" + + # Check type of var, string or normal string? + elif [[ "${1}" = +(*${g_STRINGSIGN}*) || "${DQ}" = +(${g_DQUOTESIGN}) || ${g_FUNCNAME} = +(*${g_STRINGSIGN}*) ]] + then + g_FUNCTYPE="char* " + echo "__b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= $g_MAX_RBUFFERS) __b2c__rbuffer_ptr=0; if($1 != NULL)" >> $g_CFILE + echo " {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen($1)+1)*sizeof(char));" >> $g_CFILE + echo "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], $1);}" >> $g_CFILE + echo "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], 2*sizeof(char));" >> $g_CFILE + echo "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], \"\");}" >> $g_CFILE + ARG="__b2c__rbuffer[__b2c__rbuffer_ptr]" + + # Check if float + elif [[ "$1" = +(*.*) ]] + then + g_FUNCTYPE="double " + ARG="${1}" + + # Check if no alpha chars (then integer value) + elif [[ "$1" = +([0-9]) ]] + then + g_FUNCTYPE="long " + ARG="${1}" + + # Assume variable, check if declared before + elif [[ -n $CHECK ]] + then + case $CHECK in + +(*DIR *) ) + g_FUNCTYPE="DIR* ";; + +(*FILE *) ) + g_FUNCTYPE="FILE* ";; + +(*int\* *) ) + g_FUNCTYPE="int* ";; + +(*float\* *) ) + g_FUNCTYPE="float* ";; + +(*double\* *) ) + g_FUNCTYPE="double* ";; + +(*char\* *|*STRING *) ) + g_FUNCTYPE="char* ";; + +(*long\* *) ) + g_FUNCTYPE="long* ";; + +(*void\* *) ) + g_FUNCTYPE="void* ";; + +(*int *) ) + g_FUNCTYPE="int ";; + +(*float *) ) + g_FUNCTYPE="float ";; + +(*double *|*FLOATING *) ) + g_FUNCTYPE="double ";; + +(*char *) ) + g_FUNCTYPE="char ";; + +(*long *|*NUMBER *) ) + g_FUNCTYPE="long ";; + +(*void *) ) + g_FUNCTYPE="void ";; + esac + ARG="${1}" + + # Not declared, assume integer variable + else + g_FUNCTYPE="long " + ARG="${1}" + fi + + # Free strings variables if there are any + for STR in $g_LOCALSTRINGS + do + echo "if($STR != NULL) free($STR);" >> $g_CFILE + done + echo "${g_STRINGARRAYS}" >> $g_CFILE + + # The actual return value + echo "return (${ARG});" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Push +{ + # Local variables + local CHECK TARGET + + # Check if we have an argument at all + if [[ "$1" = "PUSH" ]] + then + echo -e "\nERROR: empty PUSH at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + if [[ "$VAR" != +(*.*) ]] + then + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $1,| $1;|,$1,|,$1;| $1=| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v " noparse "` + fi + + # Allocate space for type + echo "__b2c__typestack = (int*)realloc(__b2c__typestack, (__b2c__stackptr+1)*sizeof(int));" >> $g_CFILE + + # Check type of var, string? + if [[ "${1}" = +(*${g_STRINGSIGN}*) ]] + then + echo "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" >> $g_CFILE + echo "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen($1)+1)*sizeof(char));" >> $g_CFILE + echo "strcpy(__b2c__stringstack[__b2c__stackptr], $1);} else __b2c__stringstack[__b2c__stackptr] = strdup($1);" >> $g_CFILE + echo "__b2c__typestack[__b2c__stackptr] = 1;" >> $g_CFILE + # Check if it is a normal string + elif [[ "${1}" = +(*${g_DQUOTESIGN}*) ]] + then + echo "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" >> $g_CFILE + echo "if(__b2c__stackptr == 0){__b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen($1)+1)*sizeof(char));" >> $g_CFILE + echo "strcpy(__b2c__stringstack[__b2c__stackptr], $1);} else __b2c__stringstack[__b2c__stackptr] = strdup($1);" >> $g_CFILE + echo "__b2c__typestack[__b2c__stackptr] = 1;" >> $g_CFILE + # Check if float + elif [[ "$1" = +(*.*) ]] + then + echo "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" >> $g_CFILE + echo "__b2c__doublestack[__b2c__stackptr] = $1;" >> $g_CFILE + echo "__b2c__typestack[__b2c__stackptr] = 2;" >> $g_CFILE + # Check if no alpha chars (then integer value) + elif [[ "$1" = +(![a-zA-Z]) ]] + then + echo "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE + echo "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE + echo "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE + # Assume variable, check if declared before + elif [[ -n $CHECK ]] + then + if [[ $CHECK = +(double*) ]] + then + echo "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" >> $g_CFILE + echo "__b2c__doublestack[__b2c__stackptr] = $1;" >> $g_CFILE + echo "__b2c__typestack[__b2c__stackptr] = 2;" >> $g_CFILE + else + echo "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE + echo "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE + echo "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE + fi + # Not declared, assume integer variable + else + echo "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" >> $g_CFILE + echo "__b2c__longstack[__b2c__stackptr] = $1;" >> $g_CFILE + echo "__b2c__typestack[__b2c__stackptr] = 3;" >> $g_CFILE + fi + + # Increase stackpointer + echo "__b2c__stackptr++;" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Pull +{ + local CHECK TARGET STR + + # Check if we have an argument at all + if [[ "$1" = "PULL" ]] + then + echo -e "\nERROR: empty PULL at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Argument must be a variable + if [[ "$1" = +(![a-zA-Z]) ]] + then + echo -e "\nERROR: argument in PULL statement at line $g_COUNTER in file '$g_CURFILE' is not a variable!" + exit 1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Decrease stackpointer again + echo "__b2c__stackptr--;" >> $g_CFILE + echo "if(__b2c__stackptr < 0) __b2c__stackptr=0;" >> $g_CFILE + + # Get the last value from stack + if [[ "${1}" = +(*${g_STRINGSIGN}) ]] + then + STR=${1%${g_STRINGSIGN}*} + CHECK=`grep -E "char \*${STR}${g_STRINGSIGN} = NULL;" ${TARGET}` + if [[ -z $CHECK ]] + then + echo "char *$1 = NULL;" >> $g_HFILE + fi + echo "if(__b2c__typestack[__b2c__stackptr] == 1) {" >> $g_CFILE + echo "$1 = (char*)realloc($1, (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" >> $g_CFILE + echo "strcpy($1, __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" >> $g_CFILE + else + # Variable may not be array, these should be defined with DECLARE + if [[ "$1" != +(*\[*\]*) && "$VAR" != +(*.*) ]] + then + # Not declared? Assume long + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $1,| $1;|,$1,|,$1;| $1=| ${1%%\[*}\[|,${1%%\[*}\[" | grep -v " noparse "` + if [[ -z $CHECK ]] + then + echo "long $1;" >> $g_HFILE + CHECK="long " + fi + else + # See how var was declared + CHECK=`grep -E "DIR |FILE |int |long |float |double |char |void |STRING |NUMBER |FLOATING " $TARGET | grep -E " ${1%%\[*}" | grep -v " noparse "` + fi + # Make sure internal var is copied to var of program + if [[ "$CHECK" = +(*double *) || "$CHECK" = +(*float *) || "$CHECK" = +(*FLOATING *) ]] + then + echo "if(__b2c__typestack[__b2c__stackptr] == 2) $1=__b2c__doublestack[__b2c__stackptr];" >> $g_CFILE + elif [[ "$CHECK" = +(*long *) || "$CHECK" = +(*int *) || "$CHECK" = +(*NUMBER *) ]] + then + echo "if(__b2c__typestack[__b2c__stackptr] == 3) $1=__b2c__longstack[__b2c__stackptr];" >> $g_CFILE + else + echo "if(__b2c__typestack[__b2c__stackptr] == 1) {" >> $g_CFILE + echo "$1 = (char*)realloc($1, (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" >> $g_CFILE + echo "strcpy($1, __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" >> $g_CFILE + fi + fi +} + +#----------------------------------------------------------- + +function Handle_SubFunc +{ + local ARGS TOKEN LEN CHAR DIM ARR CHECK SIZE + + # Check argument + if [[ "${1}" = "SUB" ]] + then + echo -e "\nERROR: empty SUB/FUNCTION at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if we are in a sub already + if [[ -n $g_FUNCNAME ]] + then + echo -e "\nERROR: cannot define a SUB/FUNCTION within a SUB/FUNCTION at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the funcname + g_ORIGFUNCNAME=`echo ${1%%\(*}"("` + g_PROTOTYPE=`echo ${1%%\(*}"("` + + # Start miniparser to duplicate string arguments, convert spaces + ARGS=`echo "${1##*\(}" | tr " " "\001"` + TOKEN= + LEN=${#ARGS} + + # Get the characters + until [[ $LEN -eq 0 ]] + do + CHAR="${ARGS:0:1}" + if [[ $CHAR = "," ]] + then + if [[ ${TOKEN} = +(*STRING*) || ${TOKEN} = +(*char\**) ]] + then + TOKEN=`echo ${TOKEN}` + DIM=${TOKEN##*\[}; ARR=${TOKEN##* } + if [[ $TOKEN != +(*${g_STRINGSIGN}*) && $TOKEN = +(*\[*\]*) ]] + then + g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE]," + g_STRINGARGS="$g_STRINGARGS char** ${ARR%%\[*} = __b2c_${ARR%%\[*};" + g_PROTOTYPE="$g_PROTOTYPE ${TOKEN}," + elif [[ $TOKEN != +(*${g_STRINGSIGN}*) ]] + then + g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${TOKEN##* }," + g_STRINGARGS="$g_STRINGARGS char* ${TOKEN##* } = __b2c_${TOKEN##* };" + g_PROTOTYPE="$g_PROTOTYPE ${TOKEN}," + elif [[ $TOKEN = +(*\[*\]*) ]] + then + g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE]," + if [[ -z ${DIM%%\]*} ]] + then + echo -e "\nERROR: cannot pass string array without dimension at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + g_STRINGARGS="$g_STRINGARGS char *${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE] = { NULL };" + g_STRINGARGS="$g_STRINGARGS for(__b2c__ctr=0; __b2c__ctr<${DIM%%\]*}+$g_OPTION_BASE; __b2c__ctr++){if(__b2c_${ARR%%\[*}[__b2c__ctr]!=NULL) ${ARR%%\[*}[__b2c__ctr] = strdup(__b2c_${ARR%%\[*}[__b2c__ctr]);}" + g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<${DIM%%\]*}+$g_OPTION_BASE; __b2c__ctr++)if(${ARR%%\[*}[__b2c__ctr]!=NULL){free(${ARR%%\[*}[__b2c__ctr]);}" + g_PROTOTYPE="$g_PROTOTYPE char *__b2c_${TOKEN##* }," + else + g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${TOKEN##* }," + g_STRINGARGS="$g_STRINGARGS char *${TOKEN##* } = strdup(__b2c_${TOKEN##* });" + g_LOCALSTRINGS="$g_LOCALSTRINGS ${TOKEN##* }" + g_PROTOTYPE="$g_PROTOTYPE ${TOKEN}," + fi + else + TOKEN=`echo ${TOKEN}` + if [[ $TOKEN = +(*\[*\]*\]*) ]] + then + echo -e "\nERROR: cannot pass multidimensional numeric array at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + elif [[ $TOKEN = +(*\[\]*) ]] + then + g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN}," + elif [[ $TOKEN = +(*\[*\]*) ]] + then + DIM=${TOKEN##*\[}; ARR=${TOKEN##* } + g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN%% *} __b2c_${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE]," + if [[ -z ${DIM%%\]*} ]] + then + echo -e "\nERROR: cannot pass numeric array without dimension at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + g_STRINGARGS="$g_STRINGARGS ${TOKEN%% *} ${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE] = { 0 };" + g_STRINGARGS="$g_STRINGARGS for(__b2c__ctr=0; __b2c__ctr<${DIM%%\]*}+$g_OPTION_BASE; __b2c__ctr++){ ${ARR%%\[*}[__b2c__ctr] = __b2c_${ARR%%\[*}[__b2c__ctr];}" + elif [[ $TOKEN = +(*VAR *) ]] + then + echo -e "\nERROR: variable argument list cannot be followed by other arguments at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN}," + fi + g_PROTOTYPE="$g_PROTOTYPE ${TOKEN}," + fi + TOKEN= + CHAR= + fi + # Convert back to space + if [[ "${CHAR}" = "${g_PARSEVAR}" ]] + then + TOKEN="${TOKEN} " + else + TOKEN="${TOKEN}${CHAR}" + fi + let LEN=${#ARGS}-1 + ARGS="${ARGS: -$LEN}" + done + + # Last token in the sequence of arguments + TOKEN=${TOKEN%%\)*} + TOKEN=`echo ${TOKEN}` + if [[ ${TOKEN} = +(*STRING*) || ${TOKEN} = +(*char\**) ]] + then + DIM=${TOKEN##*\[}; ARR=${TOKEN##* } + if [[ $TOKEN != +(*${g_STRINGSIGN}*) && $TOKEN = +(*\[*\]*) ]] + then + g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE])" + g_STRINGARGS="$g_STRINGARGS char** ${ARR%%\[*} = __b2c_${ARR%%\[*};" + g_PROTOTYPE="$g_PROTOTYPE ${TOKEN})" + elif [[ $TOKEN != +(*${g_STRINGSIGN}*) ]] + then + g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${TOKEN##* })" + g_STRINGARGS="$g_STRINGARGS char* ${TOKEN##* } = __b2c_${TOKEN##* };" + g_PROTOTYPE="$g_PROTOTYPE ${TOKEN})" + elif [[ $TOKEN = +(*\[*\]*) ]] + then + g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE])" + if [[ -z ${DIM%%\]*} ]] + then + echo -e "\nERROR: cannot pass string array without dimension at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + g_STRINGARGS="$g_STRINGARGS char *${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE] = { NULL };" + g_STRINGARGS="$g_STRINGARGS for(__b2c__ctr=0; __b2c__ctr<${DIM%%\]*}+$g_OPTION_BASE; __b2c__ctr++){if(__b2c_${ARR%%\[*}[__b2c__ctr]!=NULL) ${ARR%%\[*}[__b2c__ctr] = strdup(__b2c_${ARR%%\[*}[__b2c__ctr]);}" + g_STRINGARRAYS="$g_STRINGARRAYS for(__b2c__ctr=0; __b2c__ctr<${DIM%%\]*}+$g_OPTION_BASE; __b2c__ctr++)if(${ARR%%\[*}[__b2c__ctr]!=NULL){free(${ARR%%\[*}[__b2c__ctr]);}" + g_PROTOTYPE="$g_PROTOTYPE char *__b2c_${TOKEN##* })" + else + g_ORIGFUNCNAME="$g_ORIGFUNCNAME char *__b2c_${TOKEN##* })" + g_STRINGARGS="$g_STRINGARGS char *${TOKEN##* } = strdup(__b2c_${TOKEN##* });" + g_LOCALSTRINGS="$g_LOCALSTRINGS ${TOKEN##* }" + g_PROTOTYPE="$g_PROTOTYPE ${TOKEN})" + fi + else + if [[ -z ${TOKEN} || ${TOKEN} = ${1} ]] + then + TOKEN="void" + fi + if [[ $TOKEN = +(*\[*\]*\]*) ]] + then + echo -e "\nERROR: cannot pass multidimensional numeric array at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + elif [[ $TOKEN = +(*\[\]*) ]] + then + g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN})" + elif [[ $TOKEN = +(*\[*\]*) ]] + then + DIM=${TOKEN##*\[}; ARR=${TOKEN##* } + g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN%% *} __b2c_${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE])" + if [[ -z ${DIM%%\]*} ]] + then + echo -e "\nERROR: cannot pass numeric array without dimension at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + g_STRINGARGS="$g_STRINGARGS ${TOKEN%% *} ${ARR%%\[*}[${DIM%%\]*}+$g_OPTION_BASE] = { 0 };" + g_STRINGARGS="$g_STRINGARGS for(__b2c__ctr=0; __b2c__ctr<${DIM%%\]*}+$g_OPTION_BASE; __b2c__ctr++){ ${ARR%%\[*}[__b2c__ctr] = __b2c_${ARR%%\[*}[__b2c__ctr];}" + elif [[ $TOKEN = +(*VAR *) ]] + then + if [[ $g_PROTOTYPE = +(*,*) ]] + then + echo -e "\nERROR: variable argument list cannot be preceded by other arguments at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + if [[ "${TOKEN}" != +(* SIZE *) ]] + then + echo -e "\nERROR: variable argument list lacks SIZE argument at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + ARR=${TOKEN#* }; ARR=${ARR%%SIZE *}; SIZE=${TOKEN##* } + if [[ "${ARR}" != +(*${g_STRINGSIGN}*) ]] + then + echo -e "\nERROR: variable argument list is not string 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_HFILE | grep -E " $SIZE,| $SIZE;|,$SIZE,|,$SIZE;| $SIZE=| ${SIZE%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` + if [[ -z $CHECK ]] + then + g_STRINGARGS="$g_STRINGARGS long ${SIZE};" + fi + g_STRINGARGS="$g_STRINGARGS long __b2c__var_$ARR = $g_OPTION_BASE; va_list __b2c__ap; char **${ARR} = NULL; char* __b2c__va = NULL; $ARR = (char **)realloc($ARR, (__b2c__var_$ARR+1) * sizeof(char*));" + g_STRINGARGS="$g_STRINGARGS va_start(__b2c__ap, __b2c__name); ${ARR}[__b2c__var_$ARR] = strdup(__b2c__name); while (${ARR}[__b2c__var_$ARR] != NULL) {__b2c__var_$ARR++; $ARR = (char **)realloc($ARR, (__b2c__var_$ARR+1) * sizeof(char*));" + g_STRINGARGS="$g_STRINGARGS __b2c__va = va_arg(__b2c__ap, char*); if(__b2c__va!=NULL) ${ARR}[__b2c__var_$ARR] = strdup(__b2c__va); else ${ARR}[__b2c__var_$ARR] = NULL; }" + g_STRINGARGS="$g_STRINGARGS va_end(__b2c__ap); ${SIZE} = __b2c__var_$ARR - $g_OPTION_BASE; if(__b2c__var_$ARR > 0) __b2c__var_$ARR--;" + g_PROTOTYPE="__${g_PROTOTYPE}" + g_ORIGFUNCNAME="${g_ORIGFUNCNAME}char *__b2c__name, ...)" + TOKEN="char*, ..." + g_STRINGARRAYS="$g_STRINGARRAYS if($ARR != NULL) {for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr<=__b2c__var_$ARR; __b2c__ctr++) if($ARR[__b2c__ctr]!=NULL){free($ARR[__b2c__ctr]);} free($ARR);}" + else + g_ORIGFUNCNAME="$g_ORIGFUNCNAME ${TOKEN})" + fi + g_PROTOTYPE="$g_PROTOTYPE ${TOKEN})" + fi + + # Get original function name + if [[ "$g_ORIGFUNCNAME" = +(* \(*\)*) ]] + then + g_FUNCNAME=`echo ${g_ORIGFUNCNAME%% *}` + elif [[ "$g_ORIGFUNCNAME" = +(*\(*\)*) ]] + then + g_FUNCNAME=`echo ${g_ORIGFUNCNAME%%\(*}` + else + g_FUNCNAME=`echo $g_ORIGFUNCNAME` + fi + + # Add macro in case of VAR argument + if [[ $TOKEN = +(* ...*) ]] + then + echo "#define ${g_FUNCNAME}(...) __${g_FUNCNAME}(\"${g_FUNCNAME}\", __VA_ARGS__, NULL)" >> $g_HFILE + g_ORIGFUNCNAME="__${g_ORIGFUNCNAME}" + fi + + # Make symbol known to parser + g_IMPORTED="$g_FUNCNAME $g_IMPORTED" + + # 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 + + # Put prototype to header file + echo "void ${g_PROTOTYPE}; /* noparse */" >> $g_HFILE + g_PROTOTYPE= + + # Get original function name + echo "/* Created with BASH BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + echo "/* noparse $g_CURFILE BACON LINE $g_COUNTER */" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + if [[ "$g_ORIGFUNCNAME" = +(* \(*\)*) ]] + then + echo "void ${g_ORIGFUNCNAME} {" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + elif [[ "$g_ORIGFUNCNAME" = +(*\(*\)*) ]] + then + echo "void ${g_ORIGFUNCNAME} {" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + else + echo "void ${g_FUNCNAME}(void) {" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + fi + + # Finalize sub + echo "${g_STRINGARGS}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + cat $g_CFILE >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + + # Free strings variables if there are any + for STR in $g_LOCALSTRINGS + do + echo "if($STR != NULL) free(${STR});" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + done + echo "${g_STRINGARRAYS}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + echo "__B2C__PROGRAM__EXIT: ;" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + echo "}" >> ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h + + # Include header file + if [[ ${g_INCLUDE_FILES} != +(*${g_CURFILE%.*}.$g_FUNCNAME.h*) ]] + then + g_INCLUDE_FILES="$g_INCLUDE_FILES ${g_CURFILE%.*}.$g_FUNCNAME.h" + fi + + # Add to total filelist + g_TMP_FILES="$g_TMP_FILES ${g_TEMPDIR}/${g_CURFILE%.*}.$g_FUNCNAME.h" + + # Delete temp funcfile + rm $g_CFILE + + # Restore mainfile + g_CFILE=$g_COPY_CFILE + + # Restore CATCH routine + g_CATCHGOTO="$g_ORIGCATCHGOTO" + + # Reset variables + g_ORIGFUNCNAME= + g_FUNCNAME= + g_LOCALSTRINGS= + g_STRINGARRAYS= + g_STRINGARGS= +} + +#----------------------------------------------------------- + +function Handle_Deffn +{ + local SYM + + # Check if we have an argument at all + if [[ "$1" = "DEF" ]] + then + echo -e "\nERROR: empty DEF FN at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Translate to C macro + SYM=${1#* } + + echo "#define ${SYM%%=*} (${SYM#*=})" >> $g_HFILE + + # Make symbol known to parser + g_IMPORTED="${SYM%%\(*} $g_IMPORTED" +} + +#----------------------------------------------------------- + +function Handle_Const +{ + # Check if we have an argument at all + if [[ "$1" = "CONST" ]] + then + echo -e "\nERROR: empty CONST at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + echo "#define ${1%%=*} (${1#*=})" >> $g_HFILE +} + +#----------------------------------------------------------- + +function Handle_Seek +{ + local FILE OFFSET WHENCE + + # Check if we have an argument at all + if [[ "$1" = "SEEK" ]] + then + echo -e "\nERROR: empty SEEK at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if TO is available + if [[ "$1" != +(* OFFSET *) ]] + then + echo -e "\nERROR: Missing OFFSET in SEEK statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the variablename without surrounding spaces + FILE=`echo ${1%% OFFSET *}`; + + # Get filedescriptor + OFFSET=`echo ${1##* OFFSET }` + + WHENCE= + + # Check if WHENCE is available + if [[ "$1" = +(* WHENCE *) ]] + then + WHENCE=${OFFSET##* WHENCE } + OFFSET=${OFFSET%% WHENCE *} + fi + + # Convert to C function + case $WHENCE in + +(START) ) + echo "fseek($FILE, $OFFSET, SEEK_SET);" >> $g_CFILE;; + +(CURRENT) ) + echo "fseek($FILE, $OFFSET, SEEK_CUR);" >> $g_CFILE;; + +(END) ) + echo "fseek($FILE, $OFFSET, SEEK_END);" >> $g_CFILE;; + *) + echo "fseek($FILE, $OFFSET, SEEK_SET);" >> $g_CFILE;; + esac +} + +#----------------------------------------------------------- + +function Handle_Copy +{ + local FROM TO + + # Check if we have an argument at all + if [[ "$1" = "COPY" ]] + then + echo -e "\nERROR: empty COPY at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if TO is available + if [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: Missing TO in COPY statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the filename and copyname + FROM=`echo ${1%% TO *}` + TO=`echo ${1##* TO }` + + #translate to C function + echo "__b2c__inFile = fopen($FROM, \"r\"); __b2c__outFile = fopen($TO, \"w\"); __b2c__Byte = 0;" >> $g_CFILE + echo "if (__b2c__inFile != NULL && __b2c__outFile != NULL){while(__b2c__Byte!=EOF){" >> $g_CFILE + echo "__b2c__Byte=fgetc(__b2c__inFile); if(__b2c__Byte!=EOF){" >> $g_CFILE + echo "fputc(__b2c__Byte,__b2c__outFile); }}" >> $g_CFILE + echo "fclose(__b2c__inFile); fclose(__b2c__outFile);}" >> $g_CFILE + echo "else {if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Rename +{ + local FROM TO + + # Check if we have an argument at all + if [[ "$1" = "RENAME" ]] + then + echo -e "\nERROR: empty RENAME at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if TO is available + if [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: Missing TO in RENAME statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the filename and copyname + FROM=`echo ${1%% TO *}` + TO=`echo ${1##* TO }` + + # Translate to C function + echo "if(rename($FROM, $TO) < 0) {if(!__b2c__trap){ERROR = 9; if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Color +{ + local TO FROM BFG COL + + # Check if we have an argument at all + if [[ "$1" = "COLOR" ]] + then + echo -e "\nERROR: empty COLOR at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if we need to reset + if [[ "$1" = +(*RESET*) ]] + then + echo "fprintf(stdout,\"\033[0m\");" >> $g_CFILE + elif [[ "$1" = +(*INTENSE*) ]] + then + echo "fprintf(stdout,\"\033[1m\");" >> $g_CFILE + elif [[ "$1" = +(*INVERSE*) ]] + then + echo "fprintf(stdout,\"\033[7m\");" >> $g_CFILE + elif [[ "$1" = +(*NORMAL*) ]] + then + echo "fprintf(stdout,\"\033[22m\");" >> $g_CFILE + # Check if TO is available + elif [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: Missing TO in COLOR statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + # Get the target and colorname + FROM=`echo ${1%% TO *}` + case $FROM in + FG) + BFG=3;; + BG) + BFG=4;; + [01]) + ((BFG=${FROM}+3));; + *) + BFG=${FROM};; + esac + + TO=`echo ${1##* TO }` + case $TO in + BLACK) + COL=0;; + RED) + COL=1;; + GREEN) + COL=2;; + YELLOW) + COL=3;; + BLUE) + COL=4;; + MAGENTA) + COL=5;; + CYAN) + COL=6;; + WHITE) + COL=7;; + *) + COL=${TO};; + esac + + # Now select color + echo "fprintf(stdout,\"\033[%ld%ldm\", (long)${BFG}, (long)${COL});" >> $g_CFILE + fi +} + +#----------------------------------------------------------- + +function Handle_Gotoxy +{ + local X Y + + # Check if we have an argument at all + if [[ "$1" = "GOTOXY" ]] + then + echo -e "\nERROR: empty GOTOXY at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the target and colorname + if [[ "$1" = +(*,*) ]] + then + X=`echo ${1%%,*}` + Y=`echo ${1##*,}` + else + echo -e "\nERROR: missing coordinate in GOTOXY at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Translate to C + echo "fprintf(stdout, \"\033[%ld;%ldH\",(long)(${Y}),(long)(${X}));fflush(stdout);" >> $g_CFILE +} + +#----------------------------------------------------------- + +function Handle_Split +{ + local SOURCE REST BY TO SIZE TARGET CHECK + + # Check if we have an argument at all + if [[ "$1" = "SPLIT" ]] + then + echo -e "\nERROR: empty SPLIT at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if BY is available + if [[ "$1" != +(* BY *) ]] + then + echo -e "\nERROR: Missing BY in SPLIT statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if TO is available + if [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: Missing TO in SPLIT statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if SIZE is available + if [[ "$1" != +(* SIZE *) ]] + then + echo -e "\nERROR: Missing SIZE in SPLIT statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the source string + SOURCE=`echo ${1%% BY *}` + REST=`echo ${1##* BY }` + + BY=`echo ${REST%% TO *}` + REST=`echo ${REST##* TO }` + + TO=`echo ${REST%% SIZE *}` + SIZE=`echo ${REST##* SIZE }` + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Variable may not be array, these should be defined with DECLARE + if [[ "$SIZE" != +(*\[*\]*) && "$SIZE" != +(*.*) ]] + then + # Declare variable if not done yet, assuming long + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " $SIZE,| $SIZE;|,$SIZE,|,$SIZE;| $SIZE=| ${SIZE%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` + if [[ -z $CHECK ]] + then + echo "long $SIZE;" >> $g_HFILE + fi + fi + + # Translate to C code + if [[ -n $g_FUNCNAME ]] + then + if [[ $g_STRINGARGS != +(*\*\*$TO*) ]] + then + g_STRINGARGS="$g_STRINGARGS char **$TO = NULL; int __b2c__split__$TO = $g_OPTION_BASE;" + fi + else + if [[ -z `grep "$TO = NULL;" $g_HFILE` ]] + then + echo "char **$TO = NULL; int __b2c__split__$TO = $g_OPTION_BASE;" >> $g_HFILE + fi + fi + + # If the split array was used before in a loop, clear it + echo "if($TO != NULL) {for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr <= __b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr]!=NULL)" >> $g_CFILE + echo "{free($TO[__b2c__ctr]);} free($TO); $TO = NULL;} __b2c__split__$TO = $g_OPTION_BASE;" >> $g_CFILE + + # Run the SPLIT code + echo "if ($SOURCE != NULL && strlen($SOURCE) > 0 && $BY != NULL && strlen($BY) > 0) {__b2c__split_tmp = strdup($SOURCE); __b2c__split_ptr = __b2c__split_tmp; while((__b2c__split = strstr(__b2c__split_tmp, $BY)) != NULL)" >> $g_CFILE + echo "{if(__b2c__split-__b2c__split_tmp >= 0) {$TO = (char **)realloc($TO, (__b2c__split__$TO + 1) * sizeof(char*)); if(__b2c__split-__b2c__split_tmp == 0){ $TO[__b2c__split__$TO] = calloc(1, sizeof(char)); if(__b2c__collapse == 0) __b2c__split__$TO++;" >> $g_CFILE + echo "else free($TO[__b2c__split__$TO]);} else $TO[__b2c__split__$TO++] = __b2c__strndup(__b2c__split_tmp, __b2c__split-__b2c__split_tmp);}" >> $g_CFILE + echo "__b2c__split_tmp = __b2c__split + strlen($BY);} if(strlen(__b2c__split_tmp) >= 0) {$TO = (char **)realloc($TO, (__b2c__split__$TO + 1) * sizeof(char*)); if(strlen(__b2c__split_tmp) == 0)" >> $g_CFILE + echo "{$TO[__b2c__split__$TO] = calloc(1, sizeof(char)); if (__b2c__collapse == 0) __b2c__split__$TO++; else free($TO[__b2c__split__$TO]);}" >> $g_CFILE + echo "else $TO[__b2c__split__$TO++] = strdup(__b2c__split_tmp);} free(__b2c__split_ptr);} $SIZE = __b2c__split__$TO - $g_OPTION_BASE; if(__b2c__split__$TO > 0) __b2c__split__$TO--;" >> $g_CFILE + + # Add declared array to array list if we are in a function + if [[ -n $g_FUNCNAME && $g_STRINGARRAYS != +(*$TO\[*) ]] + then + g_STRINGARRAYS="$g_STRINGARRAYS if($TO != NULL) {for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr<=__b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr]!=NULL){free($TO[__b2c__ctr]);} free($TO);}" + fi +} + +#----------------------------------------------------------- + +function Handle_Sort +{ + local STR CHECK DIM TARGET TYPE VAR DOWN + + # Check if we have an argument at all + if [[ "$1" = "SORT" ]] + then + echo -e "\nERROR: empty SORT at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + # Check on SIZE argument + if [[ ${1} = +(* SIZE *) ]] + then + DIM=${1##* SIZE } + VAR=${1%% SIZE *} + else + VAR=${1} + fi + + # Check on DOWN argument + if [[ ${1} = +(* DOWN*) ]] + then + DIM=${DIM%% DOWN} + VAR=${VAR%% DOWN} + DOWN="_down" + else + DOWN= + fi + + # Declared before? + if [[ "${VAR}" = +(*${g_STRINGSIGN}) ]] + then + STR=${VAR%${g_STRINGSIGN}*} + CHECK=`grep -E "char \*${STR}${g_STRINGSIGN}\[" ${TARGET}` + else + CHECK=`grep -E "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING" $TARGET | grep -E " ${VAR}" | grep -v " noparse "` + fi + + # Verify if the array was declared at SPLIT + if [[ -z ${CHECK} ]] + then + CHECK=`grep -E "__b2c__split__${STR}${g_STRINGSIGN}" $TARGET` + if [[ -z ${CHECK} ]] + then + echo -e "\nERROR: argument to SORT not an array at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + elif [[ -z $DIM ]] + then + DIM="__b2c__split__${VAR}+1" + fi + elif [[ -z $DIM ]] + then + DIM=${CHECK##*\[}; DIM=${DIM%%\]*} + fi + + # Check if we have a string + if [[ "${VAR}" = +(*${g_STRINGSIGN}) ]] + then + echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-$g_OPTION_BASE, sizeof(char*), __b2c__sortstr$DOWN);" >> $g_CFILE + # It is a value + else + TYPE=${CHECK% *} + if [[ $TYPE = +(*double*) || $TYPE = +(*FLOATING*) ]] + then + echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-$g_OPTION_BASE, sizeof(double), __b2c__sortnrd$DOWN);" >> $g_CFILE + elif [[ $TYPE = +(*float*) ]] + then + echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-$g_OPTION_BASE, sizeof(float), __b2c__sortnrf$DOWN);" >> $g_CFILE + elif [[ $TYPE = +(*long*) || $TYPE = +(*NUMBER*) ]] + then + echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-$g_OPTION_BASE, sizeof(long), __b2c__sortnrl$DOWN);" >> $g_CFILE + else + echo "qsort(&$VAR[$g_OPTION_BASE], ${DIM}-$g_OPTION_BASE, sizeof(int), __b2c__sortnri$DOWN);" >> $g_CFILE + fi + fi +} + +#----------------------------------------------------------- + +function Handle_Alias +{ + local ORG NEW + + # Check if we have an argument at all + if [[ "$1" = "ALIAS" ]] + then + echo -e "\nERROR: empty ALIAS at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if TO is available + if [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: missing TO in ALIAS statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the source string + ORG=`echo ${1%% TO *} | tr -d "\042"` + NEW=`echo ${1##* TO } | tr -d "\042"` + + echo "#define $NEW $ORG" >> $g_HFILE + g_IMPORTED="$NEW $g_IMPORTED" +} + +#----------------------------------------------------------- + +function Handle_Lookup +{ + local SOURCE REST TO SIZE TARGET CHECK + + # Check if we have an argument at all + if [[ "$1" = "LOOKUP" ]] + then + echo -e "\nERROR: empty LOOKUP at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if TO is available + if [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: Missing TO in LOOKUP statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if SIZE is available + if [[ "$1" != +(* SIZE *) ]] + then + echo -e "\nERROR: Missing SIZE in LOOKUP statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the source string + SOURCE=`echo ${1%% TO *}` + REST=`echo ${1##* TO }` + + TO=`echo ${REST%% SIZE *}` + SIZE=`echo ${REST##* SIZE }` + + # 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%%\[*}\[|,${SIZE%%\[*}\[" | grep -v " noparse "` + if [[ -z $CHECK ]] + then + echo "long $SIZE;" >> $g_HFILE + fi + fi + + # Translate to C code + if [[ -n $g_FUNCNAME ]] + then + if [[ $g_STRINGARGS != +(*\*\*$TO*) ]] + then + g_STRINGARGS="$g_STRINGARGS char **$TO = NULL; int __b2c__split__$TO = $g_OPTION_BASE;" + fi + else + if [[ -z `grep "$TO = NULL;" $g_HFILE` ]] + then + echo "char **$TO = NULL; int __b2c__split__$TO = $g_OPTION_BASE;" >> $g_HFILE + fi + fi + + # If the split array was used before in a loop, clear it + echo "if($TO != NULL) {for(__b2c__ctr=$g_OPTION_BASE; __b2c__ctr <= __b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr] != NULL)" >> $g_CFILE + echo "{free($TO[__b2c__ctr]);} free($TO); $TO = NULL;} __b2c__split__$TO = $g_OPTION_BASE;" >> $g_CFILE + + # Run the LOOKUP code + echo "for(__b2c__ctr = $g_OPTION_BASE; __b2c__ctr < __b2c__${SOURCE}_idx + $g_OPTION_BASE; __b2c__ctr++)" >> $g_CFILE + echo "{$TO = (char **)realloc($TO, (__b2c__split__$TO + 1) * sizeof(char*));" >> $g_CFILE + echo "$TO[__b2c__split__$TO++] = strdup(__b2c__${SOURCE}[__b2c__ctr-$g_OPTION_BASE].key);} $SIZE = __b2c__split__$TO - $g_OPTION_BASE; if(__b2c__split__$TO > 0) __b2c__split__$TO--;" >> $g_CFILE + + # Add declared array to array list if we are in a function + if [[ -n $g_FUNCNAME && $g_STRINGARRAYS != +(*$TO\[*) ]] + then + g_STRINGARRAYS="$g_STRINGARRAYS if($TO != NULL) {for(__b2c__ctr = $g_OPTION_BASE; __b2c__ctr <= __b2c__split__$TO; __b2c__ctr++) if($TO[__b2c__ctr]!=NULL){free($TO[__b2c__ctr]);} free($TO);}" + fi +} + +#----------------------------------------------------------- + +function Handle_Relate +{ + local SOURCE TO TARGET CHECK STR + + # Check if we have an argument at all + if [[ "$1" = "RELATE" ]] + then + echo -e "\nERROR: empty RELATE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Check if TO is available + if [[ "$1" != +(* TO *) ]] + then + echo -e "\nERROR: Missing TO in RELATE statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Get the source string + SOURCE=`echo ${1%% TO *}` + TO=`echo ${1##* TO } | tr "," " "` + + # Determine target + if [[ -n $g_FUNCNAME ]] + then + TARGET="$g_CFILE $g_HFILE" + else + TARGET=$g_HFILE + fi + + touch $TARGET + + # Check if variable is declared as ASSOC + CHECK=`grep -E "__b2c__${SOURCE}_type" $TARGET` + if [[ -z $CHECK ]] + then + echo -e "\nERROR: Variable '$SOURCE' not declared as ASSOC in RELATE statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Assign relations + for STR in ${TO} + do + CHECK=`grep -E "__b2c__${STR}_type" $TARGET` + if [[ -z $CHECK ]] + then + echo -e "\nERROR: Variable '$STR' not declared as ASSOC in RELATE statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + g_RELATE[${g_RELATE_CTR}]="$SOURCE ${STR}" + ((g_RELATE_CTR+=1)) + done +} + +#----------------------------------------------------------- + +function Handle_Data +{ + local LINE VAR LEN IN_STRING CHAR ESCAPED + + # Check if we have an argument at all + if [[ "$1" = "DATA" ]] + then + echo -e "\nERROR: empty DATA at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + + # Start miniparser to see if we need to print something, convert spaces + LINE=`echo "${1}" | tr " " "\001"` + VAR= + LEN=${#LINE} + IN_STRING=0 + + # Get the characters + until [[ $LEN -eq 0 ]] + do + CHAR="${LINE:0:1}" + case $CHAR in + ",") + if [[ $IN_STRING -eq 0 ]] + then + # Check if var is string var + if [[ "${VAR}" = +(*${g_DQUOTESIGN}*) ]] + then + echo "${VAR}, " >> $STRINGARRAYFILE + else + echo "${VAR}, " >> $FLOATARRAYFILE + fi + 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;; + *) + ESCAPED=0;; + esac + # Convert back to space + if [[ "${CHAR}" = "${g_PARSEVAR}" ]] + then + VAR="${VAR} " + else + VAR="${VAR}${CHAR}" + fi + let LEN=${#LINE}-1 + LINE="${LINE: -$LEN}" + done + + # Write last element to file + if [[ "${VAR}" = +(*${g_DQUOTESIGN}*) ]] + then + echo "${VAR}, " >> $STRINGARRAYFILE + else + echo "${VAR}, " >> $FLOATARRAYFILE + fi +} + +#----------------------------------------------------------- +# +# Simple parser to tokenize line. +# +# Each line should begin with a statement. +# The rest of the line may contain functions, these are +# converted using C macros. +# +#----------------------------------------------------------- + +function Parse_Line +{ + local FOUND SYM INC COPY_COUNTER COPY_CURFILE STATEMENT + local LEN SEQ TOTAL EXP LINE TO_PARSE + + # Get statement without spaces + STATEMENT=`echo "${1%% *}"` + + # Check if enclosed IF/ELIF/ELSE needs to be closed + if [[ $g_IF_PARSE -eq 1 ]] + then + if [[ "${STATEMENT}" != +(ELIF*) && "${STATEMENT}" != +(ELSE*) ]] + then + echo "}" >> $g_CFILE + g_IF_PARSE=0 + fi + fi + + # In TRACE MODE show linenr and code + if [[ $g_TRACE -eq 1 && ${1} != +(*FUNCTION *) && ${1} != +(*SUB *) ]] + then + echo "if(__b2c__getch() == 27) exit(EXIT_SUCCESS); /* noparse */" >> $g_CFILE + LINE=`echo "${1}" | tr "\042" "\047"` + echo "fprintf(stderr, \"${g_CURFILE} %d: ${LINE}\n\", $g_COUNTER); /* noparse */" >> $g_CFILE + fi + + # See if we need to pass C code + if [[ $g_USE_C -eq 1 ]] + then + if [[ "${STATEMENT}" = "END" || "${STATEMENT}" = "ENDUSEC" ]] + then + let g_USE_C=0 + else + echo "${1}" >> $g_CFILE + fi + else + case "${STATEMENT}" in + "USEC") + let g_USE_C=1;; + "PRINT") + Handle_Print "${1#* }";; + "INPUT") + Handle_Input "${1#* }";; + "FOR") + ((g_LOOPCTR+=1)) + Handle_For "${1#* }";; + "NEXT") + echo "}" >> $g_CFILE + if [[ $g_LOOPCTR -gt 0 ]] + then + ((g_LOOPCTR-=1)) + if [[ $g_LOOPCTR -gt 0 ]] + then + echo "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" >> $g_CFILE + fi + fi;; + "IF") + g_IF_PARSE=0 + # Check if THEN is available + if [[ "$1" != +(* THEN*) ]] + then + echo -e "\nERROR: Missing THEN in IF statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + SYM="${1#* }" + # Translate function to C function + Parse_Equation "${SYM% THEN*}" + echo "if(${g_EQUATION}){" >> $g_CFILE + if [[ ${SYM##* THEN } != +(*THEN*) ]] + then + Tokenize "${SYM##* THEN }" + g_IF_PARSE=1 + fi + fi;; + "ELIF") + g_IF_PARSE=0 + # Check if THEN is available + if [[ "$1" != +(* THEN*) ]] + then + echo -e "\nERROR: Missing THEN in ELIF statement at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + SYM="${1#* }" + # Translate function to C function + Parse_Equation "${SYM% THEN*}" + echo "} else if(${g_EQUATION}){" >> $g_CFILE + if [[ ${SYM##* THEN } != +(*THEN*) ]] + then + Tokenize "${SYM##* THEN }" + g_IF_PARSE=1 + fi + fi;; + "ELSE") + g_IF_PARSE=0 + echo "} else {" >> $g_CFILE + if [[ ${1##*ELSE } != +(*ELSE*) ]] + then + Tokenize "${1##*ELSE }" + g_IF_PARSE=1 + fi;; + "ENDIF") + echo "}" >> $g_CFILE;; + "WHILE") + ((g_LOOPCTR+=1)) + Handle_While "${1#* }";; + "WEND") + echo "}" >> $g_CFILE + if [[ $g_LOOPCTR -gt 0 ]] + then + ((g_LOOPCTR-=1)) + if [[ $g_LOOPCTR -gt 0 ]] + then + echo "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" >> $g_CFILE + fi + fi;; + "BREAK") + # Check argument + if [[ "${1%% *}" != "${1#* }" && ${1#* } != "0" ]] + then + echo "__b2c__break_ctr = ${1#* }-1; __b2c__break_flag = 1;" >> $g_CFILE + fi + echo "break;" >> $g_CFILE;; + "CONTINUE") + # Check argument + if [[ "${1%% *}" != "${1#* }" && ${1#* } != "0" ]] + then + echo "__b2c__break_ctr = ${1#* }-1; __b2c__break_flag = 2;" >> $g_CFILE + fi + if [[ ${1#* } -gt 1 ]] + then + echo "break;" >> $g_CFILE + else + echo "continue;" >> $g_CFILE + fi;; + "REPEAT") + ((g_LOOPCTR+=1)) + echo "do{" >> $g_CFILE;; + "UNTIL") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty UNTIL at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + # Convert to legal C code + Parse_Equation "${1#* }" + echo "} while(!(${g_EQUATION}));" >> $g_CFILE + if [[ $g_LOOPCTR -gt 0 ]] + then + ((g_LOOPCTR-=1)) + if [[ $g_LOOPCTR -gt 0 ]] + then + echo "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" >> $g_CFILE + fi + fi + fi;; + "LET") + Handle_Let "${1#* }";; + +(REM*) ) + ;; + +(\'*) ) + ;; + "SYSTEM") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty SYSTEM at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + echo "SYSTEM (${1#* });" >> $g_CFILE + fi;; + "SLEEP") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty SLEEP at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + echo "usleep(${1#* }*1000);" >> $g_CFILE + fi;; + "OPEN") + Handle_Open "${1#* }";; + "CLOSE") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty CLOSE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + if [[ "$1" = +(* FILE *) ]] + then + echo "fclose(${1##* });" >> $g_CFILE + elif [[ "$1" = +(* DIRECTORY *) ]] + then + echo "closedir(${1##* });" >> $g_CFILE + elif [[ "$1" = +(* MEMORY *) ]] + then + echo "${1##* } = NULL;" >> $g_CFILE + elif [[ "$1" = +(* NETWORK *) || "$1" = +(* SERVER *) ]] + then + echo "close(${1##* });" >> $g_CFILE + else + echo -e "\nERROR: erronuous CLOSE argument at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + fi;; + "REWIND") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty REWIND at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + echo "rewind(${1#* });" >> $g_CFILE + fi;; + "MEMREWIND") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty MEMREWIND at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + echo "${1#* } = (char*)__b2c_mem_${1#* };" >> $g_CFILE + fi;; + "SEEK") + Handle_Seek "${1#* }";; + "READLN") + Handle_Readln "${1#* }";; + "WRITELN") + Handle_Writeln "${1#* }";; + "GETBYTE") + Handle_Getbyte "${1#* }";; + "PUTBYTE") + Handle_Putbyte "${1#* }";; + "GETFILE") + Handle_Getfile "${1#* }";; + "GETLINE") + Handle_Getline "${1#* }";; + "PUTLINE") + Handle_Putline "${1#* }";; + "END") + if [[ "${1#* }" = +(*IF*) ]] + then + echo "}" >> $g_CFILE + elif [[ "${1#* }" = +(*RECORD*) ]] + then + if [[ -n $g_FUNCNAME ]] + then + echo "};" >> $g_CFILE + echo "struct $g_RECORDNAME $g_RECORDVAR = { } ;" >> $g_CFILE + else + echo "};" >> $g_HFILE + echo "struct $g_RECORDNAME $g_RECORDVAR = { } ;" >> $g_HFILE + fi + g_RECORDNAME= + g_RECORDVAR= + # Restore function name if GLOBAL was used + if [[ -n $g_RECORDCACHE ]] + then + g_FUNCNAME=$g_RECORDCACHE + g_RECORDCACHE= + fi + elif [[ "${1#* }" = +(*FUNCTION*) ]] + then + Handle_Endfunction + elif [[ "${1#* }" = +(*SUB*) ]] + then + Handle_Endsub + elif [[ "${1#* }" = +(*WITH*) ]] + then + g_WITHVAR= + elif [[ "${1#* }" = +(*SELECT*) ]] + then + if [[ $g_SELECTVAR_CTR -eq 0 ]] + then + echo -e "\nERROR: invalid END SELECT at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + echo "}" >> $g_CFILE + g_SELECTVAR[$g_SELECTVAR_CTR]= + g_IN_CASE[$g_SELECTVAR_CTR]= + g_CASE_FALL= + ((g_SELECTVAR_CTR-=1)) + fi + elif [[ "${1#* }" != "END" ]] + then + echo "exit(${1#* });" >> $g_CFILE + else + echo "exit(EXIT_SUCCESS);" >> $g_CFILE + fi;; + "SUB") + Handle_SubFunc "${1#* }";; + "ENDSUB") + Handle_Endsub;; + "ENDWITH") + g_WITHVAR=;; + "ENDSELECT") + if [[ $g_SELECTVAR_CTR -eq 0 ]] + then + echo -e "\nERROR: invalid END SELECT at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + echo "}" >> $g_CFILE + g_SELECTVAR[$g_SELECTVAR_CTR]= + g_IN_CASE[$g_SELECTVAR_CTR]= + g_CASE_FALL= + ((g_SELECTVAR_CTR-=1)) + fi;; + "CALL") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty CALL at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + SYM=`echo "${1#* }"` + if [[ "$SYM" = +(* TO *) ]] + then + if [[ "${SYM##*TO }" = +(*${g_STRINGSIGN}) ]] + then + echo "${SYM##*TO } = realloc(${SYM##*TO }, (strlen(${SYM%% TO*})+1)*sizeof(char));" >> $g_CFILE + echo "strcpy(${SYM##*TO }," >> $g_CFILE + else + echo "${SYM##*TO } = " >> $g_CFILE + fi + if [[ "${SYM%% TO*}" = +(*\(*\)*) ]] + then + echo "${SYM%% TO*}" >> $g_CFILE + else + echo "${SYM%% TO*}()" >> $g_CFILE + fi + if [[ "${SYM##*TO }" = +(*${g_STRINGSIGN}) ]] + then + echo ");" >> $g_CFILE + else + echo ";" >> $g_CFILE + fi + else + if [[ "$SYM" = +(*\(*\)*) ]] + then + echo "$SYM;" >> $g_CFILE + else + echo "$SYM();" >> $g_CFILE + 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") + Handle_Data "${1#* }";; + "RESTORE") + echo "if(__b2c__floatarray_ptr > 0) __b2c__floatarray_ptr = 0;" >> $g_CFILE + echo "if(__b2c__stringarray_ptr > 0) __b2c__stringarray_ptr = 0;" >> $g_CFILE;; + "READ") + Handle_Read "${1#* }";; + "PUSH") + Handle_Push "${1#* }";; + "PULL") + Handle_Pull "${1#* }";; + "SEED") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty SEED at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + echo "srandom((unsigned int)${1#* });" >> $g_CFILE + fi;; + "DEF") + Handle_Deffn "${1#* }";; + "CONST") + Handle_Const "${1#* }";; + "INCLUDE") + # Get rid of doublequotes if they are there + INC=`echo ${1#* } | tr -d "\042"` + # Check argument + if [[ ! -f ${INC%%,*} || "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: missing file '${INC%%,*}' for INCLUDE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + TO_PARSE=0 + # See if there are arguments + if [[ ${INC} = +(*,*) ]] + then + EXP=`echo ${INC#*,} | tr "," " " | tr -d "${g_STRINGSIGN}"` + INC=${INC%%,*} + else + TO_PARSE=2 + fi + # Start walking through program + COPY_COUNTER=$g_COUNTER + g_COUNTER=1 + # Assign new file + COPY_CURFILE=$g_CURFILE + # Get rid of absolute path + g_CURFILE=${INC##*/} + while read -r LINE + do + echo -e -n "\rStarting conversion... $g_COUNTER" + # See if we need to enable flag + for SYM in ${EXP} + do + if [[ $TO_PARSE -eq 0 && "${LINE#* }" = +(${SYM%${g_STRINGSIGN}*}*) && "${LINE}" = +(*SUB*|*FUNCTION*) || "${LINE}" = +(*INCLUDE) ]] + then + TO_PARSE=1 + break + fi + done + # Line is not empty? + if [[ -n "$LINE" && $TO_PARSE -gt 0 ]] + then + if [[ "$LINE" = +(* \\) && "$LINE" != +(REM*) && "$LINE" != +(${g_SQUOTESIGN}*) ]] + then + let LEN="${#LINE}"-2 + SEQ="${LINE:0:$LEN}" + TOTAL=$TOTAL$SEQ + else + echo "/* noparse $INC BACON LINE $g_COUNTER */" >> $g_CFILE + echo "/* noparse $INC BACON LINE $g_COUNTER */" >> $g_HFILE + TOTAL="${TOTAL}${LINE}" + if [[ "${TOTAL}" != +(REM*) && "${TOTAL}" != +(${g_SQUOTESIGN}*) ]] + then + Tokenize "${TOTAL}" + fi + TOTAL= + fi + fi + # See if we need to stop parsing + if [[ $TO_PARSE -eq 1 && "${LINE}" = +(*END*) && "${LINE}" = +(*SUB*|*FUNCTION*) ]] + then + TO_PARSE=0 + fi + # Increase line number + ((g_COUNTER+=1)) + done < $INC + # Restore original counter + g_COUNTER=$COPY_COUNTER + # Restore original file + g_CURFILE=$COPY_CURFILE + fi;; + "POKE") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty POKE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + SYM=${1#* } + echo "if (!__b2c__trap){__b2c__memory__check((char*)${SYM%%,*}); if(ERROR) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} }" >> $g_CFILE + echo "*(${g_OPTION_MEMTYPE}*)(${SYM%%,*}) = (${g_OPTION_MEMTYPE})${SYM#*,};" >> $g_CFILE + fi;; + "RESIZE") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty RESIZE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + # Resolve this with C macro because of casting to (char) + SYM=${1#* } + echo "${SYM%%,*}=(long)RESIZE(${SYM});" >> $g_CFILE + fi;; + "COPY") + Handle_Copy "${1#* }";; + "DELETE") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty DELETE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + # Translate to C function + if [[ "${1#* }" = +(*FILE*) ]] + then + echo "if (unlink(${1#*FILE })==-1){if(!__b2c__trap){ERROR = 7;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + elif [[ "${1#* }" = +(*DIRECTORY*) ]] + then + echo "if (rmdir(${1#*DIRECTORY }) == -1){if(!__b2c__trap){ERROR = 20;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + else + echo "\nERROR: erronuous argument for DELETE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + fi;; + "RENAME") + Handle_Rename "${1#* }";; + "MAKEDIR") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty MAKEDIR at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + # Translate to C function + echo "if (__b2c__makedir(${1#* }) != 0){if(!__b2c__trap){ERROR = 21;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + fi;; + "CHANGEDIR") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty CHANGEDIR at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + # Translate to C function + echo "if (chdir(${1#* }) == -1){if(!__b2c__trap) {ERROR = 22;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + fi;; + "FREE") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty FREE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + # Translate to C function + if [[ ${1#* } = +(*\(*\)*) ]] + then + EXP=${1#* } + if [[ $EXP = +(*${g_STRINGSIGN}*) ]] + then + echo "if(__b2c__${EXP%%\(*}_exist(${1#*\(} != NULL) {free(__b2c__${EXP%%\(*}_exist(${1#*\(}->value); __b2c__${EXP%%\(*}_exist(${1#*\(}->value = NULL; __b2c__${EXP%%\(*}__del(${1#*\(};}" >> $g_CFILE + else + echo "if(__b2c__${EXP%%\(*}_exist(${1#*\(} != NULL) {__b2c__${EXP%%\(*}_exist(${1#*\(}->value = 0; __b2c__${EXP%%\(*}__del(${1#*\(}; }" >> $g_CFILE + fi + else + echo "if(!__b2c__trap){__b2c__memory__check((char *)${1#* });" >> $g_CFILE + echo "if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} } free((void*)${1#* });" >> $g_CFILE + fi + fi;; + "GOTO") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty GOTO at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + # Translate to C label + echo "goto ${1#* };" >> $g_CFILE + fi;; + "LABEL") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty LABEL at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + # Translate to C label + echo "${1#* }:" >> $g_CFILE + echo ";" >> $g_CFILE + fi;; + "TRAP") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty TRAP at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + if [[ "${1#* }" = "SYSTEM" ]] + then + echo "/* Error catching is enabled */" >> $g_CFILE + echo "__b2c__trap = 1;" >> $g_CFILE + echo "signal(SIGILL, __b2c__catch_signal);" >> $g_CFILE + echo "signal(SIGABRT, __b2c__catch_signal);" >> $g_CFILE + echo "signal(SIGFPE, __b2c__catch_signal);" >> $g_CFILE + echo "signal(SIGSEGV, __b2c__catch_signal);" >> $g_CFILE + elif [[ "${1#* }" = "LOCAL" ]] + then + echo "/* Error catching is disabled */" >> $g_CFILE + echo "__b2c__trap = 0;" >> $g_CFILE + echo "signal(SIGILL, SIG_DFL);" >> $g_CFILE + echo "signal(SIGABRT, SIG_DFL);" >> $g_CFILE + echo "signal(SIGFPE, SIG_DFL);" >> $g_CFILE + echo "signal(SIGSEGV, SIG_DFL);" >> $g_CFILE + else + echo -e "\nERROR: invalid argument for TRAP at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + fi;; + "CATCH") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty CATCH at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + elif [[ "${1#* }" = +(*GOTO*) ]] + then + echo "__b2c__catch_set = 1;" >> $g_CFILE + g_CATCHGOTO="${1##* GOTO }" + elif [[ "${1#* }" = +(*RESET*) ]] + then + echo "__b2c__catch_set = 0;" >> $g_CFILE + g_CATCHGOTO="__B2C__PROGRAM__EXIT" + else + echo -e "\nERROR: CATCH without GOTO or RESET at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi;; + "RESUME") + echo "longjmp(__b2c__jump, 1);" >> $g_CFILE;; + "CLEAR") + echo "fprintf(stdout,\"\033[2J\"); fprintf(stdout,\"\033[0;0f\");fflush(stdout);" >> $g_CFILE;; + "COLOR") + Handle_Color "${1#* }";; + "GOTOXY") + Handle_Gotoxy "${1#* }";; + "RECEIVE") + Handle_Receive "${1#* }";; + "SEND") + Handle_Send "${1#* }";; + "RECORD") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty RECORD at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + elif [[ -n $g_RECORDNAME ]] + then + echo -e "\nERROR: cannot define a record within a record!" + exit 1 + else + # Translate to C typedef struct + if [[ -n $g_FUNCNAME ]] + then + g_RECORDNAME="RECORD_${g_FUNCNAME}_${g_COUNTER}" + echo "struct $g_RECORDNAME{" >> $g_CFILE + else + g_RECORDNAME="RECORD_${g_COUNTER}" + echo "struct $g_RECORDNAME{" >> $g_HFILE + fi + g_RECORDVAR=${1#* } + fi;; + "WITH") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty WITH at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + elif [[ -n $g_RECORDNAME ]] + then + echo -e "\nERROR: cannot define a WITH within a WITH!" + exit 1 + else + g_WITHVAR=${1#* } + fi;; + "SPLIT") + Handle_Split "${1#* }";; + "SELECT") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty SELECT at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + ((g_SELECTVAR_CTR+=1)) + g_SELECTVAR[$g_SELECTVAR_CTR]=${1#* } + g_IN_CASE[$g_SELECTVAR_CTR]= + g_CASE_FALL= + fi;; + "CASE") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo "\nERROR: empty CASE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + if [[ -n ${g_IN_CASE[$g_SELECTVAR_CTR]} ]] + then + if [[ ${g_SELECTVAR[$g_SELECTVAR_CTR]} = +(*${g_STRINGSIGN}*) ]] + then + # Get expression without ; + if [[ -z ${1##*;} ]] + then + let LEN="${#1}"-1; EXP="${1:0:$LEN}" + g_CASE_FALL="|| !strcmp(${g_SELECTVAR[$g_SELECTVAR_CTR]}, ${EXP#* }) ${g_CASE_FALL}" + else + echo "} else if (!strcmp(${g_SELECTVAR[$g_SELECTVAR_CTR]}, ${1#* }) ${g_CASE_FALL}){" >> $g_CFILE + g_CASE_FALL= + fi + else + # Get expression without ; + if [[ -z ${1##*;} ]] + then + let LEN="${#1}"-1; EXP="${1:0:$LEN}" + g_CASE_FALL="|| ${g_SELECTVAR[$g_SELECTVAR_CTR]} == (${EXP#* }) ${g_CASE_FALL}" + else + echo "} else if (${g_SELECTVAR[$g_SELECTVAR_CTR]} == (${1#* }) ${g_CASE_FALL}){" >> $g_CFILE + g_CASE_FALL= + fi + fi + else + if [[ ${g_SELECTVAR[$g_SELECTVAR_CTR]} = +(*${g_STRINGSIGN}*) ]] + then + # Get expression without ; + if [[ -z ${1##*;} ]] + then + let LEN="${#1}"-1; EXP="${1:0:$LEN}" + g_CASE_FALL="|| !strcmp(${g_SELECTVAR[$g_SELECTVAR_CTR]}, ${EXP#* }) ${g_CASE_FALL}" + else + echo "if (!strcmp(${g_SELECTVAR[$g_SELECTVAR_CTR]}, ${1#* }) ${g_CASE_FALL}){" >> $g_CFILE + g_IN_CASE[$g_SELECTVAR_CTR]=1 + g_CASE_FALL= + fi + else + # Get expression without ; + if [[ -z ${1##*;} ]] + then + let LEN="${#1}"-1; EXP="${1:0:$LEN}" + g_CASE_FALL="|| ${g_SELECTVAR[$g_SELECTVAR_CTR]} == (${EXP#* }) ${g_CASE_FALL}" + else + echo "if (${g_SELECTVAR[$g_SELECTVAR_CTR]} == (${1#* }) ${g_CASE_FALL}){" >> $g_CFILE + g_IN_CASE[$g_SELECTVAR_CTR]=1 + g_CASE_FALL= + fi + fi + fi + fi;; + "DEFAULT") + if [[ -n ${g_IN_CASE[$g_SELECTVAR_CTR]} ]] + then + echo "} else {" >> $g_CFILE + else + echo -e "\nERROR: cannot use DEFAULT without previous CASE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + g_IN_CASE[$g_SELECTVAR_CTR]= + g_CASE_FALL=;; + "SETENVIRON") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty SETENVIRON at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + # Resolve this with C macro + echo "SETENVIRON(${1#* });" >> $g_CFILE + fi;; + "SORT") + Handle_Sort "${1#* }";; + "STOP") + echo "kill(getpid(), SIGSTOP);" >> $g_CFILE + ;; + "TRACE") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty TRACE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + if [[ "${1#* }" = +(*ON*) ]] + then + g_TRACE=1 + elif [[ "${1#* }" = +(*OFF*) ]] + then + g_TRACE=0 + fi + fi;; + "OPTION") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty OPTION at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + if [[ "${1#* }" = +(*BASE*) ]] + then + if [[ "${1##*BASE }" = +([0123456789]) ]] + then + g_OPTION_BASE=${1##*BASE } + else + echo -e "\nERROR: invalid argument to OPTION BASE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + elif [[ "${1#* }" = +(*COMPARE*) ]] + then + if [[ "${1##*COMPARE }" = +([01]|TRUE|FALSE) ]] + then + echo "__b2c__option_compare = ${1##*COMPARE };" >> $g_CFILE + else + echo -e "\nERROR: invalid argument to OPTION COMPARE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + elif [[ "${1#* }" = +(*SOCKET*) ]] + then + if [[ "${1##*SOCKET }" = +([0123456789]) ]] + then + g_OPTION_SOCKET=${1##*SOCKET } + else + echo -e "\nERROR: invalid argument to OPTION SOCKET at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + elif [[ "${1#* }" = +(*MEMSTREAM*) ]] + then + if [[ "${1##*MEMSTREAM }" = +([01]|TRUE|FALSE) ]] + then + echo "__b2c__option_memstream = ${1##*MEMSTREAM };" >> $g_CFILE + else + echo -e "\nERROR: invalid argument to OPTION MEMSTREAM at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + elif [[ "${1#* }" = +(*MEMTYPE*) ]] + then + case "${1##*MEMTYPE }" in + *short*) + echo "__b2c__memtype = 2;" >> $g_CFILE + g_OPTION_MEMTYPE="short" + ;; + *int*) + echo "__b2c__memtype = 3;" >> $g_CFILE + g_OPTION_MEMTYPE="int" + ;; + *long*|*NUMBER*) + echo "__b2c__memtype = 4;" >> $g_CFILE + g_OPTION_MEMTYPE="long" + ;; + *float*) + echo "__b2c__memtype = 5;" >> $g_CFILE + g_OPTION_MEMTYPE="float" + ;; + *double*|*FLOATING*) + echo "__b2c__memtype = 6;" >> $g_CFILE + g_OPTION_MEMTYPE="double" + ;; + *void*|*char\**|*STRING*) + echo "__b2c__memtype = 7;" >> $g_CFILE + g_OPTION_MEMTYPE="char*" + ;; + *char*) + echo "__b2c__memtype = 1;" >> $g_CFILE + g_OPTION_MEMTYPE="char" + ;; + *) + echo -e "\nERROR: invalid argument to OPTION MEMTYPE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + ;; + esac + elif [[ "${1#* }" = +(*COLLAPSE*) ]] + then + if [[ "${1##*COLLAPSE }" = +([01]|TRUE|FALSE) ]] + then + echo "__b2c__collapse = ${1##*COLLAPSE };" >> $g_CFILE + else + echo -e "\nERROR: invalid argument to OPTION COLLAPSE at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + elif [[ "${1#* }" = +(*INTERNATIONAL*) ]] + then + if [[ "${1##*INTERNATIONAL }" = +([01]|TRUE|FALSE) ]] + then + echo "#include <libintl.h>" >> $g_HFILE + echo "#include <locale.h>" >> $g_HFILE + echo "setlocale(LC_ALL, \"\");" >> $g_CFILE + echo "if(bindtextdomain(\"${g_SOURCEFILE%.*}\",\"/usr/share/locale\")==NULL){if(!__b2c__trap){ERROR = 6;if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + echo "if(textdomain(\"${g_SOURCEFILE%.*}\")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto $g_CATCHGOTO;} }" >> $g_CFILE + else + echo -e "\nERROR: invalid argument to OPTION INTERNATIONAL at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + else + echo -e "\nERROR: argument to OPTION at line $g_COUNTER in file '$g_CURFILE' not recognized!" + exit 1 + fi + fi;; + "PROTO") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty PROTO at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + SYM=`echo ${1#* } | tr -d "\042"` + # Check if ALIAS is there + if [[ $SYM = +(* ALIAS *) ]] + then + echo "#define ${SYM##* ALIAS } ${SYM%% ALIAS *}" >> $g_HFILE + g_IMPORTED="${SYM##* ALIAS } $g_IMPORTED" + g_IMPORTED="${SYM%% ALIAS *} $g_IMPORTED" + else + g_IMPORTED="`echo ${SYM} | tr ',' ' '` $g_IMPORTED" + fi + fi;; + "INCR") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty INC at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + EXP=${1#* } + if [[ ${EXP} = +(*,*) ]] + then + echo "${EXP%%,*} = ${EXP%%,*} + (${EXP#*,});" >> $g_CFILE + else + echo "${EXP} = ${EXP} + 1;" >> $g_CFILE + fi + fi;; + "DECR") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty DEC at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + EXP=${1#* } + if [[ ${EXP} = +(*,*) ]] + then + echo "${EXP%%,*} = ${EXP%%,*} - (${EXP#*,});" >> $g_CFILE + else + echo "${EXP} = ${EXP} - 1;" >> $g_CFILE + fi + fi;; + "ALARM") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty ALARM at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + EXP=${1#* } + if [[ ${EXP} = +(*,*) ]] + then + echo "signal(SIGALRM, (void*)${EXP%,*});" >> $g_CFILE + echo "alarm(${EXP#*,});" >> $g_CFILE + else + echo -e "\nERROR: missing argument in ALARM at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + fi;; + "CURSOR") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty CURSOR at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + if [[ "${1#* }" = +(*OFF*) ]] + then + echo "fprintf(stdout,\"\033[?25l\"); fflush(stdout);" >> $g_CFILE + elif [[ "${1#* }" = +(*ON*) ]] + then + echo "fprintf(stdout,\"\033[?25h\"); fflush(stdout);" >> $g_CFILE + fi + fi;; + "ALIAS") + Handle_Alias "${1#* }";; + "LOOKUP") + Handle_Lookup "${1#* }";; + "RELATE") + Handle_Relate "${1#* }";; + "TEXTDOMAIN") + # Check argument + if [[ "${1%% *}" = "${1#* }" ]] + then + echo -e "\nERROR: empty TEXTDOMAIN at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + else + EXP=${1#* } + if [[ ${EXP} = +(*,*) ]] + then + echo "bindtextdomain(${EXP});" >> $g_CFILE + echo "textdomain(${EXP%,*});" >> $g_CFILE + else + echo -e "\nERROR: missing argument in TEXTDOMAIN at line $g_COUNTER in file '$g_CURFILE'!" + exit 1 + fi + fi;; + *) + # Check on imported symbols first + FOUND=0 + for SYM in $g_IMPORTED + do + if [[ "$SYM" = ${1%%\(*} || "$SYM" = ${1%% *} ]] + then + FOUND=1 + if [[ "$1" != +(*\(*\)*) ]] + then + echo "$SYM();" >> $g_CFILE + else + echo "$SYM(${1#*\(};" >> $g_CFILE + fi + fi + done + # Not an imported symbol? Check if assignment + if [[ $FOUND -eq 0 ]] + then + Handle_Let "$1" + fi;; + esac + fi +} + +#----------------------------------------------------------- + +function Tokenize +{ + local CHAR IS_ESCAPED IS_STRING IS_STATEMENT TOKEN DATA LEN + + IS_ESCAPED=0 + IS_STRING=0 + IS_STATEMENT="" + TOKEN= + + # Initialize miniparser, convert spaces + DATA=`echo "${1}" | tr " " "\001"` + LEN=${#DATA} + + until [[ $LEN -eq 0 ]] + do + CHAR="${DATA:0:5}" + if [[ "${CHAR}" = "INTL$" ]] + then + if [[ $IS_STRING -eq 0 ]] + then + let LEN=${#DATA}-5 + DATA="${DATA: -$LEN}" + TOKEN="${TOKEN}gettext" + fi + elif [[ "${CHAR}" = "NNTL$" ]] + then + if [[ $IS_STRING -eq 0 ]] + then + let LEN=${#DATA}-5 + DATA="${DATA: -$LEN}" + TOKEN="${TOKEN}ngettext" + fi + fi + CHAR="${DATA:0:1}" + case $CHAR in + ":") + if [[ $IS_STRING -eq 0 ]] + then + Parse_Line "${TOKEN}" + unset CHAR + TOKEN= + IS_STATEMENT="" + fi;; + "$") + if [[ $IS_STRING -eq 0 || ${1} = +(*IMPORT*FROM*TYPE*) ]] + then + TOKEN="${TOKEN}${g_STRINGSIGN}" + CHAR= + IS_ESCAPED=0 + fi;; + "\\") + if [[ $IS_ESCAPED -eq 0 ]] + then + IS_ESCAPED=1 + else + IS_ESCAPED=0 + fi;; + "\"") + if [[ $IS_ESCAPED -eq 0 ]] + then + if [[ $IS_STRING -eq 0 ]] + then + IS_STRING=1 + else + IS_STRING=0 + fi + fi + IS_ESCAPED=0;; + [A-Za-z=]) + if [[ $IS_STRING -eq 0 ]] + then + IS_STATEMENT=" " + fi + IS_ESCAPED=0;; + *) + IS_ESCAPED=0;; + esac + # Convert back to space + if [[ "${CHAR}" = "${g_PARSEVAR}" ]] + then + TOKEN="${TOKEN}${IS_STATEMENT}" + else + TOKEN="${TOKEN}${CHAR}" + fi + let LEN=${#DATA}-1 + DATA="${DATA: -$LEN}" + done + Parse_Line "${TOKEN}" +} + +#----------------------------------------------------------- + +function Parse_Chunk +{ + local CHAR IS_ESCAPED IS_STRING TOKEN DATA LEN TERM EQ IS_EQUATION + + IS_ESCAPED=0 + IS_STRING=0 + IS_EQUATION=0 + TOKEN= + EQ="!" + + # Initialize miniparser, convert spaces + DATA=`echo "${1}" | tr " " "\001"` + LEN=${#DATA} + + until [[ $LEN -eq 0 ]] + do + CHAR="${DATA:0:1}" + case $CHAR in + "=") + if [[ $IS_STRING -eq 0 ]] + then + if [[ "${1%%\(*}" = +(*${g_STRINGSIGN}*) || "${1%%\(*}" = +(*${g_DQUOTESIGN}*) ]] + then + TERM="${TOKEN}" + TOKEN= + elif [[ $IS_EQUATION -eq 0 ]] + then + TOKEN="${TOKEN}==" + else + TOKEN="${TOKEN}=" + IS_EQUATION=0 + fi + IS_ESCAPED=0 + else + TOKEN="${TOKEN}=" + fi;; + "!") + if [[ $IS_STRING -eq 0 ]] + then + if [[ "${1%%\(*}" = +(*${g_STRINGSIGN}*) || "${1%%\(*}" = +(*${g_DQUOTESIGN}*) ]] + then + EQ="" + elif [[ $IS_EQUATION -eq 0 ]] + then + TOKEN="${TOKEN}!=" + IS_ESCAPED=0 + let LEN=${#DATA}-1 + DATA="${DATA: -$LEN}" + else + TOKEN="${TOKEN}!" + IS_EQUATION=0 + fi + else + TOKEN="${TOKEN}!" + fi;; + "<") + IS_EQUATION=1 + TOKEN="${TOKEN}<";; + ">") + IS_EQUATION=1 + TOKEN="${TOKEN}>";; + "#") + IS_EQUATION=1 + TOKEN="${TOKEN}#";; + "\\") + if [[ $IS_ESCAPED -eq 0 ]] + then + IS_ESCAPED=1 + else + IS_ESCAPED=0 + fi + TOKEN="${TOKEN}\\";; + "\"") + if [[ $IS_ESCAPED -eq 0 ]] + then + if [[ $IS_STRING -eq 0 ]] + then + IS_STRING=1 + else + IS_STRING=0 + fi + fi + IS_ESCAPED=0 + TOKEN="${TOKEN}\"";; + *) + # Convert back to space + if [[ "${CHAR}" = "${g_PARSEVAR}" ]] + then + TOKEN="${TOKEN} " + else + TOKEN="${TOKEN}${CHAR}" + fi + IS_ESCAPED=0;; + esac + let LEN=${#DATA}-1 + DATA="${DATA: -$LEN}" + done + + if [[ "${1%%\(*}" = +(*${g_STRINGSIGN}*) || "${1%%\(*}" = +(*${g_DQUOTESIGN}*) ]] + then + TOKEN="((__b2c__option_compare == 0) ? ${EQ}strcmp(${TERM}, $TOKEN) : ${EQ}strcasecmp(${TERM}, $TOKEN))" + fi + + g_EQUATION="${g_EQUATION} ${TOKEN} ${2}" +} + +#----------------------------------------------------------- + +function Parse_Equation +{ + local CHAR IS_ESCAPED IS_STRING TOKEN DATA LEN + local AND OR + + g_EQUATION= + IS_ESCAPED=0 + IS_STRING=0 + TOKEN= + + AND=`echo " AND " | tr " " "\001"` + OR=`echo " OR " | tr " " "\001"` + + # Initialize miniparser, convert spaces + DATA=`echo "${1}" | tr " " "\001"` + LEN=${#DATA} + + until [[ $LEN -eq 0 ]] + do + CHAR="${DATA:0:5}" + if [[ "${CHAR}" = "${AND}" ]] + then + if [[ $IS_STRING -eq 0 ]] + then + Parse_Chunk "${TOKEN}" " AND " + let LEN=${#DATA}-4 + DATA="${DATA: -$LEN}" + unset CHAR + TOKEN= + fi + fi + CHAR="${DATA:0:4}" + if [[ "${CHAR}" = "${OR}" ]] + then + if [[ $IS_STRING -eq 0 ]] + then + Parse_Chunk "${TOKEN}" " OR " + let LEN=${#DATA}-3 + DATA="${DATA: -$LEN}" + unset CHAR + TOKEN= + fi + fi + CHAR="${DATA:0:1}" + case $CHAR in + "\\") + if [[ $IS_ESCAPED -eq 0 ]] + then + IS_ESCAPED=1 + else + IS_ESCAPED=0 + fi;; + "\"") + if [[ $IS_ESCAPED -eq 0 ]] + then + if [[ $IS_STRING -eq 0 ]] + then + IS_STRING=1 + else + IS_STRING=0 + fi + fi + IS_ESCAPED=0;; + *) + IS_ESCAPED=0;; + esac + # Convert back to space + if [[ "${CHAR}" = "${g_PARSEVAR}" ]] + then + TOKEN="${TOKEN} " + else + TOKEN="${TOKEN}${CHAR}" + fi + let LEN=${#DATA}-1 + DATA="${DATA: -$LEN}" + done + Parse_Chunk "${TOKEN}" +} + +#----------------------------------------------------------- +# +# Main program +# +#----------------------------------------------------------- + +# Default BACON settings +let g_MAX_DIGITS=32 + +# 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=32 + +let g_NO_COMPILE=0 +let g_TMP_PRESERVE=0 +let g_USE_C=0 +let g_MAX_BACKLOG=5 +let g_CPP=0 +let g_XGETTEXT=0 + +g_TEMPDIR=. +g_CCNAME=cc +g_CCFLAGS= +g_INCFILES= +g_INCLUDE_FILES= +let g_TRACE=0 +let g_OPTION_BASE=0 +let g_OPTION_SOCKET=5 +g_OPTION_MEMTYPE="char" +let g_IF_PARSE=0 + +# Some global declarations +g_CURFILE= +g_FUNCNAME= +g_FUNCTYPE= +g_PROTOTYPE= +g_TMP_FILES= +g_LOCALSTRINGS= +g_STRINGARRAYS= +g_STRINGARGS= +g_BINEXT= +g_RECORDCACHE= +g_LOOPCTR=0 +g_ERRORTXT= +g_EQUATION= + +# Always create a final label +g_CATCHGOTO="__B2C__PROGRAM__EXIT" + +# Records +g_RECORDNAME= +g_RECORDVAR= +g_WITHVAR= + +# Select/Case +declare -a g_SELECTVAR +declare -a g_IN_CASE +g_SELECTVAR_CTR=0 + +# Relate +declare -a g_RELATE +g_RELATE_CTR=0 + +# Get arguments +while getopts ":c:d:i:l:o:xnjfpv" OPT +do + case $OPT in + c) g_CCNAME=$OPTARG;; + d) if [[ ! -d $OPTARG ]] + then + mkdir -p $OPTARG + fi + g_TEMPDIR=$OPTARG;; + i) if [[ ! -f $OPTARG && ! -f "/usr/include/$OPTARG" ]] + then + echo -e "ERROR: included C header file from -i option not found!" + exit 1 + fi + if [[ ! -f "/usr/include/$OPTARG" ]] + then + g_INCFILES="$g_INCFILES ${OPTARG}" + else + g_INCFILES="$g_INCFILES <${OPTARG}>" + fi;; + l) g_LDFLAGS="$g_LDFLAGS -l$OPTARG";; + o) g_CCFLAGS="$g_CCFLAGS $OPTARG";; + n) g_NO_COMPILE=1;; + j) g_CPP=1;; + f) g_CCFLAGS="$g_CCFLAGS -shared -rdynamic" + if [[ `uname -a` = +(*x86_64*) ]] + then + g_CCFLAGS="$g_CCFLAGS -fPIC" + fi + g_BINEXT=".so";; + p) g_TMP_PRESERVE=1;; + x) g_XGETTEXT=1;; + v) echo + echo "BaCon version $g_VERSION - BASH - (c) Peter van Eerten - GPL v3." + echo + exit 0;; + \?|h) echo + echo "USAGE: bacon [options] program[.bac]" + echo + echo "OPTIONS:" + echo + echo -e " -c <compiler>\tCompiler to use (default: $g_CCNAME)" + echo -e " -l <flags>\tPass libraries to linker" + echo -e " -o <options>\tPass compiler options" + echo -e " -i <include>\tAdd include file to C code" + echo -e " -d <tmpdir>\tTemporary directory (default: $g_TEMPDIR)" + echo -e " -x \t\tExtract gettext strings" + echo -e " -f \t\tCreate Shared Object" + echo -e " -n \t\tDo not compile, only convert" + echo -e " -j \t\tInvoke C Preprocessor" + echo -e " -p \t\tPreserve temporary files" + echo -e " -v \t\tShow version" + echo -e " -h \t\tShow help" + echo + exit 0;; + esac +done + +shift $(($OPTIND-1)) + +# Check if a filename was entered, if so get it +if [[ $# -eq 0 ]] +then + echo -e "ERROR: no filename? Run with '-h' to see usage." + exit 1 +elif [[ "$@" = +(http://*) ]] +then + if [[ -z `which telnet 2>/dev/null` ]] + then + echo "ERROR: No telnet client found! Cannot retrieve file." + exit 1 + fi + echo -n "Fetching file... " + # Remove http part + g_SOURCEFILE="${1#*http://}" + + # Get header to see if file exists, and if so, get length + HEAD=`(echo "set crlf on"; echo "open ${g_SOURCEFILE%%/*} 80"; sleep 1; + echo "HEAD /${1##*/} HTTP/1.1"; echo "Host: ${g_SOURCEFILE%%/*}"; echo; + sleep 1; echo "quit";) | telnet 2>/dev/null` + + LEN=`echo ${HEAD#*Content-Length: }` + + # No file found on server + if [[ "${LEN%% *}" = "telnet>" || "${HEAD}" != +(*Content-Length*) ]] + then + echo "ERROR: file not found! Check URL and try again." + exit 1 + fi + + # Get the actual contents of the file + DOWNLOAD=`(echo "set crlf on"; echo "open ${g_SOURCEFILE%%/*} 80"; sleep 1; + echo "GET /${1##*/} HTTP/1.1"; echo "Host: ${g_SOURCEFILE%%/*}"; echo; + sleep 1; echo "quit";) | telnet 2>/dev/null` + + # Set the final filename and save + g_SOURCEFILE="${1##*/}" + let START=${#DOWNLOAD}-${LEN%% *} + echo "${DOWNLOAD:${START}:${#DOWNLOAD}}" > $g_SOURCEFILE + + # Check resulting filesize with HTTP header + FILELEN=`wc -c $g_SOURCEFILE` + let FILELEN=${FILELEN%% *}-1 + if [[ ${FILELEN} -ne ${LEN%% *} ]] + then + echo "ERROR: file could not be downloaded. Try again later." + exit 1 + fi + echo "done." + +elif [[ "$@" != +(*.bac) ]] +then + g_SOURCEFILE="$@.bac" +else + g_SOURCEFILE="$@" +fi + +# Check if file exists +if [[ ! -f $g_SOURCEFILE ]] +then + echo -e "ERROR: file not found!" + exit 1 +fi + +# Change the working directory +if [[ -d ${g_SOURCEFILE%/*} ]] +then + cd ${g_SOURCEFILE%/*} +fi + +# Now create the global filenames where to write to +g_CFILE=$g_TEMPDIR/${g_SOURCEFILE##*/}.c +g_HFILE=$g_TEMPDIR/${g_SOURCEFILE##*/}.h +STRINGARRAYFILE=$g_TEMPDIR/${g_SOURCEFILE##*/}.string.h +FLOATARRAYFILE=$g_TEMPDIR/${g_SOURCEFILE##*/}.float.h + +# Check to overwrite +if [[ -f $g_CFILE || -f $g_HFILE ]] +then + rm -f $g_CFILE + rm -f $g_HFILE + rm -f $STRINGARRAYFILE + rm -f $FLOATARRAYFILE +fi + +echo -n "Starting conversion... " + +# Add to total file list +g_TMP_FILES="$g_CFILE $g_HFILE $STRINGARRAYFILE $FLOATARRAYFILE" + +# Create basic C file +echo "/* Created with BASH BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > $g_CFILE +echo "#include \"${g_SOURCEFILE##*/}.h\"" >> $g_CFILE +echo "int main(int argc, const char **argv)" >> $g_CFILE +echo "{" >> $g_CFILE +echo "/* Default is: system traps signals */" >> $g_CFILE +echo "signal(SIGILL, __b2c__catch_signal);" >> $g_CFILE +echo "signal(SIGABRT, __b2c__catch_signal);" >> $g_CFILE +echo "signal(SIGFPE, __b2c__catch_signal);" >> $g_CFILE +echo "signal(SIGSEGV, __b2c__catch_signal);" >> $g_CFILE +echo "/* Make sure internal string buffers are empty */" >> $g_CFILE +echo "__b2c__sbuffer_ptr=0;" >> $g_CFILE +echo "__b2c__rbuffer_ptr=0;" >> $g_CFILE + +# Put arguments into reserved variable ARGUMENT +echo "/* Setup the reserved variable 'ARGUMENT' */" >> $g_CFILE +echo "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" >> $g_CFILE +echo "{__b2c__arglen += strlen(argv[__b2c__counter]) + 1;} __b2c__arglen++;" >> $g_CFILE +echo "ARGUMENT${g_STRINGSIGN} = (char*)calloc(__b2c__arglen, sizeof(char));" >> $g_CFILE +echo "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" >> $g_CFILE +echo "{strcat(ARGUMENT${g_STRINGSIGN}, argv[__b2c__counter]); if(__b2c__counter != argc - 1) strcat(ARGUMENT${g_STRINGSIGN}, \" \");}" >> $g_CFILE +echo "/* By default seed random generator */" >> $g_CFILE +echo "srandom((unsigned int)time(NULL));" >> $g_CFILE +echo "/* Initialize internal stackpointer */" >> $g_CFILE +echo "__b2c__typestack = (int*)calloc(1, sizeof(int));" >> $g_CFILE +echo "__b2c__stringstack = (char**)realloc(__b2c__stringstack, sizeof(char*)); __b2c__stringstack[0] = calloc(1, sizeof(char));" >> $g_CFILE +echo "/* Rest of the program */" >> $g_CFILE + +# Create basic H file, functions are converted using macros +echo "/* Created with BASH BaCon $g_VERSION - (c) Peter van Eerten - GPL v3 */" > $g_HFILE +echo >> $g_HFILE +echo "#include <stdio.h>" >> $g_HFILE +echo "#include <stdlib.h>" >> $g_HFILE +echo "#include <stdarg.h>" >> $g_HFILE +echo "#include <sys/time.h>" >> $g_HFILE +echo "#include <sys/stat.h>" >> $g_HFILE +echo "#include <sys/types.h>" >> $g_HFILE +echo "#include <sys/wait.h>" >> $g_HFILE +echo "#include <sys/socket.h>" >> $g_HFILE +echo "#include <sys/utsname.h>" >> $g_HFILE +echo "#include <dirent.h>" >> $g_HFILE +echo "#include <setjmp.h>" >> $g_HFILE +echo "#include <netdb.h>" >> $g_HFILE +if [[ `uname` = +(*BSD*) ]] +then + echo "#include <netinet/in.h>" >> $g_HFILE +fi +echo "#include <arpa/inet.h>" >> $g_HFILE +echo "#include <signal.h>" >> $g_HFILE +echo "static jmp_buf __b2c__jump;" >> $g_HFILE +echo "static int __b2c__trap = 1;" >> $g_HFILE +echo "static int __b2c__catch_set = 0;" >> $g_HFILE +echo "static int ERROR = 0;" >> $g_HFILE +echo "static int __b2c__option_compare = 0;" >> $g_HFILE +echo "static int __b2c__option_memstream = 0;" >> $g_HFILE +echo "static int __b2c__memtype = 1;" >> $g_HFILE +echo "static int __b2c__collapse = 0;" >> $g_HFILE +echo "int __b2c__break_ctr = 0;" >> $g_HFILE +echo "int __b2c__break_flag = 0;" >> $g_HFILE +echo "int RETVAL = 0;" >> $g_HFILE +echo "char __b2c__chop_default[] = \"\r\n\t \";" >> $g_HFILE +echo "char VERSION${g_STRINGSIGN}[] = \"$g_VERSION\";" >> $g_HFILE +echo >> $g_HFILE +# Add user include files +echo "/* User include files */" >> $g_HFILE +for i in $g_INCFILES +do + if [[ "$i" = +(*<*) ]] + then + echo "#include $i" >> $g_HFILE + else + echo "#include \"$i\"" >> $g_HFILE + fi +done +echo "/* READ/DATA include files */" >> $g_HFILE +echo "int __b2c__stringarray_ptr = 0;" >> $g_HFILE +echo "#include \"${g_SOURCEFILE##*/}.string.h\"" >> $g_HFILE +echo "int __b2c__floatarray_ptr = 0;" >> $g_HFILE +echo "#include \"${g_SOURCEFILE##*/}.float.h\"" >> $g_HFILE +echo "int __b2c__ctr;" >> $g_HFILE +echo >> $g_HFILE +echo "/* Math functions */" >> $g_HFILE +echo "extern double round(double __b2c__x);" >> $g_HFILE +echo "extern long int lrint(double __b2c__x);" >> $g_HFILE +echo "#include <math.h>" >> $g_HFILE +echo "#define SQR(__b2c__x) sqrt(__b2c__x)" >> $g_HFILE +echo "#define POW(__b2c__x, __b2c__y) pow(__b2c__x, __b2c__y)" >> $g_HFILE +echo "#define SIN(__b2c__x) sin(__b2c__x)" >> $g_HFILE +echo "#define COS(__b2c__x) cos(__b2c__x)" >> $g_HFILE +echo "#define TAN(__b2c__x) tan(__b2c__x)" >> $g_HFILE +echo "#define ATN(__b2c__x) atan(__b2c__x)" >> $g_HFILE +echo "#define LOG(__b2c__x) log(__b2c__x)" >> $g_HFILE +echo "#define EXP(__b2c__x) exp(__b2c__x)" >> $g_HFILE +echo "#define SGN(__b2c__x) (__b2c__x == 0 ? 0 : (__b2c__x < 0 ? -1 : 1))" >> $g_HFILE +echo "#define ROUND(__b2c__x) lrint(__b2c__x)" >> $g_HFILE +echo "#define INT(__b2c__x) lrint(__b2c__x)" >> $g_HFILE +echo "#define MOD(__b2c__x, __b2c__y) ((long)__b2c__x % (long)__b2c__y)" >> $g_HFILE +echo "#define EVEN(__b2c__x) ((__b2c__x % 2 == 0) ? 1 : 0)" >> $g_HFILE +echo "#define ODD(__b2c__x) ((__b2c__x % 2 != 0) ? 1 : 0)" >> $g_HFILE +echo "#define FLOOR(__b2c__x) (long)floor(__b2c__x)" >> $g_HFILE +echo "#define ABS(__b2c__x) (long)abs(__b2c__x)" >> $g_HFILE +echo "#define RND random()" >> $g_HFILE +if [[ `uname` = +(*SunOS*) ]] +then + echo "#define MAXRANDOM 2147483647" >> $g_HFILE +else + echo "#define MAXRANDOM RAND_MAX" >> $g_HFILE +fi +echo "#define RANDOM(__b2c__x) ((__b2c__x != 0) ? random()/(MAXRANDOM/__b2c__x) : 0)" >> $g_HFILE +echo >> $g_HFILE +echo "/* Other functions */" >> $g_HFILE +echo "#define VAL(__b2c__x) ((__b2c__x != NULL) ? atof(__b2c__x) : 0)" >> $g_HFILE +echo >> $g_HFILE +echo "/* Unix functions */" >> $g_HFILE +echo "#include <unistd.h>" >> $g_HFILE +echo "#define SYSTEM(__b2c__x) do {if (__b2c__x != NULL) {RETVAL = system(__b2c__x); if(WIFEXITED(RETVAL)) RETVAL = WEXITSTATUS(RETVAL);} else RETVAL=0;} while(0)" >> $g_HFILE +echo >> $g_HFILE +echo "/* String functions */" >> $g_HFILE +echo "#include <string.h>" >> $g_HFILE +echo "char *__b2c__strndup(const char *__b2c__s, size_t __b2c__n){size_t __b2c__avail;" >> $g_HFILE +echo "char *__b2c__p; if (!__b2c__s) return 0; __b2c__avail = strlen(__b2c__s) + 1;" >> $g_HFILE +echo "if (__b2c__avail > __b2c__n + 1) __b2c__avail = __b2c__n + 1; __b2c__p = malloc(__b2c__avail);" >> $g_HFILE +echo "memcpy(__b2c__p, __b2c__s, __b2c__avail); __b2c__p[__b2c__avail - 1] = '\0'; return __b2c__p;}" >> $g_HFILE +echo "char __b2c__input__buffer[$g_BUFFER_SIZE];" >> $g_HFILE +echo "char* __b2c__sbuffer[$g_MAX_BUFFERS] = { NULL };" >> $g_HFILE +echo "int __b2c__sbuffer_ptr;" >> $g_HFILE +echo "char* __b2c__rbuffer[$g_MAX_RBUFFERS] = { NULL };" >> $g_HFILE +echo "int __b2c__rbuffer_ptr;" >> $g_HFILE +echo "/* Temporary pointer to perform assignments */" >> $g_HFILE +echo "char *__b2c__assign = NULL;" >> $g_HFILE +echo "char *__b2c__split = NULL; char *__b2c__split_tmp = NULL; char *__b2c__split_ptr = NULL;" >> $g_HFILE +echo "char *ERR${g_STRINGSIGN}(int);" >> $g_HFILE +echo "/* Functions for sort */" >> $g_HFILE +echo "int __b2c__sortnrd(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE +echo "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return -1; else return 1;}" >> $g_HFILE +echo "int __b2c__sortnrd_down(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE +echo "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return 1; else return -1;}" >> $g_HFILE +echo "int __b2c__sortnrf(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE +echo "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return -1; else return 1;}" >> $g_HFILE +echo "int __b2c__sortnrf_down(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE +echo "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return 1; else return -1;}" >> $g_HFILE +echo "int __b2c__sortnrl(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE +echo "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return -1; else return 1;}" >> $g_HFILE +echo "int __b2c__sortnrl_down(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE +echo "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return 1; else return -1;}" >> $g_HFILE +echo "int __b2c__sortnri(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE +echo "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return -1; else return 1;}" >> $g_HFILE +echo "int __b2c__sortnri_down(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE +echo "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return 1; else return -1;}" >> $g_HFILE +echo "int __b2c__sortstr(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE +echo "{return strcmp(*(char **) __b2c__a, *(char **) __b2c__b);}" >> $g_HFILE +echo "int __b2c__sortstr_down(const void *__b2c__a, const void *__b2c__b)" >> $g_HFILE +echo "{return strcmp(*(char **) __b2c__b, *(char **) __b2c__a);}" >> $g_HFILE +echo "/* Actual functions */" >> $g_HFILE +echo "char* __b2c__curdir(void){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE*sizeof(char));" >> $g_HFILE +echo "return (getcwd(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE));}" >> $g_HFILE +echo "#define CURDIR${g_STRINGSIGN} __b2c__curdir()" >> $g_HFILE +echo "char* __b2c__reverse(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__s)+2)*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)+1);" >> $g_HFILE +echo "for(__b2c__i=0;__b2c__i<strlen(__b2c__s);__b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__s[strlen(__b2c__s)-1-__b2c__i];}" >> $g_HFILE +echo "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define REVERSE${g_STRINGSIGN}(x) ((x != NULL) ? __b2c__reverse(x) : \"null\")" >> $g_HFILE +echo "char* __b2c__str(double d){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS);" >> $g_HFILE +echo "if(floor(d) == d) snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%ld\", (long)d); else snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%.10g\", d);" >> $g_HFILE +echo "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define STR${g_STRINGSIGN}(x) __b2c__str(x)" >> $g_HFILE +echo "char* __b2c__concat(char *__b2c__first, ...){char *__b2c__tmp; va_list __b2c__ap; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "if(__b2c__first != NULL) { __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__first)+1)*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first);}" >> $g_HFILE +echo "else {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"\");} va_start(__b2c__ap, __b2c__first);" >> $g_HFILE +echo "while((__b2c__tmp = va_arg(__b2c__ap, char *)) != NULL) {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__tmp)+strlen(__b2c__sbuffer[__b2c__sbuffer_ptr])+1)*sizeof(char));" >> $g_HFILE +echo "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__tmp);} va_end(__b2c__ap); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define CONCAT${g_STRINGSIGN}(...) __b2c__concat(__VA_ARGS__, (char*)NULL)" >> $g_HFILE +echo "char* __b2c__left(char *__b2c__src, long __b2c__n){if(__b2c__src == NULL || __b2c__n > strlen(__b2c__src) || __b2c__n < 0) return(__b2c__src);" >> $g_HFILE +echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src, (__b2c__n));" >> $g_HFILE +echo "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define LEFT${g_STRINGSIGN}(__b2c__x, __b2c__y) __b2c__left(__b2c__x, __b2c__y)" >> $g_HFILE +echo "char* __b2c__right(char *__b2c__src, long __b2c__n){if(__b2c__src == NULL || __b2c__n > strlen(__b2c__src) || __b2c__n < 0) return(__b2c__src);" >> $g_HFILE +echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+ strlen(__b2c__src)- __b2c__n);" >> $g_HFILE +echo "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define RIGHT${g_STRINGSIGN}(__b2c__x, __b2c__y) __b2c__right(__b2c__x, __b2c__y)" >> $g_HFILE +echo "char* __b2c__mid(char *__b2c__src, ...){ va_list __b2c__ap; long __b2c__start, __b2c__end; if(__b2c__src == NULL || strlen(__b2c__src) == 0) return(\"\");" >> $g_HFILE +echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); va_start(__b2c__ap, __b2c__src);" >> $g_HFILE +echo "__b2c__start = va_arg(__b2c__ap, long); if(__b2c__start < 1) return(__b2c__src); if(__b2c__start > strlen(__b2c__src)) return(\"\"); __b2c__end = va_arg(__b2c__ap, long); if((__b2c__end) < 0 || (__b2c__end) > strlen(__b2c__src)) __b2c__end = strlen(__b2c__src)-__b2c__start+1;" >> $g_HFILE +echo "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+(long)(__b2c__start)-1, (__b2c__end)); va_end(__b2c__ap); return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define MID${g_STRINGSIGN}(__b2c__string, ...) __b2c__mid(__b2c__string, __VA_ARGS__, -1)" >> $g_HFILE +echo "long __b2c__instr(char *__b2c__first, ...){char *__b2c__tmp; char *__b2c__res; int __b2c__pos; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "va_list __b2c__ap; if(__b2c__first == NULL) return (0); __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" >> $g_HFILE +echo "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" >> $g_HFILE +echo "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL || strlen(__b2c__tmp) == 0) return (0);__b2c__pos = va_arg(__b2c__ap, int);" >> $g_HFILE +echo "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); __b2c__res = strstr(__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos - 1, __b2c__tmp);" >> $g_HFILE +echo "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" >> $g_HFILE +echo "#define INSTR(...) __b2c__instr(__VA_ARGS__, -1)" >> $g_HFILE +echo "long __b2c__instrrev(char *__b2c__first, ...){char *__b2c__tmp; char *__b2c__res = NULL; int __b2c__pos; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "va_list __b2c__ap; if(__b2c__first == NULL) return (0); __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" >> $g_HFILE +echo "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" >> $g_HFILE +echo "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL || strlen(__b2c__tmp) == 0) return (0);__b2c__pos = va_arg(__b2c__ap, int);" >> $g_HFILE +echo "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); while(__b2c__res == NULL && __b2c__pos <= strlen(__b2c__sbuffer[__b2c__sbuffer_ptr])) {" >> $g_HFILE +echo "__b2c__res = strstr(__b2c__sbuffer[__b2c__sbuffer_ptr] + strlen(__b2c__sbuffer[__b2c__sbuffer_ptr]) - __b2c__pos, __b2c__tmp); __b2c__pos+=1;}" >> $g_HFILE +echo "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" >> $g_HFILE +echo "#define INSTRREV(...) __b2c__instrrev(__VA_ARGS__, -1)" >> $g_HFILE +echo "char* __b2c__spc(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 32, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define SPC${g_STRINGSIGN}(x) ((x > -1) ? __b2c__spc(x) : \"\")" >> $g_HFILE +echo "char* __b2c__tab(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 9, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define TAB${g_STRINGSIGN}(x) ((x > -1) ? __b2c__tab(x) : \"\")" >> $g_HFILE +echo "char* __b2c__fill(unsigned long __b2c__x, unsigned char __b2c__y){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__y, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define FILL${g_STRINGSIGN}(x, y) ((y > -1 && y < 256) ? __b2c__fill(x, y) : \"\")" >> $g_HFILE +echo "char* __b2c__chop(char *__b2c__src, ...){char *__b2c__tmp, *__b2c__str; int __b2c__i, __b2c__loc = 0; va_list __b2c__ap; if(strlen(__b2c__src) == 0) return(__b2c__src);" >> $g_HFILE +echo "va_start (__b2c__ap, __b2c__src); __b2c__str = va_arg (__b2c__ap, char*); if(__b2c__str == 0) __b2c__str = (char*)__b2c__chop_default; else __b2c__loc = va_arg (__b2c__ap, int); va_end (__b2c__ap);" >> $g_HFILE +echo "if(__b2c__loc == 0 || __b2c__loc == 1) {while (*__b2c__src != '\0') {for(__b2c__i = 0; __b2c__i < strlen(__b2c__str); __b2c__i++) {if (*__b2c__src == *(__b2c__str+__b2c__i)) {__b2c__src++; break; } }" >> $g_HFILE +echo "if(__b2c__i == strlen(__b2c__str)) break;} if (*__b2c__src == '\0') return(\"\");} __b2c__tmp = __b2c__src + strlen(__b2c__src) - 1;" >> $g_HFILE +echo "if(__b2c__loc == 0 || __b2c__loc == 2) {while (__b2c__tmp >= __b2c__src && *__b2c__tmp != '\0') {for(__b2c__i = 0; __b2c__i < strlen(__b2c__str); __b2c__i++) {if (*__b2c__tmp == *(__b2c__str+__b2c__i))" >> $g_HFILE +echo "{__b2c__tmp--; break; } } if(__b2c__i == strlen(__b2c__str)) break;} } __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" >> $g_HFILE +echo "for(__b2c__i = 0; __b2c__i <= __b2c__tmp - __b2c__src; __b2c__i++) __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__src[__b2c__i];" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i] = '\0'; return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define CHOP${g_STRINGSIGN}(...) __b2c__chop(__VA_ARGS__, 0)" >> $g_HFILE +echo "char* __b2c__replace(char* __b2c__x, char* __b2c__y, char* __b2c__z){" >> $g_HFILE +echo "char *__b2c__tmp, *__b2c__buf, *__b2c__haystack, *__b2c__dup = NULL; __b2c__sbuffer_ptr++;" >> $g_HFILE +echo "if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0; __b2c__haystack = strdup(__b2c__x); __b2c__dup = __b2c__haystack;" >> $g_HFILE +echo "__b2c__buf = calloc(1, sizeof(char)); while((__b2c__tmp = strstr(__b2c__haystack, __b2c__y)) != NULL) {*__b2c__tmp = '\0';" >> $g_HFILE +echo "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + strlen(__b2c__z) + 1)*sizeof(char));" >> $g_HFILE +echo "strcat(__b2c__buf, __b2c__haystack);strcat(__b2c__buf, __b2c__z);__b2c__haystack = __b2c__tmp+strlen(__b2c__y);}" >> $g_HFILE +echo "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + 1)*sizeof(char));strcat(__b2c__buf, __b2c__haystack);" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__buf)+1)*sizeof(char));" >> $g_HFILE +echo "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf);free(__b2c__buf);free(__b2c__dup);return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define REPLACE${g_STRINGSIGN}(x, y, z)((x!=NULL && y!=NULL && z!= NULL) ? __b2c__replace(x, y, z) : 0)" >> $g_HFILE +echo "#define LEN(x) ((x != NULL) ? strlen(x) : 0)" >> $g_HFILE +echo "#define EQUAL(__b2c__x, __b2c__y) ((__b2c__x != NULL && __b2c__y != NULL && __b2c__option_compare == 0) ? !strcmp(__b2c__x, __b2c__y) : ((__b2c__x != NULL && __b2c__y != NULL && __b2c__option_compare == 1) ? !strcasecmp(__b2c__x, __b2c__y) : 0) )" >> $g_HFILE +echo "char * __b2c__getenv(char *__b2c__env){static char * __b2c__tmp; __b2c__tmp = getenv(__b2c__env); if (__b2c__tmp == NULL)" >> $g_HFILE +echo "{return \"\";} return __b2c__tmp;}" >> $g_HFILE +echo "#define GETENVIRON${g_STRINGSIGN}(x) ((x != NULL) ? __b2c__getenv(x) : \"null\")" >> $g_HFILE +echo "#define SETENVIRON(x, y) if(x != NULL && y != NULL) setenv(x, y, 1)" >> $g_HFILE +echo >> $g_HFILE +echo "/* CHAR functions */" >> $g_HFILE +echo "#include <ctype.h>" >> $g_HFILE +echo "char* __b2c__ucase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE +echo "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=toupper(__b2c__s[__b2c__i]);}" >> $g_HFILE +echo "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define UCASE${g_STRINGSIGN}(x) ((x != NULL) ? __b2c__ucase(x) : \"null\")" >> $g_HFILE +echo "char* __b2c__lcase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" >> $g_HFILE +echo "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=tolower(__b2c__s[__b2c__i]);}" >> $g_HFILE +echo "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define LCASE${g_STRINGSIGN}(x) ((x != NULL) ? __b2c__lcase(x) : \"null\")" >> $g_HFILE +echo >> $g_HFILE +echo "/* I/O functions */" >> $g_HFILE +echo "FILE *__b2c__inFile; FILE *__b2c__outFile; int __b2c__Byte; struct dirent *__b2c__dir;" >> $g_HFILE +echo "char* __b2c__dec2hex(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS);" >> $g_HFILE +echo "snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%X\", __b2c__i); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "long __b2c__hex2dec(char *__b2c__h){unsigned int __b2c__i; if(sscanf(__b2c__h, \"%X\", &__b2c__i) == EOF && !__b2c__trap){ERROR = 5;" >> $g_HFILE +echo "fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} return(long)(__b2c__i);}" >> $g_HFILE +echo "unsigned char __b2c__char2asc(char *__b2c__c){return (unsigned char)*__b2c__c;}" >> $g_HFILE +echo "char* __b2c__asc2char(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char));" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, 2*sizeof(char)); snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], 2, \"%c\", __b2c__i);" >> $g_HFILE +echo "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "/* Function FILEEXISTS contributed by Armando Rivera */ " >> $g_HFILE +echo "long __b2c__fileexists(const char *__b2c__x) {struct stat __b2c__buf; if (stat(__b2c__x, &__b2c__buf) != -1) return 1; return 0;}" >> $g_HFILE +echo "#define FILEEXISTS(x) __b2c__fileexists(x)" >> $g_HFILE +echo "long __b2c__filelen(const char *__b2c__x) {struct stat __b2c__buf; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE +echo "if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0) return -1; else return(long)(__b2c__buf.st_size);}" >> $g_HFILE +echo "#define FILELEN(x) __b2c__filelen(x)" >> $g_HFILE +echo "long __b2c__filetype(const char *__b2c__x) {struct stat __b2c__buf; if(__b2c__x == NULL) return 0; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap)" >> $g_HFILE +echo "{ERROR = 24; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE +echo "if (S_ISREG(__b2c__buf.st_mode)) return 1; if (S_ISDIR(__b2c__buf.st_mode)) return 2;" >> $g_HFILE +echo "if (S_ISCHR(__b2c__buf.st_mode)) return 3; if (S_ISBLK(__b2c__buf.st_mode)) return 4; if (S_ISFIFO(__b2c__buf.st_mode)) return 5;" >> $g_HFILE +echo "if (S_ISLNK(__b2c__buf.st_mode)) return 6; if (S_ISSOCK(__b2c__buf.st_mode)) return 7; return 0;}" >> $g_HFILE +echo "#define FILETYPE(x) __b2c__filetype(x)" >> $g_HFILE +echo "long __b2c__search(FILE* __b2c__x, char* __b2c__y){long __b2c__off, __b2c__pos; char* __b2c__ptr; size_t __b2c__tot;" >> $g_HFILE +echo "if(__b2c__x == NULL && !__b2c__trap){ERROR = 2; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE +echo "if(__b2c__y == NULL && !__b2c__trap){ERROR = 25; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE +echo "__b2c__pos = ftell(__b2c__x); __b2c__ptr = (char*)malloc((strlen(__b2c__y)+1)*sizeof(char)); __b2c__off = 0; do {" >> $g_HFILE +echo "fseek(__b2c__x, __b2c__off, SEEK_SET); memset(__b2c__ptr, 0, sizeof(char)*(strlen(__b2c__y)+1));" >> $g_HFILE +echo "__b2c__tot = fread(__b2c__ptr, sizeof(char), strlen(__b2c__y), __b2c__x);__b2c__off+=1;" >> $g_HFILE +echo "} while(!feof(__b2c__x) && strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y)));" >> $g_HFILE +echo "if(strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y))) __b2c__off = 0; fseek(__b2c__x, __b2c__pos, SEEK_SET); free(__b2c__ptr); return (--__b2c__off);}" >> $g_HFILE +echo "#define SEARCH(x, y) __b2c__search(x, y)" >> $g_HFILE +echo "char *__b2c__exec(char *__b2c__x, ...){int __b2c__r, __b2c__len, __b2c__i, __b2c__page; int __b2c__wpipe[2], __b2c__rpipe[2]; char *__b2c__str, *__b2c__ans = NULL; va_list __b2c__ap;" >> $g_HFILE +echo "va_start(__b2c__ap, __b2c__x); __b2c__str = va_arg (__b2c__ap, char*); va_end(__b2c__ap); if (pipe (__b2c__rpipe) < 0 || pipe (__b2c__wpipe) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}}" >> $g_HFILE +echo "if ((__b2c__r = fork ()) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}} else if (__b2c__r == 0){" >> $g_HFILE +echo "close(__b2c__wpipe[1]);close (__b2c__rpipe[0]);dup2 (__b2c__wpipe[0], STDIN_FILENO);close (__b2c__wpipe[0]);dup2 (__b2c__rpipe[1], STDOUT_FILENO);close (__b2c__rpipe[1]); __b2c__r = system (__b2c__x); if(WIFEXITED(__b2c__r)) RETVAL = WEXITSTATUS(__b2c__r); else RETVAL=0; exit(RETVAL);}" >> $g_HFILE +echo "else{close (__b2c__wpipe[0]);close (__b2c__rpipe[1]); __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE*sizeof(char) + 1);__b2c__ans = (char *) malloc ($g_BUFFER_SIZE * sizeof (char)); __b2c__len = 0;__b2c__page = 0;" >> $g_HFILE +echo "if(__b2c__str!=NULL) __b2c__i = write(__b2c__wpipe[1], __b2c__str, strlen(__b2c__str)+1); wait(&RETVAL); RETVAL = WEXITSTATUS(RETVAL); do{__b2c__i = read (__b2c__rpipe[0], __b2c__ans, $g_BUFFER_SIZE);if (__b2c__i == -1 && !__b2c__trap){ERROR=30;fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE +echo "if (__b2c__i == 0)break;if (__b2c__len + __b2c__i > $g_BUFFER_SIZE * __b2c__page + 1){__b2c__page++;__b2c__sbuffer[__b2c__sbuffer_ptr] = realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE * __b2c__page + 1);" >> $g_HFILE +echo "if (__b2c__sbuffer[__b2c__sbuffer_ptr] == NULL && !__b2c__trap){ERROR=6; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len, __b2c__ans, __b2c__i);" >> $g_HFILE +echo " __b2c__len += __b2c__i;} while (__b2c__i > 0); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\0';close (__b2c__wpipe[1]);" >> $g_HFILE +echo "close (__b2c__rpipe[0]);free (__b2c__ans);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define EXEC${g_STRINGSIGN}(...) __b2c__exec(__VA_ARGS__, (char*)NULL)" >> $g_HFILE +echo "#define ENDFILE(x) feof(x)" >> $g_HFILE +echo "#define TELL(x) ftell(x)" >> $g_HFILE +echo "#define HEX${g_STRINGSIGN}(x) __b2c__dec2hex(x)" >> $g_HFILE +echo "#define DEC(x) __b2c__hex2dec(x)" >> $g_HFILE +echo "#define ASC(x) __b2c__char2asc(x)" >> $g_HFILE +echo "#define CHR${g_STRINGSIGN}(__b2c__x) __b2c__asc2char(__b2c__x)" >> $g_HFILE +echo "#define MEMTELL(x) (long)x" >> $g_HFILE +echo >> $g_HFILE +echo "/* Dynamic loading, errors */" >> $g_HFILE +echo "#include <dlfcn.h>" >> $g_HFILE +echo "#include <errno.h>" >> $g_HFILE +echo >> $g_HFILE +echo "/* GETKEY */" >> $g_HFILE +echo "#include <termios.h>" >> $g_HFILE +echo "long __b2c__getch(){long __b2c__ch; struct termios __b2c__oldt, __b2c__newt; tcgetattr(STDIN_FILENO, &__b2c__oldt);" >> $g_HFILE +echo "__b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);" >> $g_HFILE +echo "__b2c__ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt); return __b2c__ch;} " >> $g_HFILE +echo "#define GETKEY __b2c__getch()" >> $g_HFILE +echo "long __b2c__getxy(int __b2c__type){char __b2c__asw[$g_BUFFER_SIZE]; struct termios __b2c__old, __b2c__new; int __b2c__len, __b2c__x, __b2c__y; ssize_t __b2c__tot;" >> $g_HFILE +echo "tcgetattr(STDIN_FILENO, &__b2c__old); __b2c__new = __b2c__old;__b2c__new.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__new);" >> $g_HFILE +echo "__b2c__tot = write(STDOUT_FILENO, \"\033[6n\", strlen(\"\033[6n\")); __b2c__len = read(STDIN_FILENO, __b2c__asw, $g_BUFFER_SIZE);__b2c__asw[__b2c__len] = '\0'; " >> $g_HFILE +echo "tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__old); sscanf(__b2c__asw, \"\033[%d;%dR\", &__b2c__y, &__b2c__x); if (!__b2c__type) return(long)__b2c__x; return(long)__b2c__y;}" >> $g_HFILE +echo "#define GETX __b2c__getxy(0)" >> $g_HFILE +echo "#define GETY __b2c__getxy(1)" >> $g_HFILE +echo "long __b2c__screen(int __b2c__type){long __b2c__x; fprintf(stdout,\"\033[s\"); fprintf(stdout,\"\033[?25l\"); fprintf(stdout,\"\033[999;999H\"); fflush(stdout);" >> $g_HFILE +echo "__b2c__x = __b2c__getxy(__b2c__type); fprintf(stdout,\"\033[u\"); fprintf(stdout,\"\033[?25h\");fflush(stdout); return(__b2c__x); }" >> $g_HFILE +echo "#define COLUMNS __b2c__screen(0)" >> $g_HFILE +echo "#define ROWS __b2c__screen(1)" >> $g_HFILE +echo >> $g_HFILE +echo "/* Constants, logical stuff */" >> $g_HFILE +echo "#define PI 3.14159265" >> $g_HFILE +echo "#define NOT(__b2c__x) (!(__b2c__x))" >> $g_HFILE +echo "#define AND &&" >> $g_HFILE +echo "#define OR ||" >> $g_HFILE +echo "#define EQ ==" >> $g_HFILE +echo "#define IS ==" >> $g_HFILE +echo "#define NE !=" >> $g_HFILE +echo "#define ISNOT !=" >> $g_HFILE +echo "#define TRUE 1" >> $g_HFILE +echo "#define FALSE 0" >> $g_HFILE +echo "#define NL${g_STRINGSIGN} \"\n\"" >> $g_HFILE +echo "#define STRING char*" >> $g_HFILE +echo "#define NUMBER long" >> $g_HFILE +echo "#define FLOATING double" >> $g_HFILE +echo "#define ISTRUE(__b2c__x) (__b2c__x!=0)" >> $g_HFILE +echo "#define ISFALSE(__b2c__x) (__b2c__x==0)" >> $g_HFILE +echo "#define SIZEOF(__b2c__x) sizeof(__b2c__x)" >> $g_HFILE +echo >> $g_HFILE +echo "/* Date and time */" >> $g_HFILE +echo "#include <time.h>" >> $g_HFILE +echo "#define NOW (long)time(NULL)" >> $g_HFILE +echo "long __b2c__time(time_t __b2c__now, int __b2c__which){struct tm *ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS); ts = localtime(&__b2c__now); switch(__b2c__which) { case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%d\", ts); break;" >> $g_HFILE +echo "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%m\", ts); break; case 3: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%Y\", ts); break;" >> $g_HFILE +echo "case 4: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%H\", ts); break; case 5: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%M\", ts); break;" >> $g_HFILE +echo "case 6: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%S\", ts); break; case 7: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%W\", ts); break;}" >> $g_HFILE +echo "return(atol(__b2c__sbuffer[__b2c__sbuffer_ptr]));}" >> $g_HFILE +echo "#define DAY(x) __b2c__time(x, 1)" >> $g_HFILE +echo "#define MONTH(x) __b2c__time(x, 2)" >> $g_HFILE +echo "#define YEAR(x) __b2c__time(x, 3)" >> $g_HFILE +echo "#define HOUR(x) __b2c__time(x, 4)" >> $g_HFILE +echo "#define MINUTE(x) __b2c__time(x, 5)" >> $g_HFILE +echo "#define SECOND(x) __b2c__time(x, 6)" >> $g_HFILE +echo "#define WEEK(x) __b2c__time(x, 7)" >> $g_HFILE +echo "char * __b2c__datename(time_t __b2c__now, int __b2c__which){struct tm *ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS);" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_MAX_DIGITS); ts = localtime(&__b2c__now); switch(__b2c__which){case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%A\", ts); break;" >> $g_HFILE +echo "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_MAX_DIGITS, \"%B\", ts); break;} return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define WEEKDAY${g_STRINGSIGN}(x) __b2c__datename(x, 1)" >> $g_HFILE +echo "#define MONTH${g_STRINGSIGN}(x) __b2c__datename(x, 2)" >> $g_HFILE +echo "unsigned long __b2c__epoch(int __b2c__year, int __b2c__month, int __b2c__day, int __b2c__hour, int __b2c__minute, int __b2c__second){" >> $g_HFILE +echo "struct tm tm; time_t __b2c__t; tm.tm_year = __b2c__year - 1900; tm.tm_mon = __b2c__month - 1; tm.tm_mday = __b2c__day;" >> $g_HFILE +echo "tm.tm_hour = __b2c__hour; tm.tm_min = __b2c__minute; tm.tm_sec = __b2c__second;" >> $g_HFILE +echo "tm.tm_isdst = -1; __b2c__t = mktime(&tm); if (__b2c__t == -1) return (0); return(long) __b2c__t; }" >> $g_HFILE +echo "#define TIMEVALUE(x,y,z,a,b,c) __b2c__epoch(x,y,z,a,b,c)" >> $g_HFILE +echo "char* __b2c__os(void){struct utsname __b2c__buf; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE);" >> $g_HFILE +echo "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_BUFFER_SIZE); if(uname(&__b2c__buf) < 0 && !__b2c__trap) {ERROR = 26; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE +echo "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.sysname); strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], \" \");" >> $g_HFILE +echo "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.machine); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define OS${g_STRINGSIGN} __b2c__os()" >> $g_HFILE +echo >> $g_HFILE +echo "/* Peek and Poke */" >> $g_HFILE +echo "struct stat __b2c__sb;" >> $g_HFILE +echo "void __b2c__memory__check(void* __b2c__x) {if (stat(__b2c__x, &__b2c__sb) == -1 && errno == EFAULT) {ERROR = 1;} }" >> $g_HFILE +echo "long __b2c__malloc(long __b2c__x) {void *__b2c__mem; if(__b2c__x==0) return(0); switch(__b2c__memtype) {case 1: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(char)); break;" >> $g_HFILE +echo "case 2: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(short)); break; case 3: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(int)); break;" >> $g_HFILE +echo "case 4: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(long)); break; case 5: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(float)); break;" >> $g_HFILE +echo "case 6: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(double)); break; case 7: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(char)); break;}" >> $g_HFILE +echo "if(__b2c__mem == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} return(long)__b2c__mem;}" >> $g_HFILE +echo "#define MEMORY(__b2c__x) __b2c__malloc(__b2c__x)" >> $g_HFILE +echo "void *__b2c__realloc(void* __b2c__x, long __b2c__y) {if(__b2c__x == NULL) return (NULL); if(!__b2c__trap) {__b2c__memory__check((char*)__b2c__x);" >> $g_HFILE +echo "if(ERROR) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } switch(__b2c__memtype) {case 1: __b2c__x = realloc((void*)__b2c__x, sizeof(char)*(__b2c__y+1)); break;" >> $g_HFILE +echo "case 2: __b2c__x = realloc((void*)__b2c__x, sizeof(short)*(__b2c__y+1)); break; case 3: __b2c__x = realloc((void*)__b2c__x, sizeof(int)*(__b2c__y+1)); break;" >> $g_HFILE +echo "case 4: __b2c__x = realloc((void*)__b2c__x, sizeof(long)*(__b2c__y+1)); break; case 5: __b2c__x = realloc((void*)__b2c__x, sizeof(float)*(__b2c__y+1)); break;" >> $g_HFILE +echo "case 6: __b2c__x = realloc((void*)__b2c__x, sizeof(double)*(__b2c__y+1)); break; case 7: __b2c__x = realloc((void*)__b2c__x, sizeof(char)*(__b2c__y+1)); break;}" >> $g_HFILE +echo "if(__b2c__x == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} return (__b2c__x);}" >> $g_HFILE +echo "#define RESIZE(__b2c__x, __b2c__y) __b2c__realloc((void*)__b2c__x, __b2c__y)" >> $g_HFILE +echo "char __b2c__peek(char* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((char*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } return((char)*__b2c__x);}" >> $g_HFILE +echo "short __b2c__peeks(short* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((short*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } return((short)*__b2c__x);}" >> $g_HFILE +echo "int __b2c__peeki(int* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((int*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } return((int)*__b2c__x);}" >> $g_HFILE +echo "long __b2c__peekl(long* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((long*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } return((long)*__b2c__x);}" >> $g_HFILE +echo "float __b2c__peekf(float* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((float*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } return((float)*__b2c__x);}" >> $g_HFILE +echo "double __b2c__peekd(double* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((double*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } return((double)*__b2c__x);}" >> $g_HFILE +echo "char __b2c__peekv(char* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((char*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);} } return((char)*__b2c__x);}" >> $g_HFILE +echo "#define PEEK(__b2c__x) (__b2c__memtype==1 ? (unsigned char)__b2c__peek((char*)__b2c__x) : (__b2c__memtype==2 ? (unsigned short)__b2c__peeks((short*)__b2c__x) : (__b2c__memtype==3 ? (unsigned int)__b2c__peeki((int*)__b2c__x) : \\" >> $g_HFILE +echo "(__b2c__memtype==4 ? (unsigned long)__b2c__peekl((long*)__b2c__x) : ( __b2c__memtype==5 ? (float)__b2c__peekf((float*)__b2c__x) : (__b2c__memtype==6 ? (double)__b2c__peekd((double*)__b2c__x) : (unsigned char)__b2c__peekv((char*)__b2c__x) ))))))" >> $g_HFILE +echo "#define ADDRESS(__b2c__x) (long)(&__b2c__x)" >> $g_HFILE +echo >> $g_HFILE +echo "/* Network variables and functions */" >> $g_HFILE +echo "struct timeval __b2c__to; struct hostent *__b2c__he; char *__b2c__host; char *__b2c__port; int __b2c__yes = 1; struct sockaddr_in __b2c__addr;" >> $g_HFILE +echo "int __b2c__result; char __b2c__data_client[$g_BUFFER_SIZE] = { 0 }; char __b2c__data_server[$g_BUFFER_SIZE] = { 0 }; int __b2c__handle;" >> $g_HFILE +echo "long __b2c__netpeek(int __b2c__fd, int __b2c__usec){fd_set __b2c__rfds; struct timeval __b2c__tv; long __b2c__retval; struct termios __b2c__oldt, __b2c__newt;" >> $g_HFILE +echo "if(__b2c__fd == STDIN_FILENO){tcgetattr(STDIN_FILENO, &__b2c__oldt); __b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);}" >> $g_HFILE +echo "FD_ZERO(&__b2c__rfds); FD_SET(__b2c__fd, &__b2c__rfds);__b2c__tv.tv_usec = (__b2c__usec%1000)*1000; __b2c__tv.tv_sec = __b2c__usec/1000;" >> $g_HFILE +echo "__b2c__retval = select(__b2c__fd + 1, &__b2c__rfds, NULL, NULL, &__b2c__tv); if (__b2c__retval == -1 && !__b2c__trap) {ERROR = 16; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR);}" >> $g_HFILE +echo "if(__b2c__fd == STDIN_FILENO){if(__b2c__retval) if(read(__b2c__fd, &__b2c__retval, 1)==0) __b2c__retval=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt);} return(__b2c__retval);}" >> $g_HFILE +echo "#define WAIT(x, y) __b2c__netpeek(x, y)" >> $g_HFILE +echo "char* __b2c__nethost(char* __b2c__host) {int __b2c__y; int __b2c__flag = 0; struct in_addr __b2c__address; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= $g_MAX_BUFFERS) __b2c__sbuffer_ptr=0;" >> $g_HFILE +echo "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], $g_BUFFER_SIZE); memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, $g_BUFFER_SIZE);" >> $g_HFILE +echo "for(__b2c__y=0; __b2c__y < strlen(__b2c__host); __b2c__y++) {if(isalpha(*(__b2c__host+__b2c__y))) {__b2c__flag = 1; break;}} if(__b2c__flag) __b2c__he = gethostbyname(__b2c__host); " >> $g_HFILE +echo "else {if(inet_aton(__b2c__host, &__b2c__address)) __b2c__he = gethostbyaddr((void*)&__b2c__address, sizeof(struct in_addr), AF_INET); } if (__b2c__he == NULL || __b2c__he->h_addr == NULL || __b2c__he->h_name == NULL)" >> $g_HFILE +echo "{if(!__b2c__trap){ERROR = 11; fprintf(stderr, \"%s\n\", ERR${g_STRINGSIGN}(ERROR)); exit(ERROR); } else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"Host not found\", $g_BUFFER_SIZE-1); } else {if(__b2c__flag) {__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr);" >> $g_HFILE +echo "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], inet_ntoa(__b2c__addr.sin_addr), $g_BUFFER_SIZE-1);} else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__he->h_name, $g_BUFFER_SIZE-1);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" >> $g_HFILE +echo "#define HOST${g_STRINGSIGN}(__b2c__x) __b2c__nethost(__b2c__x)" >> $g_HFILE +echo >> $g_HFILE +echo "/* Regex */" >> $g_HFILE +echo "#include <regex.h>" >> $g_HFILE +echo "long __b2c__regex(char* __b2c__x, char* __b2c__y){regex_t __b2c__reg; int __b2c__reti; char __b2c__buf[100]; __b2c__reti = regcomp(&__b2c__reg, __b2c__y, REG_EXTENDED|REG_NOSUB);" >> $g_HFILE +echo "if(!__b2c__trap && __b2c__reti){ERROR=27; fprintf(stderr, \"%s: \", ERR${g_STRINGSIGN}(ERROR)); regerror(__b2c__reti, &__b2c__reg, __b2c__buf, sizeof(__b2c__buf)); fprintf(stderr, \"%s\n\", __b2c__buf);" >> $g_HFILE +echo "exit(ERROR);} __b2c__reti = regexec(&__b2c__reg, __b2c__x, 0, NULL, 0);" >> $g_HFILE +echo "regfree(&__b2c__reg); if( !__b2c__reti ) return (1); else return (0);}" >> $g_HFILE +echo "#define REGEX(x, y) __b2c__regex(x, y)" >> $g_HFILE +echo >> $g_HFILE +echo "/* Declare reserved variable 'ARGUMENT' */" >> $g_HFILE +echo "int __b2c__counter;" >> $g_HFILE +echo "int __b2c__arglen = 0;" >> $g_HFILE +echo "char *ARGUMENT${g_STRINGSIGN};" >> $g_HFILE +echo >> $g_HFILE +echo "/* Initialize stack arrays and pointer */" >> $g_HFILE +echo "char **__b2c__stringstack = NULL; double *__b2c__doublestack = NULL;" >> $g_HFILE +echo "long *__b2c__longstack = NULL; int *__b2c__typestack = NULL;" >> $g_HFILE +echo "int __b2c__stackptr = 0;" >> $g_HFILE +# Signal function +echo "/* Signal trapping activated with TRAP */" >> $g_HFILE +echo "void __b2c__catch_signal(int sig){" >> $g_HFILE +echo "switch (sig) {case SIGABRT: fprintf(stderr, \"ERROR: signal ABORT received - internal error. Try to compile the program with TRAP LOCAL to find the cause.\n\"); break;" >> $g_HFILE +echo "case SIGFPE: fprintf(stderr, \"ERROR: signal for FPE received - division by zero? Examine the calculations in the program.\n\"); break;" >> $g_HFILE +echo "case SIGSEGV: fprintf(stderr, \"ERROR: signal for SEGMENTATION FAULT received - memory invalid or array out of bounds? Try to compile the program with TRAP LOCAL to find the cause.\n\"); break;" >> $g_HFILE +echo "case SIGILL: fprintf(stderr, \"ERROR: signal for ILLEGAL INSTRUCTION received - executing the program on other hardware? Try to recompile the program from scratch.\n\"); break;} exit(sig);}" >> $g_HFILE +# Makedir function +echo "int __b2c__makedir(char* __b2c__in){char *__b2c__i, *__b2c__dir; if(__b2c__in == NULL || strlen(__b2c__in)==0) return 0; if(*__b2c__in != '/'){__b2c__dir = (char*)malloc((strlen(__b2c__in)+2)*sizeof(char));" >> $g_HFILE +echo "strncpy(__b2c__dir, \"./\", 2); __b2c__dir = strcat(__b2c__dir, __b2c__in);} else __b2c__dir = strdup(__b2c__in); __b2c__i = __b2c__dir; do { __b2c__i++; while(*__b2c__i != '/' && *__b2c__i != '\0') __b2c__i++;" >> $g_HFILE +echo "if(*__b2c__i == '/') {*__b2c__i = '\0'; mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); *__b2c__i = '/';} else if (*__b2c__i == '\0') mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);" >> $g_HFILE +echo "if(errno != EEXIST && errno != 0) {free(__b2c__dir); return errno;} } while (*__b2c__i != '\0'); free(__b2c__dir); return 0;}" >> $g_HFILE +# Add error function +echo >> $g_HFILE +echo "/* Initialize error function */" >> $g_HFILE +echo "char *ERR${g_STRINGSIGN}(int __b2c__nr){static char __b2c__warn[$g_BUFFER_SIZE] = { 0 }; const char* __b2c__err;" >> $g_HFILE +echo "switch(__b2c__nr){" >> $g_HFILE +echo "case 0: strcpy(__b2c__warn,\"Success\"); break;" >> $g_HFILE +echo "case 1: strcpy(__b2c__warn,\"Trying to access illegal memory: \"); strncat(__b2c__warn,strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 2: strcpy(__b2c__warn,\"Error opening file: \"); strncat(__b2c__warn,strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 3: strcpy(__b2c__warn, \"Could not open library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, $g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 4: strcpy(__b2c__warn, \"Symbol not found in library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, $g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 5: strcpy(__b2c__warn, \"Wrong hexvalue: \"); strncat(__b2c__warn, strerror(errno), $g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 6: strcpy(__b2c__warn, \"Unable to claim memory.\"); break;" >> $g_HFILE +echo "case 7: strcpy(__b2c__warn, \"Unable to delete file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 8: strcpy(__b2c__warn, \"Could not open directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 9: strcpy(__b2c__warn, \"Unable to rename file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 10: strcpy(__b2c__warn, \"NETWORK argument should contain colon with port number\"); break;" >> $g_HFILE +echo "case 11: strcpy(__b2c__warn, \"Could not resolve hostname!\"); break;" >> $g_HFILE +echo "case 12: strcpy(__b2c__warn, \"Socket error: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 13: strcpy(__b2c__warn, \"Unable to open address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 14: strcpy(__b2c__warn, \"Error reading from socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 15: strcpy(__b2c__warn, \"Error sending to socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 16: strcpy(__b2c__warn, \"Error checking socket: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 17: strcpy(__b2c__warn, \"Unable to bind the specified socket address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 18: strcpy(__b2c__warn, \"Unable to listen to socket address: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 19: strcpy(__b2c__warn, \"Cannot accept incoming connection: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 20: strcpy(__b2c__warn, \"Unable to remove directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 21: strcpy(__b2c__warn, \"Unable to create directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 22: strcpy(__b2c__warn, \"Unable to change to directory: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 23: strcpy(__b2c__warn, \"GETENVIRON argument does not exist as environment variable\"); break;" >> $g_HFILE +echo "case 24: strcpy(__b2c__warn, \"Unable to stat file: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 25: strcpy(__b2c__warn, \"Search contains illegal string\"); break;" >> $g_HFILE +echo "case 26: strcpy(__b2c__warn, \"Cannot return OS name: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 27: strcpy(__b2c__warn, \"Illegal regex expression\"); break;" >> $g_HFILE +echo "case 28: strcpy(__b2c__warn, \"Unable to create bidirectional pipes: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 29: strcpy(__b2c__warn, \"Unable to fork process: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "case 30: strcpy(__b2c__warn, \"Cannot read from pipe: \"); strncat(__b2c__warn, strerror(errno),$g_BUFFER_SIZE-48); break;" >> $g_HFILE +echo "}; ERROR = 0; return(__b2c__warn);}" >> $g_HFILE +echo >> $g_HFILE +echo "/* User program definitions */" >> $g_HFILE + +# Initialize the arrayfiles for DATA statement +echo "char *__b2c__stringarray[] = {" > $STRINGARRAYFILE +echo "double __b2c__floatarray[] = {" > $FLOATARRAYFILE + +# There are no imported symbols yet +g_IMPORTED= + +# Check if the C Preprocessor needs to run +if [[ $g_CPP -eq 1 ]] +then + if [[ -n `which cpp 2>/dev/null` ]] + then + cpp -P -w $g_SOURCEFILE $g_SOURCEFILE.cpp + FEED="${g_SOURCEFILE}.cpp" + g_TMP_FILES="$g_TMP_FILES ${g_SOURCEFILE}.cpp" + else + echo -e "ERROR: the C Preprocessor 'cpp' not found on this system! Exiting..." + exit 1 + fi +else + FEED=${g_SOURCEFILE} +fi +g_CURFILE=${g_SOURCEFILE##*/} + +# Initialize +LEN= +TOTAL= +SEQ= +g_COUNTER=1 + +# Start walking through program +while read -r LINE +do + echo -e -n "\rStarting conversion... $g_COUNTER " + + # Line is not empty? + if [[ -n "$LINE" ]] + then + if [[ "$LINE" = +(* \\) && "$LINE" != +(REM*) && "$LINE" != +(${g_SQUOTESIGN}*) ]] + then + let LEN="${#LINE}"-2 + SEQ="${LINE:0:$LEN}" + TOTAL=$TOTAL$SEQ + else + echo "/* noparse $FEED BACON LINE $g_COUNTER */" >> $g_CFILE + echo "/* noparse $FEED BACON LINE $g_COUNTER */" >> $g_HFILE + TOTAL="${TOTAL}${LINE}" + if [[ "${TOTAL}" != +(REM*) && "${TOTAL}" != +(${g_SQUOTESIGN}*) ]] + then + Tokenize "${TOTAL}" + fi + TOTAL= + fi + fi + ((g_COUNTER+=1)) +done < $FEED + +# Check if enclosed IF/ELIF/ELSE needs to be closed +if [[ $g_IF_PARSE -eq 1 ]] +then + echo "}" >> $g_CFILE +fi + +# Finalize main C-file +echo "__B2C__PROGRAM__EXIT:" >> $g_CFILE +echo "return 0;" >> $g_CFILE +echo "}" >> $g_CFILE + +# Finalize STRING ARRAY file for DATA +echo " \"\" };" >> $STRINGARRAYFILE + +# Finalize FLOAT ARRAY file for DATA +echo " 0.0};" >> $FLOATARRAYFILE + +# Include functions and subs +for i in $g_INCLUDE_FILES +do + echo "#include \"${i}\"" >> $g_HFILE +done + +echo -e "\rStarting conversion... done. " + +# Indentation only when files are preserved +if [[ $g_TMP_PRESERVE -eq 1 ]] +then + if [[ -n `which indent 2>/dev/null` ]] + then + echo -n "Applying indentation... " + for i in $g_TMP_FILES + do + if [[ $i != +(*.cpp) ]] + then + if [[ `uname` = "Darwin" || `uname` = +(*BSD*) ]] + then + mv ${i} "${i}.BAK" + indent "${i}.BAK" ${i} + rm "${i}.BAK" + else + indent $i + rm $i~ + fi + fi + done + echo "done." + else + echo "WARNING: 'indent' not found on this system!" + echo "Generated source code cannot be beautified." + fi +fi + +# Check if we need to run xgettext +if [[ ${g_XGETTEXT} -eq 1 ]] +then + if [[ -n `which xgettext 2>/dev/null` ]] + then + echo -n "Executing xgettext... " + xgettext -d ${g_SOURCEFILE%.*} -s -o ${g_SOURCEFILE%.*}.pot $g_TMP_FILES + if [[ ! -f "${g_SOURCEFILE%.*}.pot" ]] + then + echo "WARNING: catalog file not created!" + else + echo "done." + fi + else + echo "WARNING: 'xgettext' not found on this system!" + fi +fi + +# Start compilation +if [[ $g_NO_COMPILE -eq 0 ]] +then + if [[ -z `which $g_CCNAME 2>/dev/null` ]] + then + echo "WARNING: '$g_CCNAME' not found on this system!" + echo "Generated source code cannot be compiled." + exit 0 + fi + echo -n "Starting compilation... " + + # Make sure GCC uses English localization + export LANG="C" + + $g_CCNAME $g_CCFLAGS -o ${g_SOURCEFILE%.*}$g_BINEXT $g_CFILE $g_LDFLAGS > $g_TEMPDIR/${g_SOURCEFILE##*/}.log 2>&1 + + g_TMP_FILES="$g_TMP_FILES $g_TEMPDIR/${g_SOURCEFILE##*/}.log" + + if [[ -z `cat $g_TEMPDIR/${g_SOURCEFILE##*/}.log` ]] + then + echo "done." + echo "Program '${g_SOURCEFILE%.*}$g_BINEXT' ready." + else + # Only print first error + echo -e "Compiler emits messages!" + while read -r g_ERROR + do + if [[ ( ${g_ERROR} != +(*from *) || ${g_ERROR} = +(*error:*from*) ) && ${g_ERROR} = +(*[0-9]*) && ${g_ERROR} = +(*: error:*) ]] + then + g_ERRORTXT="Cause:\n\t${g_ERROR##*error:}" + g_FILE_LINE=${g_ERROR%%error:*} + break + elif [[ ( ${g_ERROR} != +(*from *) || ${g_ERROR} = +(*Error:*from*) ) && ${g_ERROR} = +(*[0-9]*) && ${g_ERROR} = +(*: Error:*) ]] + then + g_ERRORTXT="Cause:\n\t${g_ERROR##*:}" + g_FILE_LINE=${g_ERROR##*Error: } + break + elif [[ ( ${g_ERROR} != +(*from *) || ${g_ERROR} = +(*warning:*from*) ) && ${g_ERROR} = +(*[0-9]*) && ${g_ERROR} = +(*: warning:*) ]] + then + g_ERRORTXT="Cause:\n\t${g_ERROR##*warning:}" + g_FILE_LINE=${g_ERROR%%warning:*} + break + elif [[ ( ${g_ERROR} != +(*from *) || ${g_ERROR} = +(*:*from*) ) && ${g_ERROR} = +(*[0-9]:*) ]] + then + g_ERRORTXT="Cause:\n\t${g_ERROR##*:}" + g_FILE_LINE=${g_ERROR%:*} + break + fi + done < $g_TEMPDIR/${g_SOURCEFILE##*/}.log + + # Restore $-symbol if there is any + if [[ $g_ERRORTXT = +(*${g_STRINGSIGN}*) ]] + then + LEN=${#g_STRINGSIGN} + POS=0 + until [[ $POS -eq ${#g_ERRORTXT} ]] + do + SUBSTR="${g_ERRORTXT:${POS}:${LEN}}" + if [[ $SUBSTR = $g_STRINGSIGN ]] + then + SUBSTR="${g_ERRORTXT:0:${POS}}$" + ((POS+=${LEN})) + g_ERRORTXT="${SUBSTR}${g_ERRORTXT:${POS}:${#g_ERRORTXT}}" + break + fi + ((POS+=1)) + done + fi + + # Get the file where the error is + g_FILE=${g_FILE_LINE%%:*} + # Tru64Unix helper + g_FILE=${g_FILE%%,*} + + # Non-gcc or parse problem (file does not exist) + if [[ -z $g_ERROR || $g_CCFLAGS = +(*Wall*) || ! -f $g_FILE ]] + then + echo + cat $g_TEMPDIR/${g_SOURCEFILE##*/}.log + echo + else + # Get the erroneous line + if [[ ${g_FILE_LINE} = +(*line*) ]] + then + g_LINE=${g_FILE_LINE#*line} + else + g_LINE=${g_FILE_LINE#*:} + fi + # Initiate error file name and error line in C code + g_FEED=${g_FILE_LINE%%:*} + g_CURLINE=${g_LINE%%:*} + # Remove everything behind last colon + g_LINE=${g_LINE%%:*} + g_COUNTER=1 + while read -r LINE + do + if [[ $LINE = +(*BACON LINE*) && $LINE = +(*noparse*) ]] + then + g_CURLINE=${LINE##*BACON LINE } + g_FEED=${LINE##*noparse } + g_FEED=${g_FEED%% BACON LINE*} + fi + if [[ ${g_COUNTER} -eq ${g_LINE} ]] + then + COUNTER=1 + while read -r LINE + do + if [[ $COUNTER -eq ${g_CURLINE%% *} ]] + then + echo -e "\nProblem:\n\t file '$g_FEED' line $COUNTER: ${LINE}" + echo -e "$g_ERRORTXT\n" + break + fi + ((COUNTER+=1)) + done < $g_FEED + break + fi + ((g_COUNTER+=1)) + done < ${g_FILE} + fi + # Preserve temp files + g_TMP_PRESERVE=1 + fi +fi + +# Cleanup +if [[ $g_TMP_PRESERVE -eq 0 ]] +then + for i in $g_TMP_FILES + do + rm $i + done +elif [[ $g_CPP -eq 1 ]] +then + mv ${g_SOURCEFILE}.cpp $g_TEMPDIR/${g_SOURCEFILE##*/}.cpp +fi + +exit 0 diff --git a/development/bacon/bacon.info b/development/bacon/bacon.info index 92ecdd17043ae..bfae065f11b02 100644 --- a/development/bacon/bacon.info +++ b/development/bacon/bacon.info @@ -1,10 +1,10 @@ PRGNAM="bacon" -VERSION="1.0_build_21" +VERSION="1.0_build_22" HOMEPAGE="http://www.basic-converter.org" DOWNLOAD="http://www.basic-converter.org/stable/bacon.bash \ http://www.basic-converter.org/stable/bacon.bac" -MD5SUM="b673e163a01a1e56ccbcc6a3316f9106 \ - 282ae22316db3424f50d7dac264c267f" +MD5SUM="26336542b2988aa1c55084f5a3351b8d \ + 0422d7dd18c8148c1f93b893a80e7ca6" DOWNLOAD_x86_64="" MD5SUM_x86_64="" MAINTAINER="Steve Pledger" |