'  ____	        ____
' | __ )  __ _ / ___|___  _ __
' |  _ \ / _` | |   / _ \| '_ \
' | |_) | (_| | |__| (_) | | | |   --= A BaCon BASIC-to-C converter =--
' |____/ \__,_|\____\___/|_| |_|
'
' Peter van Eerten - March 2009/December 2018. License: MIT License.
'
'---------------------------------------------------------------------------------------------------------------------
' CREDITS to all people of the BaCon forum. Without them BaCon would not be as it is now.
'---------------------------------------------------------------------------------------------------------------------
'
' Though BaCon is much more powerful than KSH or BASH, this program follows the same structure
' and approach as the existing shell script implementation 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
'---------------------------------------------------------------------------------------------------------------------

' Lower bound of array starts with 1
OPTION BASE 1

' Prevent parse errors
OPTION COLLAPSE TRUE

' We use memory streams
OPTION MEMSTREAM TRUE

' Version of BACON
CONST g_VERSION$ = "3.8.1"

' Our numerical environment is POSIX
SETENVIRON "LC_NUMERIC", "POSIX"

' Verify that BaCon has been compiled with correct version
IF VERSION$ != g_VERSION$ THEN
	EPRINT "System error: this BaCon binary was compiled with a previous BaCon version and therefore may not function correctly."
	EPRINT "Recompile BaCon with the Shell implementation version ", g_VERSION$, "."
	END 1
END IF

' Link flags
g_LDFLAGS$ = "-L. -lbacon -lm"

'  Solaris
IF INSTR(OS$, "SunOS") THEN g_LDFLAGS$ = g_LDFLAGS$ & " -lnsl -lsocket"

' Global to define '$', '%' and '#'-replacement
CONST g_STRINGSIGN$ = "__b2c__string_var"
CONST g_LONGSIGN$ = "__b2c__long_var"
CONST g_FLOATSIGN$ = "__b2c__float_var"
CONST g_RANGEOP$ = "BETWEEN"

' Intense Flag for ASCII editor
DECLARE Color_Intense = 0

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

'----------------------------------------------------------------------------------------------

FUNCTION Get_Var$(VAR arg$ SIZE amount)

	LOCAL var$, result$, record$

	' Get rid of assignment notation
	IF INSTR(arg$[1], "=") THEN
		var$ = LEFT$(arg$[1], INSTR(arg$[1], "=")-1)
	ELSE
		var$ = arg$[1]
	ENDIF

	' Get rid of '*' sign in variable name
	var$ = EXTRACT$(var$, CHR$(42))

	' Get rid of '.' sign in variable name
	IF INSTR(var$, ".") THEN
		record$ = MID$(var$, 1, INSTR(var$, ".")-1)
		var$ = MID$(var$, INSTRREV(var$, ".")+1)
	ELSE
		record$ = g_RECORDVAR$
	ENDIF
	record$ = CHOP$(EXTRACT$(record$,"\\[.*", TRUE))

	' Get rid of array notation
	IF INSTR(var$, "[") THEN var$ = LEFT$(var$, INSTR(var$, "[")-1)

	' Get rid of brackets in case of function pointer or assoc var
	IF INSTR(var$, "(") THEN var$ = LEFT$(var$, INSTR(var$, "(")-1)

	' Get rid of $ sign
	IF INSTR(var$, "$") THEN var$ = REPLACE$(var$, "$", g_STRINGSIGN$)
	IF INSTR(var$, "#") THEN var$ = REPLACE$(var$, "#", g_FLOATSIGN$)
	IF INSTR(var$, "%") THEN var$ = REPLACE$(var$, "%", g_LONGSIGN$)

	result$ = g_ALL_MAIN_VARS$(record$ & var$)
	IF amount > 1 AND NOT(LEN(result$)) THEN result$ = g_ALL_FUNC_VARS$(record$ & var$, arg$[2])

	RETURN result$

END FUNCTION

'----------------------------------------------------------------------------------------------

SUB Save_Main_Var(STRING var$, STRING type$)

	' Make sure the asterisk is attached to type
	IF LEFT$(var$, 1) = "*" THEN
		type$ = type$ & FILL$(COUNT(var$, 42), 42)
		var$ = EXTRACT$(var$, CHR$(42))
	END IF

	' Get rid of assignment notation
	IF INSTR(var$, "=") THEN
		var$ = LEFT$(var$, INSTR(var$, "=")-1)
	ENDIF

	' Get rid of array notation
	IF INSTR(var$, "[") THEN
		var$ = LEFT$(var$, INSTR(var$, "[")-1)
	ENDIF

	g_ALL_MAIN_VARS$(CHOP$(EXTRACT$(g_RECORDVAR$,"\\[.*", TRUE)) & CHOP$(var$)) = type$

END SUB

'----------------------------------------------------------------------------------------------

SUB Save_Func_Var(STRING var$, STRING func$, STRING type$)

	' Make sure the asterisk is attached to type
	IF LEFT$(var$, 1) = "*" THEN
		type$ = type$ & FILL$(COUNT(var$, 42), 42)
		var$ = EXTRACT$(var$, CHR$(42))
	END IF

	' Get rid of assignment notation
	IF INSTR(var$, "=") THEN
		var$ = LEFT$(var$, INSTR(var$, "=")-1)
	ENDIF

	' Get rid of array notation
	IF INSTR(var$, "[") THEN
		var$ = LEFT$(var$, INSTR(var$, "[")-1)
	ENDIF

	g_ALL_FUNC_VARS$(CHOP$(EXTRACT$(g_RECORDVAR$,"\\[.*", TRUE)) & CHOP$(var$), func$) = type$

END SUB

'----------------------------------------------------------------------------------------------

SUB Debug_Vars

	LOCAL xxx, many

	PRINT
	LOOKUP g_ALL_MAIN_VARS$ TO mainvar$ SIZE many
	FOR xxx = 1 TO many
		PRINT g_ALL_MAIN_VARS$(mainvar$[xxx]), ":MAIN:", mainvar$[xxx], " ";
	NEXT

	PRINT
	LOOKUP g_ALL_FUNC_VARS$ TO funcvar$ SIZE many
	FOR xxx = 1 TO many
		PRINT g_ALL_FUNC_VARS$(funcvar$[xxx]), ":", TOKEN$(funcvar$[xxx], 2), ":", TOKEN$(funcvar$[xxx], 1), " ";
	NEXT
	PRINT

END SUB

'----------------------------------------------------------------------------------------------

FUNCTION Register_Numeric$(arg$)

	LOCAL type$

	IF g_OPTION_EXPLICIT$ = "1" OR g_OPTION_EXPLICIT$ = "TRUE" THEN
		EPRINT NL$, "Syntax error: OPTION EXPLICIT forces explicit variable declaration at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	ENDIF

	IF REGEX(arg$, g_FLOATSIGN$ & "$") THEN
		WRITELN "double ", arg$, ";" TO g_HFILE
		Save_Main_Var(arg$, "double")
		type$ = "double"
	ELSE
		WRITELN g_VARTYPE$, " ", arg$, ";" TO g_HFILE
		Save_Main_Var(arg$, g_VARTYPE$)
		type$ = g_VARTYPE$
	ENDIF

	RETURN type$

ENDFUNCTION

SUB Register_String(arg$)

	IF g_OPTION_EXPLICIT$ = "1" OR g_OPTION_EXPLICIT$ = "TRUE" THEN
		EPRINT NL$, "Syntax error: OPTION EXPLICIT forces explicit variable declaration at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	ENDIF

	WRITELN "char* ", arg$, " = NULL;" TO g_HFILE
	Save_Main_Var(arg$, "char*")

END SUB

'----------------------------------------------------------------------------------------------

SUB Save_Dim(STRING var$, STRING dim$)

	IF INSTR(var$, ".") THEN var$ = MID$(var$, INSTR(var$, ".")+1)

	g_ALL_DIM_VARS$(CHOP$(EXTRACT$(g_RECORDVAR$,"\\[.*", TRUE)) & var$ & "_" & g_FUNCNAME$) = dim$

END SUB

FUNCTION Get_Dim$(STRING var$)

	LOCAL record$, result$

	' Get rid of '.' sign in variable name
	IF INSTR(var$, ".") THEN
		record$ = MID$(var$, 1, INSTR(var$, ".")-1)
		var$ = MID$(var$, INSTR(var$, ".")+1)
	ELSE
		record$ = CHOP$(EXTRACT$(g_RECORDVAR$,"\\[.*", TRUE))
	ENDIF

	result$ = g_ALL_DIM_VARS$(record$ & var$ & "_")
	IF NOT(LEN(result$)) THEN result$ = g_ALL_DIM_VARS$(record$ & var$ & "_" & g_FUNCNAME$)

	RETURN result$

END FUNCTION

'----------------------------------------------------------------------------------------------
' Mini parser to obtain chunk of text separated by comma. The comma in function arguments is ignored.

FUNCTION Mini_Parser$(VAR exp$ SIZE amount)

	LOCAL in_string, in_func, escaped, x

	FOR x = 1 TO LEN(exp$[1])
		IF LEN(exp$[2]) THEN
			IF MID$(exp$[1], x, LEN(exp$[2])) = exp$[2] THEN
				IF ISFALSE(in_string) AND ISFALSE(in_func) THEN BREAK
			ENDIF
		ENDIF
		SELECT ASC(MID$(exp$[1], x, 1))
			CASE 44;
			CASE 59
				IF ISFALSE(in_string) AND ISFALSE(in_func) THEN BREAK
			CASE 92
				IF escaped THEN
					escaped = FALSE
				ELSE
					escaped = TRUE
				ENDIF
			CASE 34
				IF ISFALSE(escaped) THEN in_string = NOT(in_string)
				escaped = FALSE
			CASE 40
				IF ISFALSE(in_string) THEN INCR in_func
				escaped = FALSE
			CASE 41
				IF ISFALSE(in_string) THEN DECR in_func
				escaped = FALSE
			DEFAULT
				escaped = FALSE
		END SELECT
	NEXT

	RETURN LEFT$(exp$[1], x-1)

END FUNCTION

'----------------------------------------------------------------------------------------------

FUNCTION Check_String_Type(arg$)

	LOCAL type$

	' Get rid of casting in array indicators
	arg$ = EXTRACT$(arg$, "\\(uint64_t\\)", TRUE)

	' Remove part after '(' in case of function or assoc array
	arg$ = IIF$(TALLY(arg$, "("), TOKEN$(arg$, 1, "("), arg$)

	' It contains double quotes or ends with $
	IF INSTR(arg$, CHR$(34)) OR RIGHT$(arg$, 1) = "$" THEN
		RETURN TRUE
	ELSE
		' Check variable registration
		type$ = Get_Var$(arg$, g_FUNCNAME$)

		' Verify type
		IF INSTR(arg$, g_STRINGSIGN$) OR REGEX(arg$, "gettext|ngettext") OR REGEX(type$, "char\\*|STRING") AND NOT(REGEX(arg$, "\\[.*\\]")) THEN
			RETURN TRUE
		ELSE
			RETURN FALSE
		ENDIF
	ENDIF

END FUNCTION

'----------------------------------------------------------------------------------------------

SUB Print_Element (STRING arg$, STRING std$)

	' Check if var is string var
	IF Check_String_Type(arg$) THEN
		WRITELN "__b2c__assign = (char*)", arg$, "; if(__b2c__assign != NULL) { fputs(__b2c__assign, ", std$, "); }" TO g_CFILE
	ELSE
		WRITELN "fputs(STR", g_STRINGSIGN$, "(", arg$, "), ", std$, ");" TO g_CFILE
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Print(STRING arg$, STRING std$)

	LOCAL exp$, form$, to$, lft$, str$, toparse$, token$
	LOCAL size

	' Check if argument
	IF ISTRUE(LEN(arg$)) THEN

		' Omit semicolon if there is one
		exp$ = CHOP$(IIF$(RIGHT$(arg$, 1) = ";", LEFT$(arg$, LEN(arg$) - 1), arg$))

		' Get rid of escaped quote
		toparse$ = REPLACE$(exp$, CHR$(92) & CHR$(34), "  ")
		' If there is a FORMAT argument
		IF INSTRREV(exp$, " FORMAT ") AND EVEN(COUNT(MID$(toparse$, 1, INSTRREV(toparse$, " FORMAT ")-1), 34)) THEN
			form$ = MID$(exp$, INSTRREV(exp$, " FORMAT ") + 8)
			exp$ = MID$(exp$, 1, INSTRREV(exp$, " FORMAT ") - 1)
			' Optional TO argument?
			IF INSTR(form$, " TO ") THEN
				to$ = MID$(form$, INSTR(form$, " TO ") + 4)
			END IF
		ELIF INSTRREV(exp$, " TO ") AND EVEN(COUNT(MID$(toparse$, 1, INSTRREV(toparse$, " TO ")-1), 34)) THEN
			to$ = MID$(exp$, INSTRREV(exp$, " TO ") + 4)
			form$ = CHR$(34) & "%s" & CHR$(34)
			exp$ = MID$(exp$, 1, INSTRREV(exp$, " TO ") - 1)
		ENDIF
		IF INSTR(to$, " SIZE ") THEN
			size = VAL(MID$(to$, INSTR(to$, " SIZE ") + 6))
			to$ = LEFT$(to$, INSTR(to$, " SIZE ")-1)
		ELSE
			size = g_BUFFER_SIZE
		END IF
		IF LEN(form$) THEN
			IF LEN(to$) THEN
				' Check if var is string var, exclude RECORD elements
				IF REGEX(to$, g_STRINGSIGN$ & "$") AND NOT(INSTR(to$, ".")) THEN
					' Is variable declared already?
					IF NOT(LEN(Get_Var$(to$, g_FUNCNAME$))) THEN
						Register_String(to$)
					ENDIF
				END IF
				WRITELN "__b2c__assign = (char*)calloc(", size, "+1, sizeof(char));" TO g_CFILE
				WRITELN "snprintf(__b2c__assign, ", size, "+1, ", MID$(form$, 1, INSTR(form$, " TO ")-1), ", ", exp$, ");" TO g_CFILE
				' Now see if we have a assoc or a normal variable
				IF REGEX(to$, "\\(.*\\)$") THEN
					lft$ = LEFT$(to$, INSTR(to$, "(") - 1)
					str$ = MID$(to$, INSTR(to$, "(") + 1)
					WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
					WRITELN "if(__b2c__", lft$, "_loc->value != NULL) __b2c__STRFREE(__b2c__", lft$, "_loc->value); __b2c__", lft$, "_loc->value = __b2c__assign; " TO g_CFILE
					' Check for relations
					CALL Relate_Recurse(lft$, str$, to$, -1)
				ELSE
					WRITELN "if(", to$, " != NULL) __b2c__STRFREE(", to$, "); ", to$, " = __b2c__assign;" TO g_CFILE
				END IF
			ELSE
				WRITELN "fprintf(stdout, ", form$, ", ", exp$, ");" TO g_CFILE
			END IF
		ELSE
			' Start miniparser
			WHILE LEN(exp$)
				token$ = Mini_Parser$(exp$)
				Print_Element(CHOP$(token$), std$)
				exp$ = MID$(exp$, LEN(token$)+2)
			WEND
			' If line ends with ';' then skip newline
			IF RIGHT$(arg$, 1) <> ";" THEN WRITELN "fputs(\"\\n\", ", std$, ");" TO g_CFILE
		END IF

	ELSE
		WRITELN "fputs(\"\\n\", ", std$, ");" TO g_CFILE
	END IF

	' Flush print buffer
	WRITELN "fflush(", std$, ");" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Input(STRING arg$)

	LOCAL type$, lft$, str$, token$

	' Check if we have an argument at all
	IF ISFALSE(LEN(arg$)) THEN
		EPRINT NL$, "Syntax error: empty INPUT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	arg$ = CHOP$(arg$)

	' Start miniparser
	WHILE LEN(arg$)
		token$ = Mini_Parser$(arg$)
		arg$ = MID$(arg$, LEN(token$)+2)
		IF LEN(arg$) THEN Print_Element(CHOP$(token$), "stdout")
	WEND

	arg$ = CHOP$(token$)

	' Check if var is string var, exclude RECORD elements
	IF REGEX(arg$, g_STRINGSIGN$ & "$") AND NOT(INSTR(arg$, ".")) THEN
		' Is variable declared already?
		IF NOT(LEN(Get_Var$(arg$, g_FUNCNAME$))) THEN
			Register_String(arg$)
		ENDIF

		' Assume number, exclude RECORD elements
	ELIF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) AND NOT(REGEX(arg$, "\\(.*\\)")) AND NOT(INSTR(arg$, "->")) THEN
		' Is variable declared already?
		IF NOT(LEN(Get_Var$(arg$, g_FUNCNAME$))) THEN
			Register_Numeric$(arg$)
		ENDIF
	END IF

	' Check type of var, string?
	IF Check_String_Type(arg$) THEN

		' Translate function to C function
		WRITELN "__b2c__counter = 1; __b2c__assign = NULL; do {memset(__b2c__input__buffer, 0, ", g_BUFFER_SIZE, "); if(fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", stdin) == NULL && !feof(stdin))" TO g_CFILE
		WRITELN "{if(__b2c__trap){ERROR = 35; if(!__b2c__catch_set) RUNTIMEERROR(\"INPUT\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE

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

		' Now see if we have a assoc or a normal variable
		IF REGEX(arg$, "\\(.*\\)$") THEN
			lft$ = LEFT$(arg$, INSTR(arg$, "(") - 1)
			str$ = MID$(arg$, INSTR(arg$, "(") + 1)
			WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
			WRITELN "if(__b2c__", lft$, "_loc->value != NULL) __b2c__STRFREE(__b2c__", lft$, "_loc->value); __b2c__", lft$, "_loc->value = __b2c__assign; " TO g_CFILE
			' Check for relations
			CALL Relate_Recurse(lft$, str$, arg$, -1)
		ELSE
			WRITELN "if(", arg$, " != NULL) __b2c__STRFREE(", arg$, "); ", arg$, " = __b2c__assign;" TO g_CFILE
		END IF
		' Var is numeric
	ELSE
		' 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, "); if(fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", stdin)==NULL)" TO g_CFILE
		WRITELN "{if(__b2c__trap){ERROR = 35; if(!__b2c__catch_set) RUNTIMEERROR(\"INPUT\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE

		' Get the type
		type$ = Get_Var$(arg$, g_FUNCNAME$)

		' Make sure internal var is copied to var of program
		IF REGEX(arg$, "\\(.*\\)$") THEN
			lft$ = LEFT$(arg$, INSTR(arg$, "(") - 1)
			str$ = MID$(arg$, INSTR(arg$, "(") + 1)
			WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
			IF INSTR(type$, "double") OR INSTR(type$, "float") OR INSTR(type$, "FLOATING") THEN
				WRITELN "__b2c__", lft$, "_loc->value = atof(__b2c__input__buffer);" TO g_CFILE
			ELIF INSTR(type$, "long") OR INSTR(type$, "NUMBER") THEN
				WRITELN "__b2c__", lft$, "_loc->value = atol(__b2c__input__buffer);" TO g_CFILE
			ELSE
				WRITELN "__b2c__", lft$, "_loc->value = atoi(__b2c__input__buffer);" TO g_CFILE
			END IF
			' Check for relations
			CALL Relate_Recurse(lft$, str$, arg$, -1)
		ELSE
			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 IF
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_For(STRING arg$)

	LOCAL var$, tmp$, from$, to$, step$, lft$, str$

	' Check if TO is available
	IF NOT(INSTR(arg$, " TO ")) AND NOT(INSTR(arg$, " DOWNTO ")) AND NOT(INSTR(arg$, " IN ")) THEN
		EPRINT NL$, "Syntax error: missing IN/TO/DOWNTO in FOR statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' What kind of FOR are we dealing with
	IF INSTR(arg$, " TO ") OR INSTR(arg$, " DOWNTO ") THEN
		' Get the variablename without (surrounding) spaces
		var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "=") - 1))
		tmp$ = CHOP$(MID$(arg$, INSTR(arg$, "=") + 1))

		' Get the starting and ending value
		IF INSTR(arg$, " TO ") THEN
			from$ = CHOP$(LEFT$(tmp$, INSTR(tmp$, " TO ") - 1))
			to$ = CHOP$(MID$(tmp$, INSTR(tmp$, " TO ") + 3))
		ELSE
			from$ = CHOP$(LEFT$(tmp$, INSTR(tmp$, " DOWNTO ") - 1))
			to$ = CHOP$(MID$(tmp$, INSTR(tmp$, " DOWNTO ") + 7))
		ENDIF

		' 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
		IF INSTR(arg$, " DOWNTO ") THEN step$ = "-" & step$
	ELSE
		' Get the variablename without (surrounding) spaces
		var$ = CHOP$(LEFT$(arg$, INSTR(arg$, " IN ") - 1))
		tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " IN ") + 4))
		' Check if there is a STEP
		IF ISTRUE(INSTR(tmp$, " STEP ")) THEN
			step$ = CHOP$(MID$(tmp$, INSTR(tmp$, " STEP ") + 5))
			tmp$ = CHOP$(LEFT$(tmp$, INSTR(tmp$, " STEP ") - 1))
		ELSE
			step$ = CHR$(34) & CHR$(32) & CHR$(34)
		END IF
		' Define help variables
		IF LEN(g_FUNCNAME$) > 0 THEN
			IF NOT(INSTR(g_STRINGARGS$, "__b2c__forin_" & var$)) THEN
				g_STRINGARGS$ = g_STRINGARGS$ & " char *__b2c__forin_" & var$ & " = NULL;"
				Save_Func_Var("__b2c__forin_" & var$, g_FUNCNAME$, "char*")
				g_STRINGARGS$ = g_STRINGARGS$ & " char *__b2c__forin_" & var$ & "_ptr = NULL;"
				Save_Func_Var("__b2c__forin_" & var$ & "_ptr", g_FUNCNAME$, "char*")
				g_STRINGARGS$ = g_STRINGARGS$ & " char *__b2c__" & var$ & "_split = NULL;"
				Save_Func_Var("__b2c__" & var$ & "_split", g_FUNCNAME$, "char*")
			END IF
		ELSE
			IF NOT(LEN(Get_Var$("__b2c__forin_" & var$))) THEN
				WRITELN "char *__b2c__forin_", var$, " = NULL;" TO g_HFILE
				Save_Main_Var("__b2c__forin_" & var$, "char*")
				WRITELN "char *__b2c__forin_", var$, "_ptr = NULL;" TO g_HFILE
				Save_Main_Var("__b2c__forin_" & var$ & "_ptr", "char*")
				WRITELN "char *__b2c__", var$, "_split = NULL;" TO g_HFILE
				Save_Main_Var("__b2c__" & var$ & "_split", "char*")
			END IF
		END IF
		WRITELN "if (", tmp$, " != NULL) {__b2c__forin_", var$, " = (char*)calloc(__b2c__len(", tmp$, ")+1, 1); strcpy(__b2c__forin_", var$, ", ", tmp$, ");" TO g_CFILE
		WRITELN "__b2c__forin_", var$, "_ptr = __b2c__forin_", var$, "; }" TO g_CFILE
	END IF

	' Check if var is string var, exclude RECORD elements
	IF REGEX(var$, g_STRINGSIGN$ & "$") AND NOT(INSTR(var$, ".")) THEN
		' Is variable declared already?
		IF NOT(LEN(Get_Var$(var$, g_FUNCNAME$))) THEN
			Register_String(var$)
		END IF

		' Assume number, exclude RECORD elements
	ELIF NOT(REGEX(var$, "\\[.*\\]")) AND NOT(INSTR(var$, ".")) AND NOT(REGEX(var$, "\\(.*\\)")) AND NOT(INSTR(var$, "->")) THEN
		' Is variable declared already?
		IF NOT(LEN(Get_Var$(var$, g_FUNCNAME$))) THEN
			IF REGEX(from$ & to$ & step$, "[0-9]\\.[0-9]") OR REGEX(Get_Var$(step$, g_FUNCNAME$), "double|float|FLOATING") THEN
				WRITELN "double ", var$, ";" TO g_HFILE
				Save_Main_Var(var$, "double")
			ELSE
				Register_Numeric$(var$)
			ENDIF
		END IF
	END IF

	' Check type of var, string?
	IF Check_String_Type(var$) THEN
		WRITELN "while(1){if(", var$, " != NULL) {__b2c__STRFREE(", var$, "); ", var$, " = NULL; } __b2c__is_escaped = 0; __b2c__in_string = 0; __b2c__ctr = 0;" TO g_CFILE
		WRITELN "while(__b2c__forin_", var$, " != NULL && (__b2c__", var$, "_split = strstr(__b2c__forin_", var$, "+__b2c__ctr, ", step$, ")) != NULL) {" TO g_CFILE
		WRITELN "if(__b2c__forin_", var$, "[__b2c__ctr] == 92) { if (!__b2c__is_escaped) { __b2c__is_escaped = 1; } else { __b2c__is_escaped = 0; } }" TO g_CFILE
		WRITELN "else if(__b2c__forin_", var$, "[__b2c__ctr] == __b2c__option_dq) { if (!__b2c__is_escaped && __b2c__option_quoted) { __b2c__in_string = 1 - __b2c__in_string; } __b2c__is_escaped = 0; }" TO g_CFILE
		WRITELN "else { __b2c__is_escaped = 0; } if(__b2c__forin_", var$, "+__b2c__ctr == __b2c__", var$, "_split) { if (__b2c__in_string) { __b2c__ctr += __b2c__len(", step$, "); }" TO g_CFILE
		WRITELN "else { break; } } __b2c__ctr++; } if(__b2c__", var$, "_split == NULL && __b2c__forin_", var$, " == NULL) { break; } if(__b2c__ctr == 0 && __b2c__", var$, "_split == NULL) { __b2c__ctr = strlen(__b2c__forin_", var$, "); }" TO g_CFILE
		WRITELN var$, " = (char*)__b2c_str_realloc(", var$, ", __b2c__ctr+1); memmove(", var$, ", __b2c__forin_", var$, ", __b2c__ctr); __b2c__SETLEN(", var$, ", __b2c__ctr); ", var$, "[__b2c__ctr] = '\\0'; " TO g_CFILE
		WRITELN "if(__b2c__", var$, "_split != NULL) { __b2c__forin_", var$, " = __b2c__", var$, "_split+__b2c__len(", step$, ");} else {__b2c__forin_", var$, " = NULL;} if(__b2c__ctr == 0 && __b2c__collapse) { continue; }" TO g_CFILE
		g_LOOPVAR$[g_LOOPCTR] = var$
	ELSE
		' 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 IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_While(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
		EPRINT NL$, "Syntax 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 LEFT$(g_RELATE$[ctr], LEN(var$)) = var$ THEN
			rel$ = MID$(g_RELATE$[ctr], INSTR(g_RELATE$[ctr], " ")+1)
			WRITELN "__b2c_", rel$, "__loc = __b2c__", rel$, "__add(", str$, ";" TO g_CFILE
			IF INSTR(rel$, g_STRINGSIGN$) THEN
				WRITELN "__b2c__", rel$, "__loc->value = (char*)__b2c_Copy_String(__b2c__", rel$, "__loc->value, ", tmp$, ");" TO g_CFILE
			ELSE
				WRITELN "__b2c__", rel$, "__loc->value = ", tmp$, ";" TO g_CFILE
			END IF
			Relate_Recurse(rel$, str$, tmp$, lvl)
		END IF
	NEXT

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Let(STRING arg$)

	LOCAL in_string, escaped, pos, x, in_func
	LOCAL var$, tmp$, str$, lft$, rel$, ptr$, type$, item$

	' Start miniparser to find last unquoted '='
	FOR x = 1 TO LEN(arg$)
		SELECT ASC(MID$(arg$, x, 1))
			CASE 92
				IF escaped THEN
					escaped = FALSE
				ELSE
					escaped = TRUE
				FI
			CASE 34
				IF ISFALSE(escaped) THEN in_string = NOT(in_string)
				escaped = FALSE
			CASE 40
				IF ISFALSE(in_string) THEN INCR in_func
				escaped = FALSE
			CASE 41
				IF ISFALSE(in_string) THEN DECR in_func
				escaped = FALSE
			CASE 61
				IF ISFALSE(in_string) AND ISFALSE(in_func) THEN pos = x
				escaped = FALSE
			DEFAULT
				escaped = FALSE
		END SELECT
	NEXT

	' Check if there is an assignment at all, if not exit
	IF NOT(pos) THEN
		IF g_IGNORE_PARSE$ = "0" OR g_IGNORE_PARSE$ = "FALSE" THEN
			WRITELN arg$, ";" TO g_CFILE
			EXIT SUB
		ELSE
			EPRINT NL$, "Syntax error: could not parse line ", g_COUNTER, " in file '", g_CURFILE$, "': ", CHR$(34), arg$, CHR$(34)
			END 1
		END IF
	END IF

	' Get the variablename without surrounding spaces
	var$ = CHOP$(LEFT$(arg$, pos - 1))
	tmp$ = CHOP$(MID$(arg$, pos + 1))

	' Check for MEMORY allocation
	IF REGEX(tmp$, "[ \\t]*MEMORY[ \\t]*\\(") OR REGEX(tmp$, "[ \\t]*BLOAD[ \\t]*\\(") THEN g_SEMANTIC_MEMFREE$(var$) = IIF$(LEN(g_SEMANTIC_MEMFREE$(var$)), "", "'" & var$ & "' at line " & STR$(g_COUNTER) & " in file '" & g_CURFILE$ & "'")

	' Check if var is string var, exclude RECORD elements
	IF REGEX(var$, g_STRINGSIGN$ & "$") AND NOT(INSTR(var$, ".")) AND NOT(INSTR(var$, "->")) AND NOT(INSTR(g_DYNAMICARRAYS$, var$ & "@" & g_FUNCNAME$)) THEN
		' Is variable declared already?
		IF NOT(LEN(Get_Var$(var$, g_FUNCNAME$))) THEN
			Register_String(var$)
		END IF

		' Assume number, exclude RECORD elements
	ELIF NOT(REGEX(var$, "\\[.*\\]")) AND NOT(INSTR(var$, ".")) AND var$ != "ERROR" AND var$ != "RETVAL" AND NOT(REGEX(var$, "\\(.*\\)")) AND NOT(INSTR(var$, "->")) AND NOT(INSTR(var$, "=")) THEN

		' Is variable declared already?
		IF NOT(LEN(Get_Var$(var$, g_FUNCNAME$))) THEN
			IF REGEX(tmp$, "[0-9]\\.[0-9]") AND NOT(INSTR(tmp$, CHR$(34))) THEN
				IF g_OPTION_EXPLICIT$ = "1" OR g_OPTION_EXPLICIT$ = "TRUE" THEN
					EPRINT NL$, "Syntax error: OPTION EXPLICIT forces explicit variable declaration at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
					END 1
				ENDIF
				WRITELN "double ", var$, ";" TO g_HFILE
				Save_Main_Var(var$, "double")
			ELSE
				Register_Numeric$(var$)
			ENDIF
		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 "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
		IF INSTR(lft$, g_STRINGSIGN$) THEN
			WRITELN "__b2c__", lft$, "_loc->value = (char*)__b2c_Copy_String(__b2c__", lft$, "_loc->value, ", tmp$, ");" TO g_CFILE
		ELSE
			WRITELN "__b2c__", lft$, "_loc->value = ", tmp$, ";" TO g_CFILE
		END IF
		' Check for relations
		Relate_Recurse(lft$, str$, tmp$, -1)

		' Is there an array variable without subscript?
	ELIF NOT(INSTR(var$, "[")) AND REGEX(g_DYNAMICARRAYS$, " " & var$ & "@" & g_FUNCNAME$ & "$| " & var$ & "@" & g_FUNCNAME$ & " ") THEN
		IF INSTR(var$, g_STRINGSIGN$) THEN WRITELN "for(__b2c__ctr=0; __b2c__ctr<__b2c_array_", var$, "+", g_OPTION_BASE, "; __b2c__ctr++)if(", var$, "[__b2c__ctr]!=NULL){__b2c__STRFREE(", var$, "[__b2c__ctr]);}" TO g_CFILE
		WRITELN "free(", var$, ");" TO g_CFILE
		WRITELN g_WITHVAR$, arg$, ";" TO g_CFILE

		' Do we have a STRING variable or STRING array?
	ELIF Check_String_Type(var$) AND REGEX(var$, g_STRINGSIGN$) THEN
		type$ = Get_Var$(var$, g_FUNCNAME$)
		IF INSTR(type$, "const") THEN
			WRITELN g_WITHVAR$, var$, " = (char*)__b2c__strdup((const char*)", tmp$, ");" TO g_CFILE
			IF ISTRUE(LEN(g_FUNCNAME$)) THEN
				Save_Func_Var(var$, g_FUNCNAME$, CHOP$(EXTRACT$(type$, "const")))
			ELSE
				Save_Main_Var(var$, CHOP$(EXTRACT$(type$, "const")))
			ENDIF
		ELSE
			' Make sure to handle string pointers
			IF Check_String_Type(tmp$) THEN
				WRITELN g_WITHVAR$, var$, " = __b2c_Assign_String(&", g_WITHVAR$, var$, ", ", tmp$, ");" TO g_CFILE
			ELSE
				WRITELN "__b2c__STRFREE(", g_WITHVAR$, var$, ");", g_WITHVAR$, var$, " = __b2c__strdup((const char*)", tmp$, ");" TO g_CFILE
			ENDIF
		ENDIF
		' Also check if string var already is used for IMPORT, if so, perform dlopen again
		ptr$ = EXTRACT$(var$, "[[:punct:]]", TRUE)
		IF LEN(Get_Var$("__b2c__dlopen__pointer_" & ptr$)) THEN
			WRITELN "__b2c__dlopen__pointer_", ptr$, " = dlopen(", var$, ", RTLD_LAZY);" TO g_CFILE
		END IF
		' Check for array member in RECORD
		IF INSTR(var$, ".") AND REGEX(var$, "\\[.*\\]\\.") AND LEN(g_FUNCNAME$) AND NOT(LEN(Get_Var$(var$))) THEN
			IF NOT(INSTR(g_LOCALSTRINGS$, var$)) AND NOT(REGEX(var$, "\\[.*\\]$")) THEN
				g_LOCALSTRINGS$ = var$ & " " & g_LOCALSTRINGS$
			ENDIF
		ENDIF
		' Pointer type
	ELIF TALLY(var$, "->") THEN
		WRITELN g_WITHVAR$, arg$, ";" TO g_CFILE
		' Pointer to string
	ELIF NOT(REGEX(var$, g_STRINGSIGN$ & "$")) AND REGEX(tmp$, g_STRINGSIGN$ & "$") THEN
		type$ = EXTRACT$(Get_Var$(var$, g_FUNCNAME$), "static")
		WRITELN g_WITHVAR$, var$, "=(", type$, ")(", tmp$, ");" TO g_CFILE
		WRITELN "__b2c__INVALIDATE(", tmp$, ");" TO g_CFILE
		' Numeric or foreign type
	ELSE
		type$ = EXTRACT$(Get_Var$(var$, g_FUNCNAME$), "static")
		' Float and not assoc
		IF REGEX(type$, "float|double|FLOATING") AND NOT(INSTR(type$, "*")) THEN
			' Cast the expression to type of variable, divide symbol needs extra cast
			WRITELN g_WITHVAR$, var$, "=(", type$, ")(", DELIM$(tmp$, "/", "/(" & type$ & ")"), ");" TO g_CFILE
		ELIF REGEX(var$, ".*\\[.*\\].*") AND REGEX(type$, ".*\\*.*") THEN
			WRITELN g_WITHVAR$, arg$, ";" TO g_CFILE
			' If var is pointer then skip casting
		ELIF LEN(type$) AND NOT(INSTR(var$, "*")) THEN
			WRITELN g_WITHVAR$, var$, "=(", type$, ")(", tmp$, ");" TO g_CFILE
			' Other type
		ELSE
			WRITELN g_WITHVAR$, arg$, ";" TO g_CFILE
		ENDIF
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Open(STRING arg$)

	LOCAL check, ctr, tmp_ctr, bnd
	LOCAL file$[16], from$[16]
	LOCAL tmp$, mode$, handle$, address$, token$, exp$

	' Check if FOR is available
	IF NOT(INSTR(arg$, " FOR ")) THEN
		EPRINT NL$, "Syntax 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
		EPRINT NL$, "Syntax error: missing AS in OPEN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	ctr = 1
	exp$ = CHOP$(LEFT$(arg$, INSTR(arg$, " FOR ") - 1))

	' Start miniparser
	WHILE LEN(exp$)
		token$ = Mini_Parser$(exp$)
		file$[ctr] = CHOP$(token$)
		INCR ctr
		exp$ = MID$(exp$, LEN(token$)+2)
	WEND
	DECR ctr

	' Get the file, mode and handle
	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 for SOURCE address
	IF INSTR(handle$, "FROM") THEN
		bnd = 1
		exp$ = CHOP$(MID$(handle$, INSTR(handle$, " FROM ") + 6))
		' Start miniparser
		WHILE LEN(exp$)
			token$ = Mini_Parser$(exp$)
			from$[bnd] = CHOP$(token$)
			INCR bnd
			exp$ = MID$(exp$, LEN(token$)+2)
		WEND
		handle$ = CHOP$(LEFT$(handle$, INSTR(handle$, " FROM ")))
		DECR bnd
	END IF

	' Check if var is string var
	IF REGEX(handle$, g_STRINGSIGN$ & "$") AND mode$ <> "MEMORY" THEN
		EPRINT NL$, "Syntax error: variable for OPEN at line ", g_COUNTER, " in file '", g_CURFILE$, "' cannot be string!"
		END 1
	END IF

	' Check for OPEN/CLOSE pair
	g_SEMANTIC_OPENCLOSE$(handle$) = IIF$(LEN(g_SEMANTIC_OPENCLOSE$(handle$)), "", "'" & handle$ & "' at line " & STR$(g_COUNTER) & " in file '" & g_CURFILE$ & "'")

	' Check if variable was declared
	IF NOT(INSTR(handle$, ".")) THEN
		check = LEN(Get_Var$(handle$, g_FUNCNAME$))
	ELSE
		check = TRUE
	FI

	' File or dir?
	IF ISFALSE(check) THEN
		IF g_OPTION_EXPLICIT$ = "1" OR g_OPTION_EXPLICIT$ = "TRUE" THEN
			EPRINT NL$, "Syntax error: OPTION EXPLICIT forces explicit variable declaration at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		ENDIF
	ENDIF

	IF mode$ = "DIRECTORY" THEN
		IF ISFALSE(check) THEN
			WRITELN "DIR* ", handle$, ";" TO g_HFILE
			Save_Main_Var(handle$, "DIR*")
		END IF
	ELIF mode$ = "MEMORY" THEN
		IF ISFALSE(check) THEN
			WRITELN "char* ", handle$, " = NULL;" TO g_HFILE
			Save_Main_Var(handle$, "char*")
		END IF
		IF NOT(LEN(Get_Var$("__b2c_mem_" & handle$, g_FUNCNAME$))) THEN
			WRITELN "long __b2c_mem_", handle$, ";" TO g_HFILE
			Save_Main_Var("__b2c_mem_" & handle$, "long")
		END IF
	ELIF mode$ = "NETWORK" OR mode$ = "SERVER" OR mode$ = "UDP" OR mode$ = "DEVICE" THEN
		IF ISFALSE(check) THEN
			WRITELN "int ", handle$, ";" TO g_HFILE
			Save_Main_Var(handle$, "int")
		END IF
	ELSE
		IF ISFALSE(check) THEN
			WRITELN "FILE* ", handle$, ";" TO g_HFILE
			Save_Main_Var(handle$, "FILE*")
		END IF
	END IF

	' Convert to C syntax
	IF mode$ = "READING" THEN
		WRITELN handle$, " = fopen((const char*)", file$[1], ", \"r\");" TO g_CFILE
		WRITELN "if(", handle$, " == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR READING\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	ELIF mode$ = "WRITING" THEN
		WRITELN handle$, " = fopen((const char*)", file$[1], ", \"w\");" TO g_CFILE
		WRITELN "if(", handle$, " == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR WRITING\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	ELIF mode$ = "APPENDING" THEN
		WRITELN handle$, " = fopen((const char*)", file$[1], ", \"a\");" TO g_CFILE
		WRITELN "if(", handle$, " == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR APPENDING\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	ELIF mode$ = "READWRITE" THEN
		WRITELN handle$, " = fopen((const char*)", file$[1], ", \"r+\");" TO g_CFILE
		WRITELN "if(", handle$, " == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR READWRITE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	ELIF mode$ = "DIRECTORY" THEN
		WRITELN handle$, " = opendir(", file$[1], ");" TO g_CFILE
		WRITELN "if(", handle$, " == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR DIRECTORY\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	ELIF mode$ = "MEMORY" THEN
		IF INSTR(handle$, g_STRINGSIGN$) THEN WRITELN "if(", handle$, "!=NULL) __b2c__STRFREE(", handle$, ");" TO g_CFILE
		WRITELN handle$, " = (char*)", file$[1], "; __b2c_mem_", handle$, " = ", file$[1], ";" TO g_CFILE
		WRITELN "if(__b2c__trap){if(__b2c__memory__check(", handle$, ", sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR MEMORY\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	ELIF mode$ = "NETWORK" THEN
		' Network code
		tmp_ctr = ctr

		' Setup the array of addresses
		WRITELN "__b2c__addr = (struct sockaddr_in*)calloc(", ctr, ", sizeof(*__b2c__addr));" TO g_CFILE
		WHILE tmp_ctr > 0
			WRITELN "if (strstr(", file$[tmp_ctr], ", \":\") == NULL) {ERROR = 10; RUNTIMEERROR(\"OPEN FOR NETWORK\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!__b2c__error_callback && !setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";}" TO g_CFILE
			WRITELN "strncpy(__b2c__data_client, ", file$[tmp_ctr], ", ", 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) RUNTIMEERROR(\"OPEN FOR NETWORK\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
			WRITELN "__b2c__addr[", tmp_ctr-1, "].sin_family = AF_INET; __b2c__addr[", tmp_ctr-1, "].sin_port = htons((long)atol(__b2c__port));" TO g_CFILE
			WRITELN "__b2c__addr[", tmp_ctr-1, "].sin_addr = *((struct in_addr *)__b2c__he->h_addr);" TO g_CFILE
			DECR tmp_ctr
		WEND

		' Create the socket
		IF g_NETWORKTYPE$ = "SCTP" THEN WRITELN handle$, " = socket(AF_INET, ", g_SOCKTYPE$, ", IPPROTO_SCTP);" TO g_CFILE
		ELSE WRITELN handle$, " = socket(AF_INET, ", g_SOCKTYPE$, ", 0);" TO g_CFILE

		WRITELN "if (", handle$, " == -1) {if(__b2c__trap){ERROR = 12;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE

		' Set socket options
		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
		IF g_NETWORKTYPE$ = "BROADCAST" THEN
			WRITELN "setsockopt(", handle$, ", SOL_SOCKET, SO_BROADCAST, &__b2c__yes, sizeof(int));" TO g_CFILE
		ELIF g_NETWORKTYPE$ = "MULTICAST" THEN
			WRITELN "setsockopt(", handle$, ", IPPROTO_IP, IP_MULTICAST_LOOP, &__b2c__yes, sizeof(int));" TO g_CFILE
			WRITELN "__b2c__ttl=", g_MULTICAST_TTL, "; setsockopt(", handle$, ", IPPROTO_IP, IP_MULTICAST_TTL, &__b2c__ttl, sizeof(unsigned char));" TO g_CFILE
		ELIF g_NETWORKTYPE$ = "SCTP" THEN
			WRITELN "memset(&__b2c__initmsg, 0, sizeof(__b2c__initmsg)); __b2c__initmsg.sinit_max_attempts = 3;" TO g_CFILE
			WRITELN "__b2c__initmsg.sinit_num_ostreams = ", g_SCTP_STREAMS, "; __b2c__initmsg.sinit_max_instreams = ", g_SCTP_STREAMS, ";" TO g_CFILE
			WRITELN "setsockopt(", handle$, ", IPPROTO_SCTP, SCTP_INITMSG, &__b2c__initmsg, sizeof(__b2c__initmsg));" TO g_CFILE
		END IF
		WRITELN "setsockopt(", handle$, ", SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int));" TO g_CFILE

		' Do we need to specify a source address?
		IF LEN(from$[bnd]) THEN
			tmp_ctr = bnd
			WRITELN "__b2c__from = (struct sockaddr_in*)calloc(", bnd, ", sizeof(*__b2c__from));" TO g_CFILE
			WHILE tmp_ctr > 0
				WRITELN "strncpy(__b2c__data_client, ", from$[tmp_ctr], ", ", g_BUFFER_SIZE, ");" TO g_CFILE
				IF INSTR(from$[tmp_ctr], ":") THEN
					WRITELN "__b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\");" TO g_CFILE
				ELSE
					WRITELN "__b2c__host = __b2c__data_client;" TO g_CFILE
				END IF
				WRITELN "__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) RUNTIMEERROR(\"OPEN FOR NETWORK\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
				WRITELN "__b2c__from[", tmp_ctr-1, "].sin_family = AF_INET;" TO g_CFILE
				IF INSTR(from$[tmp_ctr], ":") THEN WRITELN "__b2c__from[", tmp_ctr-1, "].sin_port = htons((long)atol(__b2c__port));" TO g_CFILE
				WRITELN "__b2c__from[", tmp_ctr-1, "].sin_addr = *((struct in_addr *)__b2c__he->h_addr);" TO g_CFILE
				DECR tmp_ctr
			WEND

			' Set source address
			IF g_NETWORKTYPE$ = "SCTP" THEN
				' Perform a one-one SCTP bind for multiple homes
				WRITELN "__b2c__result = sctp_bindx(", handle$, ", (struct sockaddr *)__b2c__from, ", bnd, ", SCTP_BINDX_ADD_ADDR);" TO g_CFILE
			ELSE
				' Perform a bind for TCP or UDP
				WRITELN "__b2c__result = bind(", handle$, ", (struct sockaddr *)__b2c__from, sizeof(struct sockaddr));" TO g_CFILE
			END IF
			WRITELN "free(__b2c__from); if(__b2c__result == -1){if(__b2c__trap){ERROR = 17;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
		END IF

		' Setup connection
		IF g_NETWORKTYPE$ = "SCTP" THEN
			' Create a one-one SCTP socket to multiple homes
			WRITELN "#ifdef SCTP_SOCKOPT_CONNECTX_OLD" TO g_CFILE
			WRITELN "__b2c__result = sctp_connectx(", handle$, ", (struct sockaddr *)__b2c__addr, ", ctr, ", NULL);" TO g_CFILE
			WRITELN "#else" TO g_CFILE
			WRITELN "__b2c__result = sctp_connectx(", handle$, ", (struct sockaddr *)__b2c__addr, ", ctr, ");" TO g_CFILE
			WRITELN "#endif" TO g_CFILE
		ELSE
			' Create a socket for TCP or UDP
			WRITELN "__b2c__result = connect(", handle$, ", (struct sockaddr *)__b2c__addr, sizeof(struct sockaddr));" TO g_CFILE
		END IF
		WRITELN "free(__b2c__addr); if(__b2c__result == -1) {if(__b2c__trap){ERROR = 13;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR NETWORK\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	ELIF mode$ = "SERVER" THEN
		' Network code
		address$ = CHOP$(LEFT$(arg$, INSTR(arg$, " FOR ") - 1))
		address$ = REPLACE$(address$, ",", " ")
		address$ = REPLACE$(address$, CHR$(34), " ")
		WRITELN "if(strcmp(__b2c__data_server, \"", address$, "\")) {strncpy(__b2c__data_server, \"", address$, "\", ", g_BUFFER_SIZE, ");" TO g_CFILE

		' Setup the array of addresses
		tmp_ctr = ctr
		' Setup the array of addresses
		WRITELN "__b2c__addr = (struct sockaddr_in*)calloc(", ctr, ", sizeof(*__b2c__addr));" TO g_CFILE
		WHILE tmp_ctr > 0
			WRITELN "if (strstr(", file$[tmp_ctr], ", \":\") == NULL) {ERROR = 10; RUNTIMEERROR(\"OPEN FOR NETWORK\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!__b2c__error_callback && !setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";}" TO g_CFILE
			WRITELN "strncpy(__b2c__data_client, ", file$[tmp_ctr], ", ", g_BUFFER_SIZE, "); __b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\");" TO g_CFILE
			WRITELN "if (strstr(", file$[tmp_ctr], ", \"INADDR_ANY:\") || strstr(", file$[tmp_ctr], ", \"*:\")){__b2c__addr[", tmp_ctr-1, "].sin_addr.s_addr = htonl(INADDR_ANY);} else" TO g_CFILE
			WRITELN "{__b2c__he = gethostbyname(__b2c__host); if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(__b2c__trap){ERROR = 11;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
			WRITELN "__b2c__addr[", tmp_ctr-1, "].sin_addr = *((struct in_addr *)__b2c__he->h_addr);}" TO g_CFILE
			WRITELN "__b2c__addr[", tmp_ctr-1, "].sin_family = AF_INET; __b2c__addr[", tmp_ctr-1, "].sin_port = htons((long)atol(__b2c__port));" TO g_CFILE
			DECR tmp_ctr
		WEND

		IF g_NETWORKTYPE$ = "SCTP" THEN WRITELN "__b2c__handle = socket(AF_INET, ", g_SOCKTYPE$, ", IPPROTO_SCTP);" TO g_CFILE
		ELSE WRITELN "__b2c__handle = socket(AF_INET, ", g_SOCKTYPE$, ", 0);" TO g_CFILE

		WRITELN "if (__b2c__handle == -1) {if(__b2c__trap){ERROR = 12;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE

		IF g_NETWORKTYPE$ = "SCTP" THEN
			WRITELN "memset(&__b2c__initmsg, 0, sizeof(__b2c__initmsg)); __b2c__initmsg.sinit_max_attempts = 3;" TO g_CFILE
			WRITELN "__b2c__initmsg.sinit_num_ostreams = ", g_SCTP_STREAMS, "; __b2c__initmsg.sinit_max_instreams = ", g_SCTP_STREAMS, ";" TO g_CFILE
			WRITELN "setsockopt(", handle$, ", IPPROTO_SCTP, SCTP_INITMSG, &__b2c__initmsg, sizeof(__b2c__initmsg));" TO g_CFILE
		END IF

		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));" TO g_CFILE

		' Setup connection
		IF g_NETWORKTYPE$ = "SCTP" THEN WRITELN "__b2c__result = sctp_bindx(__b2c__handle, (struct sockaddr *)__b2c__addr, ", ctr, ", SCTP_BINDX_ADD_ADDR);" TO g_CFILE
		ELSE WRITELN "__b2c__result = bind(__b2c__handle, (struct sockaddr *)__b2c__addr, sizeof(struct sockaddr));" TO g_CFILE

		WRITELN "free(__b2c__addr); if(__b2c__result == -1){if(__b2c__trap){ERROR = 17;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE

		IF g_NETWORKTYPE$ = "MULTICAST" THEN
			WRITELN "__b2c__imreq.imr_multiaddr.s_addr = inet_addr(__b2c__host); __b2c__imreq.imr_interface.s_addr = INADDR_ANY;" TO g_CFILE
			WRITELN "setsockopt(__b2c__handle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &__b2c__imreq, sizeof(__b2c__imreq));" TO g_CFILE
		END IF

		IF g_NETWORKTYPE$ = "UDP" OR g_NETWORKTYPE$ = "BROADCAST" OR g_NETWORKTYPE$ = "MULTICAST" THEN
			WRITELN handle$, " = __b2c__handle; }" TO g_CFILE
		ELSE
			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) RUNTIMEERROR(\"OPEN FOR SERVER\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} } }" TO g_CFILE
			WRITELN "__b2c__result = accept(__b2c__handle, NULL, 0);" TO g_CFILE
			WRITELN "if(__b2c__result == -1){if(__b2c__trap){ERROR = 19;if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR SERVER\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
			WRITELN handle$, " = __b2c__result;" TO g_CFILE
		END IF
	ELIF mode$ = "DEVICE" THEN
		WRITELN handle$, " = open(", file$[1], ", __b2c__option_open);" TO g_CFILE
		WRITELN "if(", handle$, " < 0){if(__b2c__trap){ERROR = 32; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR DEVICE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	END IF
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Readln(STRING arg$)

	LOCAL dim
	LOCAL lft$, str$

	' Check if FROM is available
	IF NOT(INSTR(arg$, " FROM ")) THEN
		EPRINT NL$, "Syntax 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(Check_String_Type(element$[1])) THEN
		EPRINT NL$, "Syntax 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 REGEX(element$[1], g_STRINGSIGN$ & "$") AND NOT(INSTR(element$[1], ".")) THEN
		IF NOT(LEN(Get_Var$(element$[1], g_FUNCNAME$))) THEN
			Register_String(element$[1])
		ENDIF
	END IF

	' Translate function to C function
	WRITELN "__b2c__counter = 1; __b2c__assign = (char*)calloc(1, sizeof(char)); do{ if(fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", ", element$[3], ") == NULL) break;" TO g_CFILE

	' Make sure internal var is copied to var of program
	WRITELN "__b2c__assign = (char*)realloc(__b2c__assign, ", g_BUFFER_SIZE, "*__b2c__counter*sizeof(char));" TO g_CFILE
	WRITELN "strncat(__b2c__assign, __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(__b2c__assign != NULL) {__b2c__ctr = strlen(__b2c__assign); if(__b2c__ctr > 0 && __b2c__assign[__b2c__ctr-1] == 10) __b2c__assign[__b2c__ctr-1] = '\\0';}" TO g_CFILE

	' Now see if we have a assoc or a normal variable
	IF REGEX(element$[1], "\\(.*\\)$") THEN
		lft$ = LEFT$(element$[1], INSTR(element$[1], "(") - 1)
		str$ = MID$(element$[1], INSTR(element$[1], "(") + 1)
		WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
		WRITELN "if(__b2c__", lft$, "_loc->value != NULL) __b2c__STRFREE(__b2c__", lft$, "_loc->value); __b2c__", lft$, "_loc->value = __b2c__assign; " TO g_CFILE
		' Check for relations
		CALL Relate_Recurse(lft$, str$, element$[1], -1)
	ELSE
		WRITELN "if(", element$[1], " != NULL) __b2c__STRFREE(", element$[1], "); ", element$[1], " = __b2c__assign;" TO g_CFILE
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Writeln(STRING arg$)

	LOCAL var$, to$, token$, org$

	' Check if FROM is available
	IF NOT(INSTR(arg$, " TO ")) THEN
		EPRINT NL$, "Syntax error: missing TO in WRITELN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Get the variablename, filedescriptor
	var$ = CHOP$(LEFT$(arg$, INSTRREV(arg$, " TO ")))
	org$ = var$
	to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " TO ") + 4))

	' Start miniparser
	WHILE LEN(var$)
		token$ = Mini_Parser$(var$)
		Print_Element(CHOP$(token$), to$)
		var$ = MID$(var$, LEN(token$)+2)
	WEND

	IF RIGHT$(org$, 1) <> ";" THEN WRITELN "fputs(\"\\n\", ", to$, ");" TO g_CFILE
	WRITELN "fflush(", to$, ");" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Getbyte(STRING arg$)

	LOCAL var$, to$, size$, type$, chunk$

	' Check if FROM is available
	IF NOT(INSTR(arg$, " FROM ")) THEN
		EPRINT NL$, "Syntax 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 for optional chunksize
	IF INSTR(arg$, " CHUNK ") THEN
		chunk$ = MID$(arg$, INSTR(arg$, " CHUNK ") + 7)
		to$ = MID$(to$, 1, INSTR(to$, " CHUNK ") - 1)
	ELSE
		chunk$ = ""
	END IF

	' Check for optional return variable
	IF INSTR(arg$, " SIZE ") THEN
		size$ = MID$(arg$, INSTR(arg$, " SIZE ") + 6)
		to$ = MID$(to$, 1, INSTR(to$, " SIZE ") - 1)
		IF LEN(chunk$) = 0 THEN
			chunk$ = size$
			size$ = "__b2c__counter"
		ELSE
			chunk$ = MID$(chunk$, 1, INSTR(chunk$, " SIZE ") - 1)
		END IF
	ELSE
		IF LEN(chunk$) = 0 THEN
			chunk$ = "1"
		END IF
		size$ = "__b2c__counter"
	END IF

	' Variable may not be array, these should be defined with DECLARE
	IF LEN(size$) > 0 AND NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) AND NOT(REGEX(size$, "\\(.*\\)")) AND NOT(INSTR(size$, "->")) AND size$ <> "__b2c__counter" THEN
		IF NOT(LEN(Get_Var$(size$, g_FUNCNAME$))) THEN
			Register_Numeric$(size$)
		ENDIF
	END IF

	' Detect type of descriptor
	type$ = Get_Var$(to$, g_FUNCNAME$)

	' Translate function to C function
	WRITELN "if(__b2c__trap){if(__b2c__memory__check((char*)", var$, ", sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"GETBYTE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	IF INSTR(type$, "int") THEN
		WRITELN "if((", size$, " = read(", to$, ", (void*)(", var$, "), ", chunk$, ")) < 0)" TO g_CFILE
		WRITELN "{if(__b2c__trap){ERROR = 34; if(!__b2c__catch_set) RUNTIMEERROR(\"GETBYTE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	ELSE
		WRITELN size$, " = fread((void*)(", var$, "), sizeof(__b2c__MEMTYPE), ", chunk$, ", ", to$, ");" TO g_CFILE
	END IF
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Putbyte(STRING arg$)

	LOCAL var$, to$, size$, type$, chunk$

	' Check if FROM is available
	IF NOT(INSTR(arg$, " TO ")) THEN
		EPRINT NL$, "Syntax 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 for optional chunksize
	IF INSTR(arg$, " CHUNK ") THEN
		chunk$ = MID$(arg$, INSTR(arg$, " CHUNK ") + 7)
		to$ = MID$(to$, 1, INSTR(to$, " CHUNK ") - 1)
	ELSE
		chunk$ = ""
	END IF

	' Check for optional return variable
	IF INSTR(arg$, " SIZE ") THEN
		size$ = MID$(arg$, INSTR(arg$, " SIZE ") + 6)
		to$ = MID$(to$, 1, INSTR(to$, " SIZE ") - 1)
		IF LEN(chunk$) = 0 THEN
			chunk$ = size$
			size$ = "__b2c__counter"
		ELSE
			chunk$ = MID$(chunk$, 1, INSTR(chunk$, " SIZE ") - 1)
		END IF
	ELSE
		IF LEN(chunk$) = 0 THEN
			chunk$ = "1"
		END IF
		size$ = "__b2c__counter"
	END IF

	' Variable may not be array, these should be defined with DECLARE
	IF LEN(size$) > 0 AND NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) AND NOT(REGEX(size$, "\\(.*\\)")) AND NOT(INSTR(size$, "->")) AND size$ <> "__b2c__counter" THEN
		IF NOT(LEN(Get_Var$(size$, g_FUNCNAME$))) THEN
			Register_Numeric$(size$)
		ENDIF
	END IF

	' Detect type of descriptor
	type$ = Get_Var$(to$, g_FUNCNAME$)

	' Translate function to C function
	WRITELN "if(__b2c__trap){if(__b2c__memory__check((char*)", var$, ", sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"PUTBYTE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	IF INSTR(type$, "int") THEN
		WRITELN "if((", size$, " = write(", to$, ", (void*)(", var$, "), ", chunk$, ")) < 0)" TO g_CFILE
		WRITELN "{if(__b2c__trap){ERROR = 34; if(!__b2c__catch_set) RUNTIMEERROR(\"PUTBYTE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	ELSE
		WRITELN size$, " = fwrite((void*)", var$, ", sizeof(__b2c__MEMTYPE), ", chunk$, ", ", to$, "); fflush(", to$, ");" TO g_CFILE
	ENDIF
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Getfile(STRING arg$)

	LOCAL dim
	LOCAL lft$, str$

	' Check if FROM is available
	IF NOT(INSTR(arg$, " FROM ")) THEN
		EPRINT NL$, "Syntax 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

	' Check if var is string var
	IF NOT(Check_String_Type(element$[1])) THEN
		EPRINT NL$, "Syntax error: variable for GETFILE 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 REGEX(element$[1], g_STRINGSIGN$ & "$") AND NOT(INSTR(element$[1], ".")) THEN
		' Is variable declared already?
		IF NOT(LEN(Get_Var$(element$[1], g_FUNCNAME$))) THEN
			Register_String(element$[1])
		ENDIF
	END IF

	' Translate function to C function
	WRITELN "__b2c__dir = readdir(", element$[3], ");" TO g_CFILE

	' Make sure internal var is copied to var of program
	WRITELN "if(__b2c__dir != NULL) __b2c__assign = __b2c__strdup(__b2c__dir->d_name);" TO g_CFILE
	WRITELN "else __b2c__assign = (char*)calloc(1, sizeof(char));" TO g_CFILE
	' Now see if we have a assoc or a normal variable
	IF REGEX(element$[1], "\\(.*\\)$") THEN
		lft$ = LEFT$(element$[1], INSTR(element$[1], "(") - 1)
		str$ = MID$(element$[1], INSTR(element$[1], "(") + 1)
		WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
		WRITELN "if(__b2c__", lft$, "_loc->value != NULL) __b2c__STRFREE(__b2c__", lft$, "_loc->value); __b2c__", lft$, "_loc->value = __b2c__assign; " TO g_CFILE
		' Check for relations
		CALL Relate_Recurse(lft$, str$, element$[1], -1)
	ELSE
		WRITELN "if(", element$[1], " != NULL) __b2c__STRFREE(", element$[1], "); ", element$[1], " = __b2c__assign;" TO g_CFILE
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Receive(STRING arg$)

	LOCAL var$, from$, size$, chunk$, lft$, str$

	' Check if FROM is available
	IF NOT(INSTR(arg$, " FROM ")) THEN
		EPRINT NL$, "Syntax error: missing FROM in RECEIVE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Get the variablename without surrounding spaces
	var$ = CHOP$(LEFT$(arg$, INSTR(arg$, " FROM ")))

	' Get filedescriptor
	from$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6))

	' Check for optional chunksize
	IF INSTR(from$, " CHUNK ") THEN
		chunk$ = MID$(from$, INSTR(from$, " CHUNK ") + 7)
		from$ = MID$(from$, 1, INSTR(from$, " CHUNK ") - 1)
	ELSE
		chunk$ = STR$(g_BUFFER_SIZE)
	END IF

	' Check for optional return variable
	IF INSTR(arg$, " SIZE ") THEN
		from$ = MID$(from$, 1, INSTR(from$, " SIZE ") - 1)
		size$ = MID$(arg$, INSTR(arg$, " SIZE ") + 6)
		IF INSTR(chunk$, " SIZE ") THEN
			chunk$ = MID$(chunk$, 1, INSTR(chunk$, " SIZE ") - 1)
		END IF
	ELSE
		size$ = ""
	ENDIF

	' Variable may not be array, these should be defined with DECLARE
	IF LEN(size$) > 0 AND NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) AND NOT(REGEX(size$, "\\(.*\\)")) AND NOT(INSTR(size$, "->")) THEN
		IF NOT(LEN(Get_Var$(size$, g_FUNCNAME$))) THEN
			Register_Numeric$(size$)
		ENDIF
	ELSE
		IF LEN(size$) = 0 THEN
			size$ = "__b2c__counter"
		ENDIF
	END IF

	' Check if var is string var, exclude RECORD elements
	IF REGEX(var$, g_STRINGSIGN$ & "$") AND NOT(INSTR(var$, ".")) THEN
		IF NOT(LEN(Get_Var$(var$, g_FUNCNAME$))) THEN
			Register_String(var$)
		ENDIF
	END IF

	' Translate function to C function
	WRITELN "__b2c__assign = (char*)calloc((", chunk$, "+1), sizeof(char));" TO g_CFILE
	IF g_NETWORKTYPE$ = "SCTP" THEN
		WRITELN "if((", size$, " = sctp_recvmsg(", from$, ", (void*)__b2c__assign, ", chunk$, ", 0, 0, 0, 0)) < 0)" TO g_CFILE
	ELSE
		WRITELN "if((", size$, " = recv(", from$, ", (void*)__b2c__assign, ", chunk$,", 0)) < 0)" TO g_CFILE
	END IF
	WRITELN "{if(__b2c__trap){ERROR = 14; if(!__b2c__catch_set) RUNTIMEERROR(\"RECEIVE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE

	' Now see if we have a assoc or a normal variable
	IF REGEX(var$, "\\(.*\\)$") THEN
		lft$ = LEFT$(var$, INSTR(var$, "(") - 1)
		str$ = MID$(var$, INSTR(var$, "(") + 1)
		WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
		WRITELN "if(__b2c__", lft$, "_loc->value != NULL) __b2c__STRFREE(__b2c__", lft$, "_loc->value); __b2c__", lft$, "_loc->value = __b2c__assign; " TO g_CFILE
		' Check for relations
		CALL Relate_Recurse(lft$, str$, var$, -1)
	ELIF REGEX(var$, g_STRINGSIGN$ & "$") OR INSTR(MID$(var$, 1, INSTR(var$, "[")), g_STRINGSIGN$) THEN
		WRITELN "if(", var$, " != NULL) __b2c__STRFREE(", var$, "); ", var$, " = __b2c__assign;" TO g_CFILE
	ELSE
		WRITELN "memcpy((void*)", var$, ", (void*)__b2c__assign, ", chunk$, "); free(__b2c__assign);" TO g_CFILE
	END IF
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Send(STRING arg$)

	LOCAL var$, to$, chunk$, size$

	' Check if TO is available
	IF NOT(INSTR(arg$, " TO ")) THEN
		EPRINT NL$, "Syntax 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))

	' Check for optional chunksize
	IF INSTR(to$, " CHUNK ") THEN
		chunk$ = MID$(to$, INSTR(to$, " CHUNK ") + 7)
		to$ = MID$(to$, 1, INSTR(to$, " CHUNK ") - 1)
	ELSE
		chunk$ = "strlen(" & var$ & ")"
	END IF

	' Check for optional return variable
	IF INSTR(arg$, " SIZE ") THEN
		to$ = MID$(to$, 1, INSTR(to$, " SIZE ") - 1)
		size$ = MID$(arg$, INSTR(arg$, " SIZE ") + 6)
		IF INSTR(chunk$, " SIZE ") THEN
			chunk$ = MID$(chunk$, 1, INSTR(chunk$, " SIZE ") - 1)
		END IF
	ELSE
		size$ = ""
	ENDIF

	' Variable may not be array, these should be defined with DECLARE
	IF LEN(size$) > 0 AND NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) AND NOT(REGEX(size$, "\\(.*\\)")) AND NOT(INSTR(size$, "->")) THEN
		IF NOT(LEN(Get_Var$(size$, g_FUNCNAME$))) THEN
			Register_Numeric$(size$)
		ENDIF
	ELSE
		IF LEN(size$) = 0 THEN
			size$ = "__b2c__counter"
		ENDIF
	END IF

	' Translate function to C function
	IF g_NETWORKTYPE$ = "SCTP" THEN
		WRITELN "if((", size$, " = sctp_sendmsg(", to$, ", (void*)", var$, ", ", chunk$, ", NULL, 0, 0, 0, 0, 0, 0)) < 0)" TO g_CFILE
	ELSE
		WRITELN "if((", size$, " = send(", to$, ", (void*)", var$, ", ", chunk$, ", 0)) < 0)" TO g_CFILE
	ENDIF
	WRITELN "{if(__b2c__trap){ERROR = 15; if(!__b2c__catch_set) RUNTIMEERROR(\"SEND\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Getline(STRING arg$)

	LOCAL dim
	LOCAL lft$, str$

	' Check if FROM is available
	IF NOT(INSTR(arg$, " FROM ")) THEN
		EPRINT NL$, "Syntax 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(Check_String_Type(element$[1])) THEN
		EPRINT NL$, "Syntax 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 var is string var, exclude RECORD elements
	IF REGEX(element$[1], g_STRINGSIGN$ & "$") AND NOT(INSTR(element$[1], ".")) THEN
		IF NOT(LEN(Get_Var$(element$[1], g_FUNCNAME$))) THEN
			Register_String(element$[1])
		ENDIF
	END IF

	' Translate function to C function
	WRITELN "if (", element$[3], " == NULL ||", "*" & element$[3] , " == '\\0') {__b2c__assign = (char*)calloc(1, sizeof(char));} 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 "__b2c__assign = strndup(__b2c__assign, (size_t)(", element$[3], "-__b2c__assign+1)); __b2c__assign[strlen(__b2c__assign)-1]='\\0'; if(*", element$[3], " == '\\n') ", element$[3], "++;}" TO g_CFILE

	' Now see if we have a assoc or a normal variable
	IF REGEX(element$[1], "\\(.*\\)$") THEN
		lft$ = LEFT$(element$[1], INSTR(element$[1], "(") - 1)
		str$ = MID$(element$[1], INSTR(element$[1], "(") + 1)
		WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
		WRITELN "if(__b2c__", lft$, "_loc->value != NULL) __b2c__STRFREE(__b2c__", lft$, "_loc->value); __b2c__", lft$, "_loc->value = __b2c__assign; " TO g_CFILE
		' Check for relations
		CALL Relate_Recurse(lft$, str$, element$[1], -1)
	ELSE
		WRITELN "if(", element$[1], " != NULL) __b2c__STRFREE(", element$[1], "); ", element$[1], " = __b2c__assign;" TO g_CFILE
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Putline(STRING arg$)

	LOCAL var$, to$, token$

	' Check if TO is available
	IF NOT(INSTR(arg$, " TO ")) THEN
		EPRINT NL$, "Syntax error: missing TO in PUTLINE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Get text to add
	var$ = CHOP$(LEFT$(arg$, INSTRREV(arg$, " TO ")))

	' Get the filedescriptor
	to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " TO ") + 4))

	' Start miniparser
	WHILE LEN(var$)
		token$ = Mini_Parser$(var$)

		' Check if var is string var
		IF Check_String_Type(token$) THEN
			WRITELN "strcat(", to$, ", ", CHOP$(token$), ");", to$, "+=strlen(", CHOP$(token$), ");" TO g_CFILE
		ELSE
			WRITELN "strcat(", to$, ", STR", g_STRINGSIGN$, "(", CHOP$(token$), "));", to$, "+=strlen(STR", g_STRINGSIGN$, "(", CHOP$(token$), "));" TO g_CFILE
		END IF
		var$ = MID$(var$, LEN(token$)+2)
	WEND

	WRITELN "strcat(", to$, ", \"\\n\"); ", to$, "+=1;" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Import(STRING arg$)

	LOCAL lib$, type$, sym$, tmp$, token$, alias$, ptr$

	' Check if FROM is available
	IF NOT(INSTR(arg$, " FROM ")) THEN
		EPRINT NL$, "Syntax 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$ = CHOP$(LEFT$(arg$, INSTR(arg$, "(") - 1))
		tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6))
		token$ = CHOP$(MID$(arg$, 1, INSTRREV(arg$, ")") - 1))
	ELSE
		sym$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " FROM ") - 1))
		tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6))
		token$ = ""
	END IF

	' Make sure we have a symbol surrounded correctly with double quotes
	sym$ = CHR$(34) & EXTRACT$(sym$, CHR$(34)) & CHR$(34)

	' Check if TYPE is available
	IF NOT(INSTR(arg$, " TYPE ")) THEN
		EPRINT NL$, "Syntax 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$ = EXTRACT$(MID$(type$, INSTR(type$, " ALIAS ") + 7), CHR$(34))
		g_IMPORTED$ = alias$ & " " & g_IMPORTED$
		type$ = LEFT$(type$, INSTR(type$, " ALIAS ") - 1)
	ENDIF

	' 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

		IF NOT(INSTR(OS$, "OSF1")) AND NOT(INSTR(OS$, "BSD")) AND NOT(INSTR(g_LDFLAGS$, "ldl")) THEN g_LDFLAGS$ = g_LDFLAGS$ & " -ldl"

		' Create name from libname
		ptr$ = EXTRACT$(lib$, "[[:punct:]]", TRUE)

		' Check if variable was declared
		IF NOT(LEN(Get_Var$("__b2c__dlopen__pointer_" & ptr$))) THEN
			WRITELN "void* __b2c__dlopen__pointer_", ptr$, " = NULL;" TO g_HFILE
			Save_Main_Var("__b2c__dlopen__pointer_" & ptr$, "void*")
		END IF
		WRITELN "if(__b2c__dlopen__pointer_", ptr$, " == NULL){__b2c__dlopen__pointer_", ptr$, " = dlopen(", lib$, ", RTLD_LAZY); if(__b2c__dlopen__pointer_", ptr$, " == NULL){" TO g_CFILE
		WRITELN "if(__b2c__trap){ERROR = 3;if(!__b2c__catch_set) RUNTIMEERROR(\"IMPORT\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} } }" TO g_CFILE

		' Create prototype
		IF lib$ <> "NULL" THEN
			WRITELN type$, "(*", EXTRACT$(sym$,CHR$(34)), ")(", MID$(token$, INSTR(token$, "(") + 1), ");" TO g_HFILE
			WRITELN "*(", type$, "**) (&", EXTRACT$(sym$,CHR$(34)), ") = (", type$,"*)dlsym(__b2c__dlopen__pointer_", ptr$, ", ", sym$, ");" TO g_CFILE
			WRITELN "if(", sym$, " == NULL) {if(__b2c__trap){ERROR = 4;if(!__b2c__catch_set) RUNTIMEERROR(\"IMPORT\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
		ELSE
			WRITELN type$, "(*", alias$, ")(", MID$(token$, INSTR(token$, "(") + 1), ");" TO g_HFILE
			WRITELN "*(", type$, "**) (&", alias$, ") = (", type$,"*)dlsym(__b2c__dlopen__pointer_", ptr$, ", ", sym$, ");" TO g_CFILE
			WRITELN "if(", alias$, " == NULL) {if(__b2c__trap){ERROR = 4;if(!__b2c__catch_set) RUNTIMEERROR(\"IMPORT\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
		ENDIF
	END IF

	' Make symbol known to parser
	IF lib$ <> "NULL" THEN
		IF INSTR(g_IMPORTED$, " " & EXTRACT$(sym$, CHR$(34)) & " ") THEN
			IF g_SEMANTIC = 0 THEN EPRINT NL$, "Warning: duplicate symbol '", EXTRACT$(sym$, CHR$(34)), "' at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		ELSE
			g_IMPORTED$ = " " & EXTRACT$(sym$,CHR$(34)) & " " & g_IMPORTED$
		ENDIF
		IF LEN(alias$) THEN WRITELN "#define ", alias$, " ", EXTRACT$(sym$,CHR$(34)) TO g_HFILE
	ENDIF

	' Announce runtime error usage
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

END SUB

'----------------------------------------------------------------------------------------------

SUB Normal_Dyn_Array(STRING t$, STRING var$, STRING array$, int is_static, int is_local)

	LOCAL i$, j$, old$, end$, tmp_arr$, idx$, type$, org_type$
	LOCAL nr

	FOR i$ IN var$ STEP ","
		type$ = t$
		g_DYNAMICARRAYS$ = g_DYNAMICARRAYS$ & " " & i$ & "@" & g_FUNCNAME$

		' Initialize strings
		IF REGEX(type$, "STRING|char\\*$") OR INSTR(i$, g_STRINGSIGN$) THEN
			IF INSTR(IIF$(TALLY(array$, "("), TOKEN$(array$, 1, "("), array$), ",") THEN
				EPRINT NL$, "Syntax error: string array cannot have more than one dimension line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			END IF
			IF is_local THEN
				WRITELN type$, "* ", i$, ";" TO g_CFILE
				Save_Func_Var(i$, g_FUNCNAME$, type$)
				g_STRINGARGS$ = g_STRINGARGS$ & " long __b2c_array_" & CHOP$(i$) & ";"
				IF NOT(is_static) THEN
					g_STRINGARRAYS$ = g_STRINGARRAYS$ & " for(__b2c__ctr=0; __b2c__ctr<__b2c_array_" & i$ & "+" & STR$(g_OPTION_BASE) & "; __b2c__ctr++)if(" & i$ & "[__b2c__ctr]!=NULL){__b2c__STRFREE(" & i$ & "[__b2c__ctr]);}"
					g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & i$
				ENDIF
			ELSE
				WRITELN type$, "* ", i$, ";" TO g_HFILE
				Save_Main_Var(i$, type$)
				WRITELN "long __b2c_array_", CHOP$(i$), ";" TO g_HFILE
			END IF
			WRITELN i$, " = (", type$, "*)calloc(", array$, "+", g_OPTION_BASE, ", sizeof(", type$, "));" TO g_CFILE
			WRITELN "__b2c_array_", CHOP$(i$), " = ", array$, ";" TO g_CFILE
			WRITELN "for(__b2c__ctr=0; __b2c__ctr<", array$, "+",  g_OPTION_BASE, "; __b2c__ctr++)", i$, "[__b2c__ctr] = (char*)calloc(1, sizeof(char));" TO g_CFILE
		ELSE
			org_type$ = type$
			' Count elements
			nr = 0
			FOR j$ IN array$ STEP ","
				INCR nr
				type$ = type$ & "*"
			NEXT

			' Declare top most dimension
			IF is_local THEN
				WRITELN type$, " ", i$, ";" TO g_CFILE
				Save_Func_Var(i$, g_FUNCNAME$, org_type$)
				g_STRINGARGS$ = g_STRINGARGS$ & " long __b2c_array_" & CHOP$(i$) & ";"
				IF NOT(is_static) THEN
					g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & i$
				ELSE
					g_STATICARRAYS$ = g_STATICARRAYS$ & " " & i$ & ":" & STR$(COUNT(type$,42))
				ENDIF
			ELSE
				WRITELN type$, " ", i$, ";" TO g_HFILE
				Save_Main_Var(i$, org_type$)
				WRITELN "long __b2c_array_", CHOP$(i$), ";" TO g_HFILE
			END IF
			WRITELN i$, " = (", type$, ")calloc((size_t)", LEFT$(array$, INSTR(array$, ",")-1), "+", g_OPTION_BASE, ", sizeof(", LEFT$(type$, LEN(type$)-1), "));" TO g_CFILE

			' Proceed with other dimensions in array
			IF nr > 1 THEN
				old$ = LEFT$(array$, INSTR(array$, ",")-1)
				tmp_arr$ = MID$(array$, INSTR(array$, ",")+1)
				nr = 0
				idx$ = i$
				end$ = ""
				' Construct array initialization
				FOR j$ IN tmp_arr$ STEP ","
					INCR nr
					IF is_local THEN
						g_STRINGARGS$ = g_STRINGARGS$ & " int __b2c_" & CHOP$(i$) & STR$(nr) & ";"
					ELSE
						WRITELN "int __b2c_", CHOP$(i$), nr, ";" TO g_HFILE
					END IF
					idx$ = idx$ & "[__b2c_" & CHOP$(i$) & STR$(nr) & "]"
					WRITELN "for(__b2c_", CHOP$(i$), nr, " = 0; __b2c_", CHOP$(i$), STR$(nr), " < ", old$, "+", g_OPTION_BASE, "; __b2c_", CHOP$(i$), nr, "++){" TO g_CFILE
					type$ = LEFT$(type$, LEN(type$)-1)
					WRITELN idx$, " = (", type$, ")calloc((size_t)", j$, "+", g_OPTION_BASE, ", sizeof(", LEFT$(type$, LEN(type$)-1), "));" TO g_CFILE
					end$ = end$ & " }"
					old$ = j$
				NEXT
				WRITELN end$ TO g_CFILE
				type$ = LEFT$(type$, LEN(type$)-1)

				' De-initialize array members in case of FUNCTION
				IF is_local AND nr > 0 THEN
					nr = 1
					end$ = ""
					FOR j$ IN LEFT$(array$, INSTRREV(array$, ",")-1) STEP ","
						IF NOT(is_static) THEN
							g_STRINGARRAYS$ = g_STRINGARRAYS$ & " for(__b2c_" & CHOP$(i$) & STR$(nr) & " = 0; __b2c_" & CHOP$(i$) & STR$(nr) & " < " & j$ & "+" & STR$(g_OPTION_BASE) & "; __b2c_" & CHOP$(i$) & STR$(nr) & "++){"
							end$ = end$ & " if(" & idx$ & "!=NULL) __b2c__STRFREE(" & idx$ & "); }"
							idx$ = LEFT$(idx$, INSTRREV(idx$, "[")-1)
							INCR nr
						END IF
					NEXT
					IF NOT(is_static) THEN
						g_STRINGARRAYS$ = g_STRINGARRAYS$ & " " & end$
					ENDIF
				END IF
			END IF
		END IF
	NEXT

END SUB

'----------------------------------------------------------------------------------------------

SUB Record_Dyn_Array(STRING t$, STRING var$, STRING array$, int is_static)

	LOCAL i$, j$, old$, end$, tmp_arr$, idx$, type$, org_type$
	LOCAL nr

	IF LEN(g_RECORDARRAY$) THEN
		EPRINT NL$, "Syntax error: dynamic array cannot be declared within a dynamic RECORD array at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	ENDIF

	FOR i$ IN var$ STEP ","
		type$ = t$
		g_DYNAMICARRAYS$ = g_DYNAMICARRAYS$ & " " & i$ & "@" & g_FUNCNAME$

		' Initialize strings
		IF REGEX(type$, "STRING|char\\*$") OR INSTR(i$, g_STRINGSIGN$) THEN
			IF INSTR(IIF$(TALLY(array$, "("), TOKEN$(array$, 1, "("), array$), ",") THEN
				EPRINT NL$, "Syntax error: string array cannot have more than one dimension line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			END IF
			g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " " & g_RECORDVAR$ & "." & CHOP$(i$) & " = (" & type$ & "*)calloc(" & array$ & "+" & STR$(g_OPTION_BASE) & ", sizeof(" & type$ & "));"
			IF LEN(g_FUNCNAME$) > 0 THEN
				WRITELN type$, "* ", i$, ";" TO g_CFILE
				Save_Func_Var(i$, g_FUNCNAME$, type$)
				g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " long __b2c_array_" & CHOP$(i$) & "; __b2c_array_" & CHOP$(i$) & " = " & array$ & "; for(__b2c__ctr=0; __b2c__ctr<" & array$ & "+" & STR$(g_OPTION_BASE) & "; __b2c__ctr++) " & g_RECORDVAR$ & "." & CHOP$(i$) & "[__b2c__ctr] = (char*)calloc(1, sizeof(char));"
				IF NOT(is_static) THEN
					g_STRINGARRAYS$ = g_STRINGARRAYS$ & " for(__b2c__ctr=0; __b2c__ctr<__b2c_array_" & CHOP$(i$) & "+" & STR$(g_OPTION_BASE) & "; __b2c__ctr++)if(" & g_RECORDVAR$ & "." & CHOP$(i$) & "[__b2c__ctr]!=NULL){__b2c__STRFREE(" & g_RECORDVAR$ & "." & CHOP$(i$) & "[__b2c__ctr]);}"
					g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & g_RECORDVAR$ & "." & CHOP$(i$)
				ENDIF
			ELSE
				WRITELN type$, "* ", i$, ";" TO g_HFILE
				Save_Main_Var(i$, type$)
				g_RECORDEND_HEADER$ = g_RECORDEND_HEADER$ & " long __b2c_array_" & CHOP$(i$) & ";"
				g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " __b2c_array_" & CHOP$(i$) & " = " & array$ & "; for(__b2c__ctr=0; __b2c__ctr<" & array$ & "+" & STR$(g_OPTION_BASE) & "; __b2c__ctr++)" & g_RECORDVAR$ & "." & CHOP$(i$) & "[__b2c__ctr] = (char*)calloc(1, sizeof(char));"
			END IF
		ELSE
			org_type$ = type$
			' Count elements
			nr = 0
			FOR j$ IN array$ STEP ","
				INCR nr
				type$ = type$ & "*"
			NEXT

			' Declare top most dimension
			IF LEN(g_FUNCNAME$) > 0 THEN
				WRITELN type$, " ", i$, ";" TO g_CFILE
				Save_Func_Var(i$, g_FUNCNAME$, org_type$)
				g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " long __b2c_array_" & CHOP$(i$) & ";"
				IF NOT(is_static) THEN
					g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & g_RECORDVAR$ & "." & CHOP$(i$)
				ELSE
					g_STATICARRAYS$ = g_STATICARRAYS$ & " " & g_RECORDVAR$ & "." & CHOP$(i$) & ":" & STR$(COUNT(type$,42))
				ENDIF
			ELSE
				WRITELN type$, " ", i$, ";" TO g_HFILE
				Save_Main_Var(i$, org_type$)
				g_RECORDEND_HEADER$ = g_RECORDEND_HEADER$ & " long __b2c_array_" & CHOP$(i$) & ";"
			END IF
			g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " " & g_RECORDVAR$ & "." & CHOP$(i$) & " = (" & type$ & ")calloc((size_t)" & LEFT$(array$, INSTR(array$, ",")-1) & "+" & STR$(g_OPTION_BASE) & ", sizeof(" & LEFT$(type$, LEN(type$)-1) & "));"

			' Proceed with other dimensions in array
			IF nr > 1 THEN
				old$ = LEFT$(array$, INSTR(array$, ",")-1)
				tmp_arr$ = MID$(array$, INSTR(array$, ",")+1)
				nr = 0
				idx$ = g_RECORDVAR$ & "." & i$
				end$ = ""
				' Construct array initialization
				FOR j$ IN tmp_arr$ STEP ","
					INCR nr
					IF LEN(g_FUNCNAME$) > 0 THEN
						g_STRINGARGS$ = g_STRINGARGS$ & " int __b2c_" & CHOP$(i$) & STR$(nr) & ";"
					ELSE
						g_RECORDEND_HEADER$ = g_RECORDEND_HEADER$ & " int __b2c_" & CHOP$(i$) & STR$(nr) & ";"
					END IF
					idx$ = idx$ & "[__b2c_" & CHOP$(i$) & STR$(nr) & "]"
					g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " for(__b2c_" & CHOP$(i$) & STR$(nr) & " = 0; __b2c_" & CHOP$(i$) & STR$(nr) & " < " & old$ & "+" & STR$(g_OPTION_BASE) & "; __b2c_" & CHOP$(i$) & STR$(nr) & "++){"
					type$ = LEFT$(type$, LEN(type$)-1)
					g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " " & idx$ & " = (" & type$ & ")calloc((size_t)" & j$ & "+" & STR$(g_OPTION_BASE) & ", sizeof(" & LEFT$(type$, LEN(type$)-1) & "));"
					end$ = end$ & " }"
					old$ = j$
				NEXT
				g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & end$
				type$ = LEFT$(type$, LEN(type$)-1)

				' De-initialize array members in case of FUNCTION
				IF LEN(g_FUNCNAME$) > 0 AND nr > 0 THEN
					nr = 1
					end$ = ""
					FOR j$ IN LEFT$(array$, INSTRREV(array$, ",")-1) STEP ","
						IF NOT(is_static) THEN
							g_STRINGARRAYS$ = g_STRINGARRAYS$ & " for(__b2c_" & CHOP$(i$) & STR$(nr) & " = 0; __b2c_" & CHOP$(i$) & STR$(nr) & " < " & j$ & "+" & STR$(g_OPTION_BASE) & "; __b2c_" & CHOP$(i$) & STR$(nr) & "++){"
							end$ = end$ & " if(" & idx$ & "!=NULL) __b2c__STRFREE(" & idx$ & "); }"
							idx$ = LEFT$(idx$, INSTRREV(idx$, "[")-1)
							INCR nr
						END IF
					NEXT
					IF NOT(is_static) THEN
						g_STRINGARRAYS$ = g_STRINGARRAYS$ & " " & end$
					ENDIF
				END IF
			END IF
		END IF
	NEXT

END SUB

'----------------------------------------------------------------------------------------------

SUB Assoc_Array(STRING var$, STRING type$, STRING f$)

	LOCAL str$, value$

	FOR str$ IN var$ STEP ","
		value$ = CHOP$(str$)

		IF NOT(LEN(Get_Var$("__b2c__" & value$ & "_type_" & f$))) THEN
			' Check if name not already global
			IF LEN(f$) AND LEN(Get_Var$(value$)) THEN
				EPRINT NL$, "Syntax error: associative array '", value$, "' in LOCAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!"
				END 1
			ENDIF
			WRITELN "typedef struct __b2c__", value$, "_type_" & f$ & "{char *key; ", type$, " value;} __b2c__", value$, "_type_" & f$ & ";" TO g_HFILE
			WRITELN "__b2c__hashtable_t __b2c__", value$, "_table_", f$, ";" TO g_HFILE
			WRITELN "__b2c__", value$, "_type_" & f$ & " *__b2c__", value$, "_location_" & f$ & " = { NULL }; HASHTABLE_U64 *__b2c__", value$, "_temp_" & f$ & ";" TO g_HFILE
			Save_Main_Var("__b2c__" & value$ & "_type_" & f$, "__b2c__" & value$ & "_type" & f$)

			WRITELN "int __b2c_", f$, "_", value$, "_sort(const void *m1, const void *m2){ " TO g_HFILE
			WRITELN "struct __b2c__", value$, "_type_" & f$ & " *mi1 = (struct __b2c__", value$, "_type_" & f$ & " *) m1;" TO g_HFILE
			WRITELN "struct __b2c__", value$, "_type_" & f$ & " *mi2 = (struct __b2c__", value$, "_type_" & f$ & " *) m2;" TO g_HFILE
			IF INSTR(str$, g_STRINGSIGN$) OR INSTR(type$, "STRING") OR INSTR(type$, "char*") THEN
				WRITELN "if(mi1->value == NULL && mi2->value == NULL) return 0;" TO g_HFILE
				WRITELN "if(mi1->value == NULL && mi2->value != NULL) return 1;" TO g_HFILE
				WRITELN "if(mi1->value != NULL && mi2->value == NULL) return -1;" TO g_HFILE
				WRITELN "return strcmp(mi1->value, mi2->value); }" TO g_HFILE
			ELSE
				WRITELN "if(mi1->value == mi2->value) return 0;" TO g_HFILE
				WRITELN "else {if(mi1->value < mi2->value) return -1;" TO g_HFILE
				WRITELN "else return 1; } }" TO g_HFILE
			ENDIF

			WRITELN "int __b2c_", f$, "_", value$, "_sort_down(const void *m1, const void *m2){ " TO g_HFILE
			WRITELN "struct __b2c__", value$, "_type_" & f$ & " *mi1 = (struct __b2c__", value$, "_type_" & f$ & " *) m1;" TO g_HFILE
			WRITELN "struct __b2c__", value$, "_type_" & f$ & " *mi2 = (struct __b2c__", value$, "_type_" & f$ & " *) m2;" TO g_HFILE
			IF INSTR(str$, g_STRINGSIGN$) OR INSTR(type$, "STRING") OR INSTR(type$, "char*") THEN
				WRITELN "if(mi1->value == NULL && mi2->value == NULL) return 0;" TO g_HFILE
				WRITELN "if(mi1->value == NULL && mi2->value != NULL) return -1;" TO g_HFILE
				WRITELN "if(mi1->value != NULL && mi2->value == NULL) return 1;" TO g_HFILE
				WRITELN "return strcmp(mi2->value, mi1->value); }" TO g_HFILE
			ELSE
				WRITELN "if(mi1->value == mi2->value) return 0;" TO g_HFILE
				WRITELN "else {if(mi1->value < mi2->value) return 1;" TO g_HFILE
				WRITELN "else return -1; } }" TO g_HFILE
			ENDIF

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

			WRITELN "void __b2c__", value$, "__delete_", f$, "(char *idx, ...){__b2c__", value$, "_type_" & f$ & " *result = NULL; char *key = NULL, *nxt; va_list ap; key = __b2c__strdup (idx);" TO g_HFILE
			WRITELN "va_start (ap, idx); while((nxt = va_arg (ap, char *)) != NULL){" TO g_HFILE
			WRITELN "key = (char*)realloc(key, (strlen(key)+strlen(nxt)+2)*sizeof(char)); strcat(key, \" \"); strcat(key, nxt); } va_end (ap);" TO g_HFILE
			WRITELN "result = (__b2c__", value$, "_type_" & f$ & "*)__b2c__hashtable_find(&__b2c__", value$, "_table_", f$, ", (HASHTABLE_U64)(uintptr_t)(key)); if(result != NULL) {" TO g_HFILE
			IF INSTR(str$, g_STRINGSIGN$) OR INSTR(type$, "STRING") OR INSTR(type$, "char*") THEN
				WRITELN "__b2c__STRFREE(result->value);" TO g_HFILE
			ENDIF
			WRITELN "result->value = 0; free(result->key); result->key = NULL; __b2c__hashtable_remove(&__b2c__", value$, "_table_", f$, ", (HASHTABLE_U64)(uintptr_t)(key)); } free(key); }" TO g_HFILE

			WRITELN type$, " _", value$, "_", f$, "(char *idx, ...){__b2c__", value$, "_type_" & f$ & " *result = NULL; char *key = NULL, *nxt; va_list ap;" TO g_HFILE
			WRITELN "va_start (ap, idx); while((nxt = va_arg (ap, char *)) != NULL){if(key == NULL) { key = __b2c__strdup (idx); }" TO g_HFILE
			WRITELN "key = (char*)realloc(key, (strlen(key)+strlen(nxt)+2)*sizeof(char)); strcat(key, \" \"); strcat(key, nxt); } va_end (ap);" TO g_HFILE
			WRITELN "result = (__b2c__", value$, "_type_" & f$ & "*)__b2c__hashtable_find(&__b2c__", value$, "_table_", f$, ", (HASHTABLE_U64)(uintptr_t)( (key == NULL ? idx : key) )); if(key) { free(key); }" TO g_HFILE
			IF INSTR(str$, g_STRINGSIGN$) OR INSTR(type$, "STRING") OR INSTR(type$, "char*") THEN
				WRITELN "if(result == NULL) { return(EmptyString); } return(result->value);}" TO g_HFILE
			ELSE
				WRITELN "if(result == NULL) { return(0); } return(result->value);}" TO g_HFILE
			END IF

			WRITELN "char* __b2c__" & value$ & "_obtain_" & f$ & "(int dummy, ...) {__b2c__" & value$ & "_type_" & f$ & " *result; HASHTABLE_U64 *tmp; char *delim = NULL; long idx, ctr, dlen, len, buck, total=0; va_list ap; buck = __b2c__hashtable_count(&__b2c__", value$, "_table_", f$, ");" TO g_HFILE
			WRITELN "if(buck==0) { return(EmptyString); } va_start(ap, dummy); delim = va_arg(ap, char *); va_end(ap); if(delim == NULL) { delim = __b2c__option_delim; } " TO g_HFILE
			WRITELN "tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__", value$, "_table_", f$, "); dlen = __b2c__len(delim); idx = __sbuf_malloc_handle(dlen); for(ctr = 0; ctr < buck; ctr++)" TO g_HFILE
			WRITELN "{ result = (__b2c__" & value$ & "_type_" & f$ & "*)__b2c__hashtable_find(&__b2c__", value$, "_table_", f$, ", (HASHTABLE_U64)tmp[ctr]); len = __b2c__len(result->key); __sbuf_need_realloc(idx, total+len+dlen);" TO g_HFILE
			WRITELN "memmove(__b2c__sbuffer[idx]+total, result->key, len); total +=len; if(ctr<buck-1) {memmove(__b2c__sbuffer[idx]+total, delim, dlen); total+=dlen;} }" TO g_HFILE
			WRITELN "__b2c__SETLEN(__b2c__sbuffer[idx], total); __b2c__sbuffer[idx][total] = '\\0'; return (char*)(__b2c__sbuffer[idx]); }" TO g_HFILE
		ENDIF

		WRITELN "#ifndef ", value$ TO g_HFILE
		WRITELN "#define __b2c__", value$, "__add(...) __b2c_INDIRECT(__b2c__", value$, "__add_secure_, __b2c_assoc_", value$, ")(1, __VA_ARGS__, NULL)" TO g_HFILE
		WRITELN "#define __b2c__", value$, "__del(...) __b2c_INDIRECT(__b2c__", value$, "__delete_, __b2c_assoc_", value$, ")(__VA_ARGS__, NULL)" TO g_HFILE
		WRITELN "#define ", value$, "(...) __b2c_INDIRECT(_", value$, "_, __b2c_assoc_", value$, ")(__VA_ARGS__, NULL)" TO g_HFILE
		WRITELN "#define __b2c__", value$, "_loc __b2c_INDIRECT(__b2c__", value$, "_location_, __b2c_assoc_", value$, ")" TO g_HFILE
		WRITELN "#define __b2c__", value$, "_tmp __b2c_INDIRECT(__b2c__", value$, "_temp_, __b2c_assoc_", value$, ")" TO g_HFILE
		WRITELN "#define __b2c__", value$, "_tab __b2c_INDIRECT(__b2c__", value$, "_table_, __b2c_assoc_", value$, ")" TO g_HFILE
		WRITELN "#define __b2c__", value$, "_typ __b2c_INDIRECT(__b2c__", value$, "_type_, __b2c_assoc_", value$, ")" TO g_HFILE
		WRITELN "#endif" TO g_HFILE

		IF LEN(f$) THEN
			WRITELN "#undef __b2c_assoc_", value$ TO g_CFILE
			WRITELN "#define __b2c_assoc_", value$, " ", f$ TO g_CFILE
			g_STRINGARRAYS$ = g_STRINGARRAYS$ & " __b2c__" & value$ & "_tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__" & value$ & "_tab); while(__b2c__hashtable_count(&__b2c__" & value$ & "_tab))"
			g_STRINGARRAYS$ = g_STRINGARRAYS$ & " {__b2c__" & value$ & "_loc = (__b2c__" & value$ & "_typ*)__b2c__hashtable_find(&__b2c__" & value$ & "_tab, (HASHTABLE_U64)__b2c__" & value$ & "_tmp[0]); __b2c__" & value$ & "__del(__b2c__" & value$ & "_loc->key);}"
			g_STRINGARRAYS$ = g_STRINGARRAYS$ & " __b2c__hashtable_clear(&__b2c__" & value$ & "_tab); __b2c__hashtable_term(&__b2c__" & value$ & "_tab);"
			Save_Func_Var(value$, f$, type$)
		ELSE
			WRITELN "#define __b2c_assoc_", value$  TO g_HFILE
			Save_Main_Var(value$, type$)
		ENDIF
		WRITELN "__b2c__hashtable_init( &__b2c__", value$, "_tab, sizeof(__b2c__", value$, "_typ), 10240, 0);" TO g_CFILE
	NEXT

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Declare(STRING arg$)

	LOCAL var$, type$, new$, value$, array$, str$
	LOCAL opt

	IF LEN(g_RECORDNAME$) > 0 THEN
		EPRINT NL$, "Syntax error: DECLARE/GLOBAL cannot be used within a RECORD at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	ENDIF

	'  Check on a GLOBAL RECORD
	IF INSTR(arg$, "RECORD ") THEN
		' Translate to C typedef struct
		g_RECORDNAME$ = "RECORD_" & STR$(g_COUNTER)
		WRITELN "typedef struct {" TO g_HFILE
		g_RECORDVAR$ = MID$(CHOP$(arg$), INSTR(CHOP$(arg$), " ") + 1)
		IF INSTR(g_RECORDVAR$, " ARRAY ") THEN
			g_RECORDARRAY$ = MID$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "ARRAY")+5)
			g_RECORDVAR$ = LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "ARRAY")-1) & "[" & g_RECORDARRAY$ & "]"
		ENDIF
		' 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))
			IF INSTR(type$, " ARRAY ") THEN
				array$ = MID$(type$, INSTR(type$, " ARRAY ") + 7)
				type$ = MID$(type$, 1, INSTR(type$, " ARRAY ") - 1)
			ENDIF
		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$)
			IF INSTR(var$, " ARRAY ") THEN
				array$ = MID$(var$, INSTR(var$, " ARRAY ") + 7)
				var$ = MID$(var$, 1, INSTR(var$, " ARRAY ") - 1)
			ELIF REGEX(var$, "DIR$|FILE$|short$|int$|long$|float$|double$|char$|void$|STRING$|NUMBER$|FLOATING$") AND NOT(INSTR(var$, "TYPE")) THEN
				EPRINT NL$, "Syntax error: missing TYPE keyword in DECLARE/GLOBAL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			FI
			type$ = IIF$(INSTR(var$, g_STRINGSIGN$), "char*", IIF$(INSTR(var$, g_FLOATSIGN$), "double", g_VARTYPE$))
		END IF

		' Check if variable was already declared
		IF NOT(INSTR(var$, ".")) AND LEFT$(var$, 1) != "(" THEN
			FOR str$ IN EXTRACT$(var$, " ") STEP ","
				' Check for C keywords
				IF REGEX(str$, g_C_KEYWORDS$) THEN
					EPRINT NL$, "Syntax error: variable '", str$, "' in DECLARE/GLOBAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' is a C keyword or function!"
					END 1
				ENDIF
				' Previous definitions
				IF LEN(Get_Var$(str$, g_FUNCNAME$)) THEN
					EPRINT NL$, "Syntax error: variable '", str$, "' in DECLARE/GLOBAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!"
					END 1
				ENDIF
			NEXT
		END IF

		' Check for associative array
		IF INSTR(arg$, " ASSOC ") THEN
			CALL Assoc_Array(var$, type$, "")

			' Check if it is a known type, if not BaCon has to use external .h file
		ELIF NOT(REGEX(EXTRACT$(type$, "*"), "DIR|FILE|short$|int$|long$|float$|double$|char$|void|STRING|NUMBER|FLOATING")) THEN
			IF INSTR(var$, "=") THEN
				WRITELN type$, " ", var$, ";" TO g_HFILE
				Save_Main_Var(var$, type$)
			ELSE
				FOR str$ IN EXTRACT$(var$, " ") STEP ","
					WRITELN type$, " ", str$, ";" TO g_HFILE
					Save_Main_Var(str$, type$)
				NEXT
			ENDIF

			'  Check for dynamic array declaration
		ELIF ISTRUE(LEN(array$)) THEN
			Normal_Dyn_Array(type$, var$, array$, FALSE, FALSE)

			' Check if var is string var
		ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*$") ) AND NOT(INSTR(var$, "=")) THEN
			FOR str$ IN EXTRACT$(var$, " ") STEP ","
				IF NOT(LEN(Get_Var$(str$, g_FUNCNAME$))) THEN
					IF INSTR(str$, "[") THEN
						WRITELN "char *", REPLACE$(str$, "]", "+" & STR$(g_OPTION_BASE) & "]"), " = { NULL };" TO g_HFILE
						' Determine dimension needed for SORT
						value$ = MID$(str$, INSTR(str$, "[")+1)
						Save_Dim(LEFT$(str$, INSTR(str$, "[") - 1), LEFT$(value$, INSTR(value$, "]") - 1))
						' Save type
						Save_Main_Var(str$, "char**")
					ELIF INSTR(str$, "(") THEN
						' Function pointer
						WRITELN type$, " ", str$, ";" TO g_HFILE
						str$ = LEFT$(str$, INSTRREV(str$, "(")-1)
						Save_Main_Var(EXTRACT$(str$, "[\\(\\*\\)]", TRUE), "void*")
					ELSE
						WRITELN "char *", str$, " = NULL;" TO g_HFILE
						Save_Main_Var(str$, "char*")
					END IF
				END IF
			NEXT
			' Var is string array assignment
		ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*$") ) AND INSTR(var$, "=") THEN
			IF NOT(LEN(Get_Var$(var$, g_FUNCNAME$))) THEN
				IF INSTR(var$, "[") THEN
					WRITELN "char *", LEFT$(var$, INSTR(var$, "[") - 1), "[", STR$(COUNT(var$, 44)+1), "] = { NULL };" TO g_HFILE
					' Determine dimension needed for SORT
					Save_Dim(LEFT$(var$, INSTR(var$, "[") - 1), STR$(COUNT(var$, 44)+1))
					' Save type
					Save_Main_Var(var$, "char**")
					' Copy elements
					opt = g_OPTION_BASE
					array$ = MID$(var$, INSTR(var$, "{")+1)
					WHILE LEN(array$)
						str$ = Mini_Parser$(array$)
						WRITELN LEFT$(var$, INSTR(var$, "[")-1), "[", opt, "] = __b2c_Copy_String(", LEFT$(var$, INSTR(var$, "[")-1), "[", opt, "], ", CHOP$(str$, "}", 2), ");" TO g_CFILE
						array$ = MID$(array$, LEN(str$)+2)
						INCR opt
					WEND
				ELSE
					WHILE LEN(var$)
						str$ = Mini_Parser$(var$)
						WRITELN "static char *", LEFT$(str$, INSTR(str$, "=")-1), " = NULL;" TO g_HFILE
						WRITELN g_WITHVAR$, LEFT$(str$, INSTR(str$, "=")-1), " = __b2c_Copy_String(", g_WITHVAR$, LEFT$(str$, INSTR(str$, "=")-1), ", ", MID$(str$, INSTR(str$, "=")+1), ");" TO g_CFILE
						Save_Main_Var(LEFT$(str$, INSTR(str$, "=")-1), "char*")
						var$ = MID$(var$, LEN(str$)+2)
					WEND
				ENDIF
			ENDIF

			' Assume char assignment or number
		ELSE
			IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN
				FOR str$ IN EXTRACT$(var$, " ") STEP ","
					WRITELN type$, " ", REPLACE$(str$, "]", "+" & STR$(g_OPTION_BASE) & "]"), " = { 0 };" TO g_HFILE
					' Determine dimension needed for SORT
					value$ = MID$(str$, INSTR(str$, "[")+1)
					Save_Dim(LEFT$(str$, INSTR(str$, "[") - 1), LEFT$(value$, INSTR(value$, "]") - 1))
					' Save type
					Save_Main_Var(str$, type$)
				NEXT
			ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN
				WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE
				opt = g_OPTION_BASE
				IF opt > 0 AND COUNT(var$, 91) > 1 THEN EPRINT NL$, "WARNING: OPTION BASE has no impact on multidimensional array '", MID$(var$, 1, INSTR(var$, "[")-1), "' in DECLARE/GLOBAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				WHILE opt > 0 AND COUNT(var$, 91) = 1
					WRITELN " 0, " TO g_HFILE
					DECR opt
				WEND
				Save_Dim(LEFT$(var$, INSTR(var$, "[") - 1), STR$(COUNT(var$, 44)+1))
				WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE
				' Save type
				Save_Main_Var(var$, type$)
			ELIF INSTR(var$, "(") THEN
				' Function pointer
				WRITELN type$, " ", var$, ";" TO g_HFILE
				var$ = LEFT$(var$, INSTRREV(var$, "(")-1)
				Save_Main_Var(EXTRACT$(var$, "[\\(\\*\\)]", TRUE), "void*")
			ELSE
				FOR str$ IN EXTRACT$(var$, " ") STEP ","
					WRITELN type$, " ", str$, ";" TO g_HFILE
					IF NOT(INSTR(str$, "=")) AND NOT(INSTR(str$, "*")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN
						WRITELN str$, " = 0;" TO g_CFILE
					ENDIF
					Save_Main_Var(str$, type$)
				NEXT
			END IF
		ENDIF
	ENDIF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Local(STRING arg$)

	LOCAL var$, type$, new$, value$, dim$, dim2$, array$, str$
	LOCAL opt

	' Get the variablename and type
	IF INSTR(arg$, " TYPE ") THEN
		var$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TYPE ") - 1))
		type$ = CHOP$(MID$(arg$, INSTR(arg$, " TYPE ") + 6))
		IF INSTR(type$, " ARRAY ") THEN
			array$ = MID$(type$, INSTR(type$, " ARRAY ") + 7)
			type$ = MID$(type$, 1, INSTR(type$, " ARRAY ") - 1)
		ENDIF
	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$)
		IF INSTR(var$, " ARRAY ") THEN
			array$ = MID$(var$, INSTR(var$, " ARRAY ") + 7)
			var$ = MID$(var$, 1, INSTR(var$, " ARRAY ") - 1)
		ELIF REGEX(var$, "DIR$|FILE$|short$|int$|long$|float$|double$|char$|void$|STRING$|NUMBER$|FLOATING$") AND NOT(INSTR(var$, "TYPE")) THEN
			EPRINT NL$, "Syntax error: missing TYPE keyword in LOCAL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		FI
		type$ = IIF$(INSTR(var$, g_STRINGSIGN$), "char*", IIF$(INSTR(var$, g_FLOATSIGN$), "double", "long"))
	END IF

	' Check if variable was already declared
	IF NOT(INSTR(var$, ".")) AND LEFT$(var$, 1) != "(" THEN
		FOR str$ IN EXTRACT$(var$, " ") STEP ","
			' Check for C keywords
			IF REGEX(str$, g_C_KEYWORDS$) THEN
				EPRINT NL$, "Syntax error: variable '", str$, "' in LOCAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' is a C keyword or function!"
				END 1
			ENDIF
			' Previous definitions
			IF LEN(Get_Var$(str$, g_FUNCNAME$)) THEN
				EPRINT NL$, "Syntax error: variable '", str$, "' in LOCAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!"
				END 1
			ENDIF
		NEXT
	END IF

	' Check for associative array
	IF INSTR(arg$, " ASSOC ") THEN
		CALL Assoc_Array(var$, type$, g_FUNCNAME$)

		' Check if it is a known type, if not BaCon has to use external .h file
	ELIF NOT(REGEX(EXTRACT$(type$, "*"), "DIR|FILE|short$|int$|long$|float$|double$|char$|void|STRING|NUMBER|FLOATING")) AND NOT(LEN(g_RECORDNAME$)) THEN
		IF INSTR(var$, "=") THEN
			WRITELN type$, " ", var$, ";" TO g_CFILE
			IF LEN(g_FUNCNAME$) THEN
				Save_Func_Var(var$, g_FUNCNAME$, type$)
			ELSE
				Save_Main_Var(var$, type$)
			ENDIF
		ELSE
			FOR str$ IN EXTRACT$(var$, " ") STEP ","
				IF LEN(g_FUNCNAME$) THEN
					WRITELN type$, " ", str$, ";" TO g_CFILE
					Save_Func_Var(str$, g_FUNCNAME$, type$)
				ELSE
					WRITELN type$, " ", str$, ";" TO g_HFILE
					Save_Main_Var(str$, type$)
				ENDIF
			NEXT
		ENDIF

		' Check for dynamic array declaration
	ELIF ISTRUE(LEN(array$)) THEN
		IF LEN(g_RECORDNAME$) > 0 THEN
			IF INSTR(array$, "STATIC") THEN
				Record_Dyn_Array(type$, var$, MID$(array$, 1, INSTR(array$, "STATIC")-1), TRUE)
			ELSE
				Record_Dyn_Array(type$, var$, array$, FALSE)
			FI
		ELSE
			IF INSTR(array$, "STATIC") THEN
				Normal_Dyn_Array(type$, var$, MID$(array$, 1, INSTR(array$, "STATIC")-1), TRUE, TRUE)
			ELSE
				Normal_Dyn_Array(type$, var$, array$, FALSE, TRUE)
			FI
		END IF

		' Check if var is string var
	ELIF ( REGEX(type$, "STRING|char\\*$") OR INSTR(var$, g_STRINGSIGN$) ) AND NOT(INSTR(var$, "=")) AND NOT(REGEX(type$, ".+\\[.+" & g_STRINGSIGN$ & "\\]")) THEN
		FOR str$ IN EXTRACT$(var$, " ") STEP ","
			IF NOT(LEN(Get_Var$(str$, g_FUNCNAME$))) THEN
				' Check on multidimensional stringarrays
				IF REGEX(str$, "\\[.*\\]\\[") THEN
					EPRINT NL$, "Syntax 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$, "\\[.*\\]") THEN
							WRITELN "char *",  REPLACE$(str$, "]", "+" & STR$(g_OPTION_BASE) & "]"), ";" TO g_CFILE
							dim$ = MID$(str$, INSTR(str$, "[") + 1)
							Save_Dim(LEFT$(str$, INSTR(str$, "[") - 1), LEFT$(dim$, INSTR(dim$, "]") - 1))
							IF REGEX(g_RECORDVAR$, "\\[.*\\]") THEN
								IF LEN(g_RECORDARRAY$) THEN
									dim2$ = "__b2c_record_" & EXTRACT$(g_RECORDNAME$, "_TYPE")
								ELSE
									dim2$ = MID$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "[") + 1)
								ENDIF
								g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " for(__b2c__counter=0; __b2c__counter<" & LEFT$(dim2$, INSTR(dim2$, "]") - 1) & ";__b2c__counter++) {for(__b2c__ctr=0; __b2c__ctr<" & LEFT$(dim$, INSTR(dim$, "]") - 1) & "; __b2c__ctr++)" & LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "[")-1) & "[__b2c__counter]." & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr] = NULL;}"
								g_STRINGARRAYS$ = g_STRINGARRAYS$ & " for(__b2c__counter=0; __b2c__counter<" & LEFT$(dim2$, INSTR(dim2$, "]") - 1) & ";__b2c__counter++) {for(__b2c__ctr=0; __b2c__ctr<" & LEFT$(dim$, INSTR(dim$, "]") - 1) & "; __b2c__ctr++) if(" & LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "[")-1) & "[__b2c__counter]." & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr]!=NULL){__b2c__STRFREE(" & LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "[")-1) & "[__b2c__counter]." & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr]);} }"
							ELSE
								g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " for(__b2c__ctr=0; __b2c__ctr<" & LEFT$(dim$, INSTR(dim$, "]") - 1) & "; __b2c__ctr++)" & g_RECORDVAR$ & "." & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr] = NULL;"
								g_STRINGARRAYS$ = g_STRINGARRAYS$ & " for(__b2c__ctr=0; __b2c__ctr<" & LEFT$(dim$, INSTR(dim$, "]") - 1) & "; __b2c__ctr++) if(" & g_RECORDVAR$ & "." & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr]!=NULL){__b2c__STRFREE(" & g_RECORDVAR$ & "." & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr]);}"
							ENDIF
						ELSE
							WRITELN "char *", str$, ";" TO g_CFILE
							' Pointer var should not be initialized
							IF INSTR(str$, g_STRINGSIGN$) AND NOT(REGEX(g_RECORDVAR$, "\\[.*\\]")) AND NOT(LEN(g_RECORDARRAY$)) THEN
								g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " " & g_RECORDVAR$ & "." & str$ & " = NULL;"
								g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & g_RECORDVAR$ & "." & str$
							ENDIF
						END IF
						Save_Func_Var(str$, g_FUNCNAME$, "char*")
					ELSE
						IF REGEX(str$, "\\[.*\\]") THEN
							WRITELN "char *",  REPLACE$(str$, "]", "+" & STR$(g_OPTION_BASE) & "]"), " = { NULL };" TO g_CFILE
							' Determine dimension needed for SORT
							value$ = MID$(str$, INSTR(str$, "[")+1)
							Save_Dim(LEFT$(str$, INSTR(str$, "[") - 1), LEFT$(value$, INSTR(value$, "]") - 1))
							' Save type
							Save_Func_Var(str$, g_FUNCNAME$, "char**")
							dim$ = MID$(str$, INSTR(str$, "[") + 1)
							g_STRINGARRAYS$ = g_STRINGARRAYS$ & " for(__b2c__ctr=0; __b2c__ctr<" & LEFT$(dim$, INSTR(dim$, "]") - 1) & "; __b2c__ctr++)if(" & g_WITHVAR$ & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr]!=NULL){__b2c__STRFREE(" & g_WITHVAR$ & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr]);}"
						ELIF INSTR(str$, "(") THEN
							' Function pointer
							WRITELN type$, " ", str$, ";" TO g_CFILE
							str$ = LEFT$(str$, INSTRREV(str$, "(")-1)
							Save_Func_Var(EXTRACT$(str$, "[\\(\\*\\)]", TRUE), g_FUNCNAME$, "void*")
						ELSE
							WRITELN "char *", str$, " = NULL;" TO g_CFILE
							Save_Func_Var(str$, g_FUNCNAME$, "char*")
							' Defined as string?
							IF INSTR(str$, g_STRINGSIGN$) THEN
								WRITELN str$, " = __b2c_Copy_String(", str$, ", EmptyString);" TO g_CFILE
								g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & str$
							ENDIF
						END IF
					END IF
					' We are in the mainprogram
				ELSE
					IF ISTRUE(LEN(g_RECORDNAME$)) THEN
						IF REGEX(str$, "\\[.*\\]") THEN
							WRITELN "char *", REPLACE$(str$, "]", "+" & STR$(g_OPTION_BASE) & "]"), ";" TO g_HFILE
						ELSE
							WRITELN "char *", str$, ";" TO g_HFILE
							' Pointer var should not be initialized
							IF INSTR(str$, g_STRINGSIGN$) AND NOT(REGEX(g_RECORDVAR$, "\\[.*\\]")) AND NOT(LEN(g_RECORDARRAY$)) THEN g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " " & g_RECORDVAR$ & "." & CHOP$(str$) & " = NULL;"
						ENDIF
						Save_Main_Var(str$, "char*")
					ELSE
						IF REGEX(str$, "\\[.*\\]") THEN
							WRITELN "char *",  REPLACE$(str$, "]", "+" & STR$(g_OPTION_BASE) & "]"), " = { NULL };" TO g_HFILE
							' Determine dimension needed for SORT
							value$ = MID$(str$, INSTR(str$, "[")+1)
							Save_Dim(LEFT$(str$, INSTR(str$, "[") - 1), LEFT$(value$, INSTR(value$, "]") - 1))
							' Save type
							Save_Main_Var(str$, "char**")
						ELIF INSTR(str$, "(") THEN
							' Function pointer
							WRITELN type$, " ", str$, ";" TO g_HFILE
							str$ = LEFT$(str$, INSTRREV(str$, "(")-1)
							Save_Main_Var(EXTRACT$(str$, "[\\(\\*\\)]", TRUE), "void*")
						ELSE
							WRITELN "char *", str$, " = NULL; " TO g_HFILE
							Save_Main_Var(str$, "char*")
						END IF
					END IF
				END IF
			END IF
		NEXT
	ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND INSTR(var$, "=") THEN
		IF ISTRUE(LEN(g_FUNCNAME$)) THEN
			IF NOT(LEN(Get_Var$(var$, g_FUNCNAME$))) THEN
				' String array assignment
				IF INSTR(var$, "[") THEN
					WRITELN "static char *", LEFT$(var$, INSTR(var$, "[") - 1), "[", STR$(COUNT(var$, 44)+1), "] = { NULL };" TO g_CFILE
					' Determine dimension needed for SORT
					Save_Dim(LEFT$(var$, INSTR(var$, "[") - 1), STR$(COUNT(var$, 44)+1))
					' Save type
					Save_Func_Var(var$, g_FUNCNAME$, "char**")
					' Copy elements
					opt = g_OPTION_BASE
					array$ = MID$(var$, INSTR(var$, "{")+1)
					WHILE LEN(array$)
						str$ = Mini_Parser$(array$)
						WRITELN LEFT$(var$, INSTR(var$, "[")-1), "[", opt, "] = __b2c_Copy_String(", LEFT$(var$, INSTR(var$, "[")-1), "[", opt, "], ", CHOP$(str$, "}", 2), ");" TO g_CFILE
						array$ = MID$(array$, LEN(str$)+2)
						INCR opt
					WEND
				ELSE
					WHILE LEN(var$)
						str$ = Mini_Parser$(var$)
						WRITELN "static char *", LEFT$(str$, INSTR(str$, "=")-1), " = NULL;" TO g_CFILE
						WRITELN g_WITHVAR$, LEFT$(str$, INSTR(str$, "=")-1), " = __b2c_Copy_String(", g_WITHVAR$, LEFT$(str$, INSTR(str$, "=")-1), ", ", MID$(str$, INSTR(str$, "=")+1), ");" TO g_CFILE
						Save_Func_Var(LEFT$(str$, INSTR(str$, "=")-1), g_FUNCNAME$, "char*")
						var$ = MID$(var$, LEN(str$)+2)
					WEND
				ENDIF
			ENDIF
		ELSE
			IF NOT(LEN(Get_Var$(var$, g_FUNCNAME$))) THEN
				IF INSTR(var$, "[") THEN
					WRITELN "char *", LEFT$(var$, INSTR(var$, "[") - 1), "[", STR$(COUNT(var$, 44)+1), "] = { NULL };" TO g_HFILE
					' Determine dimension needed for SORT
					Save_Dim(LEFT$(var$, INSTR(var$, "[") - 1), STR$(COUNT(var$, 44)+1))
					' Save type
					Save_Main_Var(var$, "char**")
					' Copy elements
					opt = g_OPTION_BASE
					array$ = MID$(var$, INSTR(var$, "{")+1)
					WHILE LEN(array$)
						str$ = Mini_Parser$(array$)
						WRITELN LEFT$(var$, INSTR(var$, "[")-1), "[", opt, "] = __b2c_Copy_String(", LEFT$(var$, INSTR(var$, "[")-1), "[", opt, "], ", CHOP$(str$, "}", 2), ");" TO g_CFILE
						array$ = MID$(array$, LEN(str$)+2)
						INCR opt
					WEND
				ELSE
					WHILE LEN(var$)
						str$ = Mini_Parser$(var$)
						WRITELN "char *", LEFT$(str$, INSTR(str$, "=")-1), " = NULL;" TO g_HFILE
						WRITELN g_WITHVAR$, LEFT$(str$, INSTR(str$, "=")-1), " = __b2c_Copy_String(", g_WITHVAR$, LEFT$(str$, INSTR(str$, "=")-1), ", ", MID$(str$, INSTR(str$, "=")+1), ");" TO g_CFILE
						Save_Main_Var(LEFT$(str$, INSTR(str$, "=")-1), "char*")
						var$ = MID$(var$, LEN(str$)+2)
					WEND
				ENDIF
			ENDIF
		END IF
		' Assume number or complicated type
	ELSE
		IF ISTRUE(LEN(g_FUNCNAME$)) THEN
			IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN
				FOR str$ IN EXTRACT$(var$, " ") STEP ","
					IF NOT(LEN(g_RECORDNAME$)) THEN
						WRITELN type$, " ", REPLACE$(str$, "]", "+" & STR$(g_OPTION_BASE) & "]"), " = { 0 };" TO g_CFILE
					ELSE
						WRITELN type$, " ", REPLACE$(str$, "]", "+" & STR$(g_OPTION_BASE) & "]"), ";" TO g_CFILE
					ENDIF
					' Determine dimension needed for SORT
					value$ = MID$(str$, INSTR(str$, "[")+1)
					Save_Dim(LEFT$(str$, INSTR(str$, "[") - 1), LEFT$(value$, INSTR(value$, "]") - 1))
					' Save type
					Save_Func_Var(str$, g_FUNCNAME$, type$)
				NEXT
			ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN
				' Numeric array assignment
				WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_CFILE
				opt = g_OPTION_BASE
				IF opt > 0 AND COUNT(var$, 91) > 1 THEN EPRINT NL$, "WARNING: OPTION BASE has no impact on multidimensional array '", MID$(var$, 1, INSTR(var$, "[")-1), "' in LOCAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				WHILE opt > 0 AND COUNT(var$, 91) = 1
					WRITELN " 0, " TO g_CFILE
					DECR opt
				WEND
				Save_Dim(LEFT$(var$, INSTR(var$, "[") - 1), STR$(COUNT(var$, 44)+1))
				WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_CFILE
				' Save type
				Save_Func_Var(var$, g_FUNCNAME$, type$)
			ELIF INSTR(var$, "(") THEN
				' Function pointer
				WRITELN type$, " ", var$, ";" TO g_CFILE
				var$ = LEFT$(var$, INSTRREV(var$, "(")-1)
				Save_Func_Var(EXTRACT$(var$, "[\\(\\*\\)]", TRUE), g_FUNCNAME$, "void*")
			ELSE
				FOR str$ IN EXTRACT$(var$, " ") STEP ","
					WRITELN type$, " ", str$, ";" TO g_CFILE
					IF NOT(INSTR(str$, "=")) AND NOT(INSTR(str$, "*")) AND NOT(LEN(g_RECORDVAR$)) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN
						WRITELN str$, " = 0;" TO g_CFILE
					ENDIF
					Save_Func_Var(str$, g_FUNCNAME$, type$)
				NEXT
			END IF
		ELSE
			IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN
				FOR str$ IN EXTRACT$(var$, " ") STEP ","
					IF NOT(LEN(g_RECORDNAME$)) THEN
						WRITELN type$, " ", REPLACE$(str$, "]", "+" & STR$(g_OPTION_BASE) & "]"), " = { 0 };" TO g_HFILE
					ELSE
						WRITELN type$, " ", REPLACE$(str$, "]", "+" & STR$(g_OPTION_BASE) & "]"), ";" TO g_HFILE
					ENDIF
					' Determine dimension needed for SORT
					value$ = MID$(str$, INSTR(str$, "[")+1)
					Save_Dim(LEFT$(str$, INSTR(str$, "[") - 1), LEFT$(value$, INSTR(value$, "]") - 1))
					' Save type
					Save_Main_Var(str$, type$)
				NEXT
			ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN
				' Numeric array assignment
				WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE
				opt = g_OPTION_BASE
				IF opt > 0 AND COUNT(var$, 91) > 1 THEN EPRINT NL$, "WARNING: OPTION BASE has no impact on multidimensional array '", MID$(var$, 1, INSTR(var$, "[")-1), "' in LOCAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				WHILE opt > 0 AND COUNT(var$, 91) = 1
					WRITELN " 0, " TO g_HFILE
					DECR opt
				WEND
				Save_Dim(LEFT$(var$, INSTR(var$, "[") - 1), STR$(COUNT(var$, 44)+1))
				WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE
				' Save type
				Save_Main_Var(var$, type$)
			ELIF INSTR(var$, "(") THEN
				' Function pointer
				WRITELN type$, " ", var$, ";" TO g_HFILE
				var$ = LEFT$(var$, INSTRREV(var$, "(")-1)
				Save_Main_Var(EXTRACT$(var$, "[\\(\\*\\)]", TRUE), "void*")
			ELSE
				FOR str$ IN EXTRACT$(var$, " ") STEP ","
					WRITELN type$, " ", str$, ";" TO g_HFILE
					IF NOT(INSTR(str$, "=")) AND NOT(INSTR(str$, "*")) AND NOT(LEN(g_RECORDVAR$)) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN
						WRITELN str$, " = 0;" TO g_CFILE
					ENDIF
					Save_Main_Var(str$, type$)
				NEXT
			END IF
		END IF
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Read(STRING arg$)

	LOCAL type$, element$, lft$, str$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty READ at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	FOR element$ IN EXTRACT$(arg$, " ") STEP ","

		' Check if var is string var, exclude RECORD elements
		IF REGEX(element$, g_STRINGSIGN$ & "$") AND NOT(INSTR(element$, ".")) THEN
			IF NOT(LEN(Get_Var$(element$, g_FUNCNAME$))) THEN
				Register_String(element$)
			ENDIF
			type$ = "char*"
			' Assume number, exclude RECORD elements
		ELIF NOT(REGEX(element$, "\\[.*\\]")) AND NOT(INSTR(element$, ".")) AND NOT(REGEX(element$, "\\(.*\\)")) AND NOT(INSTR(element$, "->")) THEN
			' Is variable declared already?
			IF NOT(LEN(Get_Var$(element$, g_FUNCNAME$))) THEN
				type$ = Register_Numeric$(element$)
			ELSE
				type$ = Get_Var$(element$, g_FUNCNAME$)
			ENDIF
		ELSE
			' Get the type
			type$ = Get_Var$(element$, g_FUNCNAME$)
		END IF

		' Check type of var, string?
		IF Check_String_Type(element$) THEN
			' Convert to C
			WRITELN "__b2c__assign = (char*)calloc((strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1), sizeof(char));" TO g_CFILE
			WRITELN "strcpy(__b2c__assign, __b2c__stringarray[__b2c__stringarray_ptr]); __b2c__stringarray_ptr++;" TO g_CFILE

			' Now see if we have a assoc or a normal variable
			IF REGEX(element$, "\\(.*\\)$") THEN
				lft$ = LEFT$(element$, INSTR(element$, "(") - 1)
				str$ = MID$(element$, INSTR(element$, "(") + 1)
				WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
				WRITELN "if(__b2c__", lft$, "_loc->value != NULL) __b2c__STRFREE(__b2c__", lft$, "_loc->value); __b2c__", lft$, "_loc->value = __b2c__assign; " TO g_CFILE
				' Check for relations
				CALL Relate_Recurse(lft$, str$, element$, -1)
			ELSE
				WRITELN "if(", element$, " != NULL) __b2c__STRFREE(", element$, "); ", element$, " = __b2c__assign;" TO g_CFILE
			END IF
		ELSE
			IF REGEX(element$, "\\(.*\\)$") THEN
				lft$ = LEFT$(element$, INSTR(element$, "(") - 1)
				str$ = MID$(element$, INSTR(element$, "(") + 1)
				WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
				WRITELN "__b2c__", lft$, "_loc->value = (", type$, ")__b2c__floatarray[__b2c__floatarray_ptr];;" TO g_CFILE
				WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE
				' Check for relations
				CALL Relate_Recurse(lft$, str$, element$, -1)
			ELSE
				WRITELN element$, " = (", type$, ")__b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE
				WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE
			ENDIF
		END IF
	NEXT

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Endfunction()

	LOCAL line$, tfil$
	LOCAL tmp_HFILE TYPE FILE*

	' Check if we're in a FUNCTION
	IF NOT(LEN(g_FUNCNAME$)) THEN
		EPRINT NL$, "Syntax error: ENDFUNCTION outside FUNCTION at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	ENDIF

	' Check if return was found
	IF ISFALSE(LEN(g_FUNCTYPE$)) THEN
		EPRINT NL$, "Syntax 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$, ";" TO g_HFILE
	g_PROTOTYPE$ = ""

	' Open temporary header file
	tfil$ = MID$(g_CURFILE$, INSTRREV(g_CURFILE$, "/") + 1)
	OPEN g_TEMPDIR$ & "/" & LEFT$(tfil$, INSTR(tfil$, ".bac")) & g_FUNCNAME$ & ".h" FOR WRITING AS tmp_HFILE

	' Get original function name
	WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - MIT License */" TO tmp_HFILE
	WRITELN "#undef __b2c_filename" TO tmp_HFILE
	WRITELN "#define __b2c_filename ", CHR$(34), g_CURFILE$, CHR$(34) TO tmp_HFILE
	WRITELN "#undef __b2c__exitval" TO tmp_HFILE
	WRITELN "#define __b2c__exitval 0" 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

	IF g_CATCH_USED = 1 THEN WRITELN "__B2C__PROGRAM__EXIT: ;" TO tmp_HFILE

	' Make sure the function always returns something
	IF REGEX(g_FUNCTYPE$, "char\\*$|STRING$") THEN
		WRITELN "return (NULL);}" TO tmp_HFILE
	ELIF REGEX(g_FUNCTYPE$, "char$|short$|int$|long$|double$|float$|NUMBER$|FLOATING$") THEN
		WRITELN "return (0);}" TO tmp_HFILE
	ELSE
		WRITELN "}" TO tmp_HFILE
	ENDIF

	WRITELN "#undef __b2c_lineno" TO tmp_HFILE
	WRITELN "#define __b2c_lineno ", g_COUNTER TO tmp_HFILE
	CLOSE FILE tmp_HFILE

	' Include header file
	IF NOT(INSTR(g_INCLUDE_FILES$, LEFT$(tfil$, INSTR(tfil$, ".bac")) & g_FUNCNAME$ & ".h")) THEN
		g_INCLUDE_FILES$ = g_INCLUDE_FILES$ & " " & LEFT$(tfil$, INSTR(tfil$, ".bac")) & g_FUNCNAME$ & ".h"
	END IF

	' Add to total filelist
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_TEMPDIR$ & "/" & LEFT$(tfil$, INSTR(tfil$, ".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$
	g_CATCH_USED = g_ORIGCATCH_USED

	' Clear function variables
	g_ORIGFUNCNAME$ = ""
	g_FUNCNAME$ = ""
	g_FUNCTYPE$ = ""
	g_LOCALSTRINGS$ = ""
	g_STRINGARRAYS$ = ""
	g_STRINGARGS$ = ""

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Return(STRING arg$)

	LOCAL type$, element$, name$
	LOCAL x

	arg$ = CHOP$(arg$)

	' Check if we have an argument at all, if not, we return from a GOSUB
	IF ISFALSE(LEN(arg$)) THEN
		WRITELN "if(__b2c__gosub_buffer_ptr >= 0) longjmp(__b2c__gosub_buffer[__b2c__gosub_buffer_ptr], 1);" TO g_CFILE
		EXIT SUB
	END IF

	type$ = Get_Var$(arg$, g_FUNCNAME$)

	' Check type of var, string or normal string?
	IF NOT(LEN(g_FUNCTYPE$)) THEN
		IF Check_String_Type(arg$) THEN
			' Static dynamic array or array created by SPLIT or LOOKUP
			IF INSTR(g_DYNAMICARRAYS$, arg$ & "@" & g_FUNCNAME$) OR INSTR(g_STRINGARGS$, " __b2c__split__" & arg$) THEN
				g_FUNCTYPE$ = "char**"
				' We return a string
			ELSE
				g_FUNCTYPE$ = "char*"
				g_STRINGARGS$ = g_STRINGARGS$ & " char* __b2c__tmp = NULL;"
				WRITELN "__b2c__tmp = ", arg$, "; if(__b2c__tmp != NULL){ __b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= ", g_MAX_RBUFFERS, ") __b2c__rbuffer_ptr=0;" TO g_CFILE
				WRITELN " __b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)__rbuf_realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen(__b2c__tmp)+1)*sizeof(char));" TO g_CFILE
				WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], __b2c__tmp);}" TO g_CFILE
				WRITELN "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)calloc(1, sizeof(char));}" TO g_CFILE
				arg$ = "__b2c__rbuffer[__b2c__rbuffer_ptr]"
			ENDIF

			' Assume variable, check if declared before
		ELIF ISTRUE(LEN(type$)) THEN
			IF INSTR(arg$, "[") THEN
				FOR x = 1 TO COUNT(arg$, 91)
					IF RIGHT$(type$, 1) = "*" THEN type$ = LEFT$(type$, LEN(type$)-1)
				NEXT
			ELSE
				FOR name$ IN g_STATICARRAYS$
					IF INSTR(name$, arg$) THEN
						type$ = type$ & FILL$(VAL(MID$(name$, INSTR(name$, ":")+1)), 42)
						BREAK
					ENDIF
				NEXT
			ENDIF
			g_FUNCTYPE$ = type$

			' Not declared, assume actual value
		ELSE
			' Check if float
			g_FUNCTYPE$ = IIF$(INSTR(arg$, ".") OR REGEX(arg$, g_FLOATSIGN$ & "$") OR REGEX(g_FUNCNAME$, g_FLOATSIGN$ & "$"), "double", g_VARTYPE$)
		END IF
	ENDIF

	' Free strings variables if there are any
	WRITELN g_STRINGARRAYS$ TO g_CFILE
	FOR element$ IN g_LOCALSTRINGS$
		' If return argument contains string, make sure to point to return buffer
		IF INSTR(arg$, element$) THEN
			WRITELN "__b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= ", g_MAX_RBUFFERS, ") __b2c__rbuffer_ptr=0; if(", element$, " != NULL)" TO g_CFILE
			WRITELN " {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)__rbuf_realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen(", element$, ")+1)*sizeof(char));" TO g_CFILE
			WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], ", element$, "); __b2c__STRFREE(", element$, "); ", element$, " = __b2c__rbuffer[__b2c__rbuffer_ptr];}" TO g_CFILE
		ELSE
			WRITELN "if(", element$, " != NULL) __b2c__STRFREE(", element$, ");" TO g_CFILE
		FI
	NEXT

	' The actual return value
	WRITELN "__b2c__catch_set = __b2c__catch_set_backup;" TO g_CFILE
	WRITELN "return (", arg$, ");" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Push(STRING arg$)

	LOCAL type$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty PUSH at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	IF NOT(INSTR(arg$, ".")) THEN
		type$ = Get_Var$(arg$, g_FUNCNAME$)
	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 Check_String_Type(arg$) 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] = (char*)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] = __b2c__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|float|FLOATING") 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 type$, lft$, str$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax 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
		EPRINT NL$, "Syntax error: argument in PULL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' is not a variable!"
		END 1
	END IF

	' Check if var is string var, exclude RECORD elements
	IF REGEX(arg$, g_STRINGSIGN$ & "$") AND NOT(INSTR(arg$, ".")) THEN
		' Is variable declared already?
		IF NOT(LEN(Get_Var$(arg$, g_FUNCNAME$))) THEN
			Register_String(arg$)
		END IF
		type$ = "char*"

		' Assume number, exclude RECORD elements
	ELIF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) AND NOT(REGEX(arg$, "\\(.*\\)")) AND NOT(INSTR(arg$, "->")) THEN
		' Is variable declared already?
		type$ = Get_Var$(arg$, g_FUNCNAME$)
		IF NOT(LEN(type$)) THEN
			type$ = Register_Numeric$(arg$)
		ENDIF
	END IF

	' Decrease stackpointer again
	WRITELN "__b2c__stackptr--; if(__b2c__stackptr < 0) __b2c__stackptr=0;" TO g_CFILE

	' Get the last value from stack
	IF Check_String_Type(arg$) THEN
		WRITELN "if(__b2c__typestack[__b2c__stackptr] == 1) {__b2c__assign = (char*)calloc(strlen(__b2c__stringstack[__b2c__stackptr])+1, sizeof(char));" TO g_CFILE
		WRITELN "strcpy(__b2c__assign, __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" TO g_CFILE
		' Now see if we have a assoc or a normal variable
		IF REGEX(arg$, "\\(.*\\)$") THEN
			lft$ = LEFT$(arg$, INSTR(arg$, "(") - 1)
			str$ = MID$(arg$, INSTR(arg$, "(") + 1)
			WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
			WRITELN "if(__b2c__", lft$, "_loc->value != NULL) __b2c__STRFREE(__b2c__", lft$, "_loc->value); __b2c__", lft$, "_loc->value = __b2c__assign; " TO g_CFILE
			' Check for relations
			CALL Relate_Recurse(lft$, str$, arg$, -1)
		ELSE
			WRITELN "if(", arg$, " != NULL) __b2c__STRFREE(", arg$, "); ", arg$, " = __b2c__assign;" TO g_CFILE
		END IF
	ELSE
		' Now see if we have an assoc or a normal variable
		IF REGEX(arg$, "\\(.*\\)$") THEN
			lft$ = LEFT$(arg$, INSTR(arg$, "(") - 1)
			str$ = MID$(arg$, INSTR(arg$, "(") + 1)
			WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
			IF INSTR(type$, "double") OR INSTR(type$, "float") OR INSTR(type$, "FLOATING") THEN
				WRITELN "__b2c__", lft$, "_loc->value = __b2c__doublestack[__b2c__stackptr];" TO g_CFILE
			ELSE
				WRITELN "__b2c__", lft$, "_loc->value = __b2c__longstack[__b2c__stackptr];" TO g_CFILE
			END IF
			' Check for relations
			CALL Relate_Recurse(lft$, str$, arg$, -1)
		ELSE
			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
			ELSE
				WRITELN "if(__b2c__typestack[__b2c__stackptr] == 3) ", arg$, " = __b2c__longstack[__b2c__stackptr];" TO g_CFILE
			END IF
		END IF
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_SubFunc(STRING arg$)

	LOCAL x, dim
	LOCAL dim$, arr$, size$, var$

	' Check argument
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax 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
		EPRINT NL$, "Syntax 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$, "(")))
		IF INSTR(arg$, " TYPE ") THEN g_FUNCTYPE$ = MID$(arg$, INSTR(arg$, " TYPE ")+6)
	ELSE
		IF INSTR(arg$, " TYPE ") THEN
			g_FUNCTYPE$ = MID$(arg$, INSTR(arg$, " TYPE ")+6)
			g_ORIGFUNCNAME$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TYPE ")-1)) & "("
			g_PROTOTYPE$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TYPE ")-1)) & "("
		ELSE
			g_ORIGFUNCNAME$ = CHOP$(arg$) & "("
			g_PROTOTYPE$ = CHOP$(arg$) & "("
		ENDIF
	END IF
	IF INSTR(arg$, " TYPE ") THEN arg$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TYPE ")-1))

	' Get stripped function name
	IF INSTR(arg$, "(") THEN
		g_FUNCNAME$ = CHOP$(LEFT$(arg$, INSTR(arg$, "(") - 1))
	ELSE
		g_FUNCNAME$ = CHOP$(arg$)
	END IF

	' Start miniparser to duplicate string arguments
	IF INSTR(arg$, "(") THEN SPLIT CHOP$(MID$(arg$, INSTR(arg$, "(")), "() ") BY "," TO element$ SIZE dim

	' If there are no arguments to the function at all
	IF dim = 0 THEN
		g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & " void)"
		g_PROTOTYPE$ = g_PROTOTYPE$ & " void)"
	ENDIF

	FOR x = 1 TO dim
		element$[x] = CHOP$(element$[x])
		' Save type
		IF LEFT$(element$[x], 4) = "VAR " THEN
			IF dim > 1 THEN
				EPRINT NL$, "Syntax error: variable argument list cannot be followed by other arguments at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			ELIF INSTR(g_PROTOTYPE$, ",") THEN
				EPRINT NL$, "Syntax 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
				EPRINT NL$, "Syntax 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
				EPRINT NL$, "Syntax error: variable argument list is not string at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			END IF
			' These are in the function header, and do not exist yet - no need to check with Get_Var
			g_STRINGARGS$ = g_STRINGARGS$ & " long " & size$ & ";"
			Save_Func_Var(size$, g_FUNCNAME$, "long")
			Save_Func_Var(arr$, g_FUNCNAME$, "char**")
			g_STRINGARGS$ = 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$ = g_STRINGARGS$ & "va_start(__b2c__ap, __b2c__name); if(__b2c__name != NULL)" & arr$ & "[__b2c__var_" & arr$ & "] = __b2c__strdup(__b2c__name); else " & arr$ & "[__b2c__var_" & arr$ & "] = NULL; while (" & arr$ & "[__b2c__var_" & arr$ & "] != NULL) {__b2c__var_" & arr$ & "++; " & arr$ & " = (char **)realloc(" & arr$ & ", (__b2c__var_" & arr$ & "+1) * sizeof(char*));"
			g_STRINGARGS$ = g_STRINGARGS$ & "__b2c__va = va_arg(__b2c__ap, char*); if(__b2c__va != NULL) " & arr$ & "[__b2c__var_" & arr$ & "] = __b2c__strdup(__b2c__va); else " & arr$ & "[__b2c__var_" & arr$ & "] = NULL; }"
			g_STRINGARGS$ = g_STRINGARGS$ & "va_end(__b2c__ap); " & size$ & " = __b2c__var_" & arr$ & " - " & STR$(g_OPTION_BASE) & "; if(__b2c__var_" & arr$ & " > 0) __b2c__var_" & arr$ & "--;"
			g_PROTOTYPE$ = "__" & g_PROTOTYPE$ & "char*, ..."
			g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & "char *__b2c__name, ..."
			g_STRINGARRAYS$ = g_STRINGARRAYS$ & "if(" & arr$ & " != NULL) {for(__b2c__ctr=" & STR$(g_OPTION_BASE) & "; __b2c__ctr<=__b2c__var_" & arr$ & "; __b2c__ctr++) if(" & arr$ & "[__b2c__ctr]!=NULL){__b2c__STRFREE(" & arr$ & "[__b2c__ctr]);} free(" & arr$ & ");}"
			' Add macro in case of VAR argument
			WRITELN "#define ", g_FUNCNAME$, "(...) __", g_FUNCNAME$, "(__VA_ARGS__, NULL)" TO g_HFILE
			g_ORIGFUNCNAME$ = "__" & g_ORIGFUNCNAME$
		ELIF INSTR(element$[x], "STRING ") OR INSTR(element$[x], "char* ") OR INSTR(element$[x], g_STRINGSIGN$) THEN
			' Add type if it is missing
			IF NOT(INSTR(element$[x], " ")) THEN element$[x] = "char* " & element$[x]
			' Check if already declared
			IF NOT(LEN(Get_Var$(MID$(element$[x], INSTRREV(element$[x], " ")+1), g_FUNCNAME$))) THEN
				Save_Func_Var(MID$(element$[x], INSTRREV(element$[x], " ")+1), g_FUNCNAME$, LEFT$(element$[x], INSTRREV(element$[x], " ")-1))
			ELSE
				IF g_SEMANTIC = 0 THEN EPRINT NL$, "Warning: variable '", MID$(element$[x], INSTRREV(element$[x], " ")+1), "' in function header at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!"
			ENDIF
			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$ = g_ORIGFUNCNAME$ & "char *__b2c_" & arr$ & "[" & dim$ & "+" & STR$(g_OPTION_BASE) &"]"
				g_STRINGARGS$ = g_STRINGARGS$ & " char** " & arr$ & " = __b2c_" & arr$ & ";"
				g_PROTOTYPE$ = g_PROTOTYPE$ & " " & element$[x]
			ELIF NOT(INSTR(element$[x], g_STRINGSIGN$)) THEN
				g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & HEAD$(element$[x], AMOUNT(element$[x])-1) & " __b2c_" & TAIL$(element$[x], 1)
				g_STRINGARGS$ = g_STRINGARGS$ & HEAD$(element$[x], AMOUNT(element$[x])-1) & " " & TAIL$(element$[x], 1) & " = __b2c_" & TAIL$(element$[x], 1) & ";"
				g_PROTOTYPE$ = g_PROTOTYPE$ & " " & element$[x]
			ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN
				IF LEN(dim$) < 1 THEN
					g_ORIGFUNCNAME$ = CHOP$(g_ORIGFUNCNAME$ & " " & element$[x])
					g_PROTOTYPE$ = g_PROTOTYPE$ & " " & element$[x]
				ELSE
					g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & "char *__b2c_" & arr$ & "[" & dim$ & "+" & STR$(g_OPTION_BASE) &"]"
					g_STRINGARGS$ = g_STRINGARGS$ & "char *" & arr$ & "[" & dim$ & "+" & STR$(g_OPTION_BASE) & "] = { NULL };"
					g_STRINGARGS$ = g_STRINGARGS$ & "for(__b2c__ctr=0; __b2c__ctr<" & dim$ & "+" & STR$(g_OPTION_BASE) & "; __b2c__ctr++){if(__b2c_" & arr$ & "[__b2c__ctr]!=NULL) " & arr$ & "[__b2c__ctr] = __b2c__strdup(__b2c_" & arr$ & "[__b2c__ctr]);}"
					g_STRINGARRAYS$ = g_STRINGARRAYS$ & "for(__b2c__ctr=0; __b2c__ctr<" & dim$ & "+" & STR$(g_OPTION_BASE) & "; __b2c__ctr++)if(" & arr$ & "[__b2c__ctr]!=NULL){__b2c__STRFREE(" & arr$ & "[__b2c__ctr]);}"
					g_PROTOTYPE$=g_PROTOTYPE$ & "char *__b2c_" & CHOP$(MID$(element$[x], INSTR(element$[x], " ")))
				END IF
			ELSE
				g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & "char *__b2c_" & CHOP$(MID$(element$[x], INSTR(element$[x], " ")))
				var$ = CHOP$(MID$(element$[x], INSTR(element$[x], " ")))
				g_STRINGARGS$ = g_STRINGARGS$ & "char *" & var$ & " = NULL;" & var$ & " = __b2c_Copy_String(" & var$ & ", __b2c_" & var$ & ");"
				g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & CHOP$(MID$(element$[x], INSTR(element$[x], " ")))
				g_PROTOTYPE$ = g_PROTOTYPE$ & " " & element$[x]
			END IF
		ELSE
			' Add type if it is missing
			IF NOT(INSTR(element$[x], " ")) AND NOT(REGEX(element$[x], "^DIR|^FILE|^short|^int|^long|^float|^double|^char|^void|^STRING|^NUMBER|^FLOATING")) THEN
				element$[x] = IIF$(REGEX(element$[x], g_FLOATSIGN$ & "$"), "double ", g_VARTYPE$ & " ") & element$[x]
			ENDIF
			' Check if already declared
			IF NOT(LEN(Get_Var$(MID$(element$[x], INSTRREV(element$[x], " ")+1), g_FUNCNAME$))) THEN
				Save_Func_Var(MID$(element$[x], INSTRREV(element$[x], " ")+1), g_FUNCNAME$, LEFT$(element$[x], INSTRREV(element$[x], " ")-1))
			ELSE
				IF g_SEMANTIC = 0 THEN EPRINT NL$, "Warning: variable '", MID$(element$[x], INSTRREV(element$[x], " ")+1), "' in function header at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!"
			ENDIF
			IF REGEX(element$[x], ".*\\[.*\\].*\\].*") THEN
				EPRINT NL$, "Syntax error: cannot pass multidimensional numeric array at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			ELIF REGEX(element$[x], ".*\\[\\].*") THEN
				g_ORIGFUNCNAME$ = CHOP$(g_ORIGFUNCNAME$ & " " & element$[x])
			ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN
				dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1)
				arr$ = MID$(element$[x], INSTRREV(element$[x], " ")+1, INSTR(element$[x], "[") - INSTRREV(element$[x], " ")-1)
				g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & TOKEN$(element$[x], 1) & " __b2c_" & arr$ & "[" & dim$ & "+" & STR$(g_OPTION_BASE) & "]"
				g_STRINGARGS$ = g_STRINGARGS$ & TOKEN$(element$[x], 1) & " " & arr$ & "[" & dim$ & "+" & STR$(g_OPTION_BASE) & "] = { 0 };"
				g_STRINGARGS$ = g_STRINGARGS$ & "memmove(" & arr$ & ", __b2c_" & arr$ & ", (" & dim$ & "+" & STR$(g_OPTION_BASE) & ")*sizeof(" & TOKEN$(element$[x], 1) & "));"
			ELSE
				g_ORIGFUNCNAME$ = CHOP$(g_ORIGFUNCNAME$ & " " & element$[x])
			END IF
			g_PROTOTYPE$ = g_PROTOTYPE$ & " " & element$[x]
		END IF
		' Set separation
		IF x < dim THEN
			g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & ","
			g_PROTOTYPE$ = g_PROTOTYPE$ & ","
		ELSE
			g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & ")"
			g_PROTOTYPE$ = g_PROTOTYPE$ & ")"
		ENDIF
	NEXT

	' Close the current C file
	CLOSE FILE g_CFILE

	' Make symbol known to parser
	g_IMPORTED$ = g_FUNCNAME$ & " " & g_IMPORTED$

	' Save CATCH routine
	g_ORIGCATCHGOTO$ = g_CATCHGOTO$
	g_ORIGCATCH_USED = g_CATCH_USED
	g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT"
	g_CATCH_USED = 0
	g_STRINGARGS$ = g_STRINGARGS$ & " __b2c__catch_set_backup = __b2c__catch_set; __b2c__catch_set = 0;"

	' Switch to header file
	g_COPY_CFILE$ = g_CFILE$
	g_COPY_COUNTER = g_COUNTER
	g_CFILE$ = LEFT$(g_CFILE$, INSTR(g_CFILE$, ".c")) & g_FUNCNAME$ & ".tmp"

	' Open temp C file
	OPEN g_CFILE$ FOR WRITING AS g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Endsub()

	LOCAL tmp_HFILE TYPE FILE*
	LOCAL line$, element$, tfil$

	' Check if we're in a SUB
	IF NOT(LEN(g_FUNCNAME$)) THEN
		EPRINT NL$, "Syntax error: ENDSUB outside SUB at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	ENDIF

	' Close the current C file
	CLOSE FILE g_CFILE

	' Put prototype to header file
	WRITELN "void ", g_PROTOTYPE$, ";" TO g_HFILE
	g_PROTOTYPE$ = ""

	' Open temporary header file
	tfil$ = MID$(g_CURFILE$, INSTRREV(g_CURFILE$, "/") + 1)
	OPEN g_TEMPDIR$ & "/" & LEFT$(tfil$, INSTR(tfil$, ".bac")) & g_FUNCNAME$ & ".h" FOR WRITING AS tmp_HFILE

	' Get original function name
	WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - MIT License */" TO tmp_HFILE
	WRITELN "#undef __b2c_filename" TO tmp_HFILE
	WRITELN "#define __b2c_filename ", CHR$(34), g_CURFILE$, CHR$(34) TO tmp_HFILE
	WRITELN "#undef __b2c__exitval" TO tmp_HFILE
	WRITELN "#define __b2c__exitval" 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
	WRITELN g_STRINGARRAYS$ TO tmp_HFILE
	FOR element$ IN g_LOCALSTRINGS$
		IF LEN(element$) > 0 THEN WRITELN "if(", element$, " != NULL) __b2c__STRFREE(", element$, ");" TO tmp_HFILE
	NEXT
	IF g_CATCH_USED = 1 THEN WRITELN "__B2C__PROGRAM__EXIT: ;" TO tmp_HFILE
	WRITELN "__b2c__catch_set = __b2c__catch_set_backup;" TO tmp_HFILE
	WRITELN "}" TO tmp_HFILE

	WRITELN "#undef __b2c_lineno" TO tmp_HFILE
	WRITELN "#define __b2c_lineno ", g_COUNTER TO tmp_HFILE
	CLOSE FILE tmp_HFILE

	' Include header file
	IF NOT(INSTR(g_INCLUDE_FILES$, LEFT$(tfil$, INSTR(tfil$, ".bac")) & g_FUNCNAME$ & ".h")) THEN
		g_INCLUDE_FILES$ = g_INCLUDE_FILES$ & " " & LEFT$(tfil$, INSTR(tfil$, ".bac")) & g_FUNCNAME$ & ".h"
	END IF

	' Add to total filelist
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_TEMPDIR$ & "/" & LEFT$(tfil$, INSTR(tfil$, ".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$
	g_CATCH_USED = g_ORIGCATCH_USED

	' Reset variables
	g_ORIGFUNCNAME$ = ""
	g_FUNCNAME$ = ""
	g_LOCALSTRINGS$ = ""
	g_STRINGARRAYS$ = ""
	g_STRINGARGS$ = ""

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Deffn(STRING arg$)

	LOCAL sym$, left$, str$
	LOCAL cnt

	' Check if we have an argument at all
	IF ISFALSE(LEN(arg$)) THEN
		EPRINT NL$, "Syntax 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$, " ")))

	left$ = CHOP$(LEFT$(sym$, INSTR(sym$, "=") - 1))
	str$ = MID$(sym$, INSTR(sym$, "=") + 1)

	WRITELN "#define ", left$, " (", str$, ")" TO g_HFILE

	IF REGEX(left$, g_STRINGSIGN$ & "$") THEN
		' Count the amount of string functions by counting $(
		WHILE INSTR(str$, g_STRINGSIGN$ & "(")
			str$ = MID$(str$, INSTR(str$, g_STRINGSIGN$ & "(")+1)
			INCR cnt
		WEND
		INCR g_STRING_FUNC, cnt
	ENDIF

	' Make symbol known to parser
	g_IMPORTED$ = LEFT$(sym$, INSTR(sym$, "(") - 1) & " " & g_IMPORTED$

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Const(STRING arg$)

	LOCAL left$, str$
	LOCAL cnt

	' Check if we have an argument at all
	IF ISFALSE(LEN(arg$)) THEN
		EPRINT NL$, "Syntax error: empty CONST at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	left$ = CHOP$(LEFT$(arg$, INSTR(arg$, "=") - 1))

	str$ = CHOP$(MID$(arg$, INSTR(arg$, "=") + 1))

	IF REGEX(left$, g_STRINGSIGN$ & "$") THEN
		WRITELN "#define ", left$, " ", str$ TO g_HFILE
		' Count the amount of string functions by counting $(
		WHILE INSTR(str$, g_STRINGSIGN$ & "(")
			str$ = MID$(str$, INSTR(str$, g_STRINGSIGN$ & "(")+1)
			INCR cnt
		WEND
		INCR g_STRING_FUNC, cnt
	ELSE
		WRITELN "#define ", left$, " (", str$, ")" TO g_HFILE
	ENDIF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Seek(STRING arg$)

	LOCAL descriptor$, offset$, whence$

	' Check if we have an argument at all
	IF ISFALSE(LEN(arg$)) THEN
		EPRINT NL$, "Syntax 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
		EPRINT NL$, "Syntax error: missing OFFSET in SEEK statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Get the variablename, filedescriptor
	descriptor$ = LEFT$(arg$, INSTR(arg$, "OFFSET")-1)
	offset$ = MID$(arg$, INSTR(arg$, "OFFSET")+7)

	' Check for offset depart
	IF INSTR(offset$, " WHENCE ") THEN
		whence$ = MID$(offset$, INSTR(offset$, " WHENCE ")+8)
		offset$ = LEFT$(offset$, INSTR(offset$, " WHENCE ")-1)
	ENDIF

	' Convert to C function
	SELECT whence$
		CASE "START"
			WRITELN "fseek(", descriptor$, ", ", offset$, ", SEEK_SET);" TO g_CFILE
		CASE "CURRENT"
			WRITELN "fseek(", descriptor$, ", ", offset$, ", SEEK_CUR);" TO g_CFILE
		CASE "END"
			WRITELN "fseek(", descriptor$, ", ", offset$, ", SEEK_END);" TO g_CFILE
		DEFAULT
			WRITELN "fseek(", descriptor$, ", ", offset$, ", SEEK_SET);" TO g_CFILE
	ENDSELECT

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Copy(STRING arg$)

	LOCAL from$, to$, size$

	' Check if we have an argument at all
	IF ISFALSE(LEN(arg$)) THEN
		EPRINT NL$, "Syntax 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
		EPRINT NL$, "Syntax 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))

	IF INSTR(to$, " SIZE ") THEN
		size$ = MID$(to$, INSTR(to$, " SIZE ") + 6)
		to$ = MID$(to$, 1, INSTR(to$, " SIZE ") - 1)
	END IF

	' Translate to C function
	IF LEN(size$) = 0 THEN
		WRITELN "__b2c__inFile = fopen((const char*)", from$, ", \"r\"); __b2c__outFile = fopen((const char*)", to$, ", \"w\");" TO g_CFILE
		WRITELN "while ((__b2c__Byte = fread(__b2c__input__buffer, sizeof(char), sizeof(__b2c__input__buffer), __b2c__inFile)) > 0){" TO g_CFILE
		WRITELN "if (fwrite(__b2c__input__buffer, sizeof(char), __b2c__Byte, __b2c__outFile) != __b2c__Byte) {if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"COPY\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
		WRITELN "} fclose(__b2c__inFile); fclose(__b2c__outFile);" TO g_CFILE
	ELSE
		WRITELN "if (__b2c__trap){if(__b2c__memory__check((char*)", to$, ", sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"COPY\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
		IF INSTR(from$, g_STRINGSIGN$) THEN
			WRITELN "for(__b2c__ctr=0;__b2c__ctr<", size$, ";__b2c__ctr++){if(", to$, "[__b2c__ctr+", g_OPTION_BASE, "]!=NULL){__b2c__STRFREE(", to$, "[__b2c__ctr+", g_OPTION_BASE, "]); ", to$, "[__b2c__ctr+", g_OPTION_BASE, "] = NULL;}" TO g_CFILE
			WRITELN "if(", from$, "[__b2c__ctr+", g_OPTION_BASE, "]!=NULL) ", to$, "[__b2c__ctr+", g_OPTION_BASE, "]=strdup(", from$, "[__b2c__ctr+", g_OPTION_BASE, "]);}" TO g_CFILE
		ELSE
			WRITELN "memmove((void*)", to$, ", (void*)", from$, ", sizeof(__b2c__MEMTYPE)*", size$, ");" TO g_CFILE
		ENDIF
	FI
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Rename(STRING arg$)

	LOCAL from$, to$

	' Check if we have an argument at all
	IF ISFALSE(LEN(arg$)) THEN
		EPRINT NL$, "Syntax 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
		EPRINT NL$, "Syntax 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) RUNTIMEERROR(\"RENAME\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

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
		EPRINT NL$, "Syntax 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 element$[1] = "RESET" THEN
		WRITELN "fputs(\"\\033[0m\", stdout); fflush(stdout);" TO g_CFILE
	ELIF element$[1] = "INTENSE" THEN
		WRITELN "fputs(\"\\033[1m\", stdout); fflush(stdout);" TO g_CFILE
	ELIF element$[1] = "INVERSE" THEN
		WRITELN "fputs(\"\\033[7m\", stdout); fflush(stdout);" TO g_CFILE
	ELIF element$[1] = "NORMAL" THEN
		WRITELN "fputs(\"\\033[22m\", stdout); fflush(stdout);" TO g_CFILE
		' Check if TO is available
	ELIF NOT(INSTR(arg$, " TO ")) THEN
		EPRINT NL$, "Syntax 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$, "); fflush(stdout);" TO g_CFILE
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Gotoxy(STRING arg$)

	LOCAL dim
	LOCAL token$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty GOTOXY at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Get the target and colorname
	token$ = Mini_Parser$(arg$)
	arg$ = MID$(arg$, LEN(token$)+2)

	IF dim = 1 THEN
		EPRINT NL$, "Syntax 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$(arg$), "), (long)(", CHOP$(token$), ")); fflush(stdout);" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Split(STRING arg$)

	LOCAL source$, rest$, by$, to$, size$
	LOCAL is_static

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty SPLIT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Check if TO is available
	IF NOT(INSTR(arg$, " TO ")) THEN
		EPRINT NL$, "Syntax 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
		EPRINT NL$, "Syntax error: missing SIZE in SPLIT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Split up arguments
	IF NOT(INSTR(arg$, " BY ")) THEN
		source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ") - 1))
		rest$ = MID$(arg$, INSTR(arg$, " TO ") + 4)
		by$ = "__b2c__option_delim"
	ELSE
		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)
	ENDIF

	to$ = CHOP$(LEFT$(rest$, INSTR(rest$, " SIZE ") - 1))
	size$ = CHOP$(MID$(rest$, INSTR(rest$, " SIZE ") + 6))

	IF INSTR(size$, " STATIC") THEN
		size$ = MID$(size$, 1, INSTR(size$, "STATIC")-1)
		is_static = 1
	ELSE
		is_static = 0
	ENDIF

	' Variable may not be array, these should be defined with DECLARE
	IF NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) AND NOT(REGEX(size$, "\\(.*\\)")) AND NOT(INSTR(size$, "->")) THEN
		IF NOT(LEN(Get_Var$(size$, g_FUNCNAME$))) THEN
			Register_Numeric$(size$)
		ENDIF
	END IF

	' Translate to C code
	IF ISTRUE(LEN(g_FUNCNAME$)) THEN
		IF NOT(INSTR(g_STRINGARGS$, "**" & to$)) THEN
			g_STRINGARGS$ = g_STRINGARGS$ & " char **" & to$ & " = NULL; char *__b2c__" & to$ & "__dup = NULL; int __b2c__split__" & to$ & " = " & STR$(g_OPTION_BASE) & ";"
			Save_Func_Var(to$, g_FUNCNAME$, "char*")
			Save_Func_Var("__b2c__" & to$ & "__dup", g_FUNCNAME$, "char*")
			Save_Func_Var("__b2c__split__" & to$, g_FUNCNAME$, "int")
		END IF
	ELSE
		IF NOT(LEN(Get_Var$(to$))) THEN
			WRITELN "char **", to$, " = NULL; char *__b2c__", to$, "__dup = NULL; int __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_HFILE
			Save_Main_Var(to$, "char*")
			Save_Main_Var("__b2c__" & to$ & "__dup", "char*")
			Save_Main_Var("__b2c__split__" & to$, "int")
		END IF
	END IF

	' If the split array was used before in a loop, clear it
	IF INSTR(to$, g_STRINGSIGN$) THEN WRITELN "if(", to$, " != NULL) {for(__b2c__ctr=", g_OPTION_BASE, "; __b2c__ctr<=__b2c__split__", to$, "; __b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL){__b2c__STRFREE(", to$, "[__b2c__ctr]);} free(", to$, "); ", to$, " = NULL;}" TO g_CFILE
	WRITELN "__b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_CFILE
	WRITELN "if(__b2c__", to$, "__dup != NULL) {__b2c__STRFREE(__b2c__", to$, "__dup); __b2c__", to$, "__dup = NULL;}" TO g_CFILE

	' Run the SPLIT code
	IF Check_String_Type(by$) OR by$ = "__b2c__option_delim" THEN
		WRITELN "__b2c__", to$, "__dup = __b2c__strdup(", source$, "); if(__b2c__", to$, "__dup != NULL && strlen(__b2c__", to$, "__dup) > 0 && ", by$, " != NULL && strlen(", by$, ") > 0) {" TO g_CFILE
		WRITELN "__b2c__split_tmp = __b2c__", to$, "__dup; __b2c__is_escaped = 0; __b2c__in_string = 0; while (1) {__b2c__assign = __b2c__split_tmp; while ((__b2c__split = strstr (__b2c__split_tmp, ", by$, ")) != NULL) {" TO g_CFILE
		WRITELN "for (__b2c__ctr = 0; __b2c__ctr <= __b2c__split-__b2c__split_tmp; __b2c__ctr++) { if(__b2c__split_tmp[__b2c__ctr] == 92) { if (!__b2c__is_escaped) { __b2c__is_escaped = 1; }" TO g_CFILE
		WRITELN "else { __b2c__is_escaped = 0; } } else if(__b2c__split_tmp[__b2c__ctr] == __b2c__option_dq) { if (!__b2c__is_escaped && __b2c__option_quoted) { __b2c__in_string = 1 - __b2c__in_string; } __b2c__is_escaped = 0; } else {__b2c__is_escaped = 0;} }" TO g_CFILE
		WRITELN "if(__b2c__in_string) {__b2c__split_tmp = __b2c__split + strlen(", by$, "); } else {*__b2c__split = '\\0'; break;} } __b2c__split_tmp = __b2c__assign;" TO g_CFILE
		WRITELN "if(strlen(__b2c__split_tmp) >0 || (strlen(__b2c__split_tmp) == 0 && __b2c__collapse == 0)) {", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*)); " TO g_CFILE
		WRITELN to$, "[__b2c__split__", to$, "++] = __b2c__strdup(__b2c__split_tmp); }" TO g_CFILE
		WRITELN "if(__b2c__split == NULL) break; __b2c__split_tmp = __b2c__split + strlen(", by$, "); } }" TO g_CFILE
	ELSE
		WRITELN "__b2c__", to$, "__dup = __b2c__strdup(", source$, "); __b2c__counter = ", by$, "; if(__b2c__counter > __b2c__len(__b2c__", to$, "__dup)) __b2c__counter = __b2c__len(__b2c__", to$, "__dup);" TO g_CFILE
		WRITELN "if(__b2c__counter > 0) {for(__b2c__ctr = 0; __b2c__ctr < __b2c__len(__b2c__", to$, "__dup); __b2c__ctr += __b2c__counter)" TO g_CFILE
		WRITELN "{ ", to$, " = (char **) realloc(", to$, ", (__b2c__split__", to$, " + 2) * sizeof (char *));" TO g_CFILE
		WRITELN to$, "[__b2c__split__", to$, "] = __b2c__strndup(__b2c__", to$, "__dup+__b2c__ctr, __b2c__counter); __b2c__split__", to$, "++; } }" TO g_CFILE
	ENDIF
	WRITELN size$, " = __b2c__split__", to$, " - ", g_OPTION_BASE, "; if(__b2c__split__", to$, " > 0) __b2c__split__", to$, "--;" TO g_CFILE

	' Save information needed for a REDIM
	IF ISTRUE(LEN(g_FUNCNAME$)) THEN
		IF NOT(INSTR(g_STRINGARGS$, "__b2c_array_" & CHOP$(to$) )) THEN g_STRINGARGS$ = g_STRINGARGS$ & " long __b2c_array_" & CHOP$(to$) & ";"
	ELSE
		WRITELN "long __b2c_array_", CHOP$(to$), ";" TO g_HFILE
	ENDIF
	WRITELN "__b2c_array_", CHOP$(to$), " = ", size$, ";" 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$, to$)) THEN
		g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " __b2c__" & to$ & "__dup"
		IF is_static = 0 THEN
			IF INSTR(to$, g_STRINGSIGN$) THEN
				g_STRINGARRAYS$ = g_STRINGARRAYS$ & " if(" & to$ & "!= NULL){for(__b2c__ctr=" & STR$(g_OPTION_BASE) & ";__b2c__ctr<__b2c_array_" & to$ & "+" & STR$(g_OPTION_BASE) & ";__b2c__ctr++) if(" & to$ & "[__b2c__ctr]!=NULL){__b2c__STRFREE(" & to$ & "[__b2c__ctr]);} }"
			ENDIF
			g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & to$
		ENDIF
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Join(STRING arg$)

	LOCAL source$, rest$, by$, to$, size$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty JOIN at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Check if TO is available
	IF NOT(INSTR(arg$, " TO ")) THEN
		EPRINT NL$, "Syntax error: missing TO in JOIN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Check if SIZE is available
	IF NOT(INSTR(arg$, " SIZE ")) THEN
		EPRINT NL$, "Syntax error: missing SIZE in JOIN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Split up arguments
	IF NOT(INSTR(arg$, " BY ")) THEN
		source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ") - 1))
		rest$ = MID$(arg$, INSTR(arg$, " TO ") + 4)
		by$ = "EmptyString"
	ELSE
		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)
	FI

	to$ = CHOP$(LEFT$(rest$, INSTR(rest$, " SIZE ") - 1))
	size$ = CHOP$(MID$(rest$, INSTR(rest$, " SIZE ") + 6))

	' Check type of var, string?
	IF Check_String_Type(to$) = 0 THEN
		EPRINT NL$, "Syntax error: variable ", to$, " in JOIN statement must be string at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	ELSE
		IF REGEX(to$, g_STRINGSIGN$ & "$") AND NOT(INSTR(to$, ".")) THEN
			' Is variable declared already?
			IF NOT(LEN(Get_Var$(to$, g_FUNCNAME$))) THEN
				Register_String(to$)
				WRITELN to$, " = __b2c_Copy_String(", to$, ", EmptyString);" TO g_CFILE
			ENDIF
		END IF
	ENDIF

	WRITELN to$, "= (char*)__b2c_str_realloc(", to$, ", (strlen(", source$, "[0+", g_OPTION_BASE, "])+1)*sizeof(char)); strcpy(", to$, ", ", source$, "[0+", g_OPTION_BASE, "]);" TO g_CFILE

	WRITELN "for(__b2c__ctr=1; __b2c__ctr < ", size$, "; __b2c__ctr++){if(", source$, "[__b2c__ctr+", g_OPTION_BASE, "]!=NULL){" TO g_CFILE
	WRITELN to$, "= (char*)__b2c_str_realloc(", to$, ", (strlen(", to$, ")+strlen(", by$, ")+strlen(", source$, "[__b2c__ctr+", g_OPTION_BASE, "])+1)*sizeof(char));" TO g_CFILE
	WRITELN "strcat(", to$, ", ", by$, "); strcat(", to$, ", ", source$, "[__b2c__ctr+", g_OPTION_BASE, "]);} __b2c__SETLEN(", to$, ", strlen(", to$, "));}" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Sort(STRING arg$)

	LOCAL dim$, type$, var$, tmp$, down$, rel$

	' Check if we have an argument at all
	IF LEN(CHOP$(arg$)) = 0 THEN
		EPRINT NL$, "Syntax 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 ") + 6))
		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

	' What kind of array are we dealing with? Associative
	IF LEN(Get_Var$("__b2c__" & var$ & "_type_")) OR LEN(Get_Var$("__b2c__" & var$ & "_type_" & g_FUNCNAME$, g_FUNCNAME$)) THEN
		type$ = "assoc"
	ELSE
		' Static Array? Determine data type
		type$ = Get_Var$(var$, g_FUNCNAME$)
		IF LEN(type$) AND NOT(INSTR(g_DYNAMICARRAYS$, var$ & "@" & g_FUNCNAME$)) THEN
			IF LEN(dim$) = 0 THEN
				dim$ = IIF$(LEN(Get_Var$("__b2c__split__" & var$, g_FUNCNAME$)), "__b2c__split__" & var$ & "+1", Get_Dim$(var$))
			END IF
		ELSE
			' Assuming dynamic array - determine data type
			IF LEN(Get_Var$(var$, g_FUNCNAME$)) THEN
				IF LEN(dim$) = 0 THEN
					EPRINT NL$, "Syntax error: SORT needs SIZE in case of dynamic array '", var$, "' at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
					END 1
				END IF
			ENDIF
		ENDIF
	ENDIF

	' Check DIM size
	WRITELN "if((", dim$, "-", g_OPTION_BASE, ") < 0) {if(__b2c__trap){ERROR=36; if(!__b2c__catch_set) RUNTIMEERROR(\"SORT\",", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

	' Check if it is an assoc array - using Bubble Sort
	IF type$ = "assoc" THEN
		IF NOT(LEN(Get_Var$(var$))) THEN rel$ = g_FUNCNAME$
		WRITELN "__b2c__", var$, "_tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__", var$, "_tab); __b2c__counter = __b2c__hashtable_count(&__b2c__", var$, "_tab); while(__b2c__counter > 1) {" TO g_CFILE
		WRITELN "for(__b2c__ctr = 0; __b2c__ctr < __b2c__counter-1; __b2c__ctr++) {" TO g_CFILE
		WRITELN "if(__b2c_", rel$, "_", var$, "_sort", down$, "(__b2c__hashtable_find(&__b2c__", var$, "_tab, (HASHTABLE_U64)__b2c__", var$, "_tmp[__b2c__ctr]), __b2c__hashtable_find(&__b2c__", var$, "_tab, (HASHTABLE_U64)__b2c__", var$, "_tmp[__b2c__ctr+1])) > 0)" TO g_CFILE
		WRITELN "{ __b2c__hashtable_swap(&__b2c__", var$, "_tab, __b2c__ctr, __b2c__ctr+1); } } __b2c__counter--; }" TO g_CFILE
		' Check if we have a string
	ELIF REGEX(var$, g_STRINGSIGN$ & "$") THEN
		WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(char*), __b2c__sortstr", down$, ");" TO g_CFILE
		' It is a value
	ELSE
		IF INSTR(type$, "double") OR INSTR(type$, "FLOATING") THEN
			WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(double), __b2c__sortnrd", down$, ");" TO g_CFILE
		ELIF INSTR(type$, "float") THEN
			WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(float), __b2c__sortnrf", down$, ");" TO g_CFILE
		ELIF INSTR(type$, "long") OR INSTR(type$, "NUMBER") THEN
			WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(long), __b2c__sortnrl", down$, ");" TO g_CFILE
		ELIF INSTR(type$, "int") THEN
			WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(int), __b2c__sortnri", down$, ");" TO g_CFILE
		ELIF INSTR(type$, "short") THEN
			WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(short), __b2c__sortnrs", down$, ");" TO g_CFILE
		ELSE
			WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(char), __b2c__sortnrc", down$, ");" TO g_CFILE
		END IF
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Alias(STRING arg$)

	LOCAL org$, new$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty ALIAS at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Check if TO is available
	IF NOT(INSTR(arg$, "TO")) THEN
		EPRINT NL$, "Syntax error: missing TO in ALIAS statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Get the source string
	org$ = CHOP$(EXTRACT$(MID$(arg$, 1, INSTR(arg$, " TO ") - 1), CHR$(34)) )
	new$ = CHOP$(EXTRACT$(MID$(arg$, INSTR(arg$, " TO ") + 4), CHR$(34)) )

	' Translate to C
	WRITELN "#define ", new$, " ", org$ TO g_HFILE
	g_IMPORTED$ = new$ & " " & g_IMPORTED$

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Lookup(STRING arg$)

	LOCAL source$, rest$, to$, size$
	LOCAL is_static

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax 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
		EPRINT NL$, "Syntax 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
		EPRINT NL$, "Syntax 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))

	IF INSTR(size$, " STATIC") THEN
		size$ = MID$(size$, 1, INSTR(size$, "STATIC")-1)
		is_static = 1
	ELSE
		is_static = 0
	ENDIF

	' Variable may not be array, these should be defined with DECLARE
	IF NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) AND NOT(REGEX(size$, "\\(.*\\)")) AND NOT(INSTR(size$, "->")) THEN
		IF NOT(LEN(Get_Var$(size$, g_FUNCNAME$))) THEN
			Register_Numeric$(size$)
		ENDIF
	END IF

	' Translate to C code
	IF ISTRUE(LEN(g_FUNCNAME$)) THEN
		IF NOT(INSTR(g_STRINGARGS$, "**" & to$)) THEN
			g_STRINGARGS$ = g_STRINGARGS$ & " char **" & to$ & " = NULL; int __b2c__split__" & to$ & " = " & STR$(g_OPTION_BASE) & ";"
			Save_Func_Var(to$, g_FUNCNAME$, "char*")
			Save_Func_Var("__b2c__split__" & to$, g_FUNCNAME$, "int")
		END IF
	ELSE
		IF NOT(LEN(Get_Var$(to$))) THEN
			WRITELN "char **", to$, " = NULL; int __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_HFILE
			Save_Main_Var(to$, "char*")
			Save_Main_Var("__b2c__split__" & to$, "int")
		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 "{__b2c__STRFREE(", to$, "[__b2c__ctr]);} free(", to$, "); ", to$, " = NULL;} __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_CFILE

	' Run the LOOKUP code
	WRITELN "__b2c__", source$, "_tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__", source$, "_tab); for(__b2c__ctr = 0; __b2c__ctr < __b2c__hashtable_count(&__b2c__", source$, "_tab); __b2c__ctr++) {", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*));" TO g_CFILE
	IF INSTR(to$, g_STRINGSIGN$) THEN
		WRITELN "__b2c__", source$, "_loc = (__b2c__", source$, "_typ*)__b2c__hashtable_find(&__b2c__", source$, "_tab, (HASHTABLE_U64)__b2c__", source$, "_tmp[__b2c__ctr]); ", to$, "[__b2c__split__", to$, "++] = __b2c__strdup(__b2c__", source$, "_loc->key);" TO g_CFILE
	ELSE
		WRITELN to$, "[__b2c__split__", to$, "++] = __b2c__", source$, "_loc->key;" TO g_CFILE
	ENDIF
	WRITELN "} ",  size$, " = __b2c__split__", to$, " - ", g_OPTION_BASE, ";if(__b2c__split__", to$, " > 0) __b2c__split__", to$, "--;" TO g_CFILE

	' Save information needed for a REDIM
	IF ISTRUE(LEN(g_FUNCNAME$)) THEN
		IF NOT(INSTR(g_STRINGARGS$, "__b2c_array_" & to$)) THEN g_STRINGARGS$ = g_STRINGARGS$ & " long __b2c_array_" & to$ & ";"
	ELSE
		IF NOT(LEN(Get_Var$("__b2c_array_" & to$))) THEN
			WRITELN "long __b2c_array_", to$, ";" TO g_HFILE
			Save_Main_Var("__b2c_array_" & to$, "long")
		ENDIF
	ENDIF
	WRITELN "__b2c_array_", to$, " = ", size$, ";" 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$, to$ & "[")) THEN
		IF is_static = 0 THEN
			IF INSTR(to$, g_STRINGSIGN$) THEN
				g_STRINGARRAYS$ = g_STRINGARRAYS$ & " if(" & to$ & "!= NULL){for(__b2c__ctr=" & STR$(g_OPTION_BASE) & ";__b2c__ctr<__b2c_array_" & to$ & "+" & STR$(g_OPTION_BASE) & ";__b2c__ctr++) if(" & to$ & "[__b2c__ctr]!=NULL){__b2c__STRFREE(" & to$ & "[__b2c__ctr]);} }"
			ENDIF
			g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & to$
		ENDIF
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Relate(STRING arg$)

	LOCAL source$, to$, str$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax 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
		EPRINT NL$, "Syntax 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
	IF NOT(LEN(Get_Var$("__b2c__" & source$ & "_type_"))) AND NOT(LEN(Get_Var$("__b2c__" & source$ & "_type_" & g_FUNCNAME$, g_FUNCNAME$))) THEN
		EPRINT NL$, "Syntax error: variable '", source$, "' not declared as ASSOC in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Assign relations
	FOR str$ IN EXTRACT$(to$, " ") STEP ","
		IF NOT(LEN(Get_Var$("__b2c__" & str$ & "_type_"))) AND NOT(LEN(Get_Var$("__b2c__" & str$ & "_type_" & g_FUNCNAME$, g_FUNCNAME$))) THEN
			EPRINT NL$, "Syntax error: variable '", str$, "' not declared as ASSOC in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		END IF

		g_RELATE$[g_RELATE_CTR] = source$ & " " & str$
		INCR g_RELATE_CTR
	NEXT

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Data(STRING arg$)

	LOCAL var$, token$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty DATA at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	var$ = arg$

	' Start miniparser
	WHILE LEN(var$)
		token$ = Mini_Parser$(var$)
		IF INSTR(token$, CHR$(34)) THEN
			WRITELN CHOP$(token$), ", " TO STRINGARRAYFILE
			INCR g_CCTR
		ELSE
			WRITELN CHOP$(token$), ", " TO FLOATARRAYFILE
			INCR g_FCTR
		END IF
		var$ = MID$(var$, LEN(token$)+2)
	WEND

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Redim(STRING arg$)

	LOCAL type$, var$, to$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty REDIM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Check if TO is available
	IF NOT(INSTR(arg$, " TO ")) THEN
		EPRINT NL$, "Syntax error: missing TO in REDIM statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Get the source string
	var$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ") - 1))
	to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))

	type$ = Get_Var$(var$, g_FUNCNAME$)
	IF NOT(LEN(type$)) THEN
		EPRINT NL$, "Syntax error: cannot REDIM array which is not declared previously at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Delete old data from strings if new size is smaller
	IF Check_String_Type(var$) THEN
		WRITELN "if(", to$, "<__b2c_array_", MID$(var$, INSTR(var$, ".")+1), ") {for(__b2c__ctr=", to$, "+", g_OPTION_BASE, "; __b2c__ctr<__b2c_array_", MID$(var$, INSTR(var$, ".")+1), "+", g_OPTION_BASE, "; __b2c__ctr++) {if(", var$, "[__b2c__ctr]!=NULL) __b2c__STRFREE(", var$, "[__b2c__ctr]);} }" TO g_CFILE
	END IF

	' Realloc
	type$ = CHOP$(type$)
	WRITELN var$, " = (", type$, "*)realloc(", var$, ", (", to$, "+", g_OPTION_BASE, ")*sizeof(", type$, "));" TO g_CFILE

	' Re-initialize records if new area is bigger
	IF REGEX(type$, "_type$") OR REGEX(type$, "_TYPE$") THEN
		WRITELN "if(__b2c_record_", MID$(var$, INSTR(var$, ".")+1), " < ", to$, ") { for(__b2c__ctr=__b2c_record_", MID$(var$, INSTR(var$, ".")+1), "+", g_OPTION_BASE, "; __b2c__ctr<", to$, "+", g_OPTION_BASE, "; __b2c__ctr++) memset(&", var$, "[__b2c__ctr], 0, sizeof(", type$, "));}" TO g_CFILE
		WRITELN "__b2c_record_", MID$(var$, INSTR(var$, ".")+1), " = ", to$, ";" TO g_CFILE
	ELSE
		' Re-initialize strings if new area is bigger
		IF Check_String_Type(var$) THEN
			WRITELN "if(", to$, ">__b2c_array_", MID$(var$, INSTR(var$, ".")+1), ") {for(__b2c__ctr=__b2c_array_", MID$(var$, INSTR(var$, ".")+1), "+", g_OPTION_BASE, "; __b2c__ctr<", to$, "+", g_OPTION_BASE, "; __b2c__ctr++) ", var$, "[__b2c__ctr] = (char*)calloc(1, sizeof(char));}" TO g_CFILE
		END IF
		WRITELN "__b2c_array_", MID$(var$, INSTR(var$, ".")+1), " = ", to$, ";" TO g_CFILE
	ENDIF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Swap(STRING arg$)

	LOCAL var$, to$, type$, tmp$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty SWAP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Get the source string
	var$ = CHOP$(LEFT$(arg$, INSTR(arg$, ",") - 1))
	to$ = CHOP$(MID$(arg$, INSTR(arg$, ",") + 1))

	' Perform universal swap
	IF Check_String_Type(var$) AND NOT(Check_String_Type(to$)) THEN
		WRITELN "__b2c__assign = calloc(", g_MAX_DIGITS, "+1, sizeof(char)); if (floor(", to$, ") == ", to$, ") { __b2c__ctr = snprintf(__b2c__assign, ", g_MAX_DIGITS, ", \"%ld\", (long) ", to$, "); }" TO g_CFILE
		WRITELN "else { __b2c__ctr = snprintf (__b2c__assign, ", g_MAX_DIGITS, ", \"%g\", (double) ", to$, "); } ", to$, " = VAL(", var$, "); __b2c__STRFREE(", var$, "); ", var$, " = __b2c__assign;" TO g_CFILE
	ELIF NOT(Check_String_Type(var$)) AND Check_String_Type(to$) THEN
		WRITELN "__b2c__assign = calloc(", g_MAX_DIGITS, "+1, sizeof(char)); if (floor(", var$, ") == ", var$, ") { __b2c__ctr = snprintf(__b2c__assign, ", g_MAX_DIGITS, ", \"%ld\", (long) ", var$, "); }" TO g_CFILE
		WRITELN "else { __b2c__ctr = snprintf (__b2c__assign, ", g_MAX_DIGITS, ", \"%g\", (double) ", var$, "); } ", var$, " = VAL(", to$, "); __b2c__STRFREE(", to$, "); ", to$, " = __b2c__assign;" TO g_CFILE
	ELSE
		' Determine type
		IF Check_String_Type(var$) THEN
			type$ = "char *"
		ELSE
			type$ = Get_Var$(var$, g_FUNCNAME$)
			IF LEN(type$) = 0 THEN
				EPRINT NL$, "Syntax error: cannot determine type of variables in SWAP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			END IF
			' Leave one dimension out to exchange array variables
			type$ = LEFT$(type$, INSTR(type$, "*")-1)
		END IF

		' Get rid of array syntax
		tmp$ = IIF$(INSTR(var$, "["), LEFT$(var$, INSTR(var$, "[")-1), var$)

		' Declare temp variable
		IF LEN(g_FUNCNAME$) > 0 THEN
			IF NOT(LEN(Get_Var$("__b2c__" & tmp$ & "_swap", g_FUNCNAME$))) THEN
				g_STRINGARGS$ = g_STRINGARGS$ & " " & type$ & " __b2c__" & tmp$ & "_swap;"
				Save_Func_Var("__b2c__" & tmp$ & "_swap", g_FUNCNAME$, type$)
			ENDIF
		ELSE
			IF NOT(LEN(Get_Var$("__b2c__" & tmp$ & "_swap"))) THEN
				WRITELN type$, " __b2c__", tmp$, "_swap;" TO g_HFILE
				Save_Main_Var("__b2c__" & tmp$ & "_swap", type$)
			ENDIF
		ENDIF
		WRITELN "__b2c__", tmp$, "_swap = ", var$, "; ", var$, " = ", to$, "; ", to$, " = __b2c__", tmp$, "_swap;" TO g_CFILE
	ENDIF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Setserial(STRING arg$)

	LOCAL desc$, value$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty SETSERIAL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Check if a mode is available
	IF NOT(REGEX(arg$, " IMODE | OMODE | CMODE | LMODE | OTHER | SPEED ")) THEN
		EPRINT NL$, "Syntax error: no mode specified in SETSERIAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	desc$ = LEFT$(arg$, INSTR(arg$, " "))

	' Get the setting
	IF INSTR(arg$, " OTHER ") THEN
		value$ = MID$(arg$, INSTRREV(arg$, "OTHER ")+6)
	ELIF INSTR(arg$, " SPEED ") THEN
		value$ = MID$(arg$, INSTRREV(arg$, "SPEED ")+6)
	ELSE
		value$ = MID$(arg$, INSTRREV(arg$, "MODE ")+5)
	ENDIF

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

	IF INSTR(arg$, "IMODE") THEN
		IF INSTR(value$, "~") THEN
			WRITELN "__b2c__tty.c_iflag &= ", value$, ";" TO g_CFILE
		ELSE
			WRITELN "__b2c__tty.c_iflag |= ", value$, ";" TO g_CFILE
		END IF
	ELIF INSTR(arg$, "OMODE") THEN
		IF INSTR(value$, "~") THEN
			WRITELN "__b2c__tty.c_oflag &= ", value$, ";" TO g_CFILE
		ELSE
			WRITELN "__b2c__tty.c_oflag |= ", value$, ";" TO g_CFILE
		END IF
	ELIF INSTR(arg$, "CMODE") THEN
		IF INSTR(value$, "~") THEN
			WRITELN "__b2c__tty.c_cflag &= ", value$, ";" TO g_CFILE
		ELSE
			WRITELN "__b2c__tty.c_cflag |= ", value$, ";" TO g_CFILE
		END IF
	ELIF INSTR(arg$, "LMODE") THEN
		IF INSTR(value$, "~") THEN
			WRITELN "__b2c__tty.c_lflag &= ", value$, ";" TO g_CFILE
		ELSE
			WRITELN "__b2c__tty.c_lflag |= ", value$, ";" TO g_CFILE
		END IF
	ELIF INSTR(arg$, "OTHER") THEN
		WRITELN "__b2c__tty.c_cc[", LEFT$(value$, INSTR(value$, "=")-1), "] = ", MID$(value$, INSTR(value$, "=")+1), ";" TO g_CFILE
	ELIF INSTR(arg$, "SPEED") THEN
		WRITELN "cfsetospeed (&__b2c__tty, ", value$, "); cfsetispeed (&__b2c__tty, ", value$, ");" TO g_CFILE
	END IF

	WRITELN "if (tcsetattr(", desc$, ", TCSANOW, &__b2c__tty) != 0)" TO g_CFILE
	WRITELN "{if(__b2c__trap){ERROR = 33; if(!__b2c__catch_set) RUNTIMEERROR(\"SETSERIAL\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Call(STRING arg$)

	LOCAL var$, lft$, str$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty CALL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	IF NOT(INSTR(arg$, " TO ")) THEN
		IF INSTR(arg$, "(") THEN
			WRITELN arg$, ";" TO g_CFILE
		ELSE
			WRITELN arg$, "();" TO g_CFILE
		END IF
	ELSE
		var$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))
		' Check if var is string var, exclude RECORD elements
		IF REGEX(var$, g_STRINGSIGN$ & "$") AND NOT(INSTR(var$, ".")) THEN
			' Is variable declared already?
			IF NOT(LEN(Get_Var$(var$, g_FUNCNAME$))) THEN
				Register_String(var$)
			END IF
			' Assume number, exclude RECORD elements
		ELIF NOT(REGEX(var$, "\\[.*\\]")) AND NOT(INSTR(var$, ".")) AND NOT(REGEX(var$, "\\(.*\\)")) AND NOT(INSTR(var$, "->")) THEN
			' Is variable declared already?
			IF NOT(LEN(Get_Var$(var$, g_FUNCNAME$))) THEN
				Register_Numeric$(var$)
			END IF
		END IF

		' Check type of var, string?
		IF Check_String_Type(var$) THEN

			IF INSTR(MID$(arg$, 1, INSTR(arg$, " TO ")), "(") THEN
				WRITELN "__b2c__assign=(char*)__b2c__strdup(", MID$(arg$, 1, INSTR(arg$, " TO ")-1), ");" TO g_CFILE
			ELSE
				WRITELN "__b2c__assign=(char*)__b2c__strdup(", MID$(arg$, 1, INSTR(arg$, " TO ")-1), "());" TO g_CFILE
			END IF
			WRITELN "if(__b2c__assign==NULL)__b2c__assign = (char*)calloc(1, sizeof(char));" TO g_CFILE
			' Now see if we have a assoc or a normal variable
			IF REGEX(var$, "\\(.*\\)$") THEN
				lft$ = LEFT$(var$, INSTR(var$, "(") - 1)
				str$ = MID$(var$, INSTR(var$, "(") + 1)
				WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
				WRITELN "if(__b2c__", lft$, "_loc->value != NULL) __b2c__STRFREE(__b2c__", lft$, "_loc->value); __b2c__", lft$, "_loc->value = __b2c__assign; " TO g_CFILE
				' Check for relations
				CALL Relate_Recurse(lft$, str$, var$, -1)
			ELSE
				WRITELN "if(", var$, " != NULL) __b2c__STRFREE(", var$, "); ", var$, " = __b2c__assign;" TO g_CFILE
			END IF
		ELSE
			IF REGEX(var$, "\\(.*\\)$") THEN
				lft$ = LEFT$(var$, INSTR(var$, "(") - 1)
				str$ = MID$(var$, INSTR(var$, "(") + 1)
				WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
				IF INSTR(MID$(arg$, 1, INSTR(arg$, " TO ")), "(") THEN
					WRITELN "__b2c__", lft$, "_loc->value = ", MID$(arg$, 1, INSTR(arg$, " TO ")-1), ";" TO g_CFILE
				ELSE
					WRITELN "__b2c__", lft$, "_loc->value = ", MID$(arg$, 1, INSTR(arg$, " TO ")-1), "();" TO g_CFILE
				END IF
				' Check for relations
				CALL Relate_Recurse(lft$, str$, var$, -1)
			ELSE
				IF INSTR(MID$(arg$, 1, INSTR(arg$, " TO ")), "(") THEN
					WRITELN var$, " = ", MID$(arg$, 1, INSTR(arg$, " TO ")-1), ";" TO g_CFILE
				ELSE
					WRITELN var$, " = ", MID$(arg$, 1, INSTR(arg$, " TO ")-1), "();" TO g_CFILE
				END IF
			END IF
		END IF
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Run(STRING arg$)

	LOCAL escaped, in_string, x
	LOCAL token$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty RUN at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Start miniparser to find separate arguments
	FOR x = 2 TO LEN(arg$)-2
		SELECT ASC(MID$(arg$, x, 1))
			CASE 92
				IF escaped THEN
					escaped = FALSE
				ELSE
					escaped = TRUE
				FI
			CASE 34
				IF escaped THEN in_string = NOT(in_string)
				escaped = FALSE
			CASE 32
				IF ISFALSE(in_string) THEN arg$ = LEFT$(arg$, x-1) & CHR$(34) & "," & CHR$(34) & MID$(arg$, x+1)
				escaped = FALSE
			DEFAULT
				escaped = FALSE
		END SELECT
	NEXT

	' Get first token
	token$ = Mini_Parser$(arg$)

	WRITELN "execlp(", token$, "," & EXTRACT$(arg$, "\\" & CHR$(34)) & ", NULL); fflush(stdout);" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Save(type, arg$)

	LOCAL exp$, str$, size$, token$

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty SAVE/BSAVE/APPEND/BAPPEND at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	ELIF NOT(INSTR(arg$, " TO ")) THEN
		EPRINT NL$, "Syntax error: SAVE/BSAVE/APPEND/BAPPEND without TO at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	ELSE
		str$ = TOKEN$(arg$, 1, " TO ")
		exp$ = TOKEN$(arg$, 2, " TO ")
		IF AMOUNT(exp$, " SIZE ") > 1 THEN
			size$ = TOKEN$(exp$, 2, " SIZE ")
			exp$ = TOKEN$(exp$, 1, " SIZE ")
		ELSE
			size$ = "0"
		ENDIF
		' How to open the file
		SELECT type
			CASE 0, 1
				WRITELN "__b2c__outFile = fopen((const char*)", exp$, ", \"w\");" TO g_CFILE
			CASE 2, 3
				WRITELN "__b2c__outFile = fopen((const char*)", exp$, ", \"a\");" TO g_CFILE
		ENDSELECT
		WRITELN "if(__b2c__outFile == NULL){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"SAVE/BSAVE/APPEND/BAPPEND\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
		' Determine length
		SELECT type
			CASE 0, 2
				WHILE LEN(str$)
					token$ = Mini_Parser$(str$)
					Print_Element(CHOP$(token$), "__b2c__outFile")
					str$ = MID$(str$, LEN(token$)+2)
				WEND
			CASE 1, 3
				WRITELN "__b2c__assign = (char*)", str$, "; __b2c__ctr = ", size$, ";" TO g_CFILE
				WRITELN "if(fwrite(__b2c__assign, 1, __b2c__ctr, __b2c__outFile) != __b2c__ctr){if(__b2c__trap){ERROR = 2; if(!__b2c__catch_set)" TO g_CFILE
				WRITELN "RUNTIMEERROR(\"BSAVE/BAPPEND\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
		ENDSELECT
		WRITELN "fclose(__b2c__outFile);" TO g_CFILE
		IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
	END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Map(STRING arg$)

	LOCAL source$, rest$, by$, to$, size$, type$, i$
	LOCAL is_static

	' Check if we have an argument at all
	IF ISFALSE(LEN(CHOP$(arg$))) THEN
		EPRINT NL$, "Syntax error: empty MAP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Check if BY is available
	IF NOT(INSTR(arg$, " BY ")) THEN
		EPRINT NL$, "Syntax error: missing BY in MAP statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Check if TO is available
	IF NOT(INSTR(arg$, " TO ")) THEN
		EPRINT NL$, "Syntax error: missing TO in MAP statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	END IF

	' Check if SIZE is available
	IF NOT(INSTR(arg$, " SIZE ")) THEN
		EPRINT NL$, "Syntax error: missing SIZE in MAP 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))

	IF INSTR(size$, " STATIC") THEN
		size$ = MID$(size$, 1, INSTR(size$, "STATIC")-1)
		is_static = 1
	ELSE
		is_static = 0
	ENDIF

	' Remove doublequotes from BY
	by$ = EXTRACT$(by$, CHR$(34))

	' Make sure to get the type right
	type$ = "long"

	IF Check_String_Type(by$) THEN
		type$ = "char*"
	ELSE
		FOR i$ IN source$
			IF REGEX(Get_Var$(i$, g_FUNCNAME$), ".*double.*|.*FLOATING.*") THEN
				type$ = "double"
				BREAK
			ENDIF
		NEXT
	ENDIF

	' Declare target array
	IF NOT(LEN(Get_Var$(to$, g_FUNCNAME$))) THEN
		IF g_OPTION_EXPLICIT$ = "1" OR g_OPTION_EXPLICIT$ = "TRUE" THEN
			EPRINT NL$, "Syntax error: OPTION EXPLICIT forces explicit variable declaration at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		ENDIF
		IF ISTRUE(LEN(g_FUNCNAME$)) THEN
			WRITELN type$ , "* ", to$, ";" TO g_CFILE
			Save_Func_Var(to$, g_FUNCNAME$, type$ & "*")
		ELSE
			WRITELN type$ , "* ", to$, ";" TO g_HFILE
			Save_Main_Var(to$, type$ & "*")
		END IF
		WRITELN to$, " = (", type$, "*)calloc((size_t)(", size$, "+", g_OPTION_BASE, "), sizeof(", type$, "));" TO g_CFILE

		' Cleanup local array members
		IF type$ = "char*" THEN g_STRINGARRAYS$ = g_STRINGARRAYS$ & " for(__b2c__ctr=" & STR$(g_OPTION_BASE) & "; __b2c__ctr<" & size$ & "+" & STR$(g_OPTION_BASE) & "; __b2c__ctr++)if(" & to$ & "[__b2c__ctr]!=NULL){__b2c__STRFREE(" & to$ & "[__b2c__ctr]);}"

		' Not static, then cleanup
		IF is_static = 0 THEN g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & to$
	END IF

	' Create the C code
	WRITELN "for(__b2c__ctr=", g_OPTION_BASE, "; __b2c__ctr<", size$, "+", g_OPTION_BASE, "; __b2c__ctr++){" TO g_CFILE
	IF type$ = "char*" THEN
		WRITELN to$, "[__b2c__ctr] = __b2c_Copy_String(", to$, "[__b2c__ctr], ", by$, "(", REPLACE$(source$, ",", "[__b2c__ctr],"), "[__b2c__ctr])); }" TO g_CFILE
	ELSE
		WRITELN to$, "[__b2c__ctr] = ", by$, "(", REPLACE$(source$, ",", "[__b2c__ctr],"), "[__b2c__ctr]); }" TO g_CFILE
	ENDIF

ENDSUB

'----------------------------------------------------------------------------------------------

FUNCTION Count_Lines(STRING file$)

	LOCAL lines
	LOCAL newfile TYPE FILE*
	LOCAL txt$

	OPEN file$ FOR READING AS newfile

	WHILE NOT(ENDFILE(newfile)) DO
		READLN txt$ FROM newfile
		INCR lines
	WEND

	CLOSE FILE newfile

	RETURN lines

END FUNCTION

'----------------------------------------------------------------------------------------------
'
' 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$, lft$, str$, newfeed$, token$, rel$
	LOCAL dim, i, found, copy_counter, to_parse, size, trc_backup
	LOCAL newfile, src_tmp, src_in, src_out TYPE FILE*

	SPLIT statement$ BY " " TO element$ SIZE dim

	IF dim > 0 THEN

		' See if we need to pass C code
		IF ISTRUE(g_USE_C) THEN
			IF LEFT$(statement$, 8) = "END USEC" OR element$[1] = "ENDUSEC" THEN
				g_USE_C = 0
			ELIF LEFT$(statement$, 8) = "END ENUM" OR element$[1] = "ENDENUM" THEN
				g_USE_C = 0
				WRITELN "};" TO g_CFILE
			ELSE
				WRITELN statement$ TO g_CFILE
			END IF

		ELIF ISTRUE(g_USE_H) THEN
			IF LEFT$(statement$, 8) = "END USEH" OR element$[1] = "ENDUSEH" THEN
				g_USE_H = 0
			ELIF LEFT$(statement$, 8) = "END ENUM" OR element$[1] = "ENDENUM" THEN
				g_USE_H = 0
				WRITELN "};" TO g_HFILE
			ELSE
				WRITELN statement$ TO g_HFILE
			END IF

		ELIF LEFT$(element$[1], 2) = "#!" THEN
			'Do nothing

		ELIF LEFT$(element$[1], 1) = "'" THEN
			'Do nothing

		ELIF LEFT$(element$[1], 3) = "REM" THEN
			'Do nothing

		ELIF RIGHT$(element$[dim], 2) = "*/" THEN
			g_COMMENT$ = "false"

		ELIF LEFT$(element$[1], 2) = "/*" THEN
			g_COMMENT$ = "true"

		ELIF g_COMMENT$ = "false" THEN

			SELECT element$[1]
				CASE "USEC"
					g_USE_C = 1

				CASE "USEH"
					g_USE_H = 1

				CASE "PRINT"
					Handle_Print(MID$(statement$, INSTR(statement$, "PRINT") + 5), "stdout")

				CASE "EPRINT"
					Handle_Print(MID$(statement$, INSTR(statement$, "EPRINT") + 6), "stderr")

				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"
					IF INSTR(g_LOOPVAR$[g_LOOPCTR], g_STRINGSIGN$) THEN
						WRITELN "} if (__b2c__forin_", g_LOOPVAR$[g_LOOPCTR], "_ptr != NULL) { __b2c__STRFREE(__b2c__forin_", g_LOOPVAR$[g_LOOPCTR], "_ptr); }" TO g_CFILE
						g_LOOPVAR$[g_LOOPCTR]=""
					ELSE
						WRITELN "}" TO g_CFILE
					END IF
					IF g_LOOPCTR > 0 AND g_OPTION_BREAK 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
					IF ISFALSE(INSTRREV(statement$, " THEN")) THEN
						EPRINT NL$, "Syntax 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
							trc_backup = g_TRACE
							g_TRACE = 0
							CALL Tokenize(MID$(statement$, INSTRREV(statement$, " THEN") + 5))
							g_TRACE = trc_backup
							WRITELN "}" TO g_CFILE
						END IF
					ENDIF

				CASE "ELIF"
					' Check if THEN is available
					IF ISFALSE(INSTRREV(statement$, " THEN")) THEN
						EPRINT NL$, "Syntax 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)))
						IF LEN(CHOP$(MID$(statement$, INSTRREV(statement$, " THEN") + 5))) > 0 THEN
							WRITELN "else if(", exp$, "){" TO g_CFILE
							IF g_TRACE = 1 THEN g_TRACE_PREFIX$ = "ELIF"
							CALL Tokenize(MID$(statement$, INSTRREV(statement$, " THEN") + 5))
							WRITELN "}" TO g_CFILE
						ELSE
							WRITELN "} else if(", exp$, "){" TO g_CFILE
							IF g_TRACE = 1 THEN g_TRACE_PREFIX$ = "ELIF"
						END IF
					END IF

				CASE "ELSE"
					' Translate function to C function
					IF LEN(CHOP$(MID$(statement$, INSTR(statement$, " ELSE") + 5))) > 0 THEN
						WRITELN "else {" TO g_CFILE
						IF g_TRACE = 1 THEN g_TRACE_PREFIX$ = "ELSE"
						CALL Tokenize(MID$(statement$, INSTR(statement$, " ELSE") + 5))
						WRITELN "}" TO g_CFILE
					ELSE
						WRITELN "} else {" TO g_CFILE
						IF g_TRACE = 1 THEN g_TRACE_PREFIX$ = "ELSE"
					END IF

				CASE "FI"
					WRITELN "}" TO g_CFILE

				CASE "DOTIMES"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty DOTIMES at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						WRITELN "long __do_times_", g_DOTIMES, ";" TO g_HFILE
						WRITELN "for(__do_times_", g_DOTIMES, " = 0; __do_times_", g_DOTIMES, "<", MID$(statement$, INSTR(statement$, "DOTIMES") + 7), "; __do_times_", g_DOTIMES, "++) {" TO g_CFILE
						INCR g_DOTIMES
					END IF

				CASE "DO"
					WRITELN "{" TO g_CFILE

				CASE "DONE"
					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 AND g_OPTION_BREAK 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 g_OPTION_BREAK THEN
						IF dim > 1 AND VAL(MID$(statement$, INSTR(statement$, "BREAK") + 5)) <> 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
					ELSE
						EPRINT NL$, "Syntax error: use of BREAK at line ", g_COUNTER, " in file '", g_CURFILE$, "' was disbaled!"
						END 1
					ENDIF

				CASE "CONTINUE"
					' Check argument
					IF dim > 1 AND VAL(MID$(statement$, INSTR(statement$, "CONTINUE") + 8)) <> 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 = 1 THEN
						EPRINT NL$, "Syntax 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 AND g_OPTION_BREAK 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 = 1 THEN
						EPRINT NL$, "Syntax 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 = 1 THEN
						EPRINT NL$, "Syntax 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 < 3 THEN
						EPRINT NL$, "Syntax error: empty CLOSE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						exp$ = CHOP$(MID$(statement$, INSTR(statement$, "CLOSE") + 5))
						SELECT element$[2]
							CASE "FILE"
								exp$ = MID$(exp$, INSTR(exp$, " ") + 1)
								WHILE LEN(exp$)
									token$ = Mini_Parser$(exp$)
									WRITELN "fclose(", token$, ");" TO g_CFILE
									exp$ = MID$(exp$, LEN(token$)+2)
									token$ = CHOP$(token$)
									g_SEMANTIC_OPENCLOSE$(token$) = IIF$(LEN(g_SEMANTIC_OPENCLOSE$(token$)), "", "'" & token$ & "' at line " & STR$(g_COUNTER) & " in file '" & g_CURFILE$ & "'")
								WEND
							CASE "DIRECTORY"
								exp$ = MID$(exp$, INSTR(exp$, " ") + 1)
								WHILE LEN(exp$)
									token$ = Mini_Parser$(exp$)
									WRITELN "closedir(", token$, ");" TO g_CFILE
									exp$ = MID$(exp$, LEN(token$)+2)
									token$ = CHOP$(token$)
									g_SEMANTIC_OPENCLOSE$(token$) = IIF$(LEN(g_SEMANTIC_OPENCLOSE$(token$)), "", "'" & token$ & "' at line " & STR$(g_COUNTER) & " in file '" & g_CURFILE$ & "'")
								WEND
							CASE "MEMORY"
								exp$ = MID$(exp$, INSTR(exp$, " ") + 1)
								WHILE LEN(exp$)
									token$ = Mini_Parser$(exp$)
									WRITELN token$, " = NULL;" TO g_CFILE
									exp$ = MID$(exp$, LEN(token$)+2)
									token$ = CHOP$(token$)
									g_SEMANTIC_OPENCLOSE$(token$) = IIF$(LEN(g_SEMANTIC_OPENCLOSE$(token$)), "", "'" & token$ & "' at line " & STR$(g_COUNTER) & " in file '" & g_CURFILE$ & "'")
								WEND
							CASE "LIBRARY"
								exp$ = MID$(exp$, INSTR(exp$, " ") + 1)
								WHILE LEN(exp$)
									token$ = Mini_Parser$(exp$)
									WRITELN "if(__b2c__dlopen__pointer_", EXTRACT$(token$, "[[:punct:]]", TRUE), " != NULL) {dlclose(__b2c__dlopen__pointer_", EXTRACT$(token$, "[[:punct:]]", TRUE), "); __b2c__dlopen__pointer_", EXTRACT$(token$, "[[:punct:]]", TRUE), " = NULL;}" TO g_CFILE
									exp$ = MID$(exp$, LEN(token$)+2)
									token$ = CHOP$(token$)
								WEND
							CASE "NETWORK";
							CASE "SERVER";
							CASE "UDP";
							CASE "DEVICE"
								exp$ = MID$(exp$, INSTR(exp$, " ") + 1)
								WHILE LEN(exp$)
									token$ = Mini_Parser$(exp$)
									WRITELN "close(", token$, ");" TO g_CFILE
									exp$ = MID$(exp$, LEN(token$)+2)
									token$ = CHOP$(token$)
									g_SEMANTIC_OPENCLOSE$(token$) = IIF$(LEN(g_SEMANTIC_OPENCLOSE$(token$)), "", "'" & token$ & "' at line " & STR$(g_COUNTER) & " in file '" & g_CURFILE$ & "'")
								WEND
							DEFAULT
								EPRINT NL$, "Syntax error: erroneous CLOSE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
						END SELECT
					END IF

				CASE "REWIND"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax 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 = 1 THEN
						EPRINT NL$, "Syntax 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";
				CASE "ENDIF";
				CASE "ENDSUB";
				CASE "ENDWITH";
				CASE "ENDFORK";
				CASE "ENDRECORD";
				CASE "ENDSELECT";
				CASE "ENDFUNCTION"
					exp$ = IIF$(dim > 1, element$[2], MID$(element$[1], 4))
					SELECT exp$
						CASE "IF"
							WRITELN "}" TO g_CFILE
						CASE "RECORD"
							IF LEN(g_FUNCNAME$) > 0 THEN
								WRITELN "}", g_RECORDNAME$, ";" TO g_CFILE
								WRITELN "typedef ", g_RECORDNAME$, " ", EXTRACT$(g_RECORDNAME$, "_TYPE"), "_type;" TO g_CFILE
								IF LEN(g_RECORDARRAY$) THEN
									WRITELN g_RECORDNAME$, " *", LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "[")-1), " = (", g_RECORDNAME$, "*)calloc(", g_RECORDARRAY$, ", sizeof(", g_RECORDNAME$, "));" TO g_CFILE
									g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "[")-1)
									g_RECORDEND_BODY$ = " long __b2c_record_" & EXTRACT$(g_RECORDNAME$, "_TYPE") & " = " & g_RECORDARRAY$ & ";" & g_RECORDEND_BODY$
								ELSE
									WRITELN g_RECORDNAME$, " ", g_RECORDVAR$, " = { 0 } ;" TO g_CFILE
								ENDIF
							ELSE
								WRITELN "}", g_RECORDNAME$, ";" TO g_HFILE
								WRITELN "typedef ", g_RECORDNAME$, " ", EXTRACT$(g_RECORDNAME$, "_TYPE") , "_type;" TO g_HFILE
								IF LEN(g_RECORDARRAY$) THEN
									WRITELN g_RECORDNAME$, " *", LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "[")-1), ";" TO g_HFILE
									WRITELN LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "[")-1), " = (", g_RECORDNAME$, "*)calloc(", g_RECORDARRAY$, ", sizeof(", g_RECORDNAME$, "));" TO g_CFILE
									WRITELN "long __b2c_record_" & EXTRACT$(g_RECORDNAME$, "_TYPE") & ";" TO g_HFILE
									g_RECORDEND_BODY$ = g_RECORDEND_BODY$ & " __b2c_record_" & EXTRACT$(g_RECORDNAME$, "_TYPE") & " = " & g_RECORDARRAY$ & ";"
								ELSE
									WRITELN g_RECORDNAME$, " ", g_RECORDVAR$, " = { 0 } ;" TO g_HFILE
								ENDIF
								WRITELN g_RECORDEND_HEADER$ TO g_HFILE
							END IF
							WRITELN g_RECORDEND_BODY$ TO g_CFILE
							g_RECORDNAME$ = ""
							g_RECORDVAR$ = ""
							g_RECORDEND_BODY$ = ""
							g_RECORDEND_HEADER$ = ""
							g_RECORDARRAY$ = ""
							' 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 = 0 THEN
								EPRINT NL$, "Syntax 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$ = ""
								g_CASE_CONT$ = ""
								DECR g_SELECTVAR_CTR
							END IF
						CASE "FORK"
							IF dim > 2 THEN
								WRITELN "_exit(", MID$(statement$, INSTR(statement$, "FORK")+4), ");" TO g_CFILE
							ELSE
								WRITELN "_exit(EXIT_SUCCESS);" TO g_CFILE
							ENDIF
						DEFAULT
							WRITELN "exit(", IIF$(dim > 1, MID$(statement$, INSTR(statement$, "END")+3), "EXIT_SUCCESS"), ");" TO g_CFILE
					END SELECT

				CASE "SUB"
					Handle_SubFunc(MID$(statement$, INSTR(statement$, "SUB") + 3))

				CASE "CALL"
					Handle_Call(MID$(statement$, INSTR(statement$, "CALL") + 4))

				CASE "FUNCTION"
					Handle_SubFunc(MID$(statement$, INSTR(statement$, "FUNCTION") + 8))

				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"
					IF dim = 1 THEN
						WRITELN "__b2c__floatarray_ptr = 0;" TO g_CFILE
						WRITELN "__b2c__stringarray_ptr = 0;" TO g_CFILE
					ELSE
						WRITELN "__b2c__data_jump_flag = 1; if(!setjmp(__b2c__data_jump)) goto ", element$[2], ";" TO g_CFILE
						WRITELN "__b2c__floatarray_ptr = __b2c__label_floatarray_", element$[2], ";" TO g_CFILE
						WRITELN "__b2c__stringarray_ptr = __b2c__label_stringarray_", element$[2], ";" TO g_CFILE
					END IF

				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 = 1 THEN
						EPRINT NL$, "Syntax error: empty DATA at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						WRITELN "srandom((unsigned int)", MID$(statement$, INSTR(statement$, " ")+1), ");" 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$ = EXTRACT$((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] = EXTRACT$(element$[i], g_STRINGSIGN$)
						NEXT
						inc$ = MID$(inc$, 1, INSTR(inc$, ",")-1)
					ELSE
						to_parse = 2
					END IF
					' Check file extension
					IF RIGHT$(inc$, 4) <> ".bac" THEN inc$ = inc$ & ".bac"

					' Check argument
					IF NOT(FILEEXISTS(inc$)) OR dim = 1 OR (FILETYPE(inc$) != 1 AND FILETYPE(inc$) != 6) THEN
						EPRINT NL$, "System error: missing file '", inc$, "' for INCLUDE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						' Clear current terminal line
						PRINT CR$, EL$;
						' Check if the C Preprocessor needs to run
						IF ISTRUE(g_CPP) THEN
							IF ISTRUE(LEN(EXEC$("which cpp 2>/dev/null"))) THEN
								PRINT "Preprocessing '", inc$, "'... ";
								' Change next line marker to overcome C preprocessor interpretation
								OPEN inc$ & ".tmp" FOR WRITING AS src_tmp
								OPEN inc$ FOR READING AS src_in
								WHILE NOT(ENDFILE(src_in))
									READLN txt$ FROM src_in
									IF LEFT$(txt$, 1) = "#" THEN
										WRITELN txt$ TO src_tmp
									ELSE
										WRITELN "@" & txt$ & "@" TO src_tmp
									ENDIF
								WEND
								CLOSE FILE src_in, src_tmp
								SYSTEM "cpp -P -w " & inc$ & ".tmp " & inc$ & ".cpp"
								' Restore next line marker
								OPEN inc$ & ".cpp" FOR READING AS src_cpp
								OPEN inc$ & ".bac" FOR WRITING AS src_out
								WHILE NOT(ENDFILE(src_cpp))
									READLN txt$ FROM src_cpp
									WRITELN MID$(txt$, 2, LEN(txt$)-2) TO src_out
								WEND
								CLOSE FILE src_out, src_cpp
								newfeed$ = inc$ & ".bac"
								g_TMP_FILES$ = g_TMP_FILES$ & " " & inc$ & ".cpp" & " " & inc$ & ".tmp" & " " & inc$ & ".bac"
								PRINT "done."
							ELSE
								EPRINT "System error: the C Preprocessor 'cpp' not found on this system! Exiting..."
								END 1
							END IF
						ELSE
							newfeed$ = inc$
						END IF
						' Start walking through program
						copy_counter = g_COUNTER
						g_COUNTER = 1
						' Assign new file
						copy_curfile$ = g_CURFILE$
						' Set current filename
						g_CURFILE$ = newfeed$

						OPEN newfeed$ FOR READING AS newfile

						REPEAT
							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$, " "))), "^" & 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 LEN(txt$) > 0 AND to_parse > 0 THEN
								IF NOT(g_QUIET) THEN PRINT "\rConverting '", newfeed$, "'... ", g_COUNTER, EL$;
								IF RIGHT$(txt$, 1) = CR$ THEN
									EPRINT "\nSystem error: Windows file detected! Remove non-Unix CR line separators first. Exiting..."
									END 1
								ELIF RIGHT$(txt$, 2) = " \\" AND LEFT$(txt$, 3) != "REM" AND LEFT$(txt$, 1) != CHR$(39) THEN
									total$ = total$ & LEFT$(txt$, LEN(txt$)-2)
								ELSE
									total$ = CHOP$(total$ & txt$)
									IF LEFT$(total$, 3) != "REM" AND LEFT$(total$, 1) != CHR$(39) THEN
										WRITELN "#undef __b2c_lineno" TO g_CFILE
										WRITELN "#define __b2c_lineno ", g_COUNTER TO g_CFILE
										WRITELN "#undef __b2c_lineno" TO g_HFILE
										WRITELN "#define __b2c_lineno ", g_COUNTER TO g_HFILE
										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
						UNTIL ENDFILE(newfile)
						CLOSE FILE newfile

						' Save total amount of lines
						INCR g_TOTAL_LINES, g_COUNTER-1
						' Restore original counter
						g_COUNTER = copy_counter
						' Restore original file
						g_CURFILE$ = copy_curfile$
					END IF

				CASE "POKE"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty POKE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						exp$ = MID$(statement$, INSTR(statement$, "POKE") + 4)
						IF TALLY(exp$, " SIZE ") THEN
							str$ = TOKEN$(exp$, 2, " SIZE ")
							exp$ = TOKEN$(exp$, 1, " SIZE ")
							token$ = Mini_Parser$(exp$)
							exp$ = MID$(exp$, LEN(token$)+2)
							WRITELN "if (__b2c__trap){if(__b2c__memory__check((char*)", token$, ", (" & str$ & ")*sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"POKE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
							WRITELN "memset((void*)(__b2c__MEMTYPE*)(" & token$ & "), " & exp$ & ", (" & str$ & ")*sizeof(__b2c__MEMTYPE));" TO g_CFILE
						ELSE
							token$ = Mini_Parser$(exp$)
							exp$ = MID$(exp$, LEN(token$)+2)
							WRITELN "if (__b2c__trap){if(__b2c__memory__check((char*)", token$, ", sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"POKE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
							WRITELN "*(__b2c__MEMTYPE*)(", token$, ") = ( __b2c__MEMTYPE)(", exp$, ");" TO g_CFILE
						ENDIF
						IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
					END IF

				CASE "RESIZE"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty RESIZE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						exp$ = MID$(statement$, INSTR(statement$, "RESIZE") + 6)
						lft$ = CHOP$(TOKEN$(exp$, 1, " TO "))
						str$ = CHOP$(TOKEN$(exp$, 2, " TO "))
						WRITELN "if(__b2c__trap) {if(__b2c__memory__check((char*)", lft$, ", sizeof(__b2c__MEMTYPE))) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"RESIZE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
						WRITELN lft$, " = (", Get_Var$(EXTRACT$(lft$, "."), g_FUNCNAME$), ")realloc((void*)", lft$, ", sizeof(__b2c__MEMTYPE)*(", str$, "+1));" TO g_CFILE
						WRITELN "if(__b2c__trap) {if((void*)", lft$, " == NULL) {ERROR=6; if(!__b2c__catch_set) RUNTIMEERROR(\"RESIZE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
						IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
					END IF

				CASE "COPY"
					Handle_Copy(MID$(statement$, INSTR(statement$, "COPY") + 4))

				CASE "DELETE"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty DELETE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						' Translate to C function
						IF element$[2] = "FILE" THEN
							WRITELN "if (unlink(", MID$(statement$, INSTR(statement$, " FILE ") + 6), ")==-1){if(__b2c__trap){ERROR = 7;if(!__b2c__catch_set) RUNTIMEERROR(\"DELETE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
							IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
						ELIF element$[2] = "DIRECTORY" THEN
							WRITELN "if (rmdir(", MID$(statement$, INSTR(statement$, " DIRECTORY ") + 11), ") == -1){if(__b2c__trap){ERROR = 20;if(!__b2c__catch_set) RUNTIMEERROR(\"DELETE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
							IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
						ELIF element$[2] = "RECURSIVE" THEN
							WRITELN "__b2c__rmrecursive(__b2c_lineno, __b2c_filename, ", MID$(statement$, INSTR(statement$, " RECURSIVE ") + 11), ");" TO g_CFILE
						ELSE
							EPRINT NL$, "Syntax 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 = 1 THEN
						EPRINT NL$, "Syntax 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) RUNTIMEERROR(\"MAKEDIR\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
						IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
					END IF

				CASE "CHANGEDIR"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax 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) RUNTIMEERROR(\"CHANGEDIR\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
						IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
					END IF

				CASE "FREE"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty FREE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						' Translate to C function
						IF REGEX(statement$, "[a-zA-Z]+\\(.*\\)$") THEN
							' Start miniparser
							exp$ = MID$(statement$, INSTR(statement$, "FREE") + 5)
							WHILE LEN(exp$)
								token$ = CHOP$(LEFT$(exp$, INSTR(exp$, "(")-1))
								str$ = CHOP$(Mini_Parser$(exp$))
								txt$ = MID$(str$, INSTR(str$, "(")+1)
								WRITELN "__b2c__", token$, "__del(", LEFT$(txt$, LEN(txt$)-1), ", NULL);" TO g_CFILE
								exp$ = MID$(exp$, LEN(str$)+2)
							WEND
						ELSE
							FOR str$ IN EXTRACT$(MID$(statement$, INSTR(statement$, "FREE") + 5), " ") STEP ","
								IF LEN(Get_Var$("__b2c__" & str$ & "_type_")) OR LEN(Get_Var$("__b2c__" & str$ & "_type_" & g_FUNCNAME$, g_FUNCNAME$)) THEN
									WRITELN "__b2c__", str$, "_tmp = (HASHTABLE_U64*)__b2c__hashtable_keys(&__b2c__", str$, "_tab); while(__b2c__hashtable_count(&__b2c__", str$, "_tab)) {" TO g_CFILE
									WRITELN "__b2c__", str$, "_loc = (__b2c__", str$, "_typ*)__b2c__hashtable_find(&__b2c__", str$, "_tab, (HASHTABLE_U64)__b2c__", str$, "_tmp[0]);" TO g_CFILE
									WRITELN "__b2c__", str$, "__del(__b2c__", str$, "_loc->key);} __b2c__hashtable_clear(&__b2c__", str$, "_tab);" TO g_CFILE
								ELSE
									WRITELN "if(__b2c__trap){if(__b2c__memory__check((char *)", str$, ", sizeof(__b2c__MEMTYPE)))" TO g_CFILE
									WRITELN "{ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"FREE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} } free((void*)", str$, ");" TO g_CFILE
									g_SEMANTIC_MEMFREE$(str$) = IIF$(LEN(g_SEMANTIC_MEMFREE$(str$)), "", "'" & str$ & "' at line " & STR$(g_COUNTER) & " in file '" & g_CURFILE$ & "'")
								ENDIF
							NEXT
							IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
						END IF
					END IF

				CASE "ON"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty ON at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELIF NOT(INSTR(statement$, "GOTO")) THEN
						EPRINT NL$, "Syntax error: ON without GOTO at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						str$ = MID$(statement$, INSTR(statement$, "ON ")+3)
						exp$ = EXTRACT$(MID$(statement$, INSTR(statement$, "GOTO") + 5), " ")
						' Convert to C 'switch' statement
						i = 1
						WRITELN "switch(", LEFT$(str$, INSTR(str$, " GOTO ")), "){" TO g_CFILE
						WHILE LEN(exp$)
							token$ = Mini_Parser$(exp$)
							WRITELN "case ", i, ": goto ", token$, "; break;" TO g_CFILE
							exp$ = MID$(exp$, LEN(token$)+2)
							INCR i
						WEND
						WRITELN "}" TO g_CFILE
					END IF

				CASE "GOTO"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax 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 "GOSUB"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty GOSUB at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						' Translate to C label
						WRITELN "__b2c__gosub_buffer_ptr++; if (__b2c__gosub_buffer_ptr >= ", g_MAX_RBUFFERS, ") {ERROR=31; if(!__b2c__catch_set) RUNTIMEERROR(\"GOSUB\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";}" TO g_CFILE
						WRITELN "if(!setjmp(__b2c__gosub_buffer[__b2c__gosub_buffer_ptr])) goto ", element$[2], ";" TO g_CFILE
						WRITELN "__b2c__gosub_buffer_ptr--; if(__b2c__gosub_buffer_ptr < -1) __b2c__gosub_buffer_ptr = -1;" TO g_CFILE
						IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
					END IF

				CASE "LABEL"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax 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
						' Needed for RESTORE
						IF NOT(LEN(Get_Var$("__b2c__label_floatarray_" & element$[2]))) THEN
							WRITELN "int __b2c__label_floatarray_", element$[2], ";" TO g_HFILE
							WRITELN "int __b2c__label_stringarray_", element$[2], ";" TO g_HFILE
							Save_Main_Var("__b2c__label_floatarray_" & element$[2], "int")
							Save_Main_Var("__b2c__label_stringarray_" & element$[2], "int")
						ENDIF
						WRITELN "__b2c__label_floatarray_", element$[2], " = ", g_FCTR, ";" TO g_CFILE
						WRITELN "__b2c__label_stringarray_", element$[2], " = ", g_CCTR, ";" TO g_CFILE
						WRITELN "if(__b2c__data_jump_flag){ __b2c__data_jump_flag=0; longjmp(__b2c__data_jump, 1);}" TO g_CFILE
					END IF

				CASE "TRAP"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty TRAP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						IF element$[2] = "LOCAL" 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 element$[2] = "SYSTEM" 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
							EPRINT NL$, "Syntax 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 = 1 THEN
						EPRINT NL$, "Syntax error: empty CATCH at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELIF element$[2] = "GOTO" THEN
						WRITELN "__b2c__catch_set = 1;" TO g_CFILE
						g_CATCHGOTO$ = element$[3]
					ELIF element$[2] = "ERROR" THEN
						WRITELN "__b2c__error_callback = & ", element$[3], ";" TO g_CFILE
					ELIF element$[2] = "RESET" THEN
						WRITELN "__b2c__catch_set = 0;" TO g_CFILE
						g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT"
					ELSE
						EPRINT NL$, "Syntax 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 = 1 THEN
						EPRINT NL$, "Syntax error: empty RECORD at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELIF ISTRUE(LEN(g_RECORDNAME$)) THEN
						EPRINT NL$, "Syntax error: cannot define a record within a record!"
						END 1
					ELSE
						' Determine name
						g_RECORDVAR$ = MID$(statement$, INSTR(statement$, "RECORD")+6)
						IF INSTR(g_RECORDVAR$, " ARRAY ") THEN
							g_RECORDARRAY$ = MID$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "ARRAY")+5)
							g_RECORDVAR$ = CHOP$(LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "ARRAY")-1)) & "[" & g_RECORDARRAY$ & "]"
						ENDIF
						' Translate to C typedef struct
						IF ISTRUE(LEN(g_FUNCNAME$)) THEN
							g_RECORDNAME$ = LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "[")-1) & "_TYPE"
							WRITELN "typedef struct {" TO g_CFILE
							Save_Func_Var("", g_FUNCNAME$, g_RECORDNAME$)
						ELSE
							g_RECORDNAME$ = LEFT$(g_RECORDVAR$, INSTR(g_RECORDVAR$, "[")-1) & "_TYPE"
							WRITELN "typedef struct {" TO g_HFILE
							Save_Main_Var("", g_RECORDNAME$)
						ENDIF
					ENDIF

				CASE "WITH"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty WITH at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELIF ISTRUE(LEN(g_RECORDNAME$)) THEN
						EPRINT NL$, "Syntax 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 "JOIN"
					Handle_Join(MID$(statement$, INSTR(statement$, "JOIN") + 4))

				CASE "SELECT"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax 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$ = ""
						g_CASE_CONT$ =""
					END IF

				CASE "CASE"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty CASE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						' In processing of next CASE statements
						IF ISTRUE(g_IN_CASE[g_SELECTVAR_CTR]) THEN g_CASE_CONT$ = "} else "
						' Create IF
						IF Check_String_Type(g_SELECTVAR$[g_SELECTVAR_CTR]) THEN
							exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4)
							IF RIGHT$(statement$, 1) = ";" THEN
								g_CASE_FALL$ = g_CASE_FALL$ & "!__b2c__strcmp(" & g_SELECTVAR$[g_SELECTVAR_CTR] & ", " & LEFT$(exp$, LEN(exp$)-1) & ") ||"
							ELSE
								WHILE LEN(exp$)
									str$ = Mini_Parser$(exp$)
									g_CASE_FALL$ = g_CASE_FALL$ & "!__b2c__strcmp(" & g_SELECTVAR$[g_SELECTVAR_CTR] & ", " & str$ & ") "
									exp$ = MID$(exp$, LEN(str$)+2)
									IF LEN(exp$) THEN g_CASE_FALL$ = g_CASE_FALL$ & "||"
								WEND
								WRITELN g_CASE_CONT$ & "if (", g_CASE_FALL$, "){" TO g_CFILE
								g_IN_CASE[g_SELECTVAR_CTR] = 1
								g_CASE_FALL$ = ""
							END IF
						ELSE
							exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4)
							IF RIGHT$(statement$, 1) = ";" THEN
								g_CASE_FALL$ = g_CASE_FALL$ & "(" & g_SELECTVAR$[g_SELECTVAR_CTR] & ") == (" & LEFT$(exp$, LEN(exp$)-1) & ") ||"
							ELSE
								WHILE LEN(exp$)
									str$ = Mini_Parser$(exp$)
									g_CASE_FALL$ = g_CASE_FALL$ & "(" & g_SELECTVAR$[g_SELECTVAR_CTR] & ") == (" & str$ & ")"
									exp$ = MID$(exp$, LEN(str$)+2)
									IF LEN(exp$) THEN g_CASE_FALL$ = g_CASE_FALL$ & "||"
								WEND
								WRITELN g_CASE_CONT$ & "if (", g_CASE_FALL$, "){" TO g_CFILE
								g_IN_CASE[g_SELECTVAR_CTR] = 1
								g_CASE_FALL$ = ""
							END IF
						END IF
					END IF

				CASE "DEFAULT"
					IF ISTRUE(g_IN_CASE[g_SELECTVAR_CTR]) THEN
						WRITELN "} else {" TO g_CFILE
					ELSE
						EPRINT NL$, "Syntax 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 = 1 THEN
						EPRINT NL$, "Syntax 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"
					' Check argument
					IF dim = 1 THEN
						WRITELN "kill(getpid(), SIGSTOP);" TO g_CFILE
					ELSE
						WRITELN "kill(getpid(),", EXTRACT$(MID$(statement$, INSTR(statement$, "STOP") + 4), CHR$(34)), ");" TO g_CFILE
					ENDIF

				CASE "TRACE"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty TRACE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						IF element$[2] = "MONITOR" THEN
							g_TRACE = 1
							WRITELN "fprintf(stderr, \"File '", g_CURFILE$, "' line %d: TRACE ON - press <SPACE> to execute the program step by step, <ESC> to exit.\\n\", ", g_COUNTER, ");" TO g_CFILE
							g_MONITOR$ = ""
							FOR exp$ IN MID$(statement$, INSTR(statement$, "MONITOR")+7) STEP ","
								exp$ = CHOP$(EXTRACT$(exp$,"\\(.*", TRUE))
								IF NOT(LEN(Get_Var$(exp$, g_FUNCNAME$))) THEN
									EPRINT NL$, "Syntax error: cannot monitor undeclared variable '", exp$, "' at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
									END 1
								ENDIF
								IF Check_String_Type(exp$) THEN
									g_MONITOR$ = g_MONITOR$ & "__b2c__assign = " & exp$ & "; if(__b2c__assign != NULL) fprintf(stderr, \"" & EXTRACT$(exp$, g_STRINGSIGN$) & "$ = %s\\n\", __b2c__assign);"
								ELSE
									IF INSTR(exp$, g_LONGSIGN$) THEN
										g_MONITOR$ = g_MONITOR$ & "fprintf(stderr, \"" & EXTRACT$(exp$, g_LONGSIGN$) & "%% = %s\\n\", STR" & g_STRINGSIGN$ & "(" & exp$ & "));"
									ELIF INSTR(exp$, g_FLOATSIGN$) THEN
										g_MONITOR$ = g_MONITOR$ & "fprintf(stderr, \"" & EXTRACT$(exp$, g_FLOATSIGN$) & "# = %s\\n\", STR" & g_STRINGSIGN$ & "(" & exp$ & "));"
									ELSE
										g_MONITOR$ = g_MONITOR$ & "fprintf(stderr, \"" & exp$ & " = %s\\n\", STR" & g_STRINGSIGN$ & "(" & exp$ & "));"
									ENDIF
								ENDIF
							NEXT
						ELIF element$[2] = "ON" THEN
							g_TRACE = 1
							WRITELN "fprintf(stderr, \"File '", g_CURFILE$, "' line %d: TRACE ON - press <SPACE> to execute the program step by step, <ESC> to exit.\\n\", ", g_COUNTER, ");" TO g_CFILE
						ELIF element$[2] = "OFF" THEN
							g_MONITOR$ = ""
							g_TRACE = 0
						END IF
					ENDIF

				CASE "OPTION"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty OPTION at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						IF element$[2] = "BASE" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-9]") THEN
								g_OPTION_BASE = VAL(element$[3])
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION BASE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "COMPARE" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								WRITELN "__b2c__option_compare = ", element$[3], ";" TO g_CFILE
								WRITELN "#undef __b2c__STRCMP" TO g_CFILE
								IF REGEX(element$[3], "1|TRUE") THEN
									WRITELN "#define __b2c__STRCMP __b2c__strcasecmp" TO g_CFILE
								ELSE
									WRITELN "#define __b2c__STRCMP __b2c__strcmp" TO g_CFILE
								ENDIF
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION COMPARE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "QUOTED" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								WRITELN "__b2c__option_quoted = ", element$[3], ";" TO g_CFILE
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION QUOTED at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "UTF8" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								WRITELN "__b2c__option_utf8 = ", element$[3], ";" TO g_CFILE
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION UTF8 at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "PROPER" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								WRITELN "__b2c__option_proper = ", element$[3], ";" TO g_CFILE
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION PROPER at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "ERROR" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								WRITELN "__b2c__option_error = ", element$[3], ";" TO g_CFILE
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION ERROR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "DELIM" AND dim > 2 THEN
							WRITELN "__b2c__option_delim = ", MID$(statement$, INSTR(statement$, "DELIM") + 6), ";" TO g_CFILE
						ELIF element$[2] = "INPUT" AND dim > 2 THEN
							g_OPTION_INPUT$ = element$[3]
						ELIF element$[2] = "DQ" AND dim > 2 THEN
							WRITELN "__b2c__option_dq = ", MID$(statement$, INSTR(statement$, "DQ") + 3), ";" TO g_CFILE
						ELIF element$[2] = "SOCKET" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-9]") THEN
								g_OPTION_SOCKET = VAL(element$[3])
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION SOCKET at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "BREAK" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								g_OPTION_BREAK = VAL(element$[3])
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION BREAK at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "MEMSTREAM" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								WRITELN "__b2c__option_memstream = ", element$[3], ";" TO g_CFILE
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION MEMSTREAM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "MEMTYPE" AND dim > 2 THEN
							WRITELN "#undef __b2c__MEMTYPE" TO g_CFILE
							WRITELN "#define __b2c__MEMTYPE ", MID$(statement$, INSTR(statement$, "MEMTYPE")+8) TO g_CFILE
						ELIF element$[2] = "COLLAPSE" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								WRITELN "__b2c__collapse = ", element$[3], ";" TO g_CFILE
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION COLLAPSE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "DEVICE" AND dim >= 3 THEN
							WRITELN "__b2c__option_open = (", element$[3], ");" TO g_CFILE
						ELIF element$[2] = "STARTPOINT" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								WRITELN "__b2c__option_startpoint = ", element$[3], ";" TO g_CFILE
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION STARTPOINT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "INTERNATIONAL" AND dim = 3 THEN
							IF REGEX(element$[3], "1|TRUE") THEN
								WRITELN "#include <libintl.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) RUNTIMEERROR(\"OPTION INTERNATIONAL\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else 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) RUNTIMEERROR(\"OPTION INTERNATIONAL\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
								IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION INTERNATIONAL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "NETWORK" AND dim >= 3 THEN
							SELECT element$[3]
								CASE "TCP"
									g_NETWORKTYPE$ = "TCP"
									g_SOCKTYPE$ = "SOCK_STREAM"
								CASE "UDP"
									g_NETWORKTYPE$ = "UDP"
									g_SOCKTYPE$ = "SOCK_DGRAM"
								CASE "BROADCAST"
									g_NETWORKTYPE$ = "BROADCAST"
									g_SOCKTYPE$ = "SOCK_DGRAM"
								CASE "MULTICAST"
									g_NETWORKTYPE$ = "MULTICAST"
									g_SOCKTYPE$ = "SOCK_DGRAM"
									IF dim = 4 AND REGEX(element$[4], "[0-9]") THEN
										g_MULTICAST_TTL = VAL(element$[4])
									ENDIF
								CASE "SCTP"
									WRITELN "#include <netinet/sctp.h>" TO g_HFILE
									WRITELN "struct sctp_initmsg __b2c__initmsg;" TO g_HFILE
									g_NETWORKTYPE$ = "SCTP"
									g_SOCKTYPE$ = "SOCK_STREAM"
									g_LDFLAGS$ = g_LDFLAGS$ & " -lsctp"
									IF dim = 4 AND REGEX(element$[4], "[0-9]") THEN
										g_SCTP_STREAMS = VAL(element$[4])
									END IF
								DEFAULT
									EPRINT NL$, "Syntax error: invalid argument to OPTION NETWORK at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
									END 1
							END SELECT
						ELIF element$[2] = "PARSE" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								g_IGNORE_PARSE$ = element$[3]
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION PARSE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "EXPLICIT" AND dim = 3 THEN
							IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
								g_OPTION_EXPLICIT$ = element$[3]
							ELSE
								EPRINT NL$, "Syntax error: invalid argument to OPTION EXPLICIT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
								END 1
							END IF
						ELIF element$[2] = "VARTYPE" AND dim > 2 THEN
							g_VARTYPE$ = MID$(statement$, INSTR(statement$, "VARTYPE")+8)
						ELSE
							EPRINT NL$, "Syntax 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 = 1 THEN
						EPRINT NL$, "Syntax error: empty PROTO at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						exp$ = MID$(EXTRACT$(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$ = MID$(exp$, INSTR(exp$, " ALIAS ") + 7) & " " & g_IMPORTED$
							g_IMPORTED$ = MID$(exp$, 1, INSTR(exp$, " ALIAS ")) & " " & g_IMPORTED$
						ELIF INSTR(exp$, " TYPE ") THEN
							WRITELN MID$(exp$, INSTR(exp$, " TYPE ") + 6), " ", MID$(exp$, 1, INSTR(exp$, " TYPE ")), ";" TO g_HFILE
						ELSE
							g_IMPORTED$ = REPLACE$(exp$, ",", " ") & " " & g_IMPORTED$
						END IF
					END IF

				CASE "INCR"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty INCR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						' Get left side
						token$ = Mini_Parser$(statement$)
						' Get right side
						exp$ = CHOP$(MID$(statement$, LEN(token$)+2))
						IF NOT(LEN(exp$)) THEN exp$ = "1"
						token$ = CHOP$(MID$(token$, INSTR(token$, " ")))
						' Check if there is associative array assignment
						IF REGEX(token$, "[a-zA-Z]+\\(.*\\)$") THEN
							lft$ = LEFT$(token$, INSTR(token$, "(") - 1)
							str$ = MID$(token$, INSTR(token$, "(") + 1)
							WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
							WRITELN "__b2c__", lft$, "_loc->value = ", token$, " + (", exp$, ");" TO g_CFILE
							' Check for relations
							Relate_Recurse(lft$, str$, token$ & "+(" & exp$ & ")", -1)
						ELSE
							' Regular number
							IF REGEX(exp$, "[0-9]\\.[0-9]") AND NOT(LEN(Get_Var$(token$, g_FUNCNAME$))) THEN
								IF g_OPTION_EXPLICIT$ = "1" OR g_OPTION_EXPLICIT$ = "TRUE" THEN
									EPRINT NL$, "Syntax error: OPTION EXPLICIT forces explicit variable declaration at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
									END 1
								ENDIF
								WRITELN "double ", token$, ";" TO g_HFILE
								Save_Main_Var(token$, "double")
							ELIF NOT(LEN(Get_Var$(token$, g_FUNCNAME$))) THEN
								Register_Numeric$(token$)
							ENDIF
							WRITELN token$, " = ", token$, " + (", exp$, ");" TO g_CFILE
						END IF
					END IF

				CASE "DECR"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty DECR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						' Get left side
						token$ = Mini_Parser$(statement$)
						' Get right side
						exp$ = CHOP$(MID$(statement$, LEN(token$)+2))
						IF NOT(LEN(exp$)) THEN exp$ = "1"
						token$ = CHOP$(MID$(token$, INSTR(token$, " ")))
						' Check if there is associative array assignment
						IF REGEX(token$, "[a-zA-Z]+\\(.*\\)$") THEN
							lft$ = LEFT$(token$, INSTR(token$, "(") - 1)
							str$ = MID$(token$, INSTR(token$, "(") + 1)
							WRITELN "__b2c__", lft$, "_loc = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
							WRITELN "__b2c__", lft$, "_loc->value = ", token$, " - (", exp$, ");" TO g_CFILE
							' Check for relations
							Relate_Recurse(lft$, str$, token$ & "+(" & exp$ & ")", -1)
						ELSE
							' Regular number
							IF REGEX(exp$, "[0-9]\\.[0-9]") AND NOT(LEN(Get_Var$(token$, g_FUNCNAME$))) THEN
								IF g_OPTION_EXPLICIT$ = "1" OR g_OPTION_EXPLICIT$ = "TRUE" THEN
									EPRINT NL$, "Syntax error: OPTION EXPLICIT forces explicit variable declaration at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
									END 1
								ENDIF
								WRITELN "double ", token$, ";" TO g_HFILE
								Save_Main_Var(token$, "double")
							ELIF NOT(LEN(Get_Var$(token$, g_FUNCNAME$))) THEN
								Register_Numeric$(token$)
							ENDIF
							WRITELN token$, " = ", token$, " - (", exp$, ");" TO g_CFILE
						END IF
					END IF

				CASE "ALARM"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty ALARM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						str$ = EXTRACT$(LEFT$(statement$, INSTR(statement$, ",")-1), "^ALARM ", TRUE)
						exp$ = MID$(statement$, INSTR(statement$, ",")+1)
						IF NOT(INSTR(g_ALARM_FUNC$, "__b2c__" & str$)) THEN
							g_ALARM_PROTO$ = g_ALARM_PROTO$ & "void __b2c__" & str$ & "(int signal){" & str$ & "();} ;"
							g_ALARM_FUNC$ = g_ALARM_FUNC$ & " __b2c__" & str$
						ENDIF
						WRITELN "memset(&__b2c__psa, 0, sizeof(__b2c__psa)); __b2c__psa.sa_flags = SA_RESETHAND|SA_RESTART; __b2c__psa.sa_handler = __b2c__", str$, "; sigaction(SIGALRM, &__b2c__psa, NULL);" TO g_CFILE
						WRITELN "__b2c__alarm.it_value.tv_sec = (long)(", exp$, ")/1000; __b2c__alarm.it_value.tv_usec = ((", exp$, ")%1000)*1000;" TO g_CFILE
						WRITELN "__b2c__alarm.it_interval.tv_sec = 0; __b2c__alarm.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &__b2c__alarm, NULL);" TO g_CFILE
					END IF

				CASE "SIGNAL"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty SIGNAL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						' Walk through commas
						SPLIT CHOP$(MID$(statement$, INSTR(statement$, "SIGNAL") + 6)) BY "," TO sym$ SIZE dim
						IF dim = 2 THEN
							IF REGEX(sym$[1], "SIG_DFL|SIG_IGN") THEN
								WRITELN "memset(&__b2c__psa, 0, sizeof(__b2c__psa)); __b2c__psa.sa_handler = ", sym$[1], "; sigaction(", sym$[2], ", &__b2c__psa, NULL);" TO g_CFILE
							ELSE
								IF NOT(INSTR(g_ALARM_FUNC$, "__b2c__" & sym$[1])) THEN
									WRITELN "void __b2c__", sym$[1], "(int signal){", sym$[1], "();}" TO g_HFILE
									g_ALARM_FUNC$ = g_ALARM_FUNC$ & " __b2c__" & sym$[1]
								ENDIF
								WRITELN "memset(&__b2c__psa, 0, sizeof(__b2c__psa)); __b2c__psa.sa_handler = __b2c__", sym$[1], "; sigaction(", sym$[2], ", &__b2c__psa, NULL);" TO g_CFILE
							ENDIF
						ELSE
							EPRINT NL$, "Syntax error: missing argument in SIGNAL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
							END 1
						END IF
					END IF

				CASE "CURSOR"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty CURSOR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						exp$ = IIF$(dim = 3, element$[3], "1")
						IF element$[2] = "ON" THEN
							WRITELN "fprintf(stdout,\"\\033[?25h\"); fflush(stdout);" TO g_CFILE
						ELIF element$[2] = "OFF" THEN
							WRITELN "fprintf(stdout,\"\\033[?25l\"); fflush(stdout);" TO g_CFILE
						ELIF element$[2] = "UP" THEN
							WRITELN "fprintf(stdout,\"\\033[%ldA\", (long)", exp$, "); fflush(stdout);" TO g_CFILE
						ELIF element$[2] = "DOWN" THEN
							WRITELN "fprintf(stdout,\"\\033[%ldB\", (long)", exp$, "); fflush(stdout);" TO g_CFILE
						ELIF element$[2] = "FORWARD" THEN
							WRITELN "fprintf(stdout,\"\\033[%ldC\", (long)", exp$, "); fflush(stdout);" TO g_CFILE
						ELIF element$[2] = "BACK" THEN
							WRITELN "fprintf(stdout,\"\\033[%ldD\", (long)", exp$, "); fflush(stdout);" TO g_CFILE
						END IF
					ENDIF

				CASE "SCROLL"
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty SCROLL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						exp$ = IIF$(dim = 3, element$[3], "1")
						IF element$[2] = "UP" THEN
							WRITELN "fprintf(stdout,\"\\033[%ldS\", (long)", exp$, "); fflush(stdout);" TO g_CFILE
						ELIF element$[2] = "DOWN" THEN
							WRITELN "fprintf(stdout,\"\\033[%ldT\", (long)", exp$, "); fflush(stdout);" TO g_CFILE
						END IF
					END IF

				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 = 1 THEN
						EPRINT NL$, "Syntax 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 = 2 THEN
							WRITELN "if(bindtextdomain(", sym$[1], ",", sym$[2], ")==NULL){if(__b2c__trap){ERROR = 6; if(!__b2c__catch_set) RUNTIMEERROR(\"TEXTDOMAIN\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
							WRITELN "if(textdomain(", sym$[1], ")==NULL){if(__b2c__trap){ERROR = 6; if(!__b2c__catch_set) RUNTIMEERROR(\"TEXTDOMAIN\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); else if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
							IF g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" THEN g_CATCH_USED = 1
						ELSE
							EPRINT NL$, "Syntax error: missing argument in TEXTDOMAIN at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
							END 1
						END IF
					END IF

				CASE "REDIM"
					Handle_Redim(CHOP$(MID$(statement$, INSTR(statement$, "REDIM") + 5)))

				CASE "EXIT"
					IF LEN(g_FUNCNAME$) = 0 THEN
						EPRINT NL$, "Syntax error: EXIT not in FUNCTION or SUB at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					END IF
					' Free strings variables if there are any
					WRITELN g_STRINGARRAYS$ TO g_CFILE
					FOR exp$ IN g_LOCALSTRINGS$
						WRITELN "if(", exp$, " != NULL) __b2c__STRFREE(", exp$, ");" TO g_CFILE
					NEXT
					WRITELN "__b2c__catch_set = __b2c__catch_set_backup;" TO g_CFILE
					' The actual exit
					IF INSTR(g_FUNCNAME$, g_STRINGSIGN$) THEN
						WRITELN "return(NULL);" TO g_CFILE
					ELSE
						WRITELN "return __b2c__exitval;" TO g_CFILE
					END IF

				CASE "PRAGMA"
					' Check argument
					IF dim = 1 THEN
						EPRINT NL$, "Syntax error: empty PRAGMA at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
						END 1
					ELSE
						IF element$[2] = "OPTIONS" AND dim >= 3 THEN
							FOR i = 3 TO dim
								g_CCFLAGS$ = g_CCFLAGS$ & " " & element$[i]
							NEXT
						ELIF element$[2] = "COMPILER" AND dim = 3 THEN
							g_CCNAME$ = element$[3]
						ELIF element$[2] = "FRAMEWORK" AND dim >= 3 THEN
							FOR i = 3 TO dim
								g_LDFLAGS$ = g_LDFLAGS$ & " -framework " & element$[i]
							NEXT
						ELIF element$[2] = "RE" AND dim >= 3 THEN
							g_PRAGMA_REGEX$ = MID$(statement$, INSTR(statement$, "RE")+3)
							IF NOT(REGEX(g_PRAGMA_REGEX$, " LDFLAGS ")) THEN
								exp$ = HEAD$(g_PRAGMA_REGEX$, 1)
								IF INSTR(exp$, "tre") THEN
									g_LDFLAGS$ = "-ltre " & g_LDFLAGS$
								ELIF INSTR(exp$, "pcre") THEN
									g_LDFLAGS$ = " -lpcreposix -lpcre " & g_LDFLAGS$
								ELIF INSTR(exp$, "onig") THEN
									g_LDFLAGS$ = " -lonig " & g_LDFLAGS$
								ENDIF
							ELSE
								exp$ = MID$(g_PRAGMA_REGEX$, INSTR(g_PRAGMA_REGEX$, " LDFLAGS ")+9)
								g_LDFLAGS$ = HEAD$(exp$, 1) & " " & g_LDFLAGS$
							ENDIF
						ELIF element$[2] = "LDFLAGS" AND dim >= 3 THEN
							IF TALLY(TOKEN$(statement$, 2, "LDFLAGS"), "pkg-config") THEN
								g_LDFLAGS$ = g_LDFLAGS$ & " " & TOKEN$(statement$, 2, "LDFLAGS")
							ELSE
								FOR i = 3 TO dim
									IF LEFT$(element$[i], 1) = "-" OR RIGHT$(element$[i], 2) = ".a" THEN
										g_LDFLAGS$ = g_LDFLAGS$ & " " & element$[i]
									ELSE
										g_LDFLAGS$ = g_LDFLAGS$ & " -l" & element$[i]
									FI
								NEXT
							FI
						ELIF element$[2] = "INCLUDE" AND dim >= 3 THEN
							FOR i = 3 TO dim
								IF LEFT$(element$[i], 1) = "<" THEN
									WRITELN "#include ", element$[i] TO g_HFILE
								ELIF LEFT$(element$[i], 1) = "/" THEN
									WRITELN "#include ", CHR$(34), element$[i], CHR$(34) TO g_HFILE
								ELSE
									WRITELN "#include ", CHR$(34), CURDIR$, "/", element$[i], CHR$(34) TO g_HFILE
								ENDIF
							NEXT
						ELIF element$[2] = "BACONLIB" THEN
							LET g_REBUILD_ARCHIVE$ = "libbacon.a"
							g_CCFLAGS$ = g_CCFLAGS$ & " -fPIC"
						ELSE
							WRITELN "#pragma ", CHOP$(MID$(statement$, INSTR(statement$, "PRAGMA") + 6)) TO g_CFILE
						END IF
					ENDIF

				CASE "SWAP"
					Handle_Swap(CHOP$(MID$(statement$, INSTR(statement$, "SWAP") + 4)))

				CASE "SETSERIAL"
					Handle_Setserial(CHOP$(MID$(statement$, INSTR(statement$, "SETSERIAL") + 9)))

				CASE "ENUM"
					IF NOT(LEN(g_FUNCNAME$)) THEN
						WRITELN "enum {" TO g_HFILE
						g_USE_H = 1
					ELSE
						WRITELN "enum {" TO g_CFILE
						g_USE_C = 1
					ENDIF

				CASE "RUN"
					Handle_Run(CHOP$(MID$(statement$, INSTR(statement$, "RUN") + 3)))

				CASE "SAVE"
					Handle_Save(0, CHOP$(MID$(statement$, INSTR(statement$, "SAVE") + 4)))

				CASE "BSAVE"
					Handle_Save(1, CHOP$(MID$(statement$, INSTR(statement$, "BSAVE") + 5)))

				CASE "APPEND"
					Handle_Save(2, CHOP$(MID$(statement$, INSTR(statement$, "APPEND") + 6)))

				CASE "BAPPEND"
					Handle_Save(3, CHOP$(MID$(statement$, INSTR(statement$, "BAPPEND") + 7)))

				CASE "MAP"
					Handle_Map(CHOP$(MID$(statement$, INSTR(statement$, "MAP") + 3)))

				CASE "RESET"
					WRITELN "fprintf(stdout,\"\\033c\"); fflush(stdout);" TO g_CFILE

				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 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$)
					ENDIF
			END SELECT
		END IF
	END IF

END SUB

'----------------------------------------------------------------------------------------------

FUNCTION Pre_Tokenize_Functions$(arg$)

	LOCAL token$, it$, var$, type$
	LOCAL is_escaped, is_string, i, j, mem, nr = 1, many
	LOCAL src, out TYPE FILE*

	' Check if one of these conversion time functions are there
	IF INSTR(arg$, "TYPEOF$") OR INSTR(arg$, "SOURCE$") OR INSTR(arg$, "OBTAIN$") OR INSTR(arg$, "INTL$") OR INSTR(arg$, "NNTL$") OR INSTR(arg$, "LINENO") OR INSTR(arg$, "IIF(") OR INSTR(arg$, "IIF$(") OR INSTR(arg$, "EVAL(") THEN

		' If so, see if they are not part of a string and perform special treatment
		FOR i = 1 TO LEN(arg$)
			IF MID$(arg$, i, 7) = "TYPEOF$" THEN
				IF NOT(is_string) THEN
					it$ = MID$(arg$, i, INSTR(MID$(arg$, i), ")")-1)
					token$ = token$ & CHR$(34) & Get_Var$(MID$(it$, INSTR(it$, "(")+1), g_FUNCNAME$) & CHR$(34)
					INCR i, LEN(it$)+1
				END IF
			ELIF MID$(arg$, i, 7) = "SOURCE$" THEN
				IF NOT(is_string) THEN
					IF NOT(FILEEXISTS(SRCARRAYFILE$)) THEN
						OPEN g_SOURCEFILE$ FOR READING AS src
						mem = MEMORY(FILELEN(g_SOURCEFILE$))
						GETBYTE mem FROM src SIZE FILELEN(g_SOURCEFILE$)
						CLOSE FILE src

						OPTION MEMTYPE unsigned char
						OPEN SRCARRAYFILE$ FOR WRITING AS out
						WRITELN "unsigned char SOURCE", g_STRINGSIGN$, "[]={"; TO out
						FOR j = 0 TO FILELEN(g_SOURCEFILE$)-1
							IF MOD(j, 16) = 0 THEN WRITELN "" TO out
							WRITELN PEEK(mem+j), ","; TO out
						NEXT
						WRITELN "0 };" TO out
						CLOSE FILE out

						FREE mem
					ENDIF
				END IF
			ELIF MID$(arg$, i, 8) = "OBTAIN$(" THEN
				IF NOT(is_string) THEN
					intoken$ = Mini_Parser$(MID$(arg$, i+8))
					INCR i, 8+LEN(intoken$)
					IF INSTR(intoken$, ")") THEN intoken$ = HEAD$(intoken$, 1, ")") & ",NULL)" & MID$(intoken$, INSTR(intoken$, ")")+1)
					token$ = token$ & "OBTAIN$(" & intoken$
				END IF
			ELIF MID$(arg$, i, 6) = "LINENO" THEN
				IF NOT(is_string) THEN
					token$ = token$ & STR$(g_COUNTER)
					INCR i, 6
				END IF
			ELIF MID$(arg$, i, 5) = "INTL$" THEN
				IF NOT(is_string) THEN
					token$ = token$ & "gettext"
					INCR i, 5
				END IF
			ELIF MID$(arg$, i, 5) = "NNTL$" THEN
				IF NOT(is_string) THEN
					token$ = token$ & "ngettext"
					INCR i, 5
				END IF
			ELIF MID$(arg$, i, 4) = "IIF(" THEN
				IF NOT(is_string) THEN
					intoken$ = Mini_Parser$(MID$(arg$, i+4))
					IF REGEX(arg$, ".* " & g_RANGEOP$ & " .*;.*") THEN intoken$ = intoken$ & ";" & Mini_Parser$(MID$(arg$, i+4+LEN(intoken$)+1))
					INCR i, 4+LEN(intoken$)
					token$ = token$ & "IIF(" & Parse_Equation$(intoken$)
				ENDIF
			ELIF MID$(arg$, i, 5) = "IIF$(" THEN
				IF NOT(is_string) THEN
					intoken$ = Mini_Parser$(MID$(arg$, i+5))
					IF REGEX(arg$, ".* " & g_RANGEOP$ & " .*;.*") THEN intoken$ = intoken$ & ";" & Mini_Parser$(MID$(arg$, i+5+LEN(intoken$)+1))
					INCR i, 5+LEN(intoken$)
					token$ = token$ & "IIF$(" & Parse_Equation$(intoken$)
				ENDIF
			ELIF MID$(arg$, i, 5) = "EVAL(" THEN
				IF NOT(is_string) THEN
					IF nr = 1 THEN
						var$ = "__b2c_te_variable __b2c_evalvars_" & g_FUNCNAME$ & STR$(g_COUNTER) & "[] = {{EmptyString, 0}"
						LOOKUP g_ALL_FUNC_VARS$ TO funcvar$ SIZE many
						FOR xxx = 1 TO many
							IF TOKEN$(funcvar$[xxx], 2) = g_FUNCNAME$ THEN
								type$ = Get_Var$(TOKEN$(funcvar$[xxx], 1), g_FUNCNAME$)
								IF NOT(TALLY(type$, "*")) AND type$ <> "STRING" THEN
									WRITELN "double __b2c_" & TOKEN$(funcvar$[xxx], 1) & "_" & STR$(g_COUNTER) & " = (double)" & TOKEN$(funcvar$[xxx], 1) & ";" TO g_CFILE
									var$ = var$ & ",{" & CHR$(34) & TOKEN$(funcvar$[xxx], 1) & CHR$(34) & ", &__b2c_" & TOKEN$(funcvar$[xxx], 1) & "_" & STR$(g_COUNTER) & "}"
									INCR nr
								ENDIF
							ENDIF
						NEXT
						LOOKUP g_ALL_MAIN_VARS$ TO mainvar$ SIZE many
						FOR xxx = 1 TO many
							type$ = Get_Var$(mainvar$[xxx])
							IF NOT(TALLY(type$, "*")) AND type$ <> "STRING" THEN
								WRITELN "double __b2c_" & mainvar$[xxx] & "_" & STR$(g_COUNTER) & " = (double)" & mainvar$[xxx] & ";" TO g_CFILE
								var$ = var$ & ",{" & CHR$(34) & mainvar$[xxx] & CHR$(34) & ", &__b2c_" & mainvar$[xxx] & "_" & STR$(g_COUNTER) & "}"
								INCR nr
							ENDIF
						NEXT
						WRITELN var$, "};" TO g_CFILE
					ENDIF
					INCR i, 5
					token$ = token$ & "EVAL(__b2c_evalvars_" & g_FUNCNAME$ & STR$(g_COUNTER) & "," & STR$(nr) & ","
				ENDIF
			END IF
			SELECT ASC(MID$(arg$, i, 1))
					' Escape symbol
				CASE 92
					token$ = token$ & CHR$(92)
					is_escaped = NOT(is_escaped)
					' Quote symbol
				CASE 34
					token$ = token$ & CHR$(34)
					IF NOT(is_escaped) THEN is_string = NOT(is_string)
					is_escaped = FALSE
				DEFAULT
					token$ = token$ & MID$(arg$, i, 1)
					is_escaped = FALSE
			ENDSELECT
		NEXT
	ELSE
		token$ = arg$
	END IF

	RETURN token$

END FUNCTION

'----------------------------------------------------------------------------------------------

SUB Tokenize(STRING current$)

	LOCAL i, is_string, is_escaped, in_func
	LOCAL token$, item1$, item2$, result$, element$, txt$, elem$, sep$, str$, exp$
	LOCAL j, in_str, in_spac, bracket, direct, inescaped, isquote, dim, sfunc, sftot, prev

	' In TRACE MODE show linenr and code
	IF g_TRACE = 1 THEN
		IF NOT(REGEX(CHOP$(current$), "^FUNCTION|^SUB|^ELIF|^ELSE")) THEN
			WRITELN "if(__b2c__getch() == 27) {fprintf(stderr, \"TRACE OFF - exiting trace mode.\\n\"); exit(EXIT_SUCCESS);}" TO g_CFILE
			txt$ = REPLACE$(current$, CHR$(34), CHR$(39))
			txt$ = REPLACE$(txt$, CHR$(92), CHR$(92) & CHR$(92))
			WRITELN "fprintf(stderr, \"File '", g_CURFILE$, "' line %d: ", g_TRACE_PREFIX$, REPLACE$(txt$, "%", "%%"), "\\n\", ", g_COUNTER, ");" TO g_CFILE
			IF LEN(g_MONITOR$) THEN WRITELN g_MONITOR$ TO g_CFILE
			g_TRACE_PREFIX$ = ""
		ENDIF
	END IF

	' See if there are special functions which need adjustments during conversion time
	current$ = Pre_Tokenize_Functions$(current$)

	WHILE TRUE
		' Initialize parser
		is_string = FALSE
		is_escaped = FALSE
		token$ = ""

		' See if there are colons
		FOR i = 1 TO LEN(current$)
			SELECT ASC(MID$(current$, i, 1))
					' Separator
				CASE 58
					IF NOT(is_string) AND ASC(MID$(current$, i+1, 1)) = 58 THEN
						INCR i
						token$ = token$ & "::"
					ELIF NOT(is_string) AND ISFALSE(g_USE_C) AND ISFALSE(g_USE_H) AND NOT(in_func) THEN
						' If we are in a string function increase line counter
						IF INSTR(g_FUNCNAME$, g_STRINGSIGN$) AND sftot > 0 THEN INCR g_STRING_LINE
						' Determine amount of string funcs
						IF sftot > g_STRING_FUNC THEN g_STRING_FUNC = sftot
						Parse_Line(CHOP$(token$))
						token$ = ""
						sfunc = 0
						sftot = 0
					ELSE
						token$ = token$ & ":"
					END IF
					' Tab
				CASE 9
					token$ = token$ & IIF$(NOT(is_string), CHR$(32), CHR$(9))
					' String symbol
				CASE 36
					IF NOT(is_string) OR REGEX(current$, "IMPORT.*FROM.*TYPE.*") THEN
						token$ = token$ & g_STRINGSIGN$
						is_escaped = FALSE
						sfunc = 1
					ELSE
						token$ = token$ & "$"
					END IF
					' Bracket open symbol
				CASE 40
					IF NOT(is_string) AND ISFALSE(g_USE_C) AND ISFALSE(g_USE_H) THEN
						INCR in_func
						IF sfunc THEN
							INCR sftot
							sfunc = 0
						ENDIF
					ENDIF
					token$ = token$ & CHR$(40)
					' Bracket close symbol
				CASE 41
					IF NOT(is_string) AND ISFALSE(g_USE_C) AND ISFALSE(g_USE_H) THEN DECR in_func
					token$ = token$ & CHR$(41)
					' Question mark
				CASE 63
					IF NOT(is_string) AND ISFALSE(g_USE_C) AND ISFALSE(g_USE_H) AND NOT(in_func) THEN token$ = token$ & "PRINT "
					ELSE token$ = token$ & CHR$(63)
					' Square bracket
				CASE 91
					IF NOT(is_string) AND MID$(current$, i, 2) <> "[]" AND MID$(current$, i, 11) <> "[(uint64_t)" THEN token$ = token$ & "[(uint64_t)"
					ELSE token$ = token$ & CHR$(91)
					' Long symbol
				CASE 37
					IF NOT(is_string) AND REGEX(RIGHT$(token$, 1), "[a-zA-Z0-9_]+") THEN
						token$ = token$ & g_LONGSIGN$
						is_escaped = FALSE
					ELSE
						token$ = token$ & "%"
					END IF
					' Float symbol
				CASE 35
					IF NOT(is_string) AND REGEX(RIGHT$(token$, 1), "[a-zA-Z0-9_]+") AND i > 1 THEN
						token$ = token$ & g_FLOATSIGN$
						is_escaped = FALSE
					ELSE
						token$ = token$ & "#"
					END IF
					' Escape symbol
				CASE 92
					token$ = token$ & CHR$(92)
					is_escaped = NOT(is_escaped)
					' Quote symbol
				CASE 34
					token$ = token$ & CHR$(34)
					IF NOT(is_escaped) THEN is_string = NOT(is_string)
					is_escaped = FALSE
					' Ampersand symbol
				CASE 38
					IF NOT(is_string) AND ISFALSE(g_USE_C) AND ISFALSE(g_USE_H) THEN
						' ITEMIZER1: Get item on the left side
						item1$ = "" : bracket = 0 : in_spac = 0 : in_str = 0 : direct = 0 : isquote = 0
						FOR j = 1 TO LEN(token$)
							SELECT ASC(MID$(token$, LEN(token$)-j+1, 1))
									' Bracket close
								CASE 93;
								CASE 41
									isquote = 0
									INCR direct
									IF NOT(in_str) THEN
										INCR bracket
									END IF
									' Bracket open
								CASE 91;
								CASE 40
									isquote = 0
									INCR direct
									IF NOT(in_str) THEN
										DECR bracket
										IF bracket < 0 THEN
											BREAK
										ENDIF
									ENDIF
									' Equation
								CASE 61
									isquote = 0
									IF NOT(in_str) THEN BREAK
									' Comma
								CASE 44
									isquote = 0
									IF NOT(in_str) AND NOT(bracket) THEN BREAK
									' Escape symbol
								CASE 92
									IF isquote THEN
										in_str = 1
									END IF
									isquote = 0
									' Double quote
								CASE 34
									isquote = 1
									INCR direct
									in_str = NOT(in_str)
								CASE 32
									isquote = 0
									IF NOT(in_str) AND NOT(bracket) THEN
										IF direct > 0 THEN
											INCR in_spac
										END IF
									ENDIF
									' Colon
								CASE 58
									IF NOT(bracket) THEN
										isquote = 0
										IF NOT(in_str) THEN BREAK
									ENDIF
							END SELECT
							IF REGEX(MID$(token$, LEN(token$)-j+1, 1), "[A-Za-z]") THEN
								isquote = 0
								INCR direct
								IF NOT(in_str) AND NOT(bracket) THEN
									IF in_spac > 0 THEN
										BREAK
									ENDIF
								END IF
							END IF
							item1$ = MID$(token$, LEN(token$)-j+1, 1) & item1$
						NEXT
						' If ITEM is a string element continue
						IF Check_String_Type(item1$) THEN
							token$ = MID$(token$, 1, LEN(token$)-j+1)
							' ITEMIZER2: Get item on the right side
							INCR i
							item2$ = "" : bracket = 0 : in_str = 0 : inescaped = 0 : in_spac = 0 : direct = 0 : sfunc = 0
							FOR j = i TO LEN(current$)
								SELECT ASC(MID$(current$, j, 1))
										' Bracket open
									CASE 40
										INCR direct
										IF NOT(in_str) THEN INCR bracket
										IF sfunc THEN
											sfunc = 0
											INCR sftot
										ENDIF
										' Bracket close
									CASE 41
										INCR direct
										IF NOT(in_str) THEN
											DECR bracket
											IF bracket < 0 THEN
												BREAK
											ENDIF
										ENDIF
										' Comma
									CASE 44
										IF NOT(in_str) AND NOT(bracket) THEN BREAK
										' Ampersand
									CASE 38
										IF NOT(in_str) AND NOT(bracket) THEN
											in_spac = 0 : direct = 0
										END IF
										' Escape symbol
									CASE 92
										inescaped = NOT(inescaped)
										' Double quote
									CASE 34
										INCR direct
										IF NOT(inescaped) THEN in_str = NOT(in_str)
										inescaped = 0
									CASE 32
										IF NOT(in_str) AND NOT(bracket) THEN
											IF direct > 0 THEN
												INCR in_spac
											END IF
										ENDIF
										' Colon and semicolon
									CASE 58;
									CASE 59
										IF NOT(in_str) AND NOT(bracket) THEN BREAK
								END SELECT
								IF REGEX(MID$(current$, j, 1), "[A-Za-z]") THEN
									INCR direct
									IF NOT(in_str) AND NOT(bracket) THEN
										IF in_spac > 0 THEN
											BREAK
										ENDIF
									END IF
								END IF
								IF MID$(current$, j, 1) = "$" THEN
									IF NOT(in_str) OR REGEX(current$, "IMPORT.*FROM.*TYPE.*") THEN
										item2$ = item2$ & g_STRINGSIGN$
										sfunc = 1
									ELSE
										item2$ = item2$ & "$"
									ENDIF
								ELIF MID$(current$, j, 1) = "&" THEN
									IF NOT(in_str) AND NOT(bracket) THEN
										item2$ = item2$ & ","
									ELSE
										item2$ = item2$ & "&"
									END IF
								ELSE
									item2$ = item2$ & MID$(current$, j, 1)
								END IF
							NEXT
							i = j-1
							' Make sure concatenation of literals is done by C - delete comma
							exp$ = item1$ & "," & item2$
							prev = 0
							str$ = ""
							' Start miniparser
							WHILE LEN(exp$)
								elem$ = Mini_Parser$(exp$)
								IF LEFT$(CHOP$(elem$), 1) = CHR$(34) THEN
									IF prev THEN
										sep$ = " "
									ELSE
										sep$ = ","
									ENDIF
									prev = 1
								ELSE
									sep$ = ","
									prev = 0
								ENDIF
								str$ = IIF$(LEN(str$), str$ & sep$ & elem$, elem$)
								exp$ = MID$(exp$, LEN(elem$)+2)
							WEND
							' Construct concatenation
							token$ = token$ & " CONCAT" & g_STRINGSIGN$ & "(" & str$ & ") "
							INCR sftot
						ELSE
							token$ = token$ & CHR$(38)
						END IF
					ELSE
						token$ = token$ & CHR$(38)
					END IF
					is_escaped = FALSE
				DEFAULT
					token$ = token$ & MID$(current$, i, 1)
					is_escaped = FALSE
			END SELECT
		NEXT

		IF token$ = result$ THEN BREAK
		result$ = token$
		current$ = token$
	WEND

	' If we are in a string function increase line counter
	IF INSTR(g_FUNCNAME$, g_STRINGSIGN$) AND sftot > 0 THEN INCR g_STRING_LINE

	' Determine amount of string funcs
	IF sftot > g_STRING_FUNC THEN g_STRING_FUNC = sftot

	' Start parsing
	Parse_Line(CHOP$(token$))

END SUB

'----------------------------------------------------------------------------------------------

FUNCTION Parse_Equation$(STRING current$)

	LOCAL i, is_string, is_escaped, is_equation, opctr, check, is_pointer, flag
	LOCAL chunk$, token$, term$, eq$, total$, element$, last$, v1$, v2$
	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 MID$(current$, i, 9) = " " & g_RANGEOP$ & " " THEN
			IF ISFALSE(is_string) THEN
				flag = 1
			ENDIF
		ELIF MID$(current$, i, 5) = " AND " THEN
			IF NOT(flag) THEN
				IF ISFALSE(is_string) THEN
					chunk$ = chunk$ & CHR$(10)
					logop$[opctr] = " AND "
					INCR opctr : INCR i, 4
				ELSE
					chunk$ = chunk$ & " "
				END IF
			ELSE
				flag = 0
				chunk$ = chunk$ & " "
			ENDIF
		ELIF MID$(current$, i, 4) = " OR " THEN
			IF ISFALSE(is_string) THEN
				chunk$ = chunk$ & CHR$(10)
				logop$[opctr] = " OR "
				INCR opctr : INCR i, 3
			ELSE
				chunk$ = chunk$ & " "
			END IF
		ELIF MID$(current$, i, 1) = CHR$(92) THEN
			chunk$ = chunk$ & CHR$(92)
			is_escaped = NOT(is_escaped)
		ELIF MID$(current$, i, 1) = CHR$(34) THEN
			chunk$ = chunk$ & CHR$(34)
			IF ISFALSE(is_escaped) THEN is_string = NOT(is_string)
			is_escaped = FALSE
		ELSE
			chunk$ = chunk$ & MID$(current$, i, 1)
			is_escaped = FALSE
		END IF
	NEXT
	logop$[opctr] = ""
	opctr = 1

	' Start parsing
	FOR element$ IN chunk$ STEP CHR$(10)

		' Initialize for this chunk
		eq$ = ""
		token$ = ""
		is_equation = 0
		is_string = 0
		is_escaped = 0
		is_pointer = 0

		' Check if this is a string
		check = Check_String_Type(element$)

		' See if there are equal signs
		FOR i = 1 TO LEN(element$)

			IF MID$(element$, i, 7) = g_RANGEOP$ AND LEN(MID$(element$, i)) > 8 THEN
				term$ = TOKEN$(element$, 2, g_RANGEOP$)
				v1$ = Mini_Parser$(term$, "AND")
				term$ = MID$(term$, LEN(v1$)+1)
				IF REGEX(term$, "AND.*") THEN
					v2$ = MID$(term$, 4)
				ELSE
					v2$ = MID$(term$, 2)
				ENDIF
				IF check THEN
					IF REGEX(v2$, "EXCL$") THEN
						token$ = "(__b2c__STRCMP(" & token$ & ", __b2c__min_str(" & v1$ & "," & LEFT$(v2$, LEN(v2$)-4) & ")) > 0 && __b2c__STRCMP(" & token$ & ", __b2c__max_str(" & v1$ & "," & LEFT$(v2$, LEN(v2$)-4) & ")) < 0 ? 1 : 0)"
					ELSE
						token$ = "(__b2c__STRCMP(" & token$ & ", __b2c__min_str(" & v1$ & "," & v2$ & ")) >= 0 && __b2c__STRCMP(" & token$ & ", __b2c__max_str(" & v1$ & "," & v2$ & ")) <= 0 ? 1 : 0)"
					END IF
					check = 0
				ELSE
					IF REGEX(v2$, "EXCL$") THEN
						token$ = "(" & token$ & " > fmin(" & v1$ & "," & LEFT$(v2$, LEN(v2$)-4) & ") && " & token$ & " < fmax(" & v1$ & "," & LEFT$(v2$, LEN(v2$)-4) & ") ? 1 : 0)"
					ELSE
						token$ = "(" & token$ & " >= fmin(" & v1$ & "," & v2$ & ") && " & token$ & " <= fmax(" & v1$ & "," & v2$ & ") ? 1 : 0)"
					END IF
				ENDIF
				BREAK
			ENDIF

			SELECT MID$(element$, i, 2)
				CASE "=="
					IF ISFALSE(is_string) THEN
						element$ = LEFT$(element$, i-1) & "= " & MID$(element$, i+2)
					END IF
				CASE "<>"
					IF ISFALSE(is_string) THEN
						element$ = LEFT$(element$, i-1) & "!=" & MID$(element$, i+2)
					END IF
			END SELECT

			SELECT ASC(MID$(element$, i, 1))
					' Equation symbol
				CASE 61
					IF ISFALSE(is_string) THEN
						IF check OR Get_Var$(token$, g_FUNCNAME$) = "char*" THEN
							IF LEN(eq$) THEN
								eq$ = eq$ & "="
							ELSE
								term$ = token$
								token$ = ""
								check = TRUE
								eq$ = "=="
							ENDIF
						ELIF NOT(is_equation) THEN
							token$ = "(" & token$ & ")=="
						ELSE
							token$ = token$ & "="
							is_equation = 0
						END IF
					ELSE
						token$ = token$ & "="
					END IF
					' Negation
				CASE 33
					IF ISFALSE(is_string) THEN
						IF check OR Get_Var$(token$, g_FUNCNAME$) = "char*" THEN
							term$ = token$
							token$ = ""
							check = TRUE
							eq$ = "!"
						ELIF NOT(is_equation) THEN
							token$ = "(" & token$ & ")!="
							INCR i
						ELSE
							token$ = token$ & "!"
							is_equation = 0
						END IF
					ELSE
						token$ = token$ & "!"
					END IF
					' Comparison symbols
				CASE 60
					IF ISFALSE(is_string) THEN
						IF check OR Get_Var$(token$, g_FUNCNAME$) = "char*" THEN
							term$ = token$
							token$ = ""
							check = TRUE
							eq$ = "<"
						ELSE
							IF is_equation THEN
								is_equation = 0
							ELSE
								is_equation = 1
							ENDIF
							token$ = token$ & "<"
						ENDIF
					ELSE
						token$ = token$ & "<"
					ENDIF
				CASE 62
					IF NOT(is_string) AND NOT(is_pointer) THEN
						IF check OR Get_Var$(token$, g_FUNCNAME$) = "char*" THEN
							term$ = token$
							token$ = ""
							check = TRUE
							eq$ = ">"
						ELSE
							IF is_equation THEN
								is_equation = 0
							ELSE
								is_equation = 1
							ENDIF
							token$ = token$ & ">"
						ENDIF
					ELSE
						token$ = token$ & ">"
						is_pointer = 0
					ENDIF
					' Minus symbol in pointer
				CASE 45
					token$ = token$ & CHR$(45)
					IF NOT(is_string) AND NOT(is_pointer) THEN
						is_pointer = 1
					ENDIF
					' Escape symbol
				CASE 92
					token$ = token$ & CHR$(92)
					is_escaped = NOT(is_escaped)
					' Quote symbol
				CASE 34
					token$ = token$ & CHR$(34)
					IF ISFALSE(is_escaped) THEN is_string = NOT(is_string)
					is_escaped = FALSE
				DEFAULT
					' Handle normal char after '<' or '>' symbol
					IF is_equation THEN
						is_equation = 0
						last$ = RIGHT$(token$, 1)
						token$ = "(" & LEFT$(token$, LEN(token$)-1) & ")" & last$
					ENDIF
					token$ = token$ & MID$(element$, i, 1)
					is_escaped = FALSE
					is_pointer = FALSE
			END SELECT
		NEXT

		' Construct string equation
		IF check THEN token$ = "__b2c__STRCMP(" & term$ & "," & token$ & ") " & eq$ & " 0"

		total$ = total$ & token$

		' Restore logical operator
		total$ = total$ & logop$[opctr]
		INCR opctr
	NEXT

	RETURN total$

END FUNCTION

'----------------------------------------------------------------------------------------------

SUB Download_File(STRING name$)

	LOCAL total$, dat$, proxy$, unpw$
	LOCAL length, mynet, size
	LOCAL baconfile TYPE FILE*

	CATCH GOTO network_error

	' Get environment variable for proxy
	proxy$ = GETENVIRON$("HTTP_PROXY")
	IF LEN(proxy$) = 0 THEN proxy$ = GETENVIRON$("http_proxy")

	' Parse proxy settings
	IF LEN(proxy$) THEN
		IF LEFT$(proxy$, 7) <> "http://" THEN
			EPRINT "System error: proxy '", proxy$, "' not supported! Redefine to default HTTP proxy or undefine."
			END 1
		ENDIF

		proxy$ = MID$(proxy$, 8)
		IF TALLY(proxy$, "@") THEN
			unpw$ = B64ENC$(TOKEN$(proxy$, 1, "@"))
			proxy$ = TOKEN$(proxy$, 2, "@")
		ENDIF

		' Setup TCP connection on defined port
		OPEN proxy$ FOR NETWORK AS mynet

		SEND "CONNECT " & TOKEN$(name$, 1, "/") & ":80 HTTP/1.1" & "\r\n" TO mynet
		IF LEN(unpw$) THEN SEND "Proxy-Authorization: Basic " & B64ENC$(unpw$) & "\r\n" TO mynet
		SEND "\r\n" TO mynet

		' Return should be OK
		RECEIVE dat$ FROM mynet
		IF NOT(TALLY(dat$, " 200 ")) THEN
			EPRINT "System error: proxy '", proxy$, "' returns error: " & dat$
			END 1
		ENDIF
	ELSE
		' Open TCP connection on port 80
		OPEN TOKEN$(name$, 1, "/") & ":80" FOR NETWORK AS mynet
	ENDIF

	PRINT "Fetching file...";

	SEND "HEAD /" & MID$(name$, INSTR(name$, "/")+1) & " HTTP/1.1\r\nHost: " & TOKEN$(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
		EPRINT "System 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
	SEND "GET /" & MID$(name$, INSTR(name$, "/")+1) & " HTTP/1.1\r\nHost: " & TOKEN$(name$, 1, "/") & "\r\n\r\n" TO mynet
	WHILE WAIT(mynet, 2000)
		RECEIVE dat$ FROM mynet CHUNK 128 SIZE size
		IF size = 0 THEN BREAK
		EPRINT ".";
		total$ = total$ & dat$
	WEND
	CLOSE NETWORK mynet

	' Rip off HTTP headers
	total$ = MID$(total$, INSTR(total$, "\r\n\r\n")+4)

	' Check amount of data
	IF LEN(total$) != length THEN
		EPRINT "System error: file ", name$, " could not be downloaded probably due to a timeout. Try again later."
		END 1
	END IF

	' Write to file
	OPEN MID$(name$, INSTRREV(name$, "/")+1) FOR WRITING AS baconfile
	WRITELN total$ TO baconfile
	CLOSE FILE baconfile

	PRINT "done."
	EXIT SUB

	LABEL network_error
		EPRINT "System error: the site http://", LEFT$(name$, INSTR(name$, "/")-1), " is not reachable! Try again later."
		END 1

END SUB

'----------------------------------------------------------------------------

SUB Editor_Print_Line(txt$, inverse)

	LOCAL str$, sub$
	LOCAL pos, col, len, where
	LOCAL in_comment = FALSE TYPE static int

	str$ = LEFT$(txt$, COLUMNS)

	REPEAT
		' See if we have an item to highlight, look at the whole line in case result is longer than screen width
		pos = REGEX(MID$(txt$, where+1), Stat$ & "|" & Func$ & "|" & Var$ & "|" & Comm$ & "|" & Num$ & "|" & Mlc$ & "|\"(\\\\.|[^\"])*\"")

		' Check if this item is a standalone term, use original line again
		IF pos AND NOT(in_comment) THEN
			len = REGLEN
			IF REGEX(MID$(txt$, where+pos-1, 1), "[[:alpha:]]|_|\\$") OR REGEX(MID$(txt$, where+pos+len, 1), "[[:alpha:]]|_|\\$") AND MID$(str$, pos, 1) <> "'" THEN
				IF inverse THEN COLOR INVERSE
				IF Color_Intense THEN COLOR INTENSE
				PRINT MID$(str$, 1, pos+len-1);
				COLOR RESET
				str$ = MID$(str$, pos+len)
				INCR where, pos+len-1
				CONTINUE
			ENDIF
		ENDIF

		' Now find color for item
		IF pos OR in_comment THEN

			sub$ = MID$(str$, pos, len)

			' Multiline comments
			IF in_comment THEN
				col = Comm_Col
				len = LEN(str$)
				IF TALLY(txt$, "*/") THEN in_comment = FALSE
				pos = 1
			ELIF ISTOKEN(Num$, sub$, "|") THEN
				col = Num_Col
			ELIF ISTOKEN(Stat$, sub$, "|") THEN
				col = Stat_Col
			ELIF ISTOKEN(EXTRACT$(Func$, "\\"), sub$, "|") THEN
				col = Func_Col
			ELIF ISTOKEN(EXTRACT$(Var$, "\\"), sub$, "|") THEN
				col = Var_Col
			ELIF ISTOKEN(EXTRACT$(Comm$, "\\"), sub$, "|") THEN
				col = Comm_Col
				len = LEN(MID$(str$, pos))
				IF MID$(str$, pos, 2) = "/*" AND NOT(TALLY(txt$, "*/")) THEN in_comment = TRUE
			ELSE
				col = Quot_Col
			ENDIF

			' Render the keyword with the colors
			IF inverse THEN COLOR INVERSE
			IF Color_Intense THEN COLOR INTENSE
			PRINT LEFT$(str$, pos-1);
			COLOR FG TO col
			PRINT MID$(str$, pos, len);
			COLOR RESET
		ELSE
			' Text without highlighting
			IF inverse THEN COLOR INVERSE
			IF Color_Intense THEN COLOR INTENSE
			PRINT str$;
			COLOR RESET
			len = 0
		END IF

		' Last part of the string
		str$ = MID$(str$, pos+len)
		INCR where, pos+len-1

	UNTIL LEN(str$) = 0

END SUB

'----------------------------------------------------------------------------

SUB Editor_Print_Text(txt$, line)

	LOCAL x

	CURSOR OFF
	FOR x = 1 TO ROWS
		GOTOXY 1, x
		PRINT CL$;
		GOTOXY 1, x
		Editor_Print_Line(TOKEN$(txt$, line, NL$), FALSE)
		INCR line
	NEXT
	CURSOR ON

END SUB

'----------------------------------------------------------------------------

SUB Editor_Restore_Normal

	SIGNAL SIG_DFL, SIGINT
	PRINT "\033[?47l";
	GOTOXY g_CURSOR_X, g_CURSOR_Y-1
	STOP SIGINT

ENDSUB

'----------------------------------------------------------------------------

SUB Editor_Handle_Input(file$, text$)

	LOCAL xpos = 1, ypos = 1, start = 1, verticalpos = 1
	LOCAL key, special, cursor, inskey, delkey, page, total, x, myposition, nextposition
	LOCAL line$, prog$, ch$, answer$, option$, man$, str$, result$

	' Avoid errors in parsing delimited strings when element consists of strings only
	OPTION DQ 1
	OPTION COLLAPSE FALSE

	' Restore ANSI screen when <CTRL>+C is pressed
	SIGNAL Editor_Restore_Normal, SIGINT

	' Store X and Y position of cursor
	g_CURSOR_X = GETX
	g_CURSOR_Y = GETY

	' Alternate screen
	PRINT "\033[?47h"

	Editor_Print_Text(text$, 1)

	WHILE TRUE
		REPEAT
			' Position cursor
			GOTOXY xpos, ypos

			' Scan for key and delay at the same time
			key = WAIT(STDIN_FILENO, 100)

			SELECT key
					' No key pressed? Skip
				CASE 0
					CONTINUE

					' Special sequence like <cursor up>, <down>, <alt>+<e> etc
				CASE 27
					special = WAIT(STDIN_FILENO, 100)

					SELECT special
							' One of the special keys
						CASE 91
							cursor = WAIT(STDIN_FILENO, 100)
							SELECT cursor
								CASE 66
									INCR ypos
									IF verticalpos > 1 THEN
										verticalpos = 1
										PRINT CL$;
										GOTOXY 1, ypos-1
										Editor_Print_Line(TOKEN$(text$, start+ypos-2, NL$), FALSE)
									ENDIF
								CASE 65
									DECR ypos
									IF verticalpos > 1 THEN
										verticalpos = 1
										PRINT CL$;
										GOTOXY 1, ypos+1
										Editor_Print_Line(TOKEN$(text$, start+ypos, NL$), FALSE)
									ENDIF
								CASE 67
									INCR xpos
								CASE 68
									DECR xpos
								CASE 50
									inskey = WAIT(STDIN_FILENO, 100)
									IF inskey = 126 THEN
										IF ypos < ROWS THEN
											line$ = TOKEN$(text$, start+ypos-1, NL$)
											text$ = APPEND$(text$, start+ypos, line$, NL$)
											Editor_Print_Text(text$, start)
										ENDIF
									ENDIF
								CASE 51
									delkey = WAIT(STDIN_FILENO, 100)
									IF delkey = 126 THEN
										IF LEN(MID$( TOKEN$(text$, start+ypos-1, NL$), xpos)) <= 1 THEN
											line$ = TOKEN$(text$, start+ypos, NL$)
											text$ = CHANGE$(text$, start+ypos-1, TOKEN$(text$, start+ypos-1, NL$) & line$, NL$)
											text$ = DEL$(text$, start+ypos, NL$)
											Editor_Print_Text(text$, start)
										ELIF xpos < COLUMNS THEN
											line$ = TOKEN$(text$, start+ypos-1, NL$)
											line$ = LEFT$(line$, xpos-1) & MID$(line$, xpos+1)
											text$ = CHANGE$(text$, start+ypos-1, line$, NL$)
											PRINT CL$;
											GOTOXY 1, ypos
											Editor_Print_Line(line$, FALSE)
										ENDIF
									ELIF delkey = 59 THEN
										' Flush buffer
										delkey = WAIT(STDIN_FILENO, 100)
										delkey = WAIT(STDIN_FILENO, 100)
										text$ = DEL$(text$, start+ypos-1, NL$)
										Editor_Print_Text(text$, start)
									ENDIF
									' Home key
								CASE 72
									xpos = 1
									IF verticalpos > 1 THEN
										verticalpos = 1
										GOTOXY 1, ypos
										Editor_Print_Line(MID$(line$, verticalpos), FALSE)
									ENDIF
									' End key
								CASE 70
									line$ = TOKEN$(text$, start+ypos-1, NL$)
									xpos = LEN(line$)
									IF xpos > COLUMNS THEN
										verticalpos = xpos - COLUMNS + 1
										GOTOXY 1, ypos
										Editor_Print_Line(MID$(line$, verticalpos), FALSE)
										xpos = COLUMNS
									ENDIF
									' Page up key
								CASE 53
									page = WAIT(STDIN_FILENO, 100)
									IF page = 126 THEN
										IF start > ROWS THEN
											DECR start, ROWS
										ELSE
											start = 1
										END IF
										SCROLL DOWN ROWS
										Editor_Print_Text(text$, start)
									END IF
									' Page down key
								CASE 54
									page = WAIT(STDIN_FILENO, 100)
									IF page = 126 THEN
										IF start + 2*ROWS - 1 < AMOUNT(text$, NL$) THEN
											INCR start, ROWS
										ELSE
											start = AMOUNT(text$, NL$)-ROWS+1
											IF start < 1 THEN start = 1
										END IF
										SCROLL UP ROWS
										Editor_Print_Text(text$, start)
									END IF
							ENDSELECT

							' Secure range
							IF ypos < 1 THEN
								DECR start
								ypos = 1
								IF start < 1 THEN
									start = 1
								ELSE
									SCROLL DOWN
									GOTOXY 1, 1
									Editor_Print_Line(TOKEN$(text$, start, NL$), FALSE)
								ENDIF
							ENDIF

							IF ypos > ROWS THEN
								INCR start
								ypos = ROWS
								IF start+ROWS-1 > AMOUNT(text$, NL$) THEN
									start = AMOUNT(text$, NL$) - ROWS + 1
								ELSE
									SCROLL UP
									GOTOXY 1, ROWS
									Editor_Print_Line(TOKEN$(text$, start+ROWS-1, NL$), FALSE)
								ENDIF
							ELIF ypos > AMOUNT(text$, NL$) THEN
								ypos = AMOUNT(text$, NL$)
							ENDIF

							' Take care of a line longer than columns
							IF xpos < 1 THEN
								line$ = TOKEN$(text$, start+ypos-1, NL$)
								IF LEN(line$) > COLUMNS AND verticalpos > 1 THEN
									DECR verticalpos
									PRINT CL$;
									GOTOXY 1, ypos
									Editor_Print_Line(MID$(line$, verticalpos), FALSE)
								ELSE
									verticalpos = 1
								ENDIF
								xpos = 1
							ENDIF

							' Take care of a line longer than columns
							IF xpos > COLUMNS THEN
								line$ = TOKEN$(text$, start+ypos-1, NL$)
								IF LEN(line$) > COLUMNS THEN
									INCR verticalpos
									IF verticalpos > LEN(line$)-COLUMNS+1 THEN verticalpos = LEN(line$)-COLUMNS+1
									PRINT CL$;
									GOTOXY 1, ypos
									Editor_Print_Line(MID$(line$, verticalpos), FALSE)
								ELSE
									verticalpos = 1
								ENDIF
								xpos = COLUMNS
							ENDIF
					ENDSELECT

					' Backspace
				CASE 127
					IF xpos > 1 THEN
						line$ = TOKEN$(text$, start+ypos-1, NL$)
						line$ = LEFT$(line$, verticalpos-1+xpos-2) & MID$(line$, verticalpos-1+xpos)
						text$ = CHANGE$(text$, start+ypos-1, line$, NL$)
						PRINT CL$;
						GOTOXY 1, ypos
						Editor_Print_Line(MID$(line$, verticalpos), FALSE)
						DECR xpos
					ELSE
						line$ = TOKEN$(text$, start+ypos-1, NL$)
						xpos = LEN(TOKEN$(text$, start+ypos-2, NL$))+1
						text$ = CHANGE$(text$, start+ypos-2, TOKEN$(text$, start+ypos-2, NL$) & line$, NL$)
						text$ = DEL$(text$, start+ypos-1, NL$)
						Editor_Print_Text(text$, start)
						IF ypos > 1 THEN DECR ypos
						IF xpos > COLUMNS THEN
							verticalpos = xpos-COLUMNS+1
							xpos = COLUMNS
						ENDIF
						GOTOXY 1, ypos
						line$ = TOKEN$(text$, start+ypos-1, NL$)
						Editor_Print_Line(MID$(line$, verticalpos), FALSE)
					ENDIF

					' Return key
				CASE 10
					IF ypos < ROWS THEN
						line$ = TOKEN$(text$, start+ypos-1, NL$)
						text$ = CHANGE$(text$, start+ypos-1, LEFT$(line$, verticalpos-1+xpos-1), NL$)
						text$ = APPEND$(text$, start+ypos, MID$(line$, verticalpos-1+xpos), NL$)
						Editor_Print_Text(text$, start)
						INCR ypos
						xpos = 1
						verticalpos = 1
					ENDIF

					' Other keys
				DEFAULT
					line$ = TOKEN$(text$, start+ypos-1, NL$)
					' Neutralize TAB key
					IF key = 9 THEN
						ch$ = SPC$(4)
					ELSE
						ch$ = CHR$(key)
					ENDIF
					IF xpos > LEN(line$) THEN
						line$ = INSERT$(line$, verticalpos-1+xpos, SPC$(verticalpos-1+xpos-1-LEN(line$)) & ch$)
					ELSE
						line$ = INSERT$(line$, verticalpos-1+xpos, ch$)
					ENDIF
					text$ = CHANGE$(text$, start+ypos-1, line$, NL$)
					PRINT CL$;
					GOTOXY 1, ypos
					Editor_Print_Line(MID$(line$, verticalpos), FALSE)
					IF xpos < COLUMNS THEN INCR xpos, IIF(key = 9, 4, 1)
			ENDSELECT
		UNTIL special = 0 AND key = 27

		GOTOXY 1, ROWS
		PRINT CL$, "(N)ew (L)oad (S)ave (F)ind (G)oto (C)ompile (O)pts (H)igh (I)ndent (Q)uit ? ";
		key = GETKEY

		SELECT LCASE$(CHR$(key))
			CASE "n"
				start = 1
				verticalpos = 1
				GOTOXY 1,1
				text$ = " "
				file$ = ""
			CASE "l"
				INPUT NL$, "Enter file name... ", file$
				IF NOT(FILEEXISTS(file$)) THEN
					COLOR FG TO RED
					PRINT "WARNING: File does not exist!"
					COLOR RESET
					INPUT "Press <return> to continue...", key
				ELSE
					text$ = REPLACE$(LOAD$(file$), CHR$(9), SPC$(4))
					start = 1
					verticalpos = 1
				ENDIF
			CASE "s"
				IF LEN(file$) THEN
					SAVE REPLACE$(text$, SPC$(4), CHR$(9)) TO file$
					PRINT NL$, "File '" & BASENAME$(file$) & "' saved."
				ELSE
					answer$ = "y"
					INPUT NL$, "Enter file name... ", file$
					IF FILEEXISTS(file$) THEN INPUT "File '", file$, "' exists! Overwrite ([y]/n) ? ", answer$
					IF answer$ = "y" THEN
						SAVE REPLACE$(text$, SPC$(4), CHR$(9)) TO file$
						PRINT "File '" & BASENAME$(file$) & "' saved."
					ELSE
						PRINT "File NOT saved."
					ENDIF
				ENDIF
				INPUT "Press <return> to continue...", key
			CASE "f"
				INPUT NL$, "Enter term... ", word$
				PRINT "Searching...";
				total = AMOUNT(text$, NL$)
				FOR x = 1 TO total
					IF TALLY(TOKEN$(text$, x, NL$), word$) THEN
						start = x - ROWS/2
						IF start < 1 THEN start = 1
						Editor_Print_Text(text$, start)
						ypos = ROWS/2+1
						GOTOXY 1, IIF(x < ypos, x, ypos)
						Editor_Print_Line(TOKEN$(text$, IIF(x < ypos, x, start+ypos-1), NL$), TRUE)
						GOTOXY 1, ROWS
						PRINT CL$, "Press [n] for next item...";
						xpos = INSTR(TOKEN$(text$, x, NL$), word$)
						IF xpos > COLUMNS THEN xpos = COLUMNS
						GOTOXY xpos, ypos
						key = GETKEY
						IF key <> ASC("n") THEN BREAK
						GOTOXY 1, ROWS
						PRINT CL$, "Searching...";
					ENDIF
				NEXT
				GOTOXY 1, ROWS
				INPUT CL$, "Search ended. Press <return> to continue...", key
			CASE "g"
				INPUT NL$, "Enter line number... ", key
				IF key > AMOUNT(text$, NL$)-(ROWS/2) THEN
					start = AMOUNT(text$, NL$)-ROWS
				ELIF key < ROWS/2 THEN
					start = 1
				ELSE
					start = key-(ROWS/2)
				ENDIF
				ypos = key-start+1
				GOTOXY xpos, ypos
			CASE "c"
				prog$ = DIRNAME$(file$) & "/" & BASENAME$(file$, 1)
				IF FILEEXISTS(prog$) THEN DELETE FILE prog$
				SAVE REPLACE$(text$, SPC$(4), CHR$(9)) TO file$
				PRINT NL$, "Executing 'bacon " & option$ & " -d " & DIRNAME$(file$) & " " & file$ & "'..."
				SYSTEM "bacon " & option$ & " -d " & DIRNAME$(file$) & " " & file$
				IF FILEEXISTS(prog$) THEN
					PRINT "Execute ([y]/n) ? ";
					key = GETKEY
					PRINT
					IF key = ASC("y") OR key = 10 THEN
						INPUT "Arguments (<enter> means none)... ", word$
	                    PRINT "\033[?47l";
						SYSTEM prog$ & " " & word$
					ENDIF
				ENDIF
				INPUT "Press <return> to continue...", key
	            PRINT "\033[?47h";
			CASE "o"
				PRINT NL$, "Current BaCon command line options: ", option$
				PRINT "Do you want to set new options (y/[n]) ? ";
				key = GETKEY
				PRINT
				IF key = ASC("y") THEN INPUT "Enter new options: ", option$
				INPUT "Press <return> to continue...", key
			CASE "h"
				Color_Intense = NOT(Color_Intense)
			CASE "i"
				PRINT NL$, "Applying indentation...";
				result$ = ""
				myposition = nextposition = label_active = 0
				total = AMOUNT(text$, NL$)
				FOR x = 1 TO total
					myposition = nextposition
					line$ = CHOP$(TOKEN$(text$, x, NL$))
					IF LEN(line$) = 0 AND label_active THEN
						label_active = FALSE
						DECR myposition
						nextposition = myposition
					ENDIF
					IF REGEX(line$, "^(CASE|UNTIL)[ \\t]|^(DEFAULT|FI|NEXT|WEND|DONE)|^ELSE$|^ELIF.+THEN$|^END.+") THEN
						IF NOT(REGEX(line$, "^END.+[0-9]+")) THEN DECR myposition
						IF RIGHT$(line$, 6) = "SELECT" THEN DECR myposition
						IF myposition < 0 THEN myposition = 0
						nextposition = myposition
					ENDIF
					IF REGEX(line$, "^(CASE|ENUM|FOR|FUNCTION|GLOBAL RECORD|LABEL|RECORD|SELECT|SUB|WHILE|DOTIMES|WITH)[ \\t]|^(DEFAULT|REPEAT|USEC|USEH|DO$)|^IF.+THEN$|^ELIF.+THEN$|^ELSE$") THEN
						INCR nextposition
						IF LEFT$(line$, 6) = "SELECT" THEN INCR nextposition
						IF LEFT$(line$, 5) = "LABEL" THEN label_active = TRUE
					ENDIF
					IF LEN(line$) THEN
						result$ = result$ & SPC$(myposition*4) & line$ & NL$
					ELSE
						result$ = result$ & NL$
					ENDIF
				NEXT
				text$ = result$
				INPUT " done.", NL$, "Press <return> to continue...", key
			CASE "q"
				BREAK
			DEFAULT
				IF key <> 27 THEN
					COLOR FG TO RED
					PRINT NL$, "WARNING: invalid option!"
					COLOR RESET
					INPUT "Press <return> to continue...", key
				ELSE
					GOTOXY 1, ROWS
					PRINT CL$;
					Editor_Print_Line(TOKEN$(text$, start+ROWS-1, NL$), FALSE)
					CONTINUE
				ENDIF
		ENDSELECT

		Editor_Print_Text(text$, start)
	WEND

	' Back to normal screen
	CALL Editor_Restore_Normal

END SUB

'----------------------------------------------------------------------------------------------
'
' Main program
'
'----------------------------------------------------------------------------------------------

' Default BACON settings
LET g_MAX_DIGITS = 32

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

' Maximum RETURN buffers
LET g_MAX_RBUFFERS = 32

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

g_CCNAME_TMP$ = ""
g_TEMPDIR_TMP$ = ""
g_INCFILES_TMP$ = ""
g_LDFLAGS_TMP$ = ""
g_CCFLAGS_TMP$ = ""

LET g_NO_COMPILE = 0
LET g_TMP_PRESERVE = 0
LET g_QUIET = 0
LET g_SEMANTIC = 0
LET g_NO_QUESTION = 0
LET g_CPP = 0
LET g_XGETTEXT = 0
LET g_SAVE_CONFIG = 0
LET g_DEBUG = 0
LET g_LOWERCASE = 0

LET g_USE_C = 0
LET g_USE_H = 0
LET g_MAX_BACKLOG = 5

g_INCLUDE_FILES$ = ""
g_PRAGMA_REGEX$ = ""
LET g_TRACE = 0
LET g_OPTION_BASE = 0
LET g_OPTION_SOCKET = 5
LET g_OPTION_BREAK = 1

' Some global declarations
DECLARE g_ALL_MAIN_VARS$ ASSOC STRING
DECLARE g_ALL_FUNC_VARS$ ASSOC STRING
DECLARE g_ALL_DIM_VARS$ ASSOC STRING
DECLARE g_SEMANTIC_MEMFREE$ ASSOC STRING
DECLARE g_SEMANTIC_OPENCLOSE$ ASSOC STRING
g_CURFILE$ = ""
g_FUNCNAME$ = ""
g_FUNCTYPE$ = ""
g_PROTOTYPE$ = ""
g_TMP_FILES$ = ""
g_LOCALSTRINGS$ = ""
g_STRINGARRAYS$ = ""
g_STRINGARGS$ = ""
g_DYNAMICARRAYS$ = ""
g_STATICARRAYS$ = ""
g_RECORDCACHE$ = ""
LET g_LOOPCTR = 0
' For...IN loops max 16 levels deep
DECLARE g_LOOPVAR$[16]
g_ERRORTXT$ = ""
g_COMMENT$ = "false"
g_TRACE_PREFIX$ = ""
g_IGNORE_PARSE$ = "TRUE"
g_OPTION_EXPLICIT$ = "FALSE"
g_OPTION_INPUT$ = "\"\\n\""
g_VARTYPE$ = "long"
g_OBJ_FILES$ = ""
g_MAKE_LINE$ = ""
g_MONITOR$ = ""
g_STRING_FUNC = 1
g_STRING_LINE = 0
g_ALARM_FUNC$ = ""
g_ALARM_PROTO$ = ""
g_DOTIMES = 0

' Always create a final label
g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT"
g_CATCH_USED = 0

' Records
g_RECORDNAME$ = ""
g_RECORDVAR$ = ""
g_RECORDARRAY$ = ""
g_WITHVAR$ = ""
g_RECORDEND_BODY$ = ""
g_RECORDEND_HEADER$ = ""

' Socket defaults
g_SOCKTYPE$ = "SOCK_STREAM"
g_NETWORKTYPE$ = "TCP"
g_MULTICAST_TTL = 1
g_SCTP_STREAMS = 1

' Select/Case 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

g_FCTR = 0
g_CCTR = 0

' Cursor positions for ASCII editor
g_CURSOR_X = 0
g_CURSOR_Y = 0

' Timer and dir related
DECLARE starttime, ttime, RETURN_CODE
DECLARE msec_time$, old_curdir$, mapping$

' Read any configfile values
IF NOT(FILEEXISTS(GETENVIRON$("HOME") & "/.bacon/")) THEN MAKEDIR GETENVIRON$("HOME") & "/.bacon/"

IF FILEEXISTS(GETENVIRON$("HOME") & "/.bacon/bacon.cfg" ) THEN
	OPEN GETENVIRON$("HOME") & "/.bacon/bacon.cfg" FOR READING AS cfgfile
	WHILE NOT(ENDFILE(cfgfile))
		READLN line$ FROM cfgfile
		SELECT LEFT$(line$, INSTR(line$, " ")-1)
			CASE "ccname"
				g_CCNAME_TMP$ = CHOP$(MID$(line$, 7))
			CASE "tempdir"
				g_TEMPDIR_TMP$ = CHOP$(MID$(line$, 8))
			CASE "incfiles"
				g_INCFILES_TMP$ = CHOP$(MID$(line$, 9))
			CASE "ldflags"
				g_LDFLAGS_TMP$ = CHOP$(MID$(line$, 8))
			CASE "ccflags"
				g_CCFLAGS_TMP$ = CHOP$(MID$(line$, 8))
			CASE "lowercase"
				g_LOWERCASE_TMP = VAL(CHOP$(MID$(line$, 10)))
		END SELECT
	WEND
	CLOSE FILE cfgfile
ENDIF

REPEAT
	opt = CMDLINE(":c:d:i:l:o:b:r:e:axnjfpqsvwyz@")
	SELECT opt
			' Compiler option
		CASE 99
			g_CCNAME$ = ARGUMENT$

			' Include option
		CASE 105
			IF NOT(FILEEXISTS(ARGUMENT$)) AND NOT(FILEEXISTS("/usr/include/" & ARGUMENT$)) AND NOT(FILEEXISTS("/usr/local/include/" & ARGUMENT$)) THEN
				EPRINT "System error: included C header file from -i option not found!"
				END 1
			ENDIF
			IF LEN(ARGUMENT$) THEN
				IF NOT(FILEEXISTS("/usr/include/" & ARGUMENT$)) AND NOT(FILEEXISTS("/usr/local/include/" & ARGUMENT$)) THEN
					IF LEFT$(ARGUMENT$, 1) <> "/" THEN
						g_INCFILES$ = g_INCFILES$ & " " & CURDIR$ & "/" & ARGUMENT$
					ELSE
						g_INCFILES$ = g_INCFILES$ & " " & ARGUMENT$
					ENDIF
				ELSE
					g_INCFILES$ = g_INCFILES$ & " <" & ARGUMENT$ & ">"
				END IF
			END IF

			' Library flags
		CASE 108
			IF LEFT$(ARGUMENT$, 1) = "`" OR LEFT$(ARGUMENT$, 1) = "-" THEN
				g_LDFLAGS$ = g_LDFLAGS$ & " " & ARGUMENT$
			ELSE
				g_LDFLAGS$ = g_LDFLAGS$ & " -l" & ARGUMENT$
			ENDIF

			' Compiler flags
		CASE 111
			g_CCFLAGS$ = g_CCFLAGS$ & " " & ARGUMENT$

			' Temporary directory
		CASE 100
			IF NOT(FILEEXISTS(ARGUMENT$)) THEN MAKEDIR ARGUMENT$
			g_TEMPDIR$ = ARGUMENT$

			' Help option
		CASE 104;
		CASE 63;
		CASE 45
			PRINT NL$, "USAGE: bacon [options] program[.bac]"
			PRINT NL$, "OPTIONS:"
			PRINT NL$, " -c <compiler>", TAB$(1), "Compiler to use (default: cc)"
			PRINT " -l <ldflags>", 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: .)"
			PRINT " -b <archiver>", TAB$(1), "Define archiver"
			PRINT " -r <ranlib>", TAB$(1), "Define ranlib"
			PRINT " -e <file.bac>", TAB$(1), "Use embedded editor"
			PRINT " -y ", TAB$(2), "Automatically delete temporary files"
			PRINT " -a ", TAB$(2), "Rebuild BaCon archive"
			PRINT " -x ", TAB$(2), "Extract gettext strings"
			PRINT " -z ", TAB$(2), "Allow lowercase keywords"
			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 " -q ", TAB$(2), "Show summary after conversion only"
			PRINT " -s ", TAB$(2), "Suppress semantic error warnings"
			PRINT " -w ", TAB$(2), "Save options to BaCon configfile"
			PRINT " -v ", TAB$(2), "Show version"
			PRINT " -h ", TAB$(2), "Show help", NL$
			END

			' Version option
		CASE 118
			PRINT NL$, "BaCon version ", g_VERSION$, " on ", OS$, " - (c) Peter van Eerten - MIT License.", NL$
			END

			' Preserve option
		CASE 112
			g_TMP_PRESERVE = 1

			' Quiet option
		CASE 113
			g_QUIET = 1

			' Suppress semantic errors
		CASE 115
			g_SEMANTIC = 1

			' Gettext option
		CASE 120
			g_XGETTEXT = 1

			' Automatic delete option
		CASE 121
			g_NO_QUESTION = 1

			' No compile option
		CASE 110
			g_NO_COMPILE = 1

			' Rebuild BaCon archive
		CASE 97
			g_REBUILD_ARCHIVE$ = "libbacon.a"
			g_CCFLAGS$ = g_CCFLAGS$ & " -fPIC"

			' Define BaCon archiver
		CASE 98
			g_ARNAME$ = ARGUMENT$

			' Goto internal editor
		CASE 101
			IF FILEEXISTS(ARGUMENT$) THEN
				Editor_Handle_Input(ARGUMENT$, REPLACE$(LOAD$(ARGUMENT$), CHR$(9), SPC$(4)))
			ELSE
				Editor_Handle_Input(ARGUMENT$, " ")
			ENDIF
			END

			' Define BaCon ranlib
		CASE 114
			g_RANLIB$ = ARGUMENT$

			' Invoke C Preprocessor
		CASE 106
			g_CPP = 1

			' Allow lowercase keywords
		CASE 122
			g_LOWERCASE = 1

			' Shared library
		CASE 102
			g_LDFLAGS$ = g_LDFLAGS$ & " -shared -rdynamic"
			g_CCFLAGS$ = g_CCFLAGS$ & " -fPIC"
			g_BINEXT$ = ".so"

			' Write config
		CASE 119
			g_SAVE_CONFIG = 1

			' Write config
		CASE 64
			g_DEBUG = 1

	END SELECT
UNTIL opt = -1

' See if configfile must be written
IF g_SAVE_CONFIG = 1 THEN
	OPEN GETENVIRON$("HOME") & "/.bacon/bacon.cfg" FOR WRITING AS cfgfile
	WRITELN "ccname ", g_CCNAME$ TO cfgfile
	WRITELN "tempdir ", g_TEMPDIR$ TO cfgfile
	WRITELN "incfiles ", g_INCFILES$ TO cfgfile
	WRITELN "ldflags ", MID$(g_LDFLAGS$, INSTR(g_LDFLAGS$, "-lm")) TO cfgfile
	WRITELN "ccflags ", g_CCFLAGS$ TO cfgfile
	WRITELN "lowercase ", g_LOWERCASE TO cfgfile
	CLOSE FILE cfgfile
	g_CCNAME_TMP$ = g_CCNAME$
	g_TEMPDIR_TMP$ = g_TEMPDIR$
	g_INCFILES_TMP$ = g_INCFILES$
	g_LDFLAGS_TMP$ = g_LDFLAGS$
	g_CCFLAGS_TMP$ = g_CCFLAGS$
	g_LOWERCASE_TMP = g_LOWERCASE
ENDIF

' Use the commandline or configfile settings?
IF NOT(LEN(g_CCNAME$)) THEN
	g_CCNAME$ = g_CCNAME_TMP$
	IF NOT(LEN(g_CCNAME$)) THEN g_CCNAME$ = "cc"
ENDIF
IF NOT(LEN(g_TEMPDIR$)) THEN
	g_TEMPDIR$ = g_TEMPDIR_TMP$
	IF NOT(LEN(g_TEMPDIR$)) THEN g_TEMPDIR$ = "."
ENDIF
IF NOT(LEN(g_INCFILES$)) THEN g_INCFILES$ = g_INCFILES_TMP$
g_LDFLAGS$ = g_LDFLAGS$ & " " & g_LDFLAGS_TMP$
IF NOT(LEN(g_CCFLAGS$)) THEN g_CCFLAGS$ = g_CCFLAGS_TMP$
IF g_LOWERCASE = 0 THEN g_LOWERCASE = g_LOWERCASE_TMP

IF NOT(LEN(ARGUMENT$)) THEN
	IF g_SAVE_CONFIG = 0 THEN EPRINT "System error: no filename? Run with '-h' to see usage."
	END 1
ELSE
	g_SOURCEFILE$ = ARGUMENT$
ENDIF

IF LEFT$(g_SOURCEFILE$, 7) = "http://" THEN
	g_SOURCEFILE$ = MID$(g_SOURCEFILE$, 8)
	Download_File(g_SOURCEFILE$)
	g_SOURCEFILE$ = MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/")+1)
ELIF RIGHT$(g_SOURCEFILE$, 4) != ".bac" THEN
	g_SOURCEFILE$ = CHOP$(g_SOURCEFILE$) & ".bac"
END IF

IF NOT(FILEEXISTS(g_SOURCEFILE$)) THEN
	EPRINT "System error: file '", g_SOURCEFILE$, "' not found!"
	END 1
ENDIF

' Change the working directory
IF INSTR(g_SOURCEFILE$, "/") AND LEFT$(g_SOURCEFILE$, 1) = "/" THEN CHANGEDIR MID$(g_SOURCEFILE$, 1, INSTRREV(g_SOURCEFILE$, "/")-1)

' Now create the global filenames where to write to
g_CFILE$ = g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".c"
g_HFILE$ = g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".h"
g_GENERIC$ = g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h"
STRINGARRAYFILE$ = g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".string.h"
FLOATARRAYFILE$ = g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".float.h"
SRCARRAYFILE$ = g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".src.h"

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

' Check if previous temporary files exist
LET total$ = ""
amount = 0
OPEN g_TEMPDIR$ FOR DIRECTORY AS work_dir
REPEAT
	GETFILE tmpfile$ FROM work_dir
	IF LEFT$(tmpfile$, 1) != "." AND REGEX(tmpfile$, LEFT$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, ".bac")-1) & "\\..+\\..+") THEN
		total$ = total$ & " " & tmpfile$
		INCR amount
	ENDIF
UNTIL LEN(tmpfile$) = 0
CLOSE DIRECTORY work_dir

IF g_NO_QUESTION THEN
	FOR tmpfile$ IN total$
		IF REGEX(tmpfile$, LEFT$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, ".bac")-1) & "\\..+\\..+") THEN DELETE FILE g_TEMPDIR$ & "/" & tmpfile$
	NEXT
ELSE
	IF amount THEN
		INPUT "WARNING: ", amount, " temporary files found! Do you want to delete them ([y]/n)? ", answer$
		IF LEN(answer$) = 0 OR LCASE$(answer$) = "y" THEN
			FOR tmpfile$ IN total$
				IF REGEX(tmpfile$, LEFT$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, ".bac")-1) & "\\..+\\..+") THEN DELETE FILE g_TEMPDIR$ & "/" & tmpfile$
			NEXT
			PRINT "Temporary files were deleted."
		ELSE
			PRINT "Exiting..."
			END 1
		ENDIF
	ENDIF
ENDIF

' Keep start time
starttime = TIMER

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

' Create H file
OPEN g_HFILE$ FOR WRITING AS g_HFILE
WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - MIT License */" TO g_HFILE
WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_HFILE
WRITELN "#undef __b2c_filename" TO g_HFILE
WRITELN "#define __b2c_filename ", CHR$(34), MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), CHR$(34) TO g_HFILE

OPEN STRINGARRAYFILE$ FOR WRITING AS STRINGARRAYFILE
WRITELN "#undef __b2c_filename" TO STRINGARRAYFILE
WRITELN "#define __b2c_filename ", CHR$(34), STRINGARRAYFILE$, CHR$(34) TO STRINGARRAYFILE
WRITELN "char* __b2c__stringarray[] = {" TO STRINGARRAYFILE

OPEN FLOATARRAYFILE$ FOR WRITING AS FLOATARRAYFILE
WRITELN "#undef __b2c_filename" TO FLOATARRAYFILE
WRITELN "#define __b2c_filename ", CHR$(34), FLOATARRAYFILE$, CHR$(34) TO FLOATARRAYFILE
WRITELN "double __b2c__floatarray[] = {" TO FLOATARRAYFILE

IF INSTR(g_LDFLAGS$, "shared") THEN
	WRITELN "/************************************/" TO g_CFILE
	WRITELN "/* Init function for shared objects */" TO g_CFILE
	WRITELN "/************************************/" TO g_CFILE
	WRITELN "#ifdef __GNUC__" TO g_CFILE
	WRITELN "static int BaCon_init() __attribute__((constructor));" TO g_CFILE
	WRITELN "#endif" TO g_CFILE
	WRITELN "int BaCon_init(void){int argc=0; char *argv[2] = { NULL };" TO g_CFILE
ELSE
	WRITELN "/****************************/" TO g_CFILE
	WRITELN "/* Main program starts here */" TO g_CFILE
	WRITELN "/****************************/" TO g_CFILE
	WRITELN "int main(int argc, char **argv){" TO g_CFILE
ENDIF

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

' See if we have the detector
WRITELN "if(argc==2 && !strcmp(argv[1], \"-bacon\")){fprintf(stderr, \"Converted by %s.\\n\", COMPILED_BY_WHICH_BACON", g_STRINGSIGN$, "); exit(EXIT_FAILURE);}" 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 "{if(strstr(argv[__b2c__counter], \" \")||strstr(argv[__b2c__counter], \"\\011\")) __b2c__arglen += strlen(argv[__b2c__counter]) + 3;" TO g_CFILE
WRITELN "else __b2c__arglen += strlen(argv[__b2c__counter]) + 1;} __b2c__arglen++; ARGUMENT", g_STRINGSIGN$, " = (char*)calloc(__b2c__arglen, sizeof(char));" TO g_CFILE
WRITELN "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++){if(strstr(argv[__b2c__counter], \" \")||strstr(argv[__b2c__counter], \"\\011\")){" TO g_CFILE
WRITELN "strcat(ARGUMENT", g_STRINGSIGN$, ", \"\\042\"); strcat(ARGUMENT", g_STRINGSIGN$, ", argv[__b2c__counter]); strcat(ARGUMENT", g_STRINGSIGN$, ", \"\\042\");}" TO g_CFILE
WRITELN "else 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] = (char*)calloc(1, sizeof(char));" TO g_CFILE
WRITELN "/* Determine current moment and keep it for TIMER function */" TO g_CFILE
WRITELN "gettimeofday(&__b2c__tm, NULL); __b2c__elapsed_usecs = __b2c__tm.tv_usec; __b2c__elapsed_secs = __b2c__tm.tv_sec;" TO g_CFILE
WRITELN "/* Setup error signal handling */" 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 "/* Rest of the program */" TO g_CFILE

' There are no imported symbols yet
LET g_IMPORTED$ = ""

' Define statements
CONST Stat$ = "ALARM|ALIAS|APPEND|APPENDING|ARRAY|AS|ASSOC|BACK|BACONLIB|BAPPEND|BASE|BG|BLACK|BLUE|BREAK|" \
	"BROADCAST|BSAVE|BY|CALL|CASE|CATCH|CHANGEDIR|CHUNK|CLEAR|CLOSE|CMODE|COLLAPSE|COLOR|COMPARE|COMPILER|" \
	"CONST|CONTINUE|COPY|CURRENT|CURSOR|CYAN|DATA|DECLARE|DECR|DEF|DEFAULT|DELETE|DELIM|DEVICE|DIRECTORY|DO|" \
	"DONE|DOTIMES|DOWN|DOWNTO|DQ|ELIF|ELSE|END|ENDENUM|ENDFORK|ENDFUNCTION|ENDIF|ENDRECORD|ENDSELECT|ENDSUB|" \
	"ENDUSEC|ENDUSEH|ENDWITH|ENUM|EPRINT|EQ|EXIT|EXPLICIT|FG|FI|FILE|FN|FOR|FORMAT|FORWARD|FRAMEWORK|FREE|" \
	"FROM|FUNCTION|GE|GETBYTE|GETFILE|GETLINE|GLOBAL|GOSUB|GOTO|GOTOXY|GREEN|GT|IF|IMODE|IMPORT|IN|INCLUDE|" \
	"INCR|INPUT|INTENSE|INTERNATIONAL|INVERSE|IS|ISNOT|JOIN|LABEL|LDFLAGS|LE|LET|LIBRARY|LMODE|LOCAL|LOOKUP|" \
	"LT|MAGENTA|MAKEDIR|MAP|MEMREWIND|MEMSTREAM|MEMTYPE|MONITOR|MULTICAST|NE|NETWORK|NEXT|NORMAL|OFF|OFFSET|" \
	"OMODE|ON|OPEN|OPTION|OPTIONS|OTHER|PARSE|POKE|PRAGMA|PRINT|PROPER|PROTO|PULL|PUSH|PUTBYTE|PUTLINE|QUOTED|" \
	"RE|READ|READING|READLN|READWRITE|RECEIVE|RECORD|RECURSIVE|RED|REDIM|RELATE|RENAME|REPEAT|RESET|RESIZE|" \
	"RESTORE|RESUME|RETURN|REWIND|RUN|SAVE|SCROLL|SCTP|SEED|SEEK|SELECT|SEND|SERVER|SETENVIRON|SETSERIAL|SIGNAL|" \
	"SIZE|SLEEP|SOCKET|SORT|SPEED|SPLIT|START|STARTPOINT|STATIC|STEP|STOP|SUB|SWAP|SYSTEM|TCP|TEXTDOMAIN|THEN|" \
	"TO|TRACE|TRAP|TYPE|UDP|UNTIL|UP|USEC|USEH|UTF8|VAR|VARTYPE|WEND|WHENCE|WHILE|WHITE|WITH|WRITELN|WRITING|" \
	"YELLOW"
CONST Stat_Col = 2

' Define functions
CONST Func$ = "ABS|ACOS|ADDRESS|ALIGN\\$|AMOUNT|AND|APPEND\\$|ASC|ASIN|ATN|ATN2|B64DEC\\$|B64ENC\\$|BASENAME\\$|" \
	"BETWEEN|BIN\\$|BIT|BLOAD|BYTELEN|CEIL|CHANGE\\$|CHOP\\$|CHR\\$|CMDLINE|COLUMNS|CONCAT\\$|COS|COUNT|CURDIR\\$|" \
	"CUT\\$|DAY|DEC|DEG|DEL\\$|DELIM\\$|DIRNAME\\$|ENDFILE|EQUAL|ERR\\$|ERROR|EVAL|EVEN|EXCHANGE\\$|EXCL|EXEC\\$|" \
	"EXP|EXPLODE\\$|EXTRACT\\$|FILEEXISTS|FILELEN|FILETIME|FILETYPE|FILL\\$|FIRST\\$|FLATTEN\\$|FLOOR|FORK|FP|" \
	"GETENVIRON\\$|GETKEY|GETPEER\\$|GETX|GETY|HASH|HEAD\\$|HEX\\$|HOST\\$|HOSTNAME\\$|HOUR|IIF|IIF\\$|INBETWEEN\\$|" \
	"INSERT\\$|INSTR|INSTRREV|INT|INTL\\$|ISASCII|ISFALSE|ISKEY|ISTOKEN|ISTRUE|LAST\\$|LCASE\\$|LEFT\\$|LEN|LOAD\\$|" \
	"LOG|MAX|MAX\\$|MAXNUM|ME\\$|MEMCHECK|MEMORY|MEMTELL|MERGE\\$|MID\\$|MIN|MIN\\$|MINUTE|MOD|MONTH|MONTH\\$|MYPID|" \
	"NNTL\\$|NOT|NOW|NRKEYS|OBTAIN\\$|ODD|OR|OS\\$|OUTBETWEEN\\$|PEEK|POW|PROPER\\$|RAD|RANDOM|REALPATH\\$|REAP|" \
	"REGEX|REPLACE\\$|REV\\$|REVERSE\\$|RIGHT\\$|RND|ROL|ROR|ROTATE\\$|ROUND|ROWS|RUN\\$|SEARCH|SECOND|SGN|SIN|SIZEOF|" \
	"SORT\\$|SPC\\$|SQR|STR\\$|SUM|SUMF|TAB\\$|TAIL\\$|TALLY|TAN|TELL|TIMER|TIMEVALUE|TOKEN\\$|TYPEOF\\$|UCASE\\$|UCS|" \
	"ULEN|UNFLATTEN\\$|UNIQ\\$|UTF8\\$|VAL|WAIT|WEEK|WEEKDAY\\$|YEAR"
CONST Func_Col = 6

' Variables
CONST Var$ = "FALSE|TRUE|PI|MAXRANDOM|RETVAL|REGLEN|LINENO|NL\\$|CR\\$|EL\\$|CL\\$|VERSION\\$|ARGUMENT\\$|SOURCE\\$|NULL|" \
	"NUMBER|STRING|FLOATING|FILE|int|double|float|long|char|short|void|signed|unsigned|static|number|string|floating|volatile|struct"
CONST Var_Col = 3

' Numbers
CONST Num$ = "0|1|2|3|4|5|6|7|8|9"
CONST Num_Col = 1

' Comments
CONST Comm$ = "REM|'|/\\*"
CONST Comm_Col = 4

CONST Mlc$ = "\\*/"

' Quoted text
CONST Quot_Col = 5

' Allow lowercase statements and functions
IF ISTRUE(g_LOWERCASE) THEN
	FOR kwd$ IN Stat$ STEP "|"
		mapping$ = mapping$ & " -D" & LCASE$(kwd$) & "=" & kwd$
	NEXT
	FOR kwd$ IN EXTRACT$(Func$, "\\") STEP "|"
		mapping$ = mapping$ & " -D" & LCASE$(kwd$) & "=" & kwd$
	NEXT
	FOR kwd$ IN EXTRACT$(Var$, "\\") STEP "|"
		mapping$ = mapping$ & " -D" & LCASE$(kwd$) & "=" & kwd$
	NEXT
	mapping$ = mapping$ & " -Drem=REM"
	LET g_CPP = 1
ELSE
	mapping$ = ""
ENDIF

' Check if the C Preprocessor needs to run
IF ISTRUE(g_CPP) THEN
	IF ISTRUE(LEN(EXEC$("which cpp 2>/dev/null"))) THEN
		PRINT "Preprocessing '", g_SOURCEFILE$, "'... ";
		' Change next line marker to overcome C preprocessor interpretation
		OPEN g_SOURCEFILE$ & ".tmp" FOR WRITING AS src_tmp
		OPEN g_SOURCEFILE$ FOR READING AS src_in
		WHILE NOT(ENDFILE(src_in))
			READLN line$ FROM src_in
			IF LEFT$(line$, 1) = "#" THEN
				WRITELN line$ TO src_tmp
			ELSE
				WRITELN "@" & line$ & "@" TO src_tmp
			ENDIF
		WEND
		CLOSE FILE src_in, src_tmp
		SYSTEM "cpp -w -P " & mapping$ & " " & g_SOURCEFILE$ & ".tmp " & g_SOURCEFILE$ & ".cpp"
		' Restore next line marker
		OPEN g_SOURCEFILE$ & ".cpp" FOR READING AS src_cpp
		OPEN g_SOURCEFILE$ & ".bac" FOR WRITING AS src_out
		WHILE NOT(ENDFILE(src_cpp))
			READLN line$ FROM src_cpp
			WRITELN MID$(line$, 2, LEN(line$)-2) TO src_out
		WEND
		CLOSE FILE src_out, src_cpp
		FEED$ = g_SOURCEFILE$ & ".bac"
		g_TMP_FILES$ = g_TMP_FILES$ & " " & g_SOURCEFILE$ & ".cpp" & " " & g_SOURCEFILE$ & ".tmp" & " " & g_SOURCEFILE$ & ".bac"
		PRINT "done."
	ELSE
		IF ISTRUE(g_LOWERCASE) THEN
			EPRINT "System error: the C Preprocessor 'cpp' not found, cannot parse lowercase! Exiting..."
		ELSE
			EPRINT "System error: the C Preprocessor 'cpp' not found on this system! Exiting..."
		ENDIF
		END 1
	END IF
ELSE
	FEED$ = g_SOURCEFILE$
END IF
' Set current filename
LET g_CURFILE$ = g_SOURCEFILE$

' Initialize
LET total$ = ""
LET g_COUNTER = 1
LET g_TOTAL_LINES = 0

' Read source program
OPEN FEED$ FOR READING AS g_SOURCEFILE

' Start walking through program
PRINT "\rConverting '", g_SOURCEFILE$, "'... ";

REPEAT
	IF NOT(g_QUIET) THEN PRINT "\rConverting '", g_SOURCEFILE$, "'... ", g_COUNTER, EL$;

	READLN line$ FROM g_SOURCEFILE

	' Line is not empty?
	IF LEN(line$) > 0 THEN

		IF RIGHT$(line$, 1) = CR$ THEN
			EPRINT "\nSystem error: Windows file detected! Remove non-Unix CR line separators first. Exiting..."
			END 1
		ELIF RIGHT$(line$, 2) = " \\" AND LEFT$(line$, 3) != "REM" AND LEFT$(line$, 1) != CHR$(39) THEN
			total$ = total$ & LEFT$(line$, LEN(line$) - 2)
		ELSE
			total$ = CHOP$(total$ & line$)
			IF LEFT$(total$, 3) != "REM" AND LEFT$(total$, 1) != CHR$(39) THEN
				WRITELN "#undef __b2c_lineno" TO g_CFILE
				WRITELN "#define __b2c_lineno ", g_COUNTER TO g_CFILE
				WRITELN "#undef __b2c_lineno" TO g_HFILE
				WRITELN "#define __b2c_lineno ", g_COUNTER TO g_HFILE
				Tokenize(total$)
			END IF
			LET total$ = ""
		END IF
	ENDIF

	INCR g_COUNTER
UNTIL ENDFILE(g_SOURCEFILE)

IF g_DEBUG = 1 THEN Debug_Vars

CLOSE FILE g_SOURCEFILE

' Finalize main C-file
IF g_CATCH_USED = 1 THEN 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

' Create generic headerfile, functions are converted using macros
OPEN g_GENERIC$ FOR WRITING AS g_GENERIC
WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - MIT License */" TO g_GENERIC
WRITELN "#include <stdio.h>" TO g_GENERIC
WRITELN "#include <stdlib.h>" TO g_GENERIC
WRITELN "#include <stdarg.h>" TO g_GENERIC
WRITELN "#include <stdint.h>" TO g_GENERIC
WRITELN "#include <libgen.h>" TO g_GENERIC
WRITELN "#include <limits.h>" TO g_GENERIC
WRITELN "#include <float.h>" TO g_GENERIC
WRITELN "#include <sys/time.h>" TO g_GENERIC
WRITELN "#include <sys/stat.h>" TO g_GENERIC
WRITELN "#include <sys/types.h>" TO g_GENERIC
WRITELN "#include <sys/wait.h>" TO g_GENERIC
WRITELN "#include <sys/socket.h>" TO g_GENERIC
WRITELN "#include <sys/utsname.h>" TO g_GENERIC
WRITELN "#include <sys/ioctl.h>" TO g_GENERIC
WRITELN "#include <dirent.h>" TO g_GENERIC
WRITELN "#include <setjmp.h>" TO g_GENERIC
WRITELN "#include <netdb.h>" TO g_GENERIC
IF INSTR(OS$, "BSD") THEN
	WRITELN "#include <netinet/in.h>" TO g_GENERIC
	WRITELN "#define strcat(x, y) __b2c_strlcat(x, y)" TO g_GENERIC
	WRITELN "#define strcpy(x, y) __b2c_strlcpy(x, y)" TO g_GENERIC
ENDIF
WRITELN "#include <arpa/inet.h>" TO g_GENERIC
WRITELN "#include <signal.h>" TO g_GENERIC
IF LEN(g_PRAGMA_REGEX$) THEN
	IF NOT(REGEX(g_PRAGMA_REGEX$, " INCLUDE ")) THEN
		kwd$ = HEAD$(g_PRAGMA_REGEX$, 1)
		IF INSTR(kwd$, "tre") THEN
			WRITELN "#include <tre/regex.h>" TO g_GENERIC
		ELIF INSTR(kwd$, "pcre") THEN
			WRITELN "#include <pcreposix.h>" TO g_GENERIC
		ELIF INSTR(kwd$, "onig") THEN
			WRITELN "#include <onigposix.h>" TO g_GENERIC
		ENDIF
	ELSE
		kwd$ = MID$(g_PRAGMA_REGEX$, INSTR(g_PRAGMA_REGEX$, " INCLUDE ")+9)
		WRITELN "#include ", HEAD$(kwd$, 1) TO g_GENERIC
	ENDIF
ELSE
	WRITELN "#include <regex.h>" TO g_GENERIC
ENDIF
WRITELN "#include <fcntl.h>" TO g_GENERIC
WRITELN "#include <math.h>" TO g_GENERIC
WRITELN "#include <unistd.h>" TO g_GENERIC
WRITELN "#include <string.h>" TO g_GENERIC
WRITELN "#include <ctype.h>" TO g_GENERIC
WRITELN "#include <wctype.h>" TO g_GENERIC
WRITELN "#include <locale.h>" TO g_GENERIC
WRITELN "#include <dlfcn.h>" TO g_GENERIC
WRITELN "#include <errno.h>" TO g_GENERIC
WRITELN "#include <termios.h>" TO g_GENERIC
WRITELN "#include <time.h>" TO g_GENERIC
' Add user include files
FOR tmpfile$ IN g_INCFILES$
	IF INSTR(tmpfile$, "<") THEN
		WRITELN "#include ", tmpfile$ TO g_GENERIC
	ELSE
		WRITELN "#include ", CHR$(34), tmpfile$, CHR$(34) TO g_GENERIC
	ENDIF
NEXT
WRITELN "/* Undefine all symbols which happen to be BaCon keywords */" TO g_GENERIC
FOR kwd$ IN Stat$ STEP "|"
	WRITELN "#undef ", kwd$ TO g_GENERIC
NEXT
FOR kwd$ IN EXTRACT$(Func$, "\\") STEP "|"
	IF RIGHT$(kwd$, 1) <> "$" THEN WRITELN "#undef ", kwd$ TO g_GENERIC
NEXT
FOR kwd$ IN EXTRACT$(Var$, "\\") STEP "|"
	IF RIGHT$(kwd$, 1) <> "$" AND kwd$ <> "NULL" THEN WRITELN "#undef ", kwd$ TO g_GENERIC
NEXT
WRITELN "#undef REM" TO g_GENERIC

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

CLOSE FILE g_GENERIC

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

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.binary.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "unsigned long __b2c__bit(long x) { return(x ? 2<<(x-1) : 1); } unsigned long __b2c__rol(int type, long x)" TO g_CTEMP
	WRITELN "{ return((x)&lrint(pow(2, type*8-1)) ? (((x)<<1)|1)&lrint(pow(2, type*8)-1) : ((x)<<1)&lrint(pow(2, type*8)-1)); }" TO g_CTEMP
	WRITELN "unsigned long __b2c__ror(int type, long x) { return((x)&1 ? (((x)>>1)&lrint(pow(2, type*8)-1))|lrint(pow(2, type*8-1)) : ((x)>>1)&lrint(pow(2, type*8)-1)); }" TO g_CTEMP
	WRITELN "char *__b2c__bin(int type, long x) { long idx, i; idx = __sbuf_malloc_handle (type*8+1); for(i = 0; i<type*8; i++)" TO g_CTEMP
	WRITELN "{ if(x&1) { __b2c__sbuffer[idx][type*8-1-i] = 49; } else { __b2c__sbuffer[idx][type*8-1-i] = 48; } x = x>>1; }" TO g_CTEMP
	WRITELN " __b2c__sbuffer[idx][type*8] = '\\0'; __b2c__SETLEN (__b2c__sbuffer[idx], type*8); return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.binary.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.binary.o: bacon.binary.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.binary.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.chop.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__chop (char *source, ...) { char *tmp, *string; long i, length, idx, location = 0; va_list ap; if (source == NULL || __b2c__len(source) == 0)" TO g_CTEMP
	WRITELN "{ return (source); } va_start (ap, source); string = va_arg (ap, char *); if (string == 0){string = (char *) __b2c__chop_default;} else { location = va_arg (ap, int); }" TO g_CTEMP
	WRITELN "va_end (ap); length = __b2c__len(string); if (location == 0 || location == 1) { while (*source != '\\0') { for (i = 0; i < length; i++) { if (*source == *(string + i))" TO g_CTEMP
	WRITELN "{ source++; break; } } if (i == length) { break; } } if (*source == '\\0') return (EmptyString); } tmp = source + strlen(source) - 1; if (location == 0 || location == 2)" TO g_CTEMP
	WRITELN "{ while (tmp >= source && *tmp != '\\0') { for (i = 0; i < length; i++) { if (*tmp == *(string + i)) { tmp--; break; } } if (i == length) { break; } } } tmp++; idx = __sbuf_malloc_handle (tmp-source + 1);" TO g_CTEMP
	WRITELN "memmove (__b2c__sbuffer[idx], source, tmp-source); __b2c__SETLEN (__b2c__sbuffer[idx], tmp-source); __b2c__sbuffer[idx][tmp-source] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.chop.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.chop.o: bacon.chop.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.chop.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.chr.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__asc2char (int i) { long idx; int len; idx = __sbuf_malloc_handle(2); len = snprintf (__b2c__sbuffer[idx], 2, \"%c\", i);" TO g_CTEMP
	WRITELN "__b2c__SETLEN(__b2c__sbuffer[idx], len); return(char*)(__b2c__sbuffer[idx]); }" TO g_CTEMP
	WRITELN "char * __b2c__asc2utf8 (int i) { long idx; int len; char buf[5]; len = __b2c_utf8_conv(i, buf); idx = __sbuf_malloc_handle (len+1); memcpy (__b2c__sbuffer[idx], buf, len);" TO g_CTEMP
	WRITELN "__b2c__SETLEN (__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	WRITELN "unsigned int __b2c__utf8toasc(char* ptr) { unsigned int result = 0; if((*ptr&0xF0)==0xF0) { result = (*ptr&0x07)<<2; ptr++; result = result | ((*ptr&0x30)>>4); result = result << 8; result = result | ((*ptr&0x0F)<<4);" TO g_CTEMP
	WRITELN "ptr++; result = result | ((*ptr&0x3C)>>2); result = result << 8; result = result | ((*ptr&0x03)<<6); ptr++; result = result | (*ptr&0x3F); } else if((*ptr&0xE0)==0xE0) { result = (*ptr&0x0F)<<4; ptr++;" TO g_CTEMP
	WRITELN "result = result | ((*ptr&0x3C)>>2); result = result << 8; result = result | ((*ptr&0x03)<<6); ptr++; result = result | (*ptr&0x3F); } else if((*ptr&0xC0)==0xC0) { result = (*ptr&0x1C)>>2; result = result << 8;" TO g_CTEMP
	WRITELN "result = result | ((*ptr&0x03)<<6); ptr++; result = result | (*ptr&0x3F); } else if((*ptr&0x80) == 0) { result = (*ptr&0x7F); } return (result); }" TO g_CTEMP
	WRITELN "unsigned char __b2c__isascii(const char *ptr) { long x; for(x=0; *(ptr+x); x++) { if(*(ptr+x)&128) return(0); } return(1); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.chr.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.chr.o: bacon.chr.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.chr.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.cmdline.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "int __b2c__getopt(int argc, char **argv, char* str){int opt; opterr = 0; opt = getopt(argc, argv, str); __b2c__STRFREE(ARGUMENT", g_STRINGSIGN$, ");" TO g_CTEMP
	WRITELN "if(opt != -1) ARGUMENT", g_STRINGSIGN$, " = __b2c__strdup(optarg); else ARGUMENT", g_STRINGSIGN$, " = argv[optind]; return(opt);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.cmdline.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.cmdline.o: bacon.cmdline.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.cmdline.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.concat.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__concat (char *first, ...) { long length = 0, cnew, idx; char *next; va_list ap; if (first != NULL && (length = __b2c__len(first)) > 0)" TO g_CTEMP
	WRITELN "{ idx = __sbuf_malloc_handle (length + 1); memmove (__b2c__sbuffer[idx], first, length + 1); }" TO g_CTEMP
	WRITELN "else { idx = __sbuf_malloc_handle(sizeof (char)); __b2c__sbuffer[idx][0] = '\\0';} va_start (ap, first);" TO g_CTEMP
	WRITELN "while ((next = va_arg (ap, char *)) != NULL) { cnew = __b2c__len(next); __sbuf_need_realloc (idx, length + cnew + 1);" TO g_CTEMP
	WRITELN "memmove(__b2c__sbuffer[idx] + length, next, cnew); length += cnew; } va_end (ap);" TO g_CTEMP
	WRITELN "__b2c__SETLEN(__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.concat.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.concat.o: bacon.concat.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.concat.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.count.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__count (int l, char *k, char *x, unsigned int y) { long i, z = 0; if (__b2c__option_utf8) { while (*x) { if (__b2c__utf8toasc (x) == y) { z++; } if ((*x & 0xF0) == 0xF0) { x += 4; }" TO g_CTEMP
	WRITELN "else if ((*x & 0xE0) == 0xE0) { x += 3; } else if ((*x & 0xC0) == 0xC0) { x += 2; } else if ((*x & 0x80) == 0) { x++; } else { ERROR = 38; RUNTIMEFERR (\"COUNT\", ERROR, k, l); } } } else " TO g_CTEMP
	WRITELN "{ for (i = 0; x[i] != '\\0'; i++) { if (x[i] == y) { z++; } } } return z; }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.count.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.count.o: bacon.count.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.count.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.curdir.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__curdir (void) { long idx; idx = __sbuf_malloc_handle(", g_BUFFER_SIZE, "); __b2c__sbuffer[idx] = getcwd(__b2c__sbuffer[idx], ", g_BUFFER_SIZE, ");" TO g_CTEMP
	WRITELN "__b2c__SETLEN(__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); __b2c__sbuffer[idx][", g_BUFFER_SIZE, "-1] = '\\0'; return(char*)(__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.curdir.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.curdir.o: bacon.curdir.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.curdir.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.datename.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char* __b2c__datename (time_t now, int which) { struct tm *ts; long idx; int len; idx = __sbuf_malloc_handle (", g_MAX_DIGITS, "); ts = localtime (&now);" TO g_CTEMP
	WRITELN "switch (which) { case 1: len = strftime (__b2c__sbuffer[idx], ", g_MAX_DIGITS, ", \"%A\", ts); break; case 2: len = strftime (__b2c__sbuffer[idx], ", g_MAX_DIGITS, ", \"%B\", ts); break; }" TO g_CTEMP
	WRITELN "__b2c__SETLEN(__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.datename.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.datename.o: bacon.datename.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.datename.c"
	CLOSE FILE g_CTEMP

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

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

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.epoch.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "unsigned long __b2c__epoch(int year, int month, int day, int hour, int minute, int second){struct tm tm; time_t t; tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day;" TO g_CTEMP
	WRITELN "tm.tm_hour = hour; tm.tm_min = minute; tm.tm_sec = second; tm.tm_isdst = -1; t = mktime(&tm); if (t == -1) return (0); return(long) t; }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.epoch.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.epoch.o: bacon.epoch.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.epoch.c"
	CLOSE FILE g_CTEMP

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

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

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

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.filelen.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__filelen(int l, char *k, const char *x) {struct stat buf; if(stat(x, &buf) < 0 && __b2c__trap){ERROR = 24; RUNTIMEFERR(\"FILELEN\", ERROR, k, l);}" TO g_CTEMP
	WRITELN "if(x == NULL || stat(x, &buf) < 0) return -1; else return(long)(buf.st_size);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.filelen.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.filelen.o: bacon.filelen.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.filelen.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.filetime.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__filetime(int l, char *k, const char *x, int y) {struct stat buf; if(stat(x, &buf) < 0 && __b2c__trap){ERROR = 24; RUNTIMEFERR(\"FILETIME\", ERROR, k, l);}" TO g_CTEMP
	WRITELN "if(x == NULL || stat(x, &buf) < 0 || y < 0 || y > 2) return -1; switch(y) {case 0: return(long)(buf.st_atime); break;" TO g_CTEMP
	WRITELN "case 1: return(long)(buf.st_mtime); break;} return(long)(buf.st_ctime);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.filetime.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.filetime.o: bacon.filetime.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.filetime.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.filetype.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__filetype(int l, char *k, const char *x) {long fs = 0; struct stat buf; if(x == NULL) return 0; if(lstat(x, &buf) < 0 && __b2c__trap)" TO g_CTEMP
	WRITELN "{ERROR = 24; RUNTIMEFERR(\"FILETYPE\", ERROR, k, l);} if (S_ISREG(buf.st_mode)) fs = 1; if (S_ISDIR(buf.st_mode)) fs = 2;" TO g_CTEMP
	WRITELN "if (S_ISCHR(buf.st_mode)) fs = 3; if (S_ISBLK(buf.st_mode)) fs = 4; if (S_ISFIFO(buf.st_mode)) fs = 5;" TO g_CTEMP
	WRITELN "if (S_ISLNK(buf.st_mode)) fs = 6; if (S_ISSOCK(buf.st_mode)) fs = 7; return(fs);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.filetype.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.filetype.o: bacon.filetype.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.filetype.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.fill.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__fill (unsigned long amount, unsigned int txt) { long idx; char buf[5]; int x, len; if (__b2c__option_utf8) { len = __b2c_utf8_conv (txt, buf); idx = __sbuf_malloc_handle (amount * len + 1);" TO g_CTEMP
	WRITELN "for (x = 0; x < (amount * len); x += len) { memcpy (__b2c__sbuffer[idx] + x, buf, len); } __b2c__SETLEN (__b2c__sbuffer[idx], amount * len); __b2c__sbuffer[idx][amount * len] = '\\0'; } else" TO g_CTEMP
	WRITELN "{ idx = __sbuf_malloc_handle (amount + 1); memset (__b2c__sbuffer[idx], txt, amount); __b2c__SETLEN (__b2c__sbuffer[idx], amount); __b2c__sbuffer[idx][amount] = '\\0'; } return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.fill.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.fill.o: bacon.fill.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.fill.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.flatten.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char *__b2c__flatten(char *src, ...) { char quote[] = { 34, 0 }; long len, x, pos=0, escaped=0, idx; char *meta; va_list ap; if(src == NULL) return(src);" TO g_CTEMP
	WRITELN "va_start (ap, src); meta = va_arg (ap, char *); va_end (ap); if (meta == NULL) { meta = quote; } len = __b2c__len(src); idx = __sbuf_malloc_handle(len + 1);" TO g_CTEMP
	WRITELN "memmove(__b2c__sbuffer[idx], src, len); __b2c__sbuffer[idx][len] = '\\0'; for(x = 0; src[x] != 0; x++) { if(src[x] == meta[0]) { if(!escaped) { memmove(__b2c__sbuffer[idx]+pos, src+x+1, len-x-1); }" TO g_CTEMP
	WRITELN "else { pos++; escaped = 0; } } else { switch(src[x]) { case 92: if(!escaped) { memmove(__b2c__sbuffer[idx]+pos, src+x+1, len-x-1); escaped = 1; } else {pos++;} break;" TO g_CTEMP
	WRITELN "default: pos++; escaped = 0; } } } __b2c__SETLEN (__b2c__sbuffer[idx], pos); __b2c__sbuffer[idx][pos] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	WRITELN "char * __b2c__unflatten (char *src, ...) { char quote[] = { 34, 0 }; long x, pos = 1, idx; char *meta; va_list ap; if (src == NULL) return (src); va_start (ap, src);" TO g_CTEMP
	WRITELN "meta = va_arg (ap, char *); va_end (ap); if (meta == NULL) { meta = quote; } idx = __sbuf_malloc_handle (2*__b2c__len (src) + 1); __b2c__sbuffer[idx][0] = meta[0];" TO g_CTEMP
	WRITELN "for (x = 0; src[x] != 0; x++) { if (src[x] == meta[0]) { __b2c__sbuffer[idx][pos++] = 92; __b2c__sbuffer[idx][pos++] = src[x]; }" TO g_CTEMP
	WRITELN "else {__b2c__sbuffer[idx][pos++] = src[x];} } __b2c__sbuffer[idx][pos++] = meta[0]; __b2c__SETLEN (__b2c__sbuffer[idx], pos);" TO g_CTEMP
	WRITELN "__b2c__sbuffer[idx][pos] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.flatten.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.flatten.o: bacon.flatten.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.flatten.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.getenviron.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__getenv (char *env) {char *tmp; long idx; idx = __sbuf_malloc_handle (", g_BUFFER_SIZE, " * sizeof (char)); tmp = getenv (env); if (tmp == NULL) { return (EmptyString); }" TO g_CTEMP
	WRITELN "else { strncpy (__b2c__sbuffer[idx], tmp, ", g_BUFFER_SIZE, "); } __b2c__SETLEN (__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); __b2c__sbuffer[idx][", g_BUFFER_SIZE, "-1] = '\\0'; return (char*)(__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.getenviron.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.getenviron.o: bacon.getenviron.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.getenviron.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.getkey.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__getch(){long ch; struct termios oldt, newt; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); newt.c_cc[VMIN]=1;" TO g_CTEMP
	WRITELN "newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &newt); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); return(ch);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.getkey.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.getkey.o: bacon.getkey.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.getkey.c"
	CLOSE FILE g_CTEMP

	IF INSTR(OS$, "OSF1") THEN
		line$ = "int"
	ELSE
		line$ = "unsigned int"
	ENDIF
	g_CTEMP$ = g_TEMPDIR$ & "/bacon.getpeer.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__getpeer(int l, char *k, int remote) { struct sockaddr_in *peer; ", line$, " length = sizeof (peer); char port[6]; long idx; idx = __sbuf_malloc_handle(", g_BUFFER_SIZE, "*sizeof(char)); peer = (struct sockaddr_in*)calloc (1, sizeof (*peer));" TO g_CTEMP
	WRITELN "if (getpeername (remote, (struct sockaddr *) peer, &length) < 0) { if (__b2c__trap) { ERROR = 16; RUNTIMEFERR(\"GETPEER$\", ERROR, k, l); } else strncpy (__b2c__sbuffer[idx], \"Peer not found\", ", g_BUFFER_SIZE, "); }" TO g_CTEMP
	WRITELN "else { strncpy (__b2c__sbuffer[idx], inet_ntoa (peer->sin_addr), ", g_BUFFER_SIZE, "-7); strcat (__b2c__sbuffer[idx], \":\"); snprintf (port, 6, \"%d\", ntohs (peer->sin_port)); strcat (__b2c__sbuffer[idx], port); }" TO g_CTEMP
	WRITELN "free (peer); __b2c__SETLEN (__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); __b2c__sbuffer[idx][", g_BUFFER_SIZE, "-1] = '\\0'; return (char*)(__b2c__sbuffer[idx]);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.getpeer.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.getpeer.o: bacon.getpeer.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.getpeer.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.getxy.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__getxy(int type){char asw[", g_BUFFER_SIZE, "]; struct termios old, cnew; int len, x = 0, y = 0; tcgetattr(STDIN_FILENO, &old); cnew = old; cnew.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &cnew);" TO g_CTEMP
	WRITELN "if(write(STDOUT_FILENO, \"\\033[6n\", 4)>=0){len = read(STDIN_FILENO, asw, ", g_BUFFER_SIZE, "); asw[len] = '\\0'; tcsetattr(STDIN_FILENO, TCSANOW, &old); sscanf(asw, \"\\033[%d;%dR\", &y, &x);} if (!type) return(long)x; return(long)y;}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.getxy.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.getxy.o: bacon.getxy.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.getxy.c"
	CLOSE FILE g_CTEMP

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

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.hex.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__dec2hex (int nr) { long idx; int len; idx = __sbuf_malloc_handle(", g_MAX_DIGITS, "); len = snprintf (__b2c__sbuffer[idx], ", g_MAX_DIGITS, ", \"%X\", nr);" TO g_CTEMP
	WRITELN "__b2c__SETLEN (__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\\0'; return (char *) (__b2c__sbuffer[idx]);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.hex.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.hex.o: bacon.hex.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.hex.c"
	CLOSE FILE g_CTEMP

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

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.hostname.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char *__b2c__hostname(int l, char *k) { long idx; idx = __sbuf_malloc_handle (", g_BUFFER_SIZE, " * sizeof (char)); if(gethostname(__b2c__sbuffer[idx], ", g_BUFFER_SIZE, "))" TO g_CTEMP
	WRITELN "{ if (__b2c__trap) { ERROR = 26; RUNTIMEFERR(\"HOSTNAME$\", ERROR, k, l); } else strncpy (__b2c__sbuffer[idx], \"Error getting hostname\", ", g_BUFFER_SIZE, "); }" TO g_CTEMP
	WRITELN "__b2c__SETLEN(__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); __b2c__sbuffer[idx][", g_BUFFER_SIZE, "-1] = '\\0'; return (char*)(__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.hostname.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.hostname.o: bacon.hostname.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.hostname.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.inbetween.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char* __b2c__inbetween(int flag, char *haystack, char *lm, char *rm, ...) { char *l, *r, *pos, *org; int greedy = 0; long idx, len; va_list ap; va_start (ap, rm);" TO g_CTEMP
	WRITELN "greedy = va_arg (ap, int); va_end (ap); if (haystack == NULL || lm == NULL || rm == NULL) { return (EmptyString); } l = strstr (haystack, lm); if (l == NULL)" TO g_CTEMP
	WRITELN "{ return (EmptyString); } org = haystack; haystack = l + strlen(lm); if (greedy == 0) { pos = strstr (haystack, rm); if (pos == NULL) { return (EmptyString); } }" TO g_CTEMP
	WRITELN "else { pos = NULL; while (1) { r = strstr (haystack, rm); if (r) { pos = r; haystack = r + strlen (rm); } else { break; } } if (pos == NULL) { return (EmptyString); } }" TO g_CTEMP
	WRITELN "if(flag) { pos += strlen (rm); len = strlen(pos); idx = __sbuf_malloc_handle ((l-org) + len + 1); memmove(__b2c__sbuffer[idx], org, l-org); memmove(__b2c__sbuffer[idx]+(l-org), pos, len);" TO g_CTEMP
	WRITELN "__b2c__SETLEN (__b2c__sbuffer[idx], (l-org) + len); __b2c__sbuffer[idx][(l-org) + len] = '\\0'; } else { l += strlen (lm); idx = __sbuf_malloc_handle (pos - l + 1);" TO g_CTEMP
	WRITELN "memmove(__b2c__sbuffer[idx], l, pos - l); __b2c__SETLEN (__b2c__sbuffer[idx], pos - l); __b2c__sbuffer[idx][pos - l] = '\\0'; } return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.inbetween.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.inbetween.o: bacon.inbetween.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.inbetween.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.insert.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__insert (int l, char *k, char *src, int pos, char *str) { long len, tot, idx, blen; if (src == NULL || str == NULL) { return (src); } len = __b2c__len (src); tot = __b2c__len (str);" TO g_CTEMP
	WRITELN "idx = __sbuf_malloc_handle (len + tot + 1); pos--; if (pos <= 0) { memmove (__b2c__sbuffer[idx], str, tot); memmove (__b2c__sbuffer[idx] + tot, src, len); } else if (pos > len) { memmove (__b2c__sbuffer[idx], src, len);" TO g_CTEMP
	WRITELN "memmove (__b2c__sbuffer[idx] + len, str, tot); } else { if (__b2c__option_utf8) { blen = __b2c__blen (l, k, \"INSERT$\", src, pos, 0); memmove (__b2c__sbuffer[idx], src, blen); memmove (__b2c__sbuffer[idx] + blen, str, tot);" TO g_CTEMP
	WRITELN "memmove (__b2c__sbuffer[idx] + blen + tot, src + blen, len - blen); } else { memmove (__b2c__sbuffer[idx], src, pos); memmove (__b2c__sbuffer[idx] + pos, str, tot); memmove (__b2c__sbuffer[idx] + pos + tot, src + pos, len - pos); } }" TO g_CTEMP
	WRITELN "__b2c__SETLEN (__b2c__sbuffer[idx], len + tot); __b2c__sbuffer[idx][len + tot] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.insert.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.insert.o: bacon.insert.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.insert.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.instr.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__instr(int l, char *k, char *first, ...){char *tmp, *res; int pos; va_list ap; if(first == NULL) return(0); va_start(ap, first);tmp = va_arg(ap, char *); if(tmp == NULL || __b2c__len(tmp) == 0) return (0); pos = va_arg(ap, int);" TO g_CTEMP
	WRITELN "if(pos <= 0) pos = 1; va_end(ap); res = strstr(first + pos - 1, tmp); if(res == NULL) return (0); if(__b2c__option_utf8) { return (long) __b2c__ucs2_clen(l, k, \"INSTR\", first, res - first + 1); } return (long)(res - first + 1);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.instr.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.instr.o: bacon.instr.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.instr.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.instrrev.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__instrrev(int m, char *k, char *first, ...){char *tmp, *res = NULL, *found = NULL; long pos, l; va_list ap;if (first == NULL) return (0); va_start (ap, first); tmp = va_arg (ap, char *);" TO g_CTEMP
	WRITELN "if(tmp == NULL || __b2c__len(tmp) == 0) return (0); pos = va_arg (ap, int); if (pos < 0) pos = 0; va_end (ap); l = __b2c__len(first); found = first; do {res = strstr (found, tmp); if(res != NULL && res <= first + l - pos)" TO g_CTEMP
	WRITELN "{found = res + 1; continue;}if(res > first + l - pos) res = NULL;} while (res != NULL); if (__b2c__option_startpoint){if(l - (found - first)+1 > l) return 0; if (__b2c__option_utf8) { return (long) (__b2c__ulen(l, k, \"INSTRREV\", first, -1)-__b2c__ucs2_clen (l, k, \"INSTRREV\", first, found - first) + 1); }" TO g_CTEMP
	WRITELN "return (long)(l - (found - first)+1);} if (__b2c__option_utf8) { return (long) __b2c__ucs2_clen (m, k, \"INSTRREV\", first, found - first); } return (long)(found - first);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.instrrev.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.instrrev.o: bacon.instrrev.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.instrrev.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.lcase.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__lcase (int l, char *k, char *src) { long idx, len, i; size_t mbslen; wchar_t *wcs, *wp; char *local; if (src == NULL) { return (NULL); } len = __b2c__len (src); idx = __sbuf_malloc_handle (len + 1); if (__b2c__option_utf8)" TO g_CTEMP
	WRITELN "{ local = setlocale (LC_ALL, \"\"); if ((mbslen = mbstowcs (NULL, src, 0)) == (size_t) - 1) { ERROR = 38; RUNTIMEFERR (\"LCASE$\", ERROR, k, l); } wcs = (wchar_t*)calloc (mbslen + 1, sizeof (wchar_t)); if (mbstowcs (wcs, src, mbslen + 1) == (size_t) - 1)" TO g_CTEMP
	WRITELN "{ ERROR = 38; RUNTIMEFERR (\"LCASE$\", ERROR, k, l); } for (wp = wcs; *wp != 0; wp++) { *wp = towlower (*wp); } if (wcstombs (__b2c__sbuffer[idx], wcs, len) == (size_t) - 1) { ERROR = 38; RUNTIMEFERR (\"LCASE$\", ERROR, k, l); } free (wcs);" TO g_CTEMP
	WRITELN "setlocale (LC_ALL, local); } else { for (i = 0; i < len; i++) { __b2c__sbuffer[idx][i] = tolower (src[i]); } } __b2c__SETLEN (__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.lcase.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.lcase.o: bacon.lcase.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.lcase.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.left.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__left (int l, char *k, char *src, long n) { long length, idx; if (src == NULL) { return (NULL); } length = __b2c__len (src); if (n > (__b2c__option_utf8 ? __b2c__ucs2_clen (l, k, \"LEFT$\", src, length) : length) || n < 0)" TO g_CTEMP
	WRITELN "{ idx = __sbuf_malloc_handle (length + 1); memmove (__b2c__sbuffer[idx], src, length); __b2c__SETLEN (__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\\0'; } else { if (__b2c__option_utf8) { n = __b2c__blen (l, k, \"LEFT$\", src, n, 0); }" TO g_CTEMP
	WRITELN "idx = __sbuf_malloc_handle (n + 1); memmove (__b2c__sbuffer[idx], src, n); __b2c__SETLEN (__b2c__sbuffer[idx], n); __b2c__sbuffer[idx][n] = '\\0'; } return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.left.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.left.o: bacon.left.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.left.c"
	CLOSE FILE g_CTEMP

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

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.makedir.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "int __b2c__makedir (char *in) { char *i, *dir; if (in == NULL || __b2c__len (in) == 0) { return 0; } if (*in != '/') { dir = (char*)calloc(__b2c__len(in) + 3, sizeof (char)); strncpy (dir, \"./\", 2); strcat (dir, in); }" TO g_CTEMP
	WRITELN "else { dir = strdup (in); } i = dir; do { i++; while (*i != '/' && *i != '\\0') i++; if (*i == '/') { *i = '\\0'; mkdir (dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); *i = '/'; } else if (*i == '\\0')" TO g_CTEMP
	WRITELN "mkdir (dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); if (errno != EEXIST && errno != 0) { free (dir); return errno; } } while (*i != '\\0'); free (dir); return 0; }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.makedir.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.makedir.o: bacon.makedir.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.makedir.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.malloc.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "void *__rbuf_realloc(void *__b2c__ptr, size_t __b2c__size){if(__b2c__rbuffer_length[__b2c__rbuffer_ptr] < __b2c__size)" TO g_CTEMP
	WRITELN "{__b2c__rbuffer_length[__b2c__rbuffer_ptr] = (size_t)__b2c__size*4; return(realloc(__b2c__ptr, __b2c__rbuffer_length[__b2c__rbuffer_ptr]));} return(__b2c__ptr);}" TO g_CTEMP
	WRITELN "void __sbuf_need_realloc (long idx, size_t size) { if (__b2c__sbuffer[idx] == NULL) { __b2c__sbuffer[idx] = (char*)calloc(__b2c__BUFOFFSET + size*2 + 1, sizeof(char));" TO g_CTEMP
	WRITELN "*(uint32_t *) (__b2c__sbuffer[idx] + 4) = size * 2 + 1; *(uint8_t*)(__b2c__sbuffer[idx] + 8) = 1; __b2c__SETRANGE(__b2c__sbuffer[idx]); __b2c__sbuffer[idx]+=__b2c__BUFOFFSET; }" TO g_CTEMP
	WRITELN "else if (__b2c__buf (__b2c__sbuffer[idx]) <= size) { __b2c__sbuffer[idx] = (char*)realloc (__b2c__sbuffer[idx] - __b2c__BUFOFFSET, __b2c__BUFOFFSET + size * 2 + 1);" TO g_CTEMP
	WRITELN "*(uint32_t *) (__b2c__sbuffer[idx] + 4) = size * 2 + 1; *(uint8_t*)(__b2c__sbuffer[idx] + 8) = 1; __b2c__SETRANGE(__b2c__sbuffer[idx]); __b2c__sbuffer[idx]+=__b2c__BUFOFFSET; } }" TO g_CTEMP
	WRITELN "long __sbuf_malloc_handle (size_t size) {__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr>=__b2c__sbuffer_size) __b2c__sbuffer_ptr=0; __sbuf_need_realloc (__b2c__sbuffer_ptr, size); return(__b2c__sbuffer_ptr); }" TO g_CTEMP
	WRITELN "char *__b2c__strdup (const char *s) { if (s == NULL) { return (NULL); } return (strdup (s)); }" TO g_CTEMP
	WRITELN "char *__b2c__strndup (const char *s, size_t n) { char *cnew; if (s == NULL) { return (NULL); } cnew = (char*)malloc(n + 1); if(cnew == NULL) return(NULL); cnew[n] = '\\0'; return (char*)strncpy(cnew, s, n); }" TO g_CTEMP
	WRITELN "int __b2c__strcmp(const char *__b2c__s1, const char *__b2c__s2){if(__b2c__s1 == NULL && __b2c__s2 == NULL) return 0;" TO g_CTEMP
	WRITELN "if(__b2c__s1 == NULL) __b2c__s1 = EmptyString; if(__b2c__s2 == NULL) __b2c__s2 = EmptyString; return(strcmp(__b2c__s1, __b2c__s2));}" TO g_CTEMP
	WRITELN "int __b2c__strcasecmp(const char *__b2c__s1, const char *__b2c__s2){if(__b2c__s1 == NULL && __b2c__s2 == NULL) return 0;" TO g_CTEMP
	WRITELN "if(__b2c__s1 == NULL)return(-1); if(__b2c__s2 == NULL)return(1); return(strcasecmp(__b2c__s1, __b2c__s2));}" TO g_CTEMP
	WRITELN "void *__b2c_str_realloc(char *ptr, size_t size) { if (ptr == NULL || __b2c__buf((char*)ptr) <= size) { if ((long) ptr & 1)" TO g_CTEMP
	WRITELN "{ ptr = (char*)realloc(ptr - __b2c__BUFOFFSET, __b2c__BUFOFFSET + size * 2 + 1); } else { ptr = (char*)realloc(ptr, __b2c__BUFOFFSET + size * 2 + 1); }" TO g_CTEMP
	WRITELN "*(uint32_t *) ((char*)ptr + 4) = size * 2 + 1; *(uint8_t *) ((char*)ptr + 8) = 0; __b2c__SETRANGE (ptr); ptr += __b2c__BUFOFFSET; } return(ptr); }" TO g_CTEMP
	WRITELN "char *__b2c_Copy_String (char *x, char *y) { long ylen; if (x == NULL && y == NULL) return (NULL); if (y == NULL) { __b2c__STRFREE (x); return (NULL); } else" TO g_CTEMP
	WRITELN "{ ylen = __b2c__len (y); } x = (char*)__b2c_str_realloc(x, ylen); memmove (x, y, ylen+1); if ((long) x & 1) { __b2c__SETLEN (x, ylen); } x[ylen] = '\\0'; return (x); }" TO g_CTEMP
	WRITELN "char * __b2c_Assign_String (char **x, char *y) { char *tmp; if (*x != NULL && y != NULL && ((long)y&1) && __b2c__INRANGE(y)) { if(__b2c__IS_SBUF(y)) {" TO g_CTEMP
	WRITELN "tmp = *x; *x = y; __b2c__UNSETBIT(*x); __b2c__sbuffer[__b2c__sbuffer_ptr] = __b2c__topstring(tmp); __b2c__SETBIT(__b2c__sbuffer[__b2c__sbuffer_ptr]);" TO g_CTEMP
	WRITELN "return (*x); } } return (__b2c_Copy_String (*x, y)); }" TO g_CTEMP
	WRITELN "char * __b2c__topstring (char *ptr) { unsigned int len; if((long)ptr&1) { return ptr; } len = (ptr == NULL ? 0 : strlen (ptr)); ptr = (char*)realloc(ptr, __b2c__BUFOFFSET + len + 1);" TO g_CTEMP
	WRITELN "memset(ptr + len, 0, __b2c__BUFOFFSET+1); memmove(ptr + __b2c__BUFOFFSET, ptr, len + 1); *(uint32_t *) (ptr) = len; *(uint32_t *) (ptr + 4) = len + 1; __b2c__SETRANGE(ptr); return(ptr + __b2c__BUFOFFSET); }" TO g_CTEMP
	WRITELN "unsigned long __b2c__len (const char *ptr) { if (ptr == NULL) { return (0); } if (((long)ptr&1) && __b2c__INRANGE(ptr) && __b2c__VALID(ptr)) { return (*(uint32_t *) (ptr - __b2c__BUFOFFSET)); } return ((unsigned long) strlen (ptr)); }" TO g_CTEMP
	WRITELN "unsigned long __b2c__buf (const char *ptr) { if (ptr == NULL) { return (0); } if (((long)ptr&1) && __b2c__INRANGE(ptr)) { return (*(uint32_t *) (ptr - __b2c__BUFOFFSET + 4)); } return ((unsigned long) strlen (ptr)+1); }" TO g_CTEMP
	IF INSTR(OS$, "BSD") THEN
		WRITELN "char *__b2c_strlcat(char *dest, const char *src) { strlcat(dest, src, __b2c__len(dest)+__b2c__len(src)+1); return(dest); }" TO g_CTEMP
		WRITELN "char *__b2c_strlcpy(char *dest, const char *src) { strlcpy(dest, src, __b2c__len(src)+1); return(dest); }" TO g_CTEMP
	ENDIF
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.malloc.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.malloc.o: bacon.malloc.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.malloc.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.memcheck.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "void __b2c__catch_signal(int sig){" TO g_CTEMP
	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_CTEMP
	WRITELN "case SIGFPE: fprintf(stderr, \"ERROR: signal for FPE received - division by zero? Examine the calculations in the program.\\n\"); break;" TO g_CTEMP
	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_CTEMP
	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_CTEMP
	WRITELN "void __b2c__segv(int sig){longjmp(__b2c__jump, 1);}" TO g_CTEMP
	WRITELN "int __b2c__memory__check(volatile char* x, int size){int i, illegal = 0; void(*handler)(int); handler = signal(SIGSEGV, __b2c__segv);" TO g_CTEMP
	WRITELN "if(!setjmp(__b2c__jump)) {for(i = 0; i < size; i++) if(*(x+i)) continue;} else illegal = 1;" TO g_CTEMP
	WRITELN "if(__b2c__trap) signal(SIGSEGV, __b2c__catch_signal); else signal(SIGSEGV, handler); return(illegal);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.memcheck.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.memcheck.o: bacon.memcheck.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.memcheck.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.mid.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char *__b2c__mid (int l, char *k, char *src, ...) { long idx, src_len, pos, length; va_list ap; if (src == NULL) { return (EmptyString); } src_len = __b2c__len (src); va_start (ap, src); pos = va_arg (ap, int)-1;" TO g_CTEMP
	WRITELN "if (pos < 0) { pos = (__b2c__option_utf8 ? __b2c__ucs2_clen (l, k, \"MID$\", src, src_len) : src_len) + 1 + pos; } if(__b2c__option_utf8) { pos = __b2c__blen(l, k, \"MID$\", src, pos, 0); }" TO g_CTEMP
	WRITELN "if (pos > src_len) { return (EmptyString); } length = va_arg (ap, int); if(__b2c__option_utf8 && length >= 0) { length = __b2c__blen(l, k, \"MID$\", src+pos, length, 0); }" TO g_CTEMP
	WRITELN "if (length < 0 || pos + length > src_len) { length = src_len - pos; } idx = __sbuf_malloc_handle (length + 1); memmove (__b2c__sbuffer[idx], src + pos, length); __b2c__SETLEN (__b2c__sbuffer[idx], length);" TO g_CTEMP
	WRITELN "__b2c__sbuffer[idx][length] = '\\0'; va_end (ap); return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.mid.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.mid.o: bacon.mid.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.mid.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.minmax.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char* __b2c__min_str(char* x, char* y) {if(strcmp(x, y) < 0) { return(x); } return(y);}" TO g_CTEMP
	WRITELN "char* __b2c__max_str(char* x, char* y) {if(strcmp(x, y) > 0) { return(x); } return(y);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.minmax.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.minmax.o: bacon.minmax.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.minmax.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.os.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__os(int l, char *k) { struct utsname buf; long idx; idx = __sbuf_malloc_handle (", g_BUFFER_SIZE, "*sizeof (char));" TO g_CTEMP
	WRITELN "if (uname (&buf) < 0 && __b2c__trap) { ERROR = 26; RUNTIMEFERR(\"OS$\", ERROR, k, l); } strcpy (__b2c__sbuffer[idx], buf.sysname);" TO g_CTEMP
	WRITELN "strcat (__b2c__sbuffer[idx], \" \"); strcat (__b2c__sbuffer[idx], buf.machine); __b2c__SETLEN (__b2c__sbuffer[idx], strlen(__b2c__sbuffer[idx])); return (char*)(__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.os.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.os.o: bacon.os.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.os.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.peek.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "int __b2c__peek_check(int l, char *k, char* x, int size) {if(__b2c__trap) {if(__b2c__memory__check((char*)x, size)) {ERROR=1; RUNTIMEFERR(\"PEEK\", ERROR, k, l);} } return(0); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.peek.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.peek.o: bacon.peek.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.peek.c"
	CLOSE FILE g_CTEMP

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

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.reverse.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__reverse(int l, char *k, char *src) { long i, length, len, idx, blen; if (src == NULL) { return (EmptyString); } length = __b2c__len (src); idx = __sbuf_malloc_handle (length + 1);" TO g_CTEMP
	WRITELN "if(__b2c__option_utf8) { len = length; while (len > 0) { blen = __b2c__blen (l, k, \"REVERSE$\", src, 1, 0); memcpy (__b2c__sbuffer[idx] + len - blen, src, blen); src += blen; len -= blen; } } else" TO g_CTEMP
	WRITELN "{ for (i = 0; i < length; i++) { __b2c__sbuffer[idx][i] = src[length - i - 1]; } } __b2c__SETLEN (__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.reverse.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.reverse.o: bacon.reverse.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.reverse.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.right.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__right (int l, char *k, char *src, long n) { long length, idx; if (src == NULL) { return (NULL); } length = __b2c__len (src); if (n > (__b2c__option_utf8 ? __b2c__ucs2_clen (l, k, \"RIGHT$\", src, length) : length) || n < 0)" TO g_CTEMP
	WRITELN "{ idx = __sbuf_malloc_handle (length + 1); memmove (__b2c__sbuffer[idx], src, length); __b2c__SETLEN (__b2c__sbuffer[idx], length); __b2c__sbuffer[idx][length] = '\\0'; } else { if (__b2c__option_utf8) { n = __b2c__blen (l, k, \"RIGHT$\", src, n, 1); }" TO g_CTEMP
	WRITELN "idx = __sbuf_malloc_handle (n + 1); memmove (__b2c__sbuffer[idx], src + length - n, n); __b2c__SETLEN (__b2c__sbuffer[idx], n); __b2c__sbuffer[idx][n] = '\\0'; } return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.right.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.right.o: bacon.right.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.right.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.screen.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__screen(int type){long x; struct winsize tmp; ioctl(STDOUT_FILENO, TIOCGWINSZ, &tmp); if(type) { x = tmp.ws_row; } else { x = tmp.ws_col; } return(x); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.screen.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.screen.o: bacon.screen.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.screen.c"
	CLOSE FILE g_CTEMP

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

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.sort.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "int __b2c__sortnrd(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	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_CTEMP
	WRITELN "int __b2c__sortnrd_down(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	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_CTEMP
	WRITELN "int __b2c__sortnrf(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	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_CTEMP
	WRITELN "int __b2c__sortnrf_down(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	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_CTEMP
	WRITELN "int __b2c__sortnrl(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	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_CTEMP
	WRITELN "int __b2c__sortnrl_down(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	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_CTEMP
	WRITELN "int __b2c__sortnri(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	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_CTEMP
	WRITELN "int __b2c__sortnri_down(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	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_CTEMP
	WRITELN "int __b2c__sortnrs(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	WRITELN "{if (*(short*)__b2c__a==*(short*)__b2c__b) return 0; else if (*(short*)__b2c__a < *(short*)__b2c__b) return -1; else return 1;}" TO g_CTEMP
	WRITELN "int __b2c__sortnrs_down(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	WRITELN "{if (*(short*)__b2c__a==*(short*)__b2c__b) return 0; else if (*(short*)__b2c__a < *(short*)__b2c__b) return 1; else return -1;}" TO g_CTEMP
	WRITELN "int __b2c__sortnrc(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	WRITELN "{if (*(char*)__b2c__a==*(char*)__b2c__b) return 0; else if (*(char*)__b2c__a < *(char*)__b2c__b) return -1; else return 1;}" TO g_CTEMP
	WRITELN "int __b2c__sortnrc_down(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	WRITELN "{if (*(char*)__b2c__a==*(char*)__b2c__b) return 0; else if (*(char*)__b2c__a < *(char*)__b2c__b) return 1; else return -1;}" TO g_CTEMP
	WRITELN "int __b2c__sortstr(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	WRITELN "{if(*(char **)__b2c__a == NULL) return -1; if(*(char **)__b2c__b == NULL) return 1; return strcmp(*(char **) __b2c__a, *(char **) __b2c__b);}" TO g_CTEMP
	WRITELN "int __b2c__sortstr_down(const void *__b2c__a, const void *__b2c__b)" TO g_CTEMP
	WRITELN "{if(*(char **)__b2c__a == NULL) return -1; if(*(char **)__b2c__b == NULL) return 1; return strcmp(*(char **) __b2c__b, *(char **) __b2c__a);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.sort.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.sort.o: bacon.sort.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.sort.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.spc.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__spc (int amount) { long idx; idx = __sbuf_malloc_handle (amount + 1); memset (__b2c__sbuffer[idx], 32, amount);" TO g_CTEMP
	WRITELN "__b2c__SETLEN (__b2c__sbuffer[idx], amount); __b2c__sbuffer[idx][amount] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.spc.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.spc.o: bacon.spc.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.spc.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.str.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__str (double nr) {long idx; int len; idx = __sbuf_malloc_handle(", g_MAX_DIGITS, "); if (floor (nr) == nr) { len = snprintf(__b2c__sbuffer[idx], ", g_MAX_DIGITS, ", \"%ld\", (long) nr); }" TO g_CTEMP
	WRITELN "else { len = snprintf (__b2c__sbuffer[idx], ", g_MAX_DIGITS, ", \"%g\", (double) nr); } __b2c__SETLEN (__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\\0'; return(char*)(__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.str.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.str.o: bacon.str.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.str.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.sum.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__sum(int base, long *array, long nr, ...) { va_list ap; long limit = 0, total = 0; int x; va_start (ap, nr); limit = va_arg (ap, long); va_end (ap);" TO g_CTEMP
	WRITELN "for(x = base; x < nr+base; x++) { if(limit == LONG_MAX){ total += array[x]; } else { if(array[x]>limit) { total += array[x]; } } } return(total); }" TO g_CTEMP
	WRITELN "double __b2c__sumf(int base, double *array, double nr, ...) { va_list ap; double limit = 0, total = 0; int x; va_start (ap, nr); limit = va_arg (ap, double); va_end (ap);" TO g_CTEMP
	WRITELN "for(x = base; x < nr+base; x++) { if(limit == DBL_MAX){ total += array[x]; } else { if(array[x]>limit) { total += array[x]; } } } return(total); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.sum.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.sum.o: bacon.sum.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.sum.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.tab.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__tab (int amount) { long idx; idx = __sbuf_malloc_handle (amount + 1); memset(__b2c__sbuffer[idx], 9, amount);" TO g_CTEMP
	WRITELN "__b2c__SETLEN (__b2c__sbuffer[idx], amount); __b2c__sbuffer[idx][amount] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.tab.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.tab.o: bacon.tab.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.tab.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.tally.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__tally(char *haystack, ...) { char *needle, *res; int pos; long total = 0; va_list ap; if (haystack == NULL) return (0);" TO g_CTEMP
	WRITELN "va_start (ap, haystack); needle = va_arg (ap, char *); if (needle == NULL || __b2c__len(needle) == 0) return (0); pos = va_arg (ap, int); if (pos <= 0) pos = 1; va_end (ap);" TO g_CTEMP
	WRITELN "haystack+=pos-1; while((res = strstr(haystack, needle)) != NULL) { haystack = res+1; total++; } return (long) (total); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.tally.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.tally.o: bacon.tally.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.tally.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.time.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__time (time_t now, int which){ long result; char *buffer; struct tm *ts; buffer = (char*)calloc(", g_MAX_DIGITS, ", sizeof (char)); ts = localtime (&now); switch (which) {" TO g_CTEMP
	WRITELN "case 1: strftime (buffer, ", g_MAX_DIGITS, ", \"%d\", ts); break; case 2: strftime (buffer, ", g_MAX_DIGITS, ", \"%m\", ts); break; case 3: strftime (buffer, ", g_MAX_DIGITS, ", \"%Y\", ts); break;" TO g_CTEMP
	WRITELN "case 4: strftime (buffer, ", g_MAX_DIGITS, ", \"%H\", ts); break; case 5: strftime (buffer, ", g_MAX_DIGITS, ", \"%M\", ts); break; case 6: strftime (buffer, ", g_MAX_DIGITS, ", \"%S\", ts); break;" TO g_CTEMP
	WRITELN "case 7: strftime (buffer, ", g_MAX_DIGITS, ", \"%W\", ts); break; } result = atol(buffer); free(buffer); return(result); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.time.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.time.o: bacon.time.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.time.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.timer.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "unsigned long __b2c__timer(){struct timeval time; gettimeofday(&time, NULL); if(difftime(time.tv_sec, __b2c__elapsed_secs) < 1) return(unsigned long)((time.tv_usec-__b2c__elapsed_usecs)/1000);" TO g_CTEMP
	WRITELN "else return(unsigned long)((difftime(time.tv_sec, __b2c__elapsed_secs)-1)*1000+((1000000-__b2c__elapsed_usecs)+time.tv_usec)/1000);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.timer.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.timer.o: bacon.timer.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.timer.c"
	CLOSE FILE g_CTEMP

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

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.ucase.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__ucase (int l, char *k, char *src) { long idx, len, i; size_t mbslen; wchar_t *wcs, *wp; char *local; if (src == NULL) { return (NULL); } len = __b2c__len (src); idx = __sbuf_malloc_handle (len + 1); if (__b2c__option_utf8)" TO g_CTEMP
	WRITELN "{ local = setlocale (LC_ALL, \"\"); if ((mbslen = mbstowcs (NULL, src, 0)) == (size_t) - 1) { ERROR = 38; RUNTIMEFERR (\"UCASE$\", ERROR, k, l); } wcs = (wchar_t*)calloc (mbslen + 1, sizeof (wchar_t)); if (mbstowcs (wcs, src, mbslen + 1) == (size_t) - 1)" TO g_CTEMP
	WRITELN "{ ERROR = 38; RUNTIMEFERR (\"UCASE$\", ERROR, k, l); } for (wp = wcs; *wp != 0; wp++) { *wp = towupper (*wp); } if (wcstombs (__b2c__sbuffer[idx], wcs, len) == (size_t) - 1) { ERROR = 38; RUNTIMEFERR (\"UCASE$\", ERROR, k, l); } free (wcs);" TO g_CTEMP
	WRITELN "setlocale (LC_ALL, local); } else { for (i = 0; i < len; i++) { __b2c__sbuffer[idx][i] = toupper (src[i]); } } __b2c__SETLEN (__b2c__sbuffer[idx], len); __b2c__sbuffer[idx][len] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.ucase.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.ucase.o: bacon.ucase.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.ucase.c"
	CLOSE FILE g_CTEMP

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

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.version.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "void __b2c__version(char* in){if(strcmp(\"", g_VERSION$, "\", in)) {printf(\"System error: this BaCon binary was compiled with a previous BaCon archive and therefore may not function correctly.\\n\");" TO g_CTEMP
	WRITELN "printf(\"Recompile your program using the '-a' flag.\\n\"); exit(EXIT_FAILURE);} }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.version.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.version.o: bacon.version.c" & NL$ & TAB$(1) & g_CCNAME$ & " " &  g_CCFLAGS$ & " -c bacon.version.c"
	CLOSE FILE g_CTEMP

	g_CTEMP$ = g_TEMPDIR$ & "/bacon.wait.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "long __b2c__netpeek(int l, char *k, int fd, int usec){fd_set rfds; struct timeval tv; long retval; struct termios oldt = { 0}, newt = { 0 }; if(fd == STDIN_FILENO){tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO);" TO g_CTEMP
	WRITELN "newt.c_cc[VMIN]=1; newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &newt);} FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_usec = (usec%1000)*1000; tv.tv_sec = usec/1000; retval = select(fd + 1, &rfds, NULL, NULL, &tv);" TO g_CTEMP
	WRITELN "if (retval == -1 && __b2c__trap) {ERROR = 16; RUNTIMEFERR(\"WAIT\", ERROR, k, l);} if(fd == STDIN_FILENO){if(retval) if(read(fd, &retval, 1)==0) retval=0; tcsetattr(STDIN_FILENO, TCSANOW, &oldt);} return(retval);}" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.wait.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.wait.o: bacon.wait.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.wait.c"
	CLOSE FILE g_CTEMP
ENDIF

IF LEN(g_REBUILD_ARCHIVE$) OR LEN(g_PRAGMA_REGEX$) THEN
	g_CTEMP$ = g_TEMPDIR$ & "/bacon.extract.c"
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_CTEMP$
	OPEN g_CTEMP$ FOR WRITING AS g_CTEMP
	WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_CTEMP
	WRITELN "char * __b2c__extract(int l, char *k, char *src, ...) { int reti, flag, len, pos = 0; char *needle, *tmp; regex_t regex; char __b2c__buf[100]; regmatch_t where[1]; long idx;" TO g_CTEMP
	WRITELN "va_list __b2c__ap; va_start (__b2c__ap, src); needle = va_arg (__b2c__ap, char *); flag = va_arg (__b2c__ap, int); va_end (__b2c__ap); if (src == NULL || needle == NULL)" TO g_CTEMP
	WRITELN "{ return (src); } if (__b2c__len(src) == 0 || __b2c__len(needle) == 0) { return(src); } idx = __sbuf_malloc_handle (__b2c__len(src) + 1);" TO g_CTEMP
	WRITELN "if (flag > 0) { if (__b2c__option_compare == 0) reti = regcomp (&regex, needle, REG_EXTENDED); else reti = regcomp (&regex, needle, REG_EXTENDED | REG_ICASE);" TO g_CTEMP
	WRITELN "if (__b2c__trap && reti) { ERROR = 27; regerror (reti, &regex, __b2c__buf, sizeof (__b2c__buf)); fprintf (stderr, \"%s\\n\", __b2c__buf); RUNTIMEFERR(\"EXTRACT$\", ERROR, k, l); }" TO g_CTEMP
	WRITELN "while ((reti = regexec (&regex, src, 1, where, 0)) == 0) { memcpy (__b2c__sbuffer[idx] + pos, src, (size_t) where[0].rm_so); pos += where[0].rm_so; src += (long) where[0].rm_eo;}" TO g_CTEMP
	WRITELN "regfree (&regex); len = strlen(src); memcpy (__b2c__sbuffer[idx] + pos, src, len); pos += len; } else { while ((tmp = strstr (src, needle)) != NULL) {" TO g_CTEMP
	WRITELN "memcpy (__b2c__sbuffer[idx] + pos , src, (size_t) (tmp - src) ); pos += tmp - src; src = tmp + __b2c__len(needle); }" TO g_CTEMP
	WRITELN "len = strlen(src); memcpy (__b2c__sbuffer[idx] + pos, src, len ); pos += len; }" TO g_CTEMP
	WRITELN "__b2c__SETLEN (__b2c__sbuffer[idx], pos); __b2c__sbuffer[idx][pos] = '\\0'; return (char *) (__b2c__sbuffer[idx]); }" TO g_CTEMP
	g_OBJ_FILES$ = g_OBJ_FILES$ & " bacon.extract.o"
	g_MAKE_LINE$ = g_MAKE_LINE$ & NL$ & "bacon.extract.o: bacon.extract.c" & NL$ & TAB$(1) & g_CCNAME$ & " " & g_CCFLAGS$ & " -c bacon.extract.c"
	CLOSE FILE g_CTEMP

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

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

	IF LEN(g_PRAGMA_REGEX$) THEN
		g_TMP_FILES$ = g_TMP_FILES$ & " libregex.a"
		g_REBUILD_ARCHIVE$ = "libregex.a"
		g_LDFLAGS$ = "-lregex " & g_LDFLAGS$
	ENDIF
END IF

' Include ALARM prototypes
IF LEN(g_ALARM_PROTO$) THEN WRITELN g_ALARM_PROTO$ TO g_HFILE

' Include functions and subs
FOR incfiles$ IN g_INCLUDE_FILES$
	IF LEN(incfiles$) > 0 THEN WRITELN "#include \"", incfiles$, CHR$(34) TO g_HFILE
NEXT

' Check if generated source file exists
IF FILEEXISTS(SRCARRAYFILE$) THEN
	WRITELN "#include \"", SRCARRAYFILE$, "\"" TO g_HFILE
	g_TMP_FILES$ = g_TMP_FILES$ & " " & SRCARRAYFILE$
ENDIF

' Close all filehandles
CLOSE FILE FLOATARRAYFILE, STRINGARRAYFILE, g_HFILE, g_CFILE

INCR g_TOTAL_LINES, g_COUNTER-1
ttime = TIMER-starttime
PRINT MOD(ttime, 1000) FORMAT "%.3ld" TO msec_time$
PRINT "\rConverting '", g_SOURCEFILE$, "'... done, ", g_TOTAL_LINES, " lines were processed in ", FLOOR(ttime/1000), ".", msec_time$, " seconds."

' Check MEMORY/FREE
IF g_SEMANTIC = 0 THEN
	LOOKUP g_SEMANTIC_MEMFREE$ TO semantic$ SIZE COUNTER
	WHILE COUNTER > 0
		IF LEN(g_SEMANTIC_MEMFREE$(semantic$[COUNTER])) THEN EPRINT "Warning: no FREE for the memory address ", g_SEMANTIC_MEMFREE$(semantic$[COUNTER]), "!"
		DECR COUNTER
	WEND
ENDIF

' Check OPEN/CLOSE handles
IF g_SEMANTIC = 0 THEN
	LOOKUP g_SEMANTIC_OPENCLOSE$ TO semantic$ SIZE COUNTER
	WHILE COUNTER > 0
		IF LEN(g_SEMANTIC_OPENCLOSE$(semantic$[COUNTER])) THEN EPRINT "Warning: no CLOSE for the OPEN handle ", g_SEMANTIC_OPENCLOSE$(semantic$[COUNTER]), "!"
		DECR COUNTER
	WEND
ENDIF

' Show error in case function has no end
IF LEN(g_FUNCNAME$) THEN
	EPRINT "Syntax error: the SUB/FUNCTION '", g_FUNCNAME$, "' has no END in file '", g_CURFILE$, "'!"
	END 1
ENDIF

' Start indentation
IF ISTRUE(g_TMP_PRESERVE) THEN
	IF ISTRUE(LEN(EXEC$("which indent 2>/dev/null"))) THEN
		PRINT "Applying indentation... ";
		FOR tmpfile$ IN g_TMP_FILES$
			IF NOT(REGEX(tmpfile$, ".*\\.cpp")) AND NOT(REGEX(tmpfile$, ".*\\.tmp")) AND NOT(REGEX(tmpfile$, ".*\\.bac$")) AND NOT(REGEX(tmpfile$, ".*\\.a$")) THEN
				IF ISTRUE(INSTR(OS$, "Darwin")) OR ISTRUE(INSTR(OS$, "BSD")) THEN
					RENAME tmpfile$ TO tmpfile$ & ".BAK"
					SYSTEM "indent " & tmpfile$ & ".BAK " & tmpfile$
					DELETE FILE tmpfile$ & ".BAK"
				ELSE
					SYSTEM "indent " & tmpfile$
					DELETE FILE tmpfile$ & "~"
				END IF
			END IF
		NEXT
		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 "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(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

' Creation of the Makefile
OPEN g_TEMPDIR$ & "/Makefile.bacon" FOR WRITING AS makefile
WRITELN "# Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - MIT License", NL$ TO makefile
WRITELN BASENAME$(g_SOURCEFILE$, 1), g_BINEXT$, ": ", BASENAME$(g_SOURCEFILE$), ".o ", g_REBUILD_ARCHIVE$ TO makefile
WRITELN TAB$(1), g_CCNAME$, " -o ", BASENAME$(g_SOURCEFILE$, 1), g_BINEXT$, " ", BASENAME$(g_SOURCEFILE$), ".o ", g_LDFLAGS$ TO makefile
WRITELN BASENAME$(g_SOURCEFILE$), ".o: ", BASENAME$(g_SOURCEFILE$), ".c" TO makefile
WRITELN TAB$(1), g_CCNAME$, " ", g_CCFLAGS$, " -c ", BASENAME$(g_SOURCEFILE$), ".c" TO makefile
IF LEN(g_REBUILD_ARCHIVE$) AND NOT(g_NO_COMPILE) THEN
	PRINT "New BaCon archive requested! Creating..."
	IF FILEEXISTS(g_TEMPDIR$ & "/" & g_REBUILD_ARCHIVE$) THEN DELETE FILE g_TEMPDIR$ & "/" & g_REBUILD_ARCHIVE$
	WRITELN NL$, g_REBUILD_ARCHIVE$, ": ", g_OBJ_FILES$ TO makefile
	WRITELN TAB$(1), g_ARNAME$, " ", g_REBUILD_ARCHIVE$, " ", g_OBJ_FILES$, " >/dev/null 2>&1" TO makefile
	IF (LEN(g_RANLIB$)) THEN WRITELN TAB$(1), g_RANLIB$, " ", g_REBUILD_ARCHIVE$ TO makefile
	WRITELN g_MAKE_LINE$ TO makefile
ENDIF
WRITELN NL$, ".PHONY: clean" TO makefile
WRITELN "clean:" TO makefile
WRITELN TAB$(1), "rm -f *.o *.c ", BASENAME$(g_SOURCEFILE$, 1), g_BINEXT$, " ", BASENAME$(g_SOURCEFILE$, 1), ".*.* ", g_REBUILD_ARCHIVE$, " Makefile.bacon" TO makefile
CLOSE FILE makefile
g_TMP_FILES$ = g_TMP_FILES$ & " " & g_TEMPDIR$ & "/Makefile.bacon"

' Start compilation
IF ISFALSE(g_NO_COMPILE) THEN

	IF ISFALSE(LEN(EXEC$("which " & g_CCNAME$ & " 2>/dev/null"))) THEN
		EPRINT "ERROR: '", g_CCNAME$, "' not found on this system!"
		EPRINT "Generated source code cannot be compiled."
		END 0
	END IF
	PRINT "Compiling '", g_SOURCEFILE$, "'... ";

	' Make sure GCC uses English localization
	SETENVIRON "LANG", "C"

	old_curdir$ = CURDIR$
	CHANGEDIR g_TEMPDIR$
	SYSTEM "make -f Makefile.bacon 2>" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".log"
	RETURN_CODE = RETVAL

	' Go back to working directory
	CHANGEDIR old_curdir$

	' Add temp file
	g_TMP_FILES$ = g_TMP_FILES$ & " " & g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".log " & g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".o"

	IF ISFALSE(FILELEN(g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".log")) THEN
		PRINT "Done, program '", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4), g_BINEXT$, "' ready."
	ELSE
		' Only print first error
		EPRINT "Compiler error:"
		OPEN 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$ = "Cause:" & NL$ & TAB$(1) & MID$(g_ERROR$, INSTRREV(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$ = "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$ = "Cause:" & NL$ & TAB$(1) & MID$(g_ERROR$, INSTRREV(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$ = "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

		' Go find last mentioning of error file
		WHILE NOT(ENDFILE(errlog)) DO
			READLN g_ERROR$ FROM errlog
			IF REGEX(g_ERROR$, ":[[:digit:]]*:[[:digit:]]*:") AND NOT(REGEX(g_ERROR$, ".bac.generic.h")) THEN g_FILE_LINE$ = HEAD$(g_ERROR$, 1)
		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$ = g_TEMPDIR$ & "/" & 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 INSTR(g_CCFLAGS$, "Wall") OR NOT(FILEEXISTS(g_FILE$)) OR REGEX(g_FILE$, ".bac.generic.h$") THEN
			EPRINT
			SYSTEM "cat " & g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".log"
			EPRINT
		ELSE
			' Get the error string from the logfile
			IF INSTR(MID$(g_FILE_LINE$, 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
			' Get the filename
			OPEN g_FILE$ FOR READING AS errlog
			SEEK errlog OFFSET SEARCH(errlog, "#define __b2c_filename")
			READLN g_FEED$ FROM errlog
			g_FEED$ = EXTRACT$(MID$(g_FEED$, INSTR(g_FEED$, "__b2c_filename")+15), CHR$(34))
			' If no line number was found
			IF g_LINE = 0 THEN g_LINE = 1
			' Error is at end of file
			IF g_LINE >= Count_Lines(g_FILE$)-1 THEN
				COUNTER = Count_Lines(g_FEED$)
				line$ = "undefined syntax error, hint: check for missing ENDIF, WEND, NEXT."
			ELSE
				' Get the line number in the source
				REWIND errlog
				WHILE NOT(ENDFILE(errlog)) DO
					READLN line$ FROM errlog
					DECR g_LINE
					IF g_LINE = 0 THEN BREAK
				WEND
				SEEK errlog OFFSET SEARCH(errlog, "#define __b2c_lineno", 2)
				READLN g_CURLINE$ FROM errlog
				COUNTER = VAL(MID$(g_CURLINE$, INSTR(g_CURLINE$, "__b2c_lineno")+13))
				' Get the line text
				PUSH COUNTER
				OPEN g_FEED$ FOR READING AS g_SOURCEFILE
				WHILE NOT(ENDFILE(g_SOURCEFILE)) DO
					READLN line$ FROM g_SOURCEFILE
					DECR COUNTER
					IF COUNTER = 0 THEN BREAK
				WEND
				CLOSE FILE g_SOURCEFILE
				PULL COUNTER
			ENDIF
			CLOSE FILE errlog
			' Print the error
			EPRINT NL$, "Description:", NL$, TAB$(1), " file '", g_FEED$, "' line ", COUNTER, ": ", CHOP$(line$)
			EPRINT g_ERRORTXT$, NL$
			' Print extra hints
			IF REGEX(g_ERRORTXT$, ".*implicit.*declaration.*") THEN
				EPRINT TAB$(1), " hint: check for missing header file or library.", NL$
			ENDIF
		END IF
		' Preserve temp files
		g_TMP_PRESERVE = 1
	END IF
END IF

' Cleanup
IF ISFALSE(g_TMP_PRESERVE) THEN
	FOR tmpfile$ IN g_TMP_FILES$
		IF FILEEXISTS(tmpfile$) THEN
			DELETE FILE tmpfile$
		ELSE
			PRINT NL$, "Warning: duplicate SUB or FUNCTION found! Temporary file ", tmpfile$, " already deleted."
		END IF
	NEXT
	IF LEN(g_REBUILD_ARCHIVE$) THEN
		OPEN g_TEMPDIR$ FOR DIRECTORY AS work_dir
		REPEAT
			GETFILE tmpfile$ FROM work_dir
			IF LEFT$(tmpfile$, 1) != "." AND REGEX(tmpfile$, "bacon\\..+\\.o") THEN DELETE FILE g_TEMPDIR$ & "/" & tmpfile$
		UNTIL LEN(tmpfile$) = 0
		CLOSE DIRECTORY work_dir
	ENDIF
END IF

END RETURN_CODE
