' ____ ____ ' | __ ) __ _ / ___|___ _ __ ' | _ \ / _` | | / _ \| '_ \ ' | |_) | (_| | |__| (_) | | | | --= A BaCon BASIC-to-C converter =-- ' |____/ \__,_|\____\___/|_| |_| ' ' Peter van Eerten - March 2009/September 2013. License: GPL version 3. ' '---------------------------------------------------------------------------------------------- ' 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 implementations where possible. ' ' The reason for this is maintainability and consistency: a bug should show up in all versions ' and should be solved in all versions. ' '---------------------------------------------------------------------------------------------- ' GLOBAL INITIALIZATIONS '---------------------------------------------------------------------------------------------- ' Provide compile options PRAGMA OPTIONS -O2 ' 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$ = "2.3.0" ' 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 either the BASH or KSH implementation version ", g_VERSION$, "." END 1 END IF ' Link flags IF INSTR(OS$, "OSF1") OR INSTR(OS$, "BSD") THEN g_LDFLAGS$ = "-lm" ELSE g_LDFLAGS$ = "-lm -ldl" ' Solaris IF INSTR(OS$, "SunOS" ) THEN g_LDFLAGS$ = g_LDFLAGS$ & " -lnsl -lsocket" ' Global to define '$'-replacement CONST g_STRINGSIGN$ = "__b2c__string_var" '---------------------------------------------------------------------------------------------- FUNCTION Check_Declared(STRING filename$, STRING v$) LOCAL txt$, needle$ LOCAL expr LOCAL thefile TYPE FILE* needle$ = REPLACE$(v$, "*", "\\*") OPEN filename$ FOR READING AS thefile WHILE NOT(ENDFILE(thefile)) DO READLN txt$ FROM thefile IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN expr = REGEX(txt$, "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING") IF ISTRUE(expr) THEN IF INSTR(needle$, "[") THEN expr = REGEX(txt$, " " & LEFT$(needle$, INSTR(needle$, "[")-1) & "\\[|," & LEFT$(needle$, INSTR(needle$, "[")-1) & "\\[" ) ELSE expr = REGEX(txt$, " " & needle$ & ",| " & needle$ & ";|\\*" & needle$ & " |," & needle$ & ",|," & needle$ & ";| " & needle$ & " +=|\\*" & needle$ & ";") END IF IF ISTRUE(expr) THEN BREAK ENDIF ENDIF WEND CLOSE FILE thefile RETURN expr END FUNCTION '---------------------------------------------------------------------------------------------- FUNCTION Check_Type$(STRING filename$, STRING v$) LOCAL txt$, needle$ LOCAL expr LOCAL thefile TYPE FILE* needle$ = CHOP$(REPLACE$(v$, "*", "\\*")) OPEN filename$ FOR READING AS thefile WHILE NOT(ENDFILE(thefile)) DO READLN txt$ FROM thefile IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 THEN expr = REGEX(txt$, "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING") IF ISTRUE(expr) THEN IF INSTR(needle$, "[") THEN IF INSTR(needle$, g_STRINGSIGN$) THEN expr = REGEX(txt$, " *" & LEFT$(needle$, INSTR(needle$, "[")-1) & "\\[") ELSE expr = REGEX(txt$, " " & LEFT$(needle$, INSTR(needle$, "[")-1) & "\\[") ENDIF ELSE expr = REGEX(txt$, " " & needle$ & ",| " & needle$ & ";|," & needle$ & ",|," & needle$ & ";| " & needle$ & " +=") END IF IF ISTRUE(expr) THEN BREAK ENDIF ENDIF WEND CLOSE FILE thefile IF ISTRUE(expr) THEN RETURN txt$ RETURN "" END FUNCTION '---------------------------------------------------------------------------------------------- FUNCTION Search(STRING file$, STRING line$) LOCAL found, mem LOCAL txt$ LOCAL handle TYPE FILE* found = -1 mem = MEMORY(FILELEN(file$)) OPEN file$ FOR READING AS handle GETBYTE mem FROM handle SIZE FILELEN(file$) OPEN mem FOR MEMORY AS txt$ IF INSTRREV(txt$, line$) THEN found = TRUE CLOSE MEMORY txt$ CLOSE FILE handle FREE mem RETURN found END FUNCTION '---------------------------------------------------------------------------------------------- SUB Print_Element (STRING arg$, STRING std$) LOCAL len, check ' Get part just before '(' len = INSTR(arg$, "(")-1 IF len < 0 THEN len = LEN(arg$) ' Check on string by reference variable check = Search(g_HFILE$, "char *" & arg$ & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & arg$ & " = NULL;") ENDIF ' Check if var is string var IF INSTR(MID$(arg$, 1, len), g_STRINGSIGN$) OR INSTR(MID$(arg$, 1, len), CHR$(34)) OR REGEX(MID$(arg$, 1, len), "gettext|ngettext") OR check >= 0 THEN WRITELN "__b2c__assign = ", arg$, "; if(__b2c__assign != NULL) fprintf(", std$, ", \"%s\", __b2c__assign);" TO g_CFILE ELSE WRITELN "fprintf(", std$, ", \"%s\", STR", g_STRINGSIGN$, "(", arg$, "));" TO g_CFILE END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Print(STRING arg$, STRING std$) LOCAL exp$, form$, to$ LOCAL x, in_string, in_func, pos, escaped, check, size ' Check if argument IF ISTRUE(LEN(arg$)) THEN ' Omit semicolon if there is one IF RIGHT$(arg$, 1) = ";" THEN exp$ = LEFT$(arg$, LEN(arg$) - 1) ELSE exp$ = arg$ END IF ' If there is a FORMAT argument IF INSTR(exp$, " FORMAT ") THEN form$ = MID$(exp$, INSTR(exp$, " FORMAT ") + 8) ' Optional TO argument? IF INSTR(form$, " TO ") THEN to$ = MID$(form$, INSTR(form$, " TO ") + 4) 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 ' Check if variable is declared IF NOT(REGEX(to$, "\\[.*\\]")) THEN check = Search(g_HFILE$, "char *" & to$ & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & to$ & " = NULL;") ENDIF IF check < 0 THEN WRITELN "char *", to$, " = NULL;" TO g_HFILE END IF WRITELN to$, " = (char*)realloc(", to$, ", (", size, "+1)*sizeof(char));" TO g_CFILE WRITELN "snprintf(", to$, ", ", size, "+1, ", MID$(form$, 1, INSTR(form$, " TO ")-1), ", ", LEFT$(exp$, INSTR(exp$, " FORMAT ")), ");" TO g_CFILE ELSE WRITELN "fprintf(stdout, ", form$, ", ", LEFT$(exp$, INSTR(exp$, " FORMAT ")), ");" TO g_CFILE END IF ELSE ' Start miniparser in_string = FALSE in_func = 0 pos = 1 escaped = 0 FOR x = 1 TO LEN(exp$) SELECT MID$(exp$, x, 1) CASE ","; CASE ";" IF ISFALSE(in_string) AND ISFALSE(in_func) THEN IF x-pos > 0 THEN Print_Element(CHOP$(MID$(exp$, pos, x-pos)), std$) END IF pos = x + 1 escaped = FALSE END IF CASE CHR$(92) escaped = TRUE CASE CHR$(34) IF ISFALSE(escaped) THEN in_string = NOT(in_string) escaped = FALSE CASE "(" IF ISFALSE(in_string) THEN INCR in_func escaped = FALSE CASE ")" IF ISFALSE(in_string) THEN DECR in_func escaped = FALSE DEFAULT escaped = FALSE END SELECT NEXT IF pos < LEN(exp$) THEN Print_Element(CHOP$(MID$(exp$, pos)), std$) END IF ' If line ends with ';' then skip newline IF RIGHT$(arg$, 1) <> ";" THEN WRITELN "fprintf(", std$, ", \"\\n\");" TO g_CFILE END IF END IF ELSE WRITELN "fprintf(", std$, ", \"\\n\");" TO g_CFILE END IF ' Flush print buffer WRITELN "fflush(", std$, ");" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Input(STRING arg$) LOCAL x, in_string, in_func, pos, check, escaped LOCAL type$ ' Check if we have an argument at all IF ISFALSE(LEN(arg$)) THEN EPRINT NL$, "Syntax error: empty INPUT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF ' Start miniparser in_string = FALSE in_func = 0 pos = 1 escaped = 0 FOR x = 1 TO LEN(arg$) SELECT MID$(arg$, x, 1) CASE ","; CASE ";" IF ISFALSE(in_string) AND ISFALSE(in_func) THEN IF x-pos > 0 THEN Print_Element(CHOP$(MID$(arg$, pos, x-pos)), "stdout") END IF pos = x + 1 escaped = FALSE END IF CASE CHR$(92) escaped = TRUE CASE CHR$(34) IF ISFALSE(escaped) THEN in_string = NOT(in_string) escaped = FALSE CASE "(" IF ISFALSE(in_string) THEN INCR in_func escaped = FALSE CASE ")" IF ISFALSE(in_string) THEN DECR in_func escaped = FALSE DEFAULT escaped = FALSE END SELECT NEXT arg$ = CHOP$(MID$(arg$, pos)) ' Check type of var, string? IF INSTR(arg$, g_STRINGSIGN$) THEN IF NOT(REGEX(arg$, "\\[.*\\]")) THEN ' Is variable declared already? check = Search(g_HFILE$, "char *" & arg$ & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & arg$ & " = NULL;") ENDIF IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE END IF ' Translate function to C function WRITELN "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, ");" TO g_CFILE WRITELN "__b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", stdin);" TO g_CFILE ' Make sure internal var is copied to var of program WRITELN arg$, " = (char*)realloc(", arg$, ", (", g_BUFFER_SIZE, "+1)*__b2c__counter*sizeof(char));" TO g_CFILE WRITELN "if(__b2c__counter == 1) strncpy(", arg$, ", __b2c__input__buffer, ", g_BUFFER_SIZE, ");" TO g_CFILE WRITELN "else strncat(", arg$, ", __b2c__input__buffer, ", g_BUFFER_SIZE, "); __b2c__counter++;" TO g_CFILE WRITELN "} while (!strstr(__b2c__input__buffer, \"\\n\") && strlen(__b2c__input__buffer));" TO g_CFILE ' Cut off last newline WRITELN "if (strlen(__b2c__input__buffer))", arg$, "[strlen(", arg$, ")-1] = '\\0'; else ", arg$, "=calloc(1, sizeof(char));" TO g_CFILE ' Var is numeric or stringarray ELSE ' Variable may not be array, these should be defined with DECLARE IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN ' Is variable declared already? check = Check_Declared(g_HFILE$, arg$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$) IF ISFALSE(check) THEN WRITELN "long ", arg$, ";" TO g_HFILE END IF ' Get the type type$ = Check_Type$(g_HFILE$, arg$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, arg$) END IF ' Translate function to C function - we do not need endless buffer here because numbers never can have more than 10 digits anyway WRITELN "memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, "); __b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", stdin);" TO g_CFILE ' Make sure internal var is copied to var of program IF INSTR(type$, "double ") OR INSTR(type$, "float ") OR INSTR(type$, "FLOATING ") THEN WRITELN arg$, " = atof(__b2c__input__buffer);" TO g_CFILE ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN WRITELN arg$, " = atol(__b2c__input__buffer);" TO g_CFILE ELSE WRITELN arg$, " = atoi(__b2c__input__buffer);" TO g_CFILE END IF END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_For(STRING arg$) LOCAL var$, tmp$, from$, to$, step$ LOCAL check ' Check if TO is available IF NOT(INSTR(arg$, " TO ")) AND NOT(INSTR(arg$, " IN ")) THEN EPRINT NL$, "Syntax error: missing IN/TO 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 ") 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 from$ = CHOP$(LEFT$(tmp$, INSTR(tmp$, " TO ") - 1)) to$ = CHOP$(MID$(tmp$, INSTR(tmp$, " TO ") + 3)) ' Check if there is a STEP IF ISTRUE(INSTR(to$, " STEP ")) THEN step$ = CHOP$(MID$(to$, INSTR(to$, " STEP ") + 5)) to$ = CHOP$(LEFT$(to$, INSTR(to$, " STEP ") - 1)) ELSE step$ = "1" END IF 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;" g_STRINGARGS$ = g_STRINGARGS$ & " char *__b2c__forin_" & var$ & "_end = NULL;" END IF ELSE check = Search(g_HFILE$, "char *__b2c__forin_" & var$ & " = NULL;") IF check < 0 THEN WRITELN "char *__b2c__forin_", var$, " = NULL;" TO g_HFILE WRITELN "char *__b2c__forin_", var$, "_end = NULL;" TO g_HFILE END IF END IF WRITELN "if (", tmp$, " != NULL) __b2c__forin_", var$, "= strdup(", tmp$, ");" TO g_CFILE END IF IF INSTR(var$, g_STRINGSIGN$) THEN ' Is variable declared already? check = Search(g_HFILE$, "char *" & var$ & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & var$ & " = NULL;") ENDIF IF check < 0 THEN WRITELN "char *", var$, " = NULL;" TO g_HFILE END IF WRITELN "__b2c__assign=(char*)__b2c__strdup(strtok_r(__b2c__forin_", var$, ", ", step$, ", &__b2c__forin_", var$, "_end)); if(", var$, " != NULL) free(", var$, "); ", var$, " = __b2c__assign;" TO g_CFILE WRITELN "while(", var$, " != NULL){" TO g_CFILE IF NOT(INSTR(g_LOCALSTRINGS$, "__b2c__forin_" & var$)) THEN g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " __b2c__forin_" & var$ g_LOOPVAR$[g_LOOPCTR] = var$ g_LOOPSTEP$[g_LOOPCTR] = step$ ELSE ' Variable may not be array, these should be defined with DECLARE IF NOT(REGEX(var$, "\\[.*\\]")) AND ISFALSE(INSTR(var$, ".")) THEN ' Is variable declared already? check = Check_Declared(g_HFILE$, var$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$) IF ISFALSE(check) THEN IF REGEX(from$ & to$ & step$, "[0-9]\\.[0-9]") THEN WRITELN "double ", var$, ";" TO g_HFILE ELSE WRITELN "long ", var$, ";" TO g_HFILE END IF END IF END IF ' Translate function to C function IF VAL(step$) < 0 THEN WRITELN "for(", var$," = ", from$, "; ", var$, " >= ", to$, ";", var$, " += ", step$, "){" TO g_CFILE ELSE WRITELN "for(", var$," = ", from$, "; ", var$, " <= ", to$, ";", var$, " += ", step$, "){" TO g_CFILE END IF END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_While (STRING arg$) ' Check if DO is available IF ISFALSE(INSTRREV(arg$, " DO")) THEN WRITELN "while(", Parse_Equation$(arg$), "){" TO g_CFILE ELSE WRITELN "while(", Parse_Equation$(LEFT$(arg$, INSTRREV(arg$, " DO"))), "){" TO g_CFILE END IF END SUB '---------------------------------------------------------------------------------------------- ' $1: name of ASSOC variable ' $2: name of index ' $3: actual value to assign ' $4: recursion level SUB Relate_Recurse(STRING var$, STRING str$, STRING tmp$, NUMBER lvl) LOCAL rel$ LOCAL ctr ' Check endless recursion INCR lvl IF lvl > g_RELATE_CTR THEN 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$, "__location = __b2c__", rel$, "__add(", str$, ";" TO g_CFILE IF INSTR(rel$, g_STRINGSIGN$) THEN WRITELN "__b2c__", rel$, "__location->value = realloc(__b2c__", rel$, "__location->value, (strlen(", tmp$, ")+1)*sizeof(char));" TO g_CFILE WRITELN "strcpy(__b2c__", rel$, "__location->value, ", tmp$, ");" TO g_CFILE ELSE WRITELN "__b2c__", rel$, "__location->value = ", tmp$, ";" TO g_CFILE END IF Relate_Recurse(rel$, str$, tmp$, lvl) END IF NEXT END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Let(STRING arg$) LOCAL check, ctr LOCAL var$, tmp$, str$, lft$, rel$, ptr$ ' Check if we have an argument at all IF NOT(INSTR(arg$, "=")) THEN EPRINT NL$, "Syntax error: could not parse line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF ' Get the variablename without surrounding spaces var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "=") - 1)) tmp$ = CHOP$(MID$(arg$, INSTR(arg$, "=") + 1)) ' Check if var is string var, exclude RECORD elements IF REGEX(var$, g_STRINGSIGN$ & "$") AND NOT(INSTR(var$, ".")) AND NOT(INSTR(g_DYNAMICARRAYS$, var$)) THEN ' Is variable declared already? check = Search(g_HFILE$, "char *" & var$ & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & var$ & " = NULL;") END IF IF check < 0 AND NOT(REGEX(g_PROTOTYPE$, ".* " & var$ & "[ ,)]+")) THEN WRITELN "char *", var$, " = NULL;" TO g_HFILE END IF ' Assume number, exclude RECORD elements ELIF NOT(REGEX(var$, "\\[.*\\]")) AND NOT(INSTR(var$, ".")) AND var$ != "ERROR" AND var$ != "RETVAL" AND NOT(REGEX(var$, "\\(.*\\)")) AND NOT(INSTR(var$, "->")) THEN ' Is variable declared already? check = Check_Declared(g_HFILE$, var$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$) IF ISFALSE(check) AND NOT(REGEX(g_PROTOTYPE$, ".* " & var$ & "[ ,)]+")) THEN IF INSTR(tmp$, ".") AND NOT(INSTR(tmp$, CHR$(34))) THEN WRITELN "double ", var$, ";" TO g_HFILE ELSE WRITELN "long ", var$, ";" TO g_HFILE END IF END IF ' Check if there is associative array assignment IF REGEX(var$, "\\(.*\\)$") THEN lft$ = LEFT$(var$, INSTR(var$, "(") - 1) str$ = MID$(var$, INSTR(var$, "(") + 1) WRITELN "__b2c__", lft$, "__location = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE IF INSTR(lft$, g_STRINGSIGN$) THEN WRITELN "__b2c__assign=(char*)__b2c__strdup(", tmp$, "); if(__b2c__assign==NULL)__b2c__assign=calloc(1, sizeof(char));" TO g_CFILE WRITELN "if(__b2c__", lft$, "__location->value != NULL) free(__b2c__", lft$, "__location->value); __b2c__", lft$, "__location->value = __b2c__assign; " TO g_CFILE ELSE WRITELN "__b2c__", lft$, "__location->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 INSTR(g_DYNAMICARRAYS$, var$) 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){free(", 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 not STRING array? ELIF INSTR(var$, g_STRINGSIGN$) AND NOT(REGEX(var$, ".*\\[.*" & g_STRINGSIGN$ & ".*\\].*")) THEN WRITELN "__b2c__assign=(char*)__b2c__strdup(", tmp$, "); if(__b2c__assign==NULL)__b2c__assign=calloc(1, sizeof(char)); if(", g_WITHVAR$, var$," != NULL) free(", g_WITHVAR$, var$, "); ", g_WITHVAR$, var$, " = __b2c__assign; " TO g_CFILE ' Also check if string var already is used for IMPORT, if so, perform dlopen again ptr$ = EXTRACT$(var$, "\"|-|\\.|/|_|\\(|\\)", TRUE) check = Search(g_CFILE$, "void* __b2c__dlopen__pointer_" & ptr$ & ";") IF check >= 0 THEN WRITELN "__b2c__dlopen__pointer_", ptr$, " = dlopen(", var$, ", RTLD_LAZY);" TO g_CFILE END IF ELSE WRITELN g_WITHVAR$, arg$, ";" TO g_CFILE END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Open(STRING arg$) LOCAL check, in_func, pos, ctr, tmp_ctr, bnd, x LOCAL file$[16], from$[16] LOCAL tmp$, mode$, handle$, line$, address$ ' 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 ' Start miniparser line$ = CHOP$(LEFT$(arg$, INSTR(arg$, " FOR ") - 1)) in_func = 0 pos = 1 ctr = 1 FOR x = 1 TO LEN(line$) SELECT MID$(line$, x, 1) CASE "," IF NOT(in_func) THEN file$[ctr] = CHOP$(MID$(line$, pos, x-pos)) pos = x + 1 INCR ctr END IF CASE "(" INCR in_func CASE ")" DECR in_func END SELECT NEXT file$[ctr] = CHOP$(MID$(line$, pos)) ' 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)) IF INSTR(handle$, "FROM") THEN line$ = CHOP$(MID$(handle$, INSTR(handle$, " FROM ") + 6)) in_func = 0 pos = 1 bnd = 1 FOR x = 1 TO LEN(line$) SELECT MID$(line$, x, 1) CASE "," IF NOT(in_func) THEN from$[bnd] = CHOP$(MID$(line$, pos, x-pos)) pos = x + 1 INCR bnd END IF CASE "(" INCR in_func CASE ")" DECR in_func END SELECT NEXT from$[bnd] = CHOP$(MID$(line$, pos)) handle$ = CHOP$(LEFT$(handle$, INSTR(handle$, " FROM "))) END IF ' Check if var is string var IF INSTR(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 if variable was declared IF NOT(INSTR(handle$, ".")) THEN check = Check_Declared(g_HFILE$, handle$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, handle$) END IF ' File or dir? IF mode$ = "DIRECTORY" THEN IF ISFALSE(check) THEN WRITELN "DIR* ", handle$, ";" TO g_HFILE END IF ELIF mode$ = "MEMORY" THEN IF ISFALSE(check) THEN WRITELN "char* ", handle$, ";" TO g_HFILE END IF check = Check_Declared(g_HFILE$, "__b2c_mem_" & handle$ & ";") IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, "__b2c_mem_" & handle$ & ";") IF ISFALSE(check) THEN WRITELN "long __b2c_mem_", handle$, ";" TO g_HFILE 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 END IF ELSE IF ISFALSE(check) THEN WRITELN "FILE* ", handle$, ";" TO g_HFILE END IF END IF ' Convert to C syntax IF mode$ = "READING" THEN WRITELN handle$, " = fopen(", 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE ELIF mode$ = "WRITING" THEN WRITELN handle$, " = fopen(", 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE ELIF mode$ = "APPENDING" THEN WRITELN handle$, " = fopen(", 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE ELIF mode$ = "READWRITE" THEN WRITELN handle$, " = fopen(", 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); 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE ELIF mode$ = "MEMORY" THEN IF INSTR(handle$, g_STRINGSIGN$) THEN WRITELN "if(", handle$, "!=NULL)free(", 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$, ")) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"OPEN FOR MEMORY\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); 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 = 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(!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); 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 = 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); 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); 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); 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 = 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(!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); 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); 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); 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); 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); 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Seek(STRING arg$) LOCAL dim ' Check if we have an argument at all IF ISFALSE(LEN(arg$)) THEN 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 SPLIT arg$ BY " " TO element$ SIZE dim ' Convert to C function IF dim EQ 3 THEN WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_SET);" TO g_CFILE ELIF dim EQ 5 THEN IF element$[5] = "START" THEN WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_SET);" TO g_CFILE ELIF element$[4] = "CURRENT" THEN WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_CUR);" TO g_CFILE ELIF element$[4] = "END" THEN WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_END);" TO g_CFILE END IF ELSE EPRINT NL$, "Syntax error: erroneous SEEK statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Copy(STRING arg$) LOCAL from$, to$ ' Check if we have an argument at all IF ISFALSE(LEN(arg$)) THEN 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)) ' Translate to C function WRITELN "__b2c__inFile = fopen(", from$, ", \"r\"); __b2c__outFile = fopen(", to$, ", \"w\"); __b2c__Byte = 0;" TO g_CFILE WRITELN "if (__b2c__inFile != NULL && __b2c__outFile != NULL){while(__b2c__Byte!=EOF){" TO g_CFILE WRITELN "__b2c__Byte=fgetc(__b2c__inFile); if(__b2c__Byte!=EOF){" TO g_CFILE WRITELN "fputc(__b2c__Byte,__b2c__outFile); }}" TO g_CFILE WRITELN "fclose(__b2c__inFile); fclose(__b2c__outFile);}" TO g_CFILE WRITELN "else { if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) RUNTIMEERROR(\"COPY\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Rename(STRING arg$) LOCAL from$, to$ ' Check if we have an argument at all IF ISFALSE(LEN(arg$)) THEN 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Readln(STRING arg$) LOCAL dim, check ' Check if FROM is available IF NOT(INSTR(arg$, " FROM ")) THEN 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(INSTR(element$[1], g_STRINGSIGN$)) 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 NOT(REGEX(element$[1], "\\[.*\\]")) THEN ' Is variable declared already? check = Search(g_HFILE$, "char *" & element$[1] & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & element$[1] & " = NULL;") ENDIF IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE END IF ' Translate function to C function WRITELN "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, ");" TO g_CFILE WRITELN "__b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", ", element$[3], ");" TO g_CFILE ' Make sure internal var is copied to var of program WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", g_BUFFER_SIZE, "+1)*__b2c__counter*sizeof(char));" TO g_CFILE WRITELN "if(__b2c__counter == 1) strncpy(", element$[1], ", __b2c__input__buffer, ", g_BUFFER_SIZE, ");" TO g_CFILE WRITELN "else strncat(", element$[1], ", __b2c__input__buffer, ", g_BUFFER_SIZE, "); __b2c__counter++;" TO g_CFILE WRITELN "} while (!strstr(__b2c__input__buffer, \"\\n\") && strlen(__b2c__input__buffer));" TO g_CFILE ' Cut off last newline WRITELN "if (strlen(__b2c__input__buffer))", element$[1], "[strlen(", element$[1], ")-1]='\\0';" TO g_CFILE ' Cut off CR if available WRITELN "if(strlen(", element$[1], ")>0 && ", element$[1], "[strlen(", element$[1], ")-1]=='\\r') ", element$[1], "[strlen(", element$[1], ")-1]='\\0';" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Writeln(STRING arg$) LOCAL in_string, in_func, pos, escaped, x, len LOCAL var$, to$ ' Check if FROM is available IF NOT(INSTR(arg$, " TO ")) THEN 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$ = LEFT$(arg$, INSTRREV(arg$, " TO ")) to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " TO ") + 4)) ' Start miniparser in_string = FALSE in_func = 0 pos = 1 escaped = 0 FOR x = 1 TO LEN(var$) SELECT MID$(var$, x, 1) CASE "," IF ISFALSE(in_string) AND ISFALSE(in_func) THEN len = INSTR(MID$(var$, pos, x-pos), "(")-1 IF len < 0 THEN len = x-pos IF INSTR(MID$(var$, pos, len), g_STRINGSIGN$) OR INSTR(MID$(var$, pos, len), CHR$(34)) THEN WRITELN "fprintf(", to$, ", \"%s\", ", MID$(var$, pos, x-pos), ");" TO g_CFILE ELSE WRITELN "fprintf(", to$, ", \"%s\", STR", g_STRINGSIGN$, "(", MID$(var$, pos, x-pos), "));" TO g_CFILE END IF pos = x+1 escaped = FALSE END IF CASE CHR$(92) escaped = TRUE CASE CHR$(34) IF ISFALSE(escaped) THEN in_string = NOT(in_string) END IF escaped = FALSE CASE "(" IF ISFALSE(in_string) THEN INCR in_func END IF escaped = FALSE CASE ")" IF ISFALSE(in_string) THEN DECR in_func END IF escaped = FALSE DEFAULT escaped = FALSE END SELECT NEXT var$ = MID$(var$, pos) ' Write last element to file len = INSTR(var$, "(")-1 IF len < 0 THEN len = LEN(var$) IF INSTR(LEFT$(var$, len), g_STRINGSIGN$) OR INSTR(LEFT$(var$, len), CHR$(34)) THEN WRITELN "fprintf(", to$, ", \"%s\\n\", ", var$, ");" TO g_CFILE ELSE WRITELN "fprintf(", to$, ", \"%s\\n\", STR", g_STRINGSIGN$, "(", var$, "));" TO g_CFILE END IF WRITELN "fflush(", to$, ");" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Getbyte(STRING arg$) LOCAL dim 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 size$ <> "__b2c__counter" THEN check = Check_Declared(g_HFILE$, size$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$) IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE END IF ' Detect type of descriptor type$ = Check_Type$(g_HFILE$, to$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, to$) END IF ' Translate function to C function WRITELN "if(!__b2c__trap){if(__b2c__memory__check((void*)", var$, ")) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"GETBYTE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE ELSE WRITELN size$, " = fread((void*)(", var$, "), sizeof(", g_OPTION_MEMTYPE$, "), ", chunk$, ", ", to$, ");" TO g_CFILE END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Putbyte(STRING arg$) LOCAL dim 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 size$ <> "__b2c__counter" THEN check = Check_Declared(g_HFILE$, size$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$) IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE END IF ' Detect type of descriptor type$ = Check_Type$(g_HFILE$, to$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, to$) END IF ' Translate function to C function WRITELN "if(!__b2c__trap){if(__b2c__memory__check((void*)", var$, ")) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"PUTBYTE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); 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(\"GETBYTE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE ELSE WRITELN size$, " = fwrite((void*)", var$, ", sizeof(", g_OPTION_MEMTYPE$, "), ", chunk$, ", ", to$, "); fflush(", to$, ");" TO g_CFILE ENDIF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Getfile(STRING arg$) LOCAL dim, check ' 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 ' Translate function to C function WRITELN "__b2c__dir = readdir(", element$[3], ");" TO g_CFILE ' Check if variable is declared IF NOT(INSTR(element$[1], "[")) AND NOT(INSTR(element$[1], "]")) THEN check = Search(g_HFILE$, "char *" & element$[1] & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & element$[1] & " = NULL;") ENDIF END IF IF check < 0 AND NOT(REGEX(element$[1], "\\[.*\\]")) AND NOT(INSTR(element$[1], ".")) THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE ' Always realloc VAR to correct size, maybe it was resized somewhere else WRITELN "if(__b2c__dir != NULL) {", element$[1], " = realloc(", element$[1], ", (strlen(__b2c__dir->d_name)+1)*sizeof(char));" TO g_CFILE ' Make sure internal var is copied to var of program WRITELN "strcpy(", element$[1], ", __b2c__dir->d_name); ", element$[1], "[strlen(__b2c__dir->d_name)] = '\\0';}" TO g_CFILE WRITELN "else {", element$[1], " = realloc(", element$[1], ", sizeof(char)); ", element$[1], "[0] = '\\0';}" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Receive(STRING arg$) LOCAL var$, from$, size$, chunk$ LOCAL check ' 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$, ".")) THEN check = Check_Declared(g_HFILE$, size$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$) IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE ENDIF ELSE IF LEN(size$) = 0 THEN size$ = "__b2c__counter" ENDIF END IF ' Check if variable is declared IF REGEX(var$, ".*" & g_STRINGSIGN$) THEN check = Search(g_HFILE$, "char *" & var$ & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & var$ & " = NULL;") ENDIF IF check < 0 THEN WRITELN "char *", var$, " = NULL;" TO g_HFILE WRITELN var$, " = (char*)realloc(", var$, ", (", chunk$, "+1)*sizeof(char)); memset(", var$, ", '\\0', sizeof(char)*(", chunk$, "+1));" TO g_CFILE END IF ' Translate function to C function IF g_NETWORKTYPE$ = "SCTP" THEN WRITELN "if((", size$, " = sctp_recvmsg(", from$, ", (void*)", var$, ", ", chunk$, ", 0, 0, 0, 0)) < 0)" TO g_CFILE ELSE WRITELN "if((", size$, " = recv(", from$, ", (void*)", var$, ", ", 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Send(STRING arg$) LOCAL var$, to$, chunk$, size$ LOCAL check ' 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$, ".")) THEN check = Check_Declared(g_HFILE$, size$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$) IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Getline(STRING arg$) LOCAL dim, check ' Check if FROM is available IF NOT(INSTR(arg$, " FROM ")) THEN 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(INSTR(element$[1], g_STRINGSIGN$)) 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 variable is declared IF NOT(INSTR(element$[1], "[")) AND NOT(INSTR(element$[1], "]")) THEN ' Is variable declared already? check = Search(g_HFILE$, "char *" & element$[1] & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & element$[1] & " = NULL;") ENDIF IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE END IF ' Translate function to C function WRITELN "if (", element$[3], " == NULL ||", "*" & element$[3] , " == '\\0') {", element$[1], " = (char*)realloc(", element$[1], ", 2*sizeof(char)); strcpy(", element$[1], ", \"\");}" TO g_CFILE WRITELN "else { __b2c__assign = ", element$[3], "; while(*", element$[3], " != '\\0' && *", element$[3], " != '\\n') ", element$[3], "++;" TO g_CFILE ' Make sure internal var is copied to var of program WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", element$[3], "-__b2c__assign+1)*sizeof(char));" TO g_CFILE WRITELN "strncpy(", element$[1], ", __b2c__assign, ", element$[3], "-__b2c__assign);" TO g_CFILE ' Make sure to end the string WRITELN element$[1], "[(", element$[3], "-__b2c__assign)] = '\\0'; ", element$[3], "++;}" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Putline(STRING arg$) LOCAL in_string, in_func, pos, escaped, x, len LOCAL var$, to$ ' Check if TO is available IF NOT(INSTR(arg$, " TO ")) THEN EPRINT NL$, "Syntax error: missing TO in PUTLINE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF ' Get the variablename, filedescriptor var$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO "))) to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4)) ' Start miniparser in_string = FALSE in_func = 0 pos = 1 escaped = 0 FOR x = 1 TO LEN(var$) SELECT MID$(var$, x, 1) CASE "," IF ISFALSE(in_string) AND ISFALSE(in_func) THEN len = INSTR(MID$(var$, pos, x-pos), "(")-1 IF len < 0 THEN len = x-pos IF INSTR(MID$(var$, pos, len), g_STRINGSIGN$) OR INSTR(MID$(var$, pos, len), CHR$(34)) THEN WRITELN "strcat(", to$, ", ", CHOP$(MID$(var$, pos, x-pos)), ");", to$, "+=strlen(", CHOP$(MID$(var$, pos, x-pos)), ");" TO g_CFILE ELSE WRITELN "strcat(", to$, ", STR", g_STRINGSIGN$, "(", CHOP$(MID$(var$, pos, x-pos)), "));", to$, "+=strlen(STR", g_STRINGSIGN$, "(", CHOP$(MID$(var$, pos, x-pos)), "));" TO g_CFILE END IF pos = x+1 escaped = FALSE END IF CASE CHR$(92) escaped = TRUE CASE CHR$(34) IF ISFALSE(escaped) THEN in_string = NOT(in_string) END IF escaped = FALSE CASE "(" IF ISFALSE(in_string) THEN INCR in_func END IF escaped = FALSE CASE ")" IF ISFALSE(in_string) THEN DECR in_func END IF escaped = FALSE DEFAULT escaped = FALSE END SELECT NEXT var$ = MID$(var$, pos) ' Check if var is string var len = INSTR(MID$(var$, pos, x-pos), "(")-1 IF len < 0 THEN len = x-pos IF INSTR(LEFT$(var$, len), g_STRINGSIGN$) OR INSTR(LEFT$(var$, len), CHR$(34)) THEN WRITELN "strcat(", to$, ", ", var$, "); strcat(", to$, ", \"\\n\"); ", to$, "+=strlen(", var$, ")+1;" TO g_CFILE ELSE WRITELN "strcat(", to$, ", STR", g_STRINGSIGN$, "(", var$, ")); strcat(", to$, ", \"\\n\"); ", to$, "+=strlen(STR", g_STRINGSIGN$, "(", var$, "))+1;" TO g_CFILE END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_SubFunc(STRING arg$) LOCAL x, dim, check LOCAL arg_s$, dim$, arr$, size$ ' Check argument IF ISFALSE(LEN(CHOP$(arg$))) THEN 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$, "("))) ELSE g_ORIGFUNCNAME$ = CHOP$(arg$ & "(") g_PROTOTYPE$ = CHOP$(arg$ & "(") END IF ' Start miniparser to duplicate string arguments arg_s$ = CHOP$(MID$(arg$, INSTR(arg$, "(") + 1)) SPLIT arg_s$ BY "," TO element$ SIZE dim x = 1 WHILE dim > 1 DO IF INSTR(element$[x], "STRING ") OR INSTR(element$[x], "char* ") THEN element$[x] = CHOP$(element$[x]) arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ")-1) dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1) IF NOT(INSTR(element$[x], g_STRINGSIGN$)) AND REGEX(element$[x], ".*\\[.*\\].*") THEN g_ORIGFUNCNAME$ = 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$ & "char *__b2c_" & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) & "," g_STRINGARGS$ = g_STRINGARGS$ & "char *" & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) & " = __b2c_" & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) & ";" 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){free(" & 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], " "))) & "," g_STRINGARGS$ = g_STRINGARGS$ & "char *" & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) & " = __b2c__strdup(__b2c_" & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) & ");" g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) g_PROTOTYPE$ = g_PROTOTYPE$ & " " & element$[x] & "," END IF ELSE element$[x] = CHOP$(element$[x]) 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], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ") - 1) g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & MID$(element$[x], 1, INSTR(element$[x], " ")) &" __b2c_" & arr$ & "[" & dim$ & "+" & STR$(g_OPTION_BASE) &"]," g_STRINGARGS$ = g_STRINGARGS$ & MID$(element$[x], 1, INSTR(element$[x], " ")) & " " & arr$ & "[" & dim$ & "+" & STR$(g_OPTION_BASE) & "] = { 0 };" g_STRINGARGS$ = g_STRINGARGS$ & "for(__b2c__ctr=0; __b2c__ctr<" & dim$ & "+" & STR$(g_OPTION_BASE) & "; __b2c__ctr++){" & arr$ & "[__b2c__ctr] = __b2c_" & arr$ & "[__b2c__ctr];}" ELIF INSTR(element$[x], "VAR ") THEN EPRINT NL$, "Syntax error: variable argument list cannot be followed by other arguments at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE g_ORIGFUNCNAME$ = CHOP$(g_ORIGFUNCNAME$ & " " & element$[x] & ",") END IF g_PROTOTYPE$ = g_PROTOTYPE$ & " " & CHOP$(element$[x]) & "," END IF INCR x DECR dim WEND ' Last token in the sequence of arguments IF ISTRUE(dim) THEN element$[x] = CHOP$(LEFT$(element$[x], INSTR(element$[x], ")") - 1)) IF INSTR(element$[x], "STRING ") OR INSTR(element$[x], "char* ") THEN arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ")-1) dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1) IF NOT(INSTR(element$[x], g_STRINGSIGN$)) AND REGEX(element$[x], ".*\\[.*\\].*") THEN g_ORIGFUNCNAME$ = 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$ & "char *__b2c_" & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) & ")" g_STRINGARGS$ = g_STRINGARGS$ & "char *" & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) & " = __b2c_" & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) & ";" 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){free(" & 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], " "))) & ")" g_STRINGARGS$ = g_STRINGARGS$ & "char *" & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) & " = __b2c__strdup(__b2c_" & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) & ");" g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & CHOP$(MID$(element$[x], INSTR(element$[x], " "))) g_PROTOTYPE$ = g_PROTOTYPE$ & " " & element$[x] & ")" END IF ELSE IF INSTR(g_ORIGFUNCNAME$, element$[x]) OR LEN(element$[x]) EQ 0 THEN element$[x] = "void " IF REGEX(element$[x], ".*\\[.*\\].*\\].*") THEN 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], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ") - 1) g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & MID$(element$[x], 1, INSTR(element$[x], " ")) &" __b2c_" & arr$ & "[" & dim$ & "+" & STR$(g_OPTION_BASE) &"])" g_STRINGARGS$ = g_STRINGARGS$ & MID$(element$[x], 1, INSTR(element$[x], " ")) & " " & arr$ & "[" & dim$ & "+" & STR$(g_OPTION_BASE) & "] = { 0 };" g_STRINGARGS$ = g_STRINGARGS$ & "for(__b2c__ctr=0; __b2c__ctr<" & dim$ & "+" & STR$(g_OPTION_BASE) & "; __b2c__ctr++){" & arr$ & "[__b2c__ctr] = __b2c_" & arr$ & "[__b2c__ctr];}" ELIF INSTR(element$[x], "VAR ") THEN IF INSTR(g_PROTOTYPE$, ",") THEN 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 check = Check_Declared(g_HFILE$, size$) IF ISFALSE(check) THEN g_STRINGARGS$ = g_STRINGARGS$ & " long " & size$ & ";" 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$ g_ORIGFUNCNAME$ = g_ORIGFUNCNAME$ & "char *__b2c__name, ...)" element$[x] = "char*, ..." 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){free(" & arr$ & "[__b2c__ctr]);} free(" & arr$ & ");}" ELSE g_ORIGFUNCNAME$ = CHOP$(g_ORIGFUNCNAME$ & " " & element$[x] & ")") END IF g_PROTOTYPE$ = g_PROTOTYPE$ & " " & element$[x] & ")" END IF END IF ' Get original function name IF INSTR(g_ORIGFUNCNAME$, " (") THEN g_FUNCNAME$ = LEFT$(g_ORIGFUNCNAME$, INSTR(g_ORIGFUNCNAME$, " (") - 1) ELIF INSTR(g_ORIGFUNCNAME$, "(") THEN g_FUNCNAME$ = LEFT$(g_ORIGFUNCNAME$, INSTR(g_ORIGFUNCNAME$, "(") - 1) ELSE g_FUNCNAME$ = g_ORIGFUNCNAME$ END IF ' Close the current C file CLOSE FILE g_CFILE ' Add macro in case of VAR argument IF INSTR(element$[x], " ...") THEN WRITELN "#define ", g_FUNCNAME$, "(...) __", g_FUNCNAME$, "(__VA_ARGS__, NULL)" TO g_HFILE g_ORIGFUNCNAME$ = "__" & g_ORIGFUNCNAME$ END IF ' Make symbol known to parser g_IMPORTED$ = g_FUNCNAME$ & " " & g_IMPORTED$ ' Save CATCH routine g_ORIGCATCHGOTO$ = g_CATCHGOTO$ g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" g_STRINGARGS$ = g_STRINGARGS$ & " __b2c__catch_set_backup = __b2c__catch_set; __b2c__catch_set = 0;" ' Switch to header file g_COPY_CFILE$ = g_CFILE$ g_COPY_COUNTER = g_COUNTER g_CFILE$ = 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$ ' Close the current C file CLOSE FILE g_CFILE ' Put prototype to header file WRITELN "void ", g_PROTOTYPE$, "; /* noparse */" TO g_HFILE g_PROTOTYPE$ = "" ' Open temporary header file OPEN g_TEMPDIR$ & "/" & LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")) & g_FUNCNAME$ & ".h" FOR WRITING AS tmp_HFILE ' Get original function name WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO tmp_HFILE WRITELN "/* noparse ", g_CURFILE$, " BACON LINE ", g_COPY_COUNTER, " */" TO tmp_HFILE IF INSTR(g_ORIGFUNCNAME$, " (") THEN WRITELN "void ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE ELIF INSTR(g_ORIGFUNCNAME$, "(") THEN WRITELN "void ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE ELSE WRITELN "void ", g_FUNCNAME$, "(void) {" TO tmp_HFILE END IF ' Finalize sub WRITELN g_STRINGARGS$ TO tmp_HFILE OPEN g_CFILE$ FOR READING AS g_CFILE WHILE NOT(ENDFILE(g_CFILE)) DO READLN line$ FROM g_CFILE IF NOT(ENDFILE(g_CFILE)) THEN WRITELN line$ TO tmp_HFILE WEND CLOSE FILE g_CFILE ' Free strings variables if there are any WRITELN g_STRINGARRAYS$ TO tmp_HFILE FOR element$ IN g_LOCALSTRINGS$ IF LEN(element$) > 0 THEN WRITELN "if(", element$, " != NULL) free(", element$, ");" TO tmp_HFILE NEXT WRITELN "__B2C__PROGRAM__EXIT: ;" TO tmp_HFILE WRITELN "__b2c__catch_set = __b2c__catch_set_backup;" TO tmp_HFILE WRITELN "}" TO tmp_HFILE CLOSE FILE tmp_HFILE ' Include header file IF NOT(INSTR(g_INCLUDE_FILES$, LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")) & g_FUNCNAME$ & ".h")) THEN g_INCLUDE_FILES$ = g_INCLUDE_FILES$ & " " & LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")) & g_FUNCNAME$ & ".h" END IF ' Add to total filelist g_TMP_FILES$ = g_TMP_FILES$ & " " & g_TEMPDIR$ & "/" & LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")) & g_FUNCNAME$ & ".h" ' Delete temp funcfile DELETE FILE g_CFILE$ ' Restore mainfile g_CFILE$ = g_COPY_CFILE$ OPEN g_CFILE$ FOR APPENDING AS g_CFILE ' Restore CATCH routine g_CATCHGOTO$ = g_ORIGCATCHGOTO$ ' Reset variables g_ORIGFUNCNAME$ = "" g_FUNCNAME$ = "" g_LOCALSTRINGS$ = "" g_STRINGARRAYS$ = "" g_STRINGARGS$ = "" END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Endfunction() LOCAL line$ LOCAL tmp_HFILE TYPE FILE* 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$, "; /* noparse */" TO g_HFILE g_PROTOTYPE$ = "" ' Open temporary header file OPEN g_TEMPDIR$ & "/" & LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")) & g_FUNCNAME$ & ".h" FOR WRITING AS tmp_HFILE ' Get original function name WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO tmp_HFILE WRITELN "/* noparse ", g_CURFILE$, " BACON LINE ", g_COPY_COUNTER, " */" TO tmp_HFILE IF NOT(INSTR(g_ORIGFUNCNAME$, "(")) THEN WRITELN g_FUNCTYPE$, " ", g_FUNCNAME$, "(void) {" TO tmp_HFILE ELSE WRITELN g_FUNCTYPE$, " ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE END IF ' Add function body WRITELN g_STRINGARGS$ TO tmp_HFILE OPEN g_CFILE$ FOR READING AS g_CFILE WHILE NOT(ENDFILE(g_CFILE)) DO READLN line$ FROM g_CFILE IF NOT(ENDFILE(g_CFILE)) THEN WRITELN line$ TO tmp_HFILE WEND CLOSE FILE g_CFILE WRITELN "__B2C__PROGRAM__EXIT: ;" TO tmp_HFILE ' Make sure the function always returns something IF INSTR(g_FUNCTYPE$, "char*") THEN WRITELN "return (NULL);}" TO tmp_HFILE ELSE WRITELN "return (0);}" TO tmp_HFILE CLOSE FILE tmp_HFILE ' Include header file IF NOT(INSTR(g_INCLUDE_FILES$, LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")) & g_FUNCNAME$ & ".h")) THEN g_INCLUDE_FILES$ = g_INCLUDE_FILES$ & " " & LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")) & g_FUNCNAME$ & ".h" END IF ' Add to total filelist g_TMP_FILES$ = g_TMP_FILES$ & " " & g_TEMPDIR$ & "/" & LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")) & g_FUNCNAME$ & ".h" ' Delete temp funcfile DELETE FILE g_CFILE$ ' Restore mainfile g_CFILE$ = g_COPY_CFILE$ OPEN g_CFILE$ FOR APPENDING AS g_CFILE ' Restore CATCH routine g_CATCHGOTO$ = g_ORIGCATCHGOTO$ ' Clear function variables g_ORIGFUNCNAME$ = "" g_FUNCNAME$ = "" g_FUNCTYPE$ = "" g_LOCALSTRINGS$ = "" g_STRINGARRAYS$ = "" g_STRINGARGS$ = "" END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Return(STRING arg$) LOCAL type$, thearg$, element$ ' Check if we have an argument at all, if not, we return from a GOSUB IF ISFALSE(LEN(CHOP$(arg$))) THEN WRITELN "if(__b2c__gosub_buffer_ptr >= 0) longjmp(__b2c__gosub_buffer[__b2c__gosub_buffer_ptr], 1);" TO g_CFILE GOTO End_Func END IF type$ = Check_Type$(g_CFILE$, arg$) ' Check type of var, func using string but returning a value? IF INSTR(arg$, "(") AND INSTR(arg$, g_STRINGSIGN$) AND NOT(INSTR(LEFT$(arg$, INSTR(arg$, "(")), g_STRINGSIGN$)) AND NOT(REGEX(LEFT$(arg$, INSTR(arg$, "(")), "gettext|ngettext")) THEN g_FUNCTYPE$ = "double " thearg$ = MID$(arg$, INSTR(arg$, "(")+1) WRITELN "__b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= ", g_MAX_RBUFFERS, ") __b2c__rbuffer_ptr=0; if(", MID$(thearg$, 1, INSTRREV(thearg$, ")")-1), " != NULL)" TO g_CFILE WRITELN " {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)__rbuf_realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen(", MID$(thearg$, 1, INSTRREV(thearg$, ")")-1), ")+1)*sizeof(char));" TO g_CFILE WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], ", MID$(thearg$, 1, INSTRREV(thearg$, ")")-1), ");}" TO g_CFILE WRITELN "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)__rbuf_realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], 2*sizeof(char));" TO g_CFILE WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], \"\");}" TO g_CFILE thearg$ = MID$(arg$, 1, INSTR(arg$, "(")) & "__b2c__rbuffer[__b2c__rbuffer_ptr]" & MID$(arg$, INSTRREV(arg$, ")")) ' Do we return a string array? ELIF NOT(INSTR(g_LOCALSTRINGS$, " " & CHOP$(arg$))) AND INSTR(arg$, g_STRINGSIGN$) THEN g_FUNCTYPE$ = "char** " thearg$ = arg$ ' Check type of var, string or normal string? ELIF INSTR(arg$, g_STRINGSIGN$) OR INSTR(arg$, CHR$(34)) OR INSTR(g_FUNCNAME$, g_STRINGSIGN$) THEN g_FUNCTYPE$ = "char* " WRITELN "__b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= ", g_MAX_RBUFFERS, ") __b2c__rbuffer_ptr=0; if(", arg$, " != NULL)" TO g_CFILE WRITELN " {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)__rbuf_realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], ", arg$, ");}" TO g_CFILE WRITELN "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)__rbuf_realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], 2*sizeof(char));" TO g_CFILE WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], \"\");}" TO g_CFILE thearg$ = "__b2c__rbuffer[__b2c__rbuffer_ptr]" ' Check if float ELIF INSTR(arg$, ".") THEN g_FUNCTYPE$ = "double " thearg$ = arg$ ' Check if no alpha chars (then integer value) ELIF REGEX(arg$, "[0-9]") THEN g_FUNCTYPE$ = "long " thearg$ = arg$ ' Assume variable, check if declared before ELIF ISTRUE(LEN(type$)) THEN IF INSTR(type$, "DIR* ") THEN g_FUNCTYPE$ = "DIR* " ELIF INSTR(type$, "FILE ") THEN g_FUNCTYPE$ = "FILE* " ELIF INSTR(type$, "int* ") THEN g_FUNCTYPE$ = "int* " ELIF INSTR(type$, "short* ") THEN g_FUNCTYPE$ = "short* " ELIF INSTR(type$, "float* ") THEN g_FUNCTYPE$ = "float* " ELIF INSTR(type$, "double* ") THEN g_FUNCTYPE$ = "double* " ELIF INSTR(type$, "char* ") OR INSTR(type$, "STRING ") THEN g_FUNCTYPE$ = "char* " ELIF INSTR(type$, "long* ") THEN g_FUNCTYPE$ = "long* " ELIF INSTR(type$, "void* ") THEN g_FUNCTYPE$ = "void* " ELIF INSTR(type$, "int ") THEN g_FUNCTYPE$ = "int " ELIF INSTR(type$, "short ") THEN g_FUNCTYPE$ = "short " ELIF INSTR(type$, "float ") THEN g_FUNCTYPE$ = "float " ELIF INSTR(type$, "double ") OR INSTR(type$, "FLOATING ") THEN g_FUNCTYPE$ = "double " ELIF INSTR(type$, "char ") THEN g_FUNCTYPE$ = "char " ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN g_FUNCTYPE$ = "long " ELIF INSTR(type$, "void ") THEN g_FUNCTYPE$ = "void " END IF thearg$ = arg$ ' Not declared, assume integer variable ELSE g_FUNCTYPE$ = "long " thearg$ = arg$ END IF ' Free strings variables if there are any WRITELN g_STRINGARRAYS$ TO g_CFILE FOR element$ IN g_LOCALSTRINGS$ IF LEN(element$) > 0 THEN WRITELN "if(", element$, " != NULL) free(", element$, ");" TO g_CFILE NEXT ' The actual return value WRITELN "__b2c__catch_set = __b2c__catch_set_backup;" TO g_CFILE WRITELN "return (", thearg$, ");" TO g_CFILE LABEL End_Func END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Deffn(STRING arg$) LOCAL sym$ ' 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$, " "))) WRITELN "#define ", LEFT$(sym$, INSTR(sym$, "=") -1), " (", MID$(sym$, INSTR(sym$, "=") + 1), ")" TO g_HFILE ' Make symbol known to parser g_IMPORTED$ = LEFT$(sym$, INSTR(sym$, "(") - 1) & " " & g_IMPORTED$ END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Const(STRING arg$) ' Check if we have an argument at all IF ISFALSE(LEN(arg$)) THEN EPRINT NL$, "Syntax error: empty CONST at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF WRITELN "#define ", LEFT$(arg$, INSTR(arg$, "=") - 1), " (", CHOP$(MID$(arg$, INSTR(arg$, "=") + 1)), ")" TO g_HFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Push(STRING arg$) LOCAL type$ ' Check if we have an argument at all IF ISFALSE(LEN(CHOP$(arg$))) THEN 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$ = Check_Type$(g_HFILE$, arg$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, arg$) END IF END IF ' Allocate space for type WRITELN "__b2c__typestack = (int*)realloc(__b2c__typestack, (__b2c__stackptr+1)*sizeof(int));" TO g_CFILE ' Check type of var, string? IF INSTR(arg$, g_STRINGSIGN$) THEN WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" TO g_CFILE WRITELN "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE WRITELN "strcpy(__b2c__stringstack[__b2c__stackptr], ", arg$, ");} else __b2c__stringstack[__b2c__stackptr] = __b2c__strdup(", arg$, ");" TO g_CFILE WRITELN "__b2c__typestack[__b2c__stackptr] = 1;" TO g_CFILE ' Check if it is a normal string ELIF INSTR(arg$, CHR$(34)) THEN WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" TO g_CFILE WRITELN "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE WRITELN "strcpy(__b2c__stringstack[__b2c__stackptr], ", arg$, ");} else __b2c__stringstack[__b2c__stackptr] = __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 .*") THEN WRITELN "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" TO g_CFILE WRITELN "__b2c__doublestack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE WRITELN "__b2c__typestack[__b2c__stackptr] = 2;" TO g_CFILE ELSE WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE END IF ' Not declared, assume integer variable ELSE WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE END IF ' Increase stackpointer WRITELN "__b2c__stackptr++;" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Pull(STRING arg$) LOCAL check LOCAL type$ ' Check if we have an argument at all IF ISFALSE(LEN(CHOP$(arg$))) THEN 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 ' Decrease stackpointer again WRITELN "__b2c__stackptr--;" TO g_CFILE WRITELN "if(__b2c__stackptr < 0) __b2c__stackptr=0;" TO g_CFILE ' Get the last value from stack IF INSTR(arg$, g_STRINGSIGN$) THEN IF NOT(REGEX(arg$, "\\[.*\\]")) THEN ' Is variable declared already? check = Search(g_HFILE$, "char *" & arg$ & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & arg$ & " = NULL;") ENDIF IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE END IF WRITELN "if(__b2c__typestack[__b2c__stackptr] == 1) {" TO g_CFILE WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" TO g_CFILE WRITELN "strcpy(", arg$, ", __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" TO g_CFILE ELSE ' Variable may not be array, these should be defined with DECLARE IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN ' Not declared? Assume long check = Check_Declared(g_HFILE$, arg$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$) IF ISFALSE(check) THEN WRITELN "long ", arg$, "; /* pull */" TO g_HFILE END IF ' See how var was declared type$ = Check_Type$(g_HFILE$, arg$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, arg$) END IF ' Make sure internal var is copied to var of program IF INSTR(type$, "double ") OR INSTR(type$, "float ") OR INSTR(type$, "FLOATING ") THEN WRITELN "if(__b2c__typestack[__b2c__stackptr] == 2) ", arg$, "=__b2c__doublestack[__b2c__stackptr];" TO g_CFILE ELIF INSTR(type$, "long ") OR INSTR(type$, "int ") OR INSTR(type$, "NUMBER ") THEN WRITELN "if(__b2c__typestack[__b2c__stackptr] == 3) ", arg$, "=__b2c__longstack[__b2c__stackptr];" TO g_CFILE ELSE WRITELN "if(__b2c__typestack[__b2c__stackptr] == 1) {" TO g_CFILE WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" TO g_CFILE WRITELN "strcpy(", arg$, ", __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" TO g_CFILE END IF END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Import(STRING arg$) LOCAL lib$, type$, sym$, tmp$, token$, alias$, ptr$ LOCAL check ' 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$ = EXTRACT$((CHOP$(LEFT$(arg$, INSTR(arg$, "(") - 1))), CHR$(34)) tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6)) token$ = CHOP$(MID$(arg$, 1, INSTR(arg$, ")") - 1)) ELSE sym$ = EXTRACT$((CHOP$(MID$(arg$, 1, INSTR(arg$, " FROM ") - 1))), CHR$(34)) tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6)) token$ = "" END IF ' Check if TYPE is available IF NOT(INSTR(arg$, " TYPE ")) THEN 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)) WRITELN "#define ", alias$, " ", sym$ TO g_HFILE 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 ' Create name from libname ptr$ = EXTRACT$(lib$, "\"|-|\\.|/|_|\\(|\\)", TRUE) ' Check if variable was declared check = Search(g_CFILE$, "void* __b2c__dlopen__pointer_" & ptr$ & ";") IF check < 0 THEN WRITELN "void* __b2c__dlopen__pointer_", ptr$, ";" TO g_CFILE WRITELN "__b2c__dlopen__pointer_", ptr$, " = dlopen(", lib$, ", RTLD_LAZY);" TO g_CFILE END IF WRITELN "if(__b2c__dlopen__pointer_", ptr$, " == NULL){if(!__b2c__trap){ERROR = 3;if(!__b2c__catch_set) RUNTIMEERROR(\"IMPORT\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE ' Check if token was declared check = Search(g_HFILE$, type$ & "(\\*" & sym$ & ")") IF check < 0 THEN WRITELN type$, "(*", sym$, ")(", MID$(token$, INSTR(token$, "(") + 1), ");" TO g_HFILE END IF ' Translate to C function WRITELN "*(", type$, "**) (&", sym$, ") = dlsym(__b2c__dlopen__pointer_", ptr$, ", \"", sym$, "\");" TO g_CFILE WRITELN "if(", sym$, " == NULL) {if(!__b2c__trap){ERROR = 4;if(!__b2c__catch_set) RUNTIMEERROR(\"IMPORT\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE END IF ' Make symbol known to parser g_IMPORTED$ = sym$ & " " & g_IMPORTED$ END SUB '---------------------------------------------------------------------------------------------- SUB Normal_Dyn_Array(STRING t$, STRING var$, STRING array$, int is_static) LOCAL i$, j$, old$, end$, tmp_arr$, idx$, type$ LOCAL nr FOR i$ IN var$ STEP "," type$ = t$ g_DYNAMICARRAYS$ = g_DYNAMICARRAYS$ & " " & i$ ' Initialize strings IF REGEX(type$, "STRING|char\\*$") OR INSTR(i$, g_STRINGSIGN$) THEN IF INSTR(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 LEN(g_FUNCNAME$) > 0 THEN WRITELN type$, "* ", i$, ";" TO g_CFILE 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){free(" & i$ & "[__b2c__ctr]);}" g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & i$ ENDIF ELSE WRITELN type$, "* ", i$, ";" TO g_HFILE WRITELN "long __b2c_array_", CHOP$(i$), "; /* noparse */" 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] = calloc(1, sizeof(char));" TO g_CFILE ELSE ' 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 IF NOT(is_static) THEN g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & i$ ENDIF ELSE WRITELN type$, " ", 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 LEN(g_FUNCNAME$) > 0 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 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) free (" & 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$ LOCAL nr FOR i$ IN var$ STEP "," type$ = t$ g_DYNAMICARRAYS$ = g_DYNAMICARRAYS$ & " " & i$ ' Initialize strings IF REGEX(type$, "STRING|char\\*$") OR INSTR(i$, g_STRINGSIGN$) THEN IF INSTR(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$, "; /* noparse */" TO g_CFILE 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] = 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){free(" & g_RECORDVAR$ & "." & CHOP$(i$) & "[__b2c__ctr]);}" g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & g_RECORDVAR$ & "." & CHOP$(i$) ENDIF ELSE WRITELN type$, "* ", i$, "; /* noparse */" TO g_HFILE 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] = calloc(1, sizeof(char));" END IF ELSE ' 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$, "; /* noparse */" TO g_CFILE IF NOT(is_static) THEN g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & g_RECORDVAR$ & "." & CHOP$(i$) ENDIF ELSE WRITELN type$, " ", i$, "; /* noparse */" TO g_HFILE 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) free (" & 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 Handle_Declare(STRING arg$) LOCAL var$, type$, new$, value$, array$, str$ LOCAL check, option IF LEN(g_RECORDNAME$) > 0 THEN EPRINT NL$, "Syntax error: DECLARE 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 "struct ", g_RECORDNAME$, "{" TO g_HFILE g_RECORDVAR$ = MID$(CHOP$(arg$), INSTR(CHOP$(arg$), " ") + 1) ' Store current function name IF LEN(g_FUNCNAME$) > 0 THEN g_RECORDCACHE$ = g_FUNCNAME$ g_FUNCNAME$ = "" END IF ELSE ' Get the variablename and type IF INSTR(arg$, " TYPE ") THEN var$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TYPE "))) type$ = CHOP$(MID$(arg$, INSTR(arg$, " TYPE ") + 6)) 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$, g_STRINGSIGN$) THEN type$ = "char*" ELSE type$ = "long" END IF IF INSTR(var$, " ARRAY ") THEN array$ = MID$(var$, INSTR(var$, " ARRAY ") + 7) var$ = MID$(var$, 1, INSTR(var$, " ARRAY ") - 1) END IF END IF ' Check if variable was already declared IF NOT(INSTR(var$, ".")) THEN check = Check_Declared(g_HFILE$, var$) ELSE check = FALSE IF ISTRUE(check) THEN EPRINT NL$, "Syntax error: variable in DECLARE or GLOBAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!" END 1 END IF ' If array, increase dimensions when OPTION BASE is set IF REGEX(var$, "\\[.*\\]") AND NOT(INSTR(var$, "=")) THEN new$ = "" REPEAT new$ = new$ & LEFT$(var$, INSTR(var$, "[") - 1) & "[" value$ = MID$(var$, INSTR(var$, "[") + 1) new$ = new$ & MID$(value$, 1, INSTR(value$, "]") - 1) & "+" & STR$(g_OPTION_BASE) & "]" var$ = MID$(var$, INSTR(var$, "]") + 1) UNTIL NOT(REGEX(var$, "\\[.*\\]")) var$ = new$ END IF ' Check if it is a known type, if not BaCon has to use external .h file - create fake declaration for now IF NOT(REGEX(EXTRACT$(type$, "*"), "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING")) THEN WRITELN "/* long ", EXTRACT$(var$, "*"), "; */" TO g_HFILE WRITELN type$, " ", var$, ";" TO g_HFILE ' Check for associative array ELIF INSTR(arg$, " ASSOC ") THEN FOR str$ IN var$ STEP "," value$ = CHOP$(str$) WRITELN "struct __b2c__", value$, "_type {char *key; /* noparse */ ", type$, " value; /* noparse */ };" TO g_HFILE WRITELN "struct __b2c__", value$, "_type *__b2c__", value$, " = { NULL }; struct __b2c__", value$, "_type *__b2c__", value$, "__location; size_t __b2c__", value$, "_idx = 0;" TO g_HFILE WRITELN "static int __b2c__", value$, "_comp(const void *__b2c__m1, const void *__b2c__m2){ " TO g_HFILE WRITELN "struct __b2c__", value$, "_type *__b2c__mi1 = (struct __b2c__", value$, "_type *) __b2c__m1;" TO g_HFILE WRITELN "struct __b2c__", value$, "_type *__b2c__mi2 = (struct __b2c__", value$, "_type *) __b2c__m2;" TO g_HFILE WRITELN "if(__b2c__mi1->key == NULL && __b2c__mi2->key == NULL) return 0;" TO g_HFILE WRITELN "if(__b2c__mi1->key == NULL && __b2c__mi2->key != NULL) return 1;" TO g_HFILE WRITELN "if(__b2c__mi1->key != NULL && __b2c__mi2->key == NULL) return -1;" TO g_HFILE WRITELN "return strcmp(__b2c__mi1->key, __b2c__mi2->key); }" TO g_HFILE WRITELN "struct __b2c__", value$, "_type * __b2c__", value$, "_exist (char *__b2c__index){struct __b2c__", value$, "_type __b2c__", value$, "_key; __b2c__", value$, "_key.key = __b2c__index;" TO g_HFILE WRITELN "return(lfind(&__b2c__", value$, "_key, __b2c__", value$, ", &__b2c__", value$, "_idx, sizeof(struct __b2c__", value$, "_type), __b2c__", value$, "_comp)); }" TO g_HFILE WRITELN "struct __b2c__", value$, "_type *__b2c__", value$, "__add(char *__b2c__index){struct __b2c__", value$, "_type __b2c__", value$, "_key, *__b2c__", value$, "__result; __b2c__", value$, "_key.key = __b2c__index;" TO g_HFILE WRITELN "__b2c__", value$, "__result = lfind(&__b2c__", value$, "_key, __b2c__", value$, ", &__b2c__", value$, "_idx, sizeof(struct __b2c__", value$, "_type), __b2c__", value$, "_comp);" TO g_HFILE WRITELN "if(__b2c__", value$, "__result == NULL){__b2c__", value$, "_idx++; __b2c__", value$, " = (struct __b2c__", value$, "_type *) realloc (__b2c__", value$, ", __b2c__", value$, "_idx * sizeof (struct __b2c__", value$, "_type));" TO g_HFILE WRITELN "__b2c__", value$, "[__b2c__", value$, "_idx - 1].key = __b2c__strdup (__b2c__index); __b2c__", value$, "[__b2c__", value$, "_idx-1].value = 0;" TO g_HFILE WRITELN "__b2c__", value$, "__result = &__b2c__", value$, "[__b2c__", value$, "_idx-1];} return(__b2c__", value$, "__result);}" TO g_HFILE WRITELN "void __b2c__", value$, "__del(struct __b2c__", value$, "_type *__b2c__", value$, "__arg){" TO g_HFILE WRITELN "if(__b2c__", value$, "__arg != NULL) {free(__b2c__", value$, "__arg->key); __b2c__", value$, "__arg->key = NULL;" TO g_HFILE WRITELN "qsort(__b2c__", value$, ", __b2c__", value$, "_idx, sizeof(struct __b2c__", value$, "_type), __b2c__", value$, "_comp);" TO g_HFILE WRITELN "__b2c__", value$, "_idx--; __b2c__", value$, " = (struct __b2c__", value$, "_type *) realloc (__b2c__", value$, ", __b2c__", value$, "_idx * sizeof (struct __b2c__", value$, "_type));} }" TO g_HFILE WRITELN type$, " ", value$, "(char *__b2c__index){struct __b2c__", value$, "_type __b2c__", value$, "_key, *__b2c__", value$, "__result; __b2c__", value$, "_key.key = __b2c__index;" TO g_HFILE WRITELN "__b2c__", value$, "__result = lfind(&__b2c__", value$, "_key, __b2c__", value$, ", &__b2c__", value$, "_idx, sizeof(struct __b2c__", value$, "_type), __b2c__", value$, "_comp);" TO g_HFILE IF INSTR(str$, g_STRINGSIGN$) OR INSTR(type$, "STRING") OR INSTR(type$, "char*") THEN WRITELN "if(__b2c__", value$, "__result == NULL) return(\"\"); return __b2c__", value$, "__result->value;}" TO g_HFILE ELSE WRITELN "if(__b2c__", value$, "__result == NULL) return(0); return __b2c__", value$, "__result->value;}" TO g_HFILE END IF NEXT ' Check for dynamic array declaration ELIF ISTRUE(LEN(array$)) THEN Normal_Dyn_Array(type$, var$, array$, FALSE) ' Check if var is string var ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*$") ) AND NOT(INSTR(var$, "=")) THEN check = Search(g_HFILE$, "char *" & var$ & " = NULL;") IF check < 0 THEN FOR str$ IN CHOP$(var$) STEP "," IF INSTR(str$, "[") THEN WRITELN "char *", CHOP$(str$), " = { NULL };" TO g_HFILE ELSE WRITELN "char *", CHOP$(str$), " = NULL; " TO g_HFILE ' Pointer var should not be initialized IF INSTR(str$, g_STRINGSIGN$) THEN WRITELN CHOP$(str$), " = calloc(1, sizeof(char));" TO g_CFILE END IF NEXT END IF ' Var is string array assignment ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND INSTR(var$, "=") THEN WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE option = g_OPTION_BASE WHILE option > 0 WRITELN " \"\", " TO g_HFILE DECR option WEND WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE ' Assume char assignment or number ELSE IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN FOR str$ IN CHOP$(var$) STEP "," WRITELN type$, " ", str$, " = { 0 };" TO g_HFILE NEXT ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE option = g_OPTION_BASE WHILE option > 0 WRITELN " 0, " TO g_HFILE DECR option WEND WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND NOT(INSTR(var$, "*")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN WRITELN type$, " ", var$, ";" TO g_HFILE WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE ELSE WRITELN type$, " ", var$, ";" TO g_HFILE END IF ENDIF ENDIF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Local(STRING arg$) LOCAL var$, type$, new$, value$, dim$, array$, str$ LOCAL check, option ' 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 ELSE var$ = CHOP$(arg$) IF INSTR(var$, g_STRINGSIGN$) THEN type$ = "char*" ELSE type$ = "long" END IF IF INSTR(var$, " ARRAY ") THEN array$ = MID$(var$, INSTR(var$, " ARRAY ") + 7) var$ = MID$(var$, 1, INSTR(var$, " ARRAY ") - 1) END IF END IF check = 0 ' Check if variable was already declared IF NOT(INSTR(var$, ".")) THEN IF LEN(g_FUNCNAME$) > 0 THEN check = Check_Declared(g_CFILE$, var$) ELSE check = Check_Declared(g_HFILE$, var$) END IF IF ISTRUE(check) THEN EPRINT NL$, "Syntax error: variable in LOCAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!" END 1 END IF ' If array, increase dimensions when OPTION BASE is set IF REGEX(var$, "\\[.*\\]") AND NOT(INSTR(var$, "=")) THEN new$ = "" REPEAT new$ = new$ & LEFT$(var$, INSTR(var$, "[") - 1) & "[" value$ = MID$(var$, INSTR(var$, "[") + 1) new$ = new$ & MID$(value$, 1, INSTR(value$, "]") - 1) & "+" & STR$(g_OPTION_BASE) & "]" var$ = MID$(var$, INSTR(var$, "]") + 1) UNTIL NOT(REGEX(var$, "\\[.*\\]")) var$ = new$ END IF ' Check if it is a known type, if not BaCon has to use external .h file - create fake declaration for now IF NOT(REGEX(EXTRACT$(type$, "*"), "DIR|FILE|int|short|long|float|double|char|void|STRING|NUMBER|FLOATING")) THEN WRITELN "/* long ", EXTRACT$(var$, "*"), "; */" TO g_CFILE WRITELN type$, " ", var$, ";" TO g_CFILE ' 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) ELSE Normal_Dyn_Array(type$, var$, array$, FALSE) 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 check = Search(g_HFILE$, "char *" & var$ & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & var$ & " = NULL;") ENDIF IF check < 0 THEN FOR str$ IN var$ STEP "," ' 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 *", CHOP$(str$), ";" TO g_CFILE 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_RECORDVAR$ & "." & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr]!=NULL){free(" & g_RECORDVAR$ & "." & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr]);}" ELSE WRITELN "char *", CHOP$(str$), "; /* noparse */" TO g_CFILE END IF ELSE IF REGEX(str$, "\\[.*\\]") THEN WRITELN "char *", CHOP$(str$), " = { NULL};" TO g_CFILE 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){free(" & g_WITHVAR$ & LEFT$(str$, INSTR(str$, "[")-1) & "[__b2c__ctr]);}" ELSE WRITELN "char *", CHOP$(str$), " = NULL;" TO g_CFILE ' Pointer var should not be initialized IF INSTR(str$, g_STRINGSIGN$) THEN WRITELN CHOP$(str$), " = calloc(1, sizeof(char));" TO g_CFILE g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & CHOP$(str$) END IF END IF END IF ' We are in the mainprogram ELSE IF ISTRUE(LEN(g_RECORDNAME$)) THEN WRITELN "char *", CHOP$(str$), "; /* noparse */" TO g_HFILE ELSE IF REGEX(str$, "\\[.*\\]") THEN WRITELN "char *", CHOP$(str$), " = { NULL };" TO g_HFILE ELSE WRITELN "char *", CHOP$(str$), " = NULL; " TO g_HFILE ' Pointer var should not be initialized IF INSTR(str$, g_STRINGSIGN$) THEN WRITELN CHOP$(str$), " = calloc(1, sizeof(char));" TO g_CFILE END IF END IF END IF NEXT END IF ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND INSTR(var$, "=") THEN IF ISTRUE(LEN(g_FUNCNAME$)) THEN ' String array assignment WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_CFILE option = g_OPTION_BASE WHILE option > 0 WRITELN " \"\", " TO g_CFILE DECR option WEND WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_CFILE ELSE ' String array assignment WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE option = g_OPTION_BASE WHILE option > 0 WRITELN " \"\", " TO g_HFILE DECR option WEND WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE END IF ' Assume number or complicated type ELSE IF ISTRUE(LEN(g_FUNCNAME$)) THEN IF ISTRUE(LEN(g_RECORDNAME$)) THEN WRITELN type$, " ", var$, "; /* noparse */" TO g_CFILE ELSE IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN FOR str$ IN var$ STEP "," WRITELN type$, " ", str$, " = { 0 };" TO g_CFILE NEXT ELIF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN ' Numeric array assignment WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_CFILE option = g_OPTION_BASE WHILE option > 0 WRITELN " 0, " TO g_CFILE DECR option WEND WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_CFILE ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND NOT(INSTR(var$, "*")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN WRITELN type$, " ", var$, ";" TO g_CFILE WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE ELSE WRITELN type$, " ", var$, ";" TO g_CFILE END IF END IF ELSE IF ISTRUE(LEN(g_RECORDNAME$)) THEN WRITELN type$, " ", var$, "; /* noparse */" TO g_HFILE ELSE IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN FOR str$ IN var$ STEP "," WRITELN type$, " ", str$, " = { 0 };" TO g_HFILE NEXT ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN ' Numeric array assignment WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE option = g_OPTION_BASE WHILE option > 0 WRITELN " 0, " TO g_HFILE DECR option WEND WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND NOT(INSTR(var$, "*")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN WRITELN type$, " ", var$, ";" TO g_HFILE WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE ELSE WRITELN type$, " ", var$, ";" TO g_HFILE END IF END IF END IF END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Read(STRING arg$) LOCAL check LOCAL type$, element$ ' 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 type of var, string? IF RIGHT$(element$, LEN(g_STRINGSIGN$)) = g_STRINGSIGN$ THEN check = Search(g_HFILE$, "char *" & element$ & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & element$ & " = NULL;") ENDIF IF check < 0 THEN WRITELN "char *", element$, " = NULL;" TO g_HFILE ' Convert to C WRITELN element$, " = (char*)realloc(", element$, ", (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" TO g_CFILE WRITELN "strcpy(", element$, ", __b2c__stringarray[__b2c__stringarray_ptr]);" TO g_CFILE WRITELN "__b2c__stringarray_ptr++;" TO g_CFILE ELSE ' Variable may not be array, these should be defined with DECLARE type$ = "" IF NOT(REGEX(element$, "\\[.*\\]")) AND NOT(INSTR(element$, ".")) THEN ' Not declared? Assume long check = Check_Declared(g_HFILE$, element$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, element$) IF ISFALSE(check) THEN WRITELN "long ", element$, ";" TO g_HFILE type$ = "long " ENDIF END IF ' See how var was declared IF LEN(type$) = 0 THEN type$ = Check_Type$(g_HFILE$, element$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, element$) END IF END IF ' Convert to C IF INSTR(type$, "char* ") OR INSTR(type$, "char *") OR INSTR(type$, "STRING ") THEN WRITELN element$, " = (char*)realloc(", element$, ", (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" TO g_CFILE WRITELN "strcpy(", element$, ", __b2c__stringarray[__b2c__stringarray_ptr]);" TO g_CFILE WRITELN "__b2c__stringarray_ptr++;" TO g_CFILE ELSE WRITELN element$, " = (", LEFT$(type$, INSTR(type$, " ")), ")__b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE END IF END IF NEXT 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 "fprintf(stdout,\"\\033[0m\"); fflush(stdout);" TO g_CFILE ELIF element$[1] = "INTENSE" THEN WRITELN "fprintf(stdout,\"\\033[1m\"); fflush(stdout);" TO g_CFILE ELIF element$[1] = "INVERSE" THEN WRITELN "fprintf(stdout,\"\\033[7m\"); fflush(stdout);" TO g_CFILE ELIF element$[1] = "NORMAL" THEN WRITELN "fprintf(stdout,\"\\033[22m\"); 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 ' 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 SPLIT arg$ BY "," TO element$ SIZE dim IF dim EQ 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$(element$[2]), "), (long)(", CHOP$(element$[1]), ")); fflush(stdout);" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Split(STRING arg$) LOCAL source$, rest$, by$, to$, size$ LOCAL check, 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 BY is available IF NOT(INSTR(arg$, " BY ")) THEN EPRINT NL$, "Syntax error: missing BY in SPLIT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF ' Check if TO is available IF NOT(INSTR(arg$, " TO ")) THEN 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 ' 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 ' Variable may not be array, these should be defined with DECLARE IF NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) THEN check = Check_Declared(g_HFILE$, size$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$) IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE END IF ' Translate to C code IF ISTRUE(LEN(g_FUNCNAME$)) THEN IF NOT(INSTR(g_STRINGARGS$, "**" & to$)) THEN g_STRINGARGS$ = g_STRINGARGS$ & " char **" & to$ & " = NULL; char *__b2c__" & to$ & "__dup = NULL; int __b2c__split__" & to$ & " = " & STR$(g_OPTION_BASE) & ";" END IF ELSE check = Search(g_HFILE$, to$ & " = NULL;") IF check < 0 THEN WRITELN "char **", to$, " = NULL; char *__b2c__", to$, "__dup = NULL; int __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_HFILE END IF END IF ' If the split array was used before in a loop, clear it 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){free(", 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) {free(__b2c__", to$, "__dup); __b2c__", to$, "__dup = NULL;}" TO g_CFILE ' Run the SPLIT code WRITELN "if (", source$, " != NULL && strlen(", source$, ") > 0 && ", by$, " != NULL && strlen(", by$, ") > 0) {__b2c__", to$, "__dup = __b2c__strdup(", source$, "); __b2c__split_tmp = __b2c__", to$, "__dup;" TO g_CFILE WRITELN "while(1) {if((__b2c__split = strstr(__b2c__split_tmp, ", by$, ")) != NULL) *__b2c__split = '\\0'; if(strlen(__b2c__split_tmp) >0 || (strlen(__b2c__split_tmp) == 0 && __b2c__collapse == 0)) {" TO g_CFILE WRITELN to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*)); " TO g_CFILE IF INSTR(to$, g_STRINGSIGN$) THEN WRITELN to$, "[__b2c__split__", to$, "++] = __b2c__strdup(__b2c__split_tmp); } " TO g_CFILE ELSE WRITELN to$, "[__b2c__split__", to$, "++] = __b2c__split_tmp; } " TO g_CFILE WRITELN "if(__b2c__split == NULL) break; __b2c__split_tmp = __b2c__split + strlen(", by$, "); } } ", size$, " = __b2c__split__", to$, " - ", g_OPTION_BASE, "; if(__b2c__split__", to$, " > 0) __b2c__split__", to$, "--;" 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__split__" & to$ & ";__b2c__ctr++) if(" & to$ & "[__b2c__ctr]!=NULL){free(" & 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$ LOCAL check ' 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 BY is available IF NOT(INSTR(arg$, " BY ")) THEN EPRINT NL$, "Syntax error: missing BY in JOIN 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 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 ' 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)) ' Check type of var, string? IF NOT(INSTR(to$, g_STRINGSIGN$)) 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 NOT(REGEX(to$, "\\[.*\\]")) THEN ' Is variable declared already? check = Search(g_HFILE$, "char *" & to$ & " = NULL;") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & to$ & " = NULL;") ENDIF IF check < 0 THEN WRITELN "char *", to$, " = NULL;" TO g_HFILE END IF ENDIF WRITELN to$, "=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$, "=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, "]);} }" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Sort(STRING arg$) LOCAL dim$, type$, var$, down$ LOCAL check ' Check if we have an argument at all IF ISFALSE(LEN(CHOP$(arg$))) THEN 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") + 5)) var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "SIZE") - 1)) ELSE var$ = arg$ END IF ' Check on DOWN argument IF INSTR(arg$, "DOWN") THEN IF LEN(dim$) > 0 THEN dim$ = CHOP$(LEFT$(dim$, INSTR(dim$, "DOWN") - 1)) var$ = CHOP$(LEFT$(var$, INSTR(var$, "DOWN") - 1)) down$ = "_down" ELSE down$ = "" END IF ' Declared before? IF INSTR(var$, g_STRINGSIGN$) THEN check = Search(g_HFILE$, "char *" & var$ & "[") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "char *" & var$ & "[") ENDIF ELSE check = Check_Declared(g_HFILE$, var$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$) END IF ' Verify if the array was declared at SPLIT IF check < 0 THEN check = Search(g_HFILE$, "__b2c__split__" & var$) IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, "__b2c__split__" & var$) ENDIF IF ISFALSE(check) THEN EPRINT NL$, "Syntax error: argument to SORT not an array at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELIF LEN(dim$) = 0 THEN dim$ = "__b2c__split__" & var$ & "+1" END IF ELIF LEN(dim$) = 0 THEN ' See how var was declared type$ = Check_Type$(g_HFILE$, var$ & "[") IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, var$ & "[") ENDIF dim$ = MID$(type$, INSTR(type$, "[") + 1, INSTR(type$, "]") - INSTR(type$, "[") - 1) END IF ' Check if we have a string IF INSTR(var$, g_STRINGSIGN$) THEN WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(char*), __b2c__sortstr", down$, ");" TO g_CFILE ' It is a value ELSE ' See how var was declared type$ = Check_Type$(g_HFILE$, var$ & "[") IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, var$ & "[") IF INSTR(type$, "double ") OR INSTR(type$, "FLOATING ") THEN WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(double), __b2c__sortnrd", down$, ");" TO g_CFILE ELIF INSTR(type$, "float ") THEN WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(float), __b2c__sortnrf", down$, ");" TO g_CFILE ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(long), __b2c__sortnrl", down$, ");" TO g_CFILE ELSE WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(int), __b2c__sortnri", down$, ");" TO g_CFILE END IF END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Alias(STRING arg$) LOCAL dim ' Check if we have an argument at all IF ISFALSE(LEN(CHOP$(arg$))) THEN EPRINT NL$, "Syntax error: empty ALIAS at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF ' Get the target and colorname SPLIT EXTRACT$(arg$, CHR$(34)) BY "TO" TO element$ SIZE dim IF dim EQ 1 THEN EPRINT NL$, "Syntax error: missing TO in ALIAS statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF ' Translate to C WRITELN "#define ", element$[2], " ", element$[1] TO g_HFILE g_IMPORTED$ = element$[2] & " " & g_IMPORTED$ END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Lookup(STRING arg$) LOCAL source$, rest$, to$, size$ LOCAL check, 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$, ".")) THEN check = Check_Declared(g_HFILE$, size$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$) IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE END IF ' Translate to C code IF ISTRUE(LEN(g_FUNCNAME$)) THEN IF NOT(INSTR(g_STRINGARGS$, "**" & to$)) THEN g_STRINGARGS$ = g_STRINGARGS$ & " char **" & to$ & " = NULL; int __b2c__split__" & to$ & " = " & STR$(g_OPTION_BASE) & ";" END IF ELSE check = Search(g_HFILE$, to$ & " = NULL;") IF check < 0 THEN WRITELN "char **", to$, " = NULL; int __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_HFILE END IF END IF ' If the split array was used before in a loop, clear it WRITELN "if(", to$, " != NULL) {for(__b2c__ctr=", g_OPTION_BASE, "; __b2c__ctr <= __b2c__split__", to$, "; __b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL)" TO g_CFILE WRITELN "{free(", to$, "[__b2c__ctr]);} free(", to$, "); ", to$, " = NULL;} __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_CFILE ' Run the LOOKUP code WRITELN "for(__b2c__ctr = ", g_OPTION_BASE, "; __b2c__ctr < __b2c__", source$, "_idx + ", g_OPTION_BASE, "; __b2c__ctr++)", "{", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*));" TO g_CFILE IF INSTR(to$, g_STRINGSIGN$) THEN WRITELN to$, "[__b2c__split__", to$, "++] = __b2c__strdup(__b2c__", source$, "[__b2c__ctr-", g_OPTION_BASE, "].key);" TO g_CFILE ELSE WRITELN to$, "[__b2c__split__", to$, "++] = __b2c__", source$, "[__b2c__ctr-", g_OPTION_BASE, "].key;" TO g_CFILE WRITELN "} ", size$, " = __b2c__split__", to$, " - ", g_OPTION_BASE, ";if(__b2c__split__", to$, " > 0) __b2c__split__", to$, "--;" TO g_CFILE ' Add declared array to array list if we are in a function IF ISTRUE(LEN(g_FUNCNAME$)) AND NOT(INSTR(g_STRINGARRAYS$, 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__split__" & to$ & ";__b2c__ctr++) if(" & to$ & "[__b2c__ctr]!=NULL){free(" & to$ & "[__b2c__ctr]);} }" ENDIF g_LOCALSTRINGS$ = g_LOCALSTRINGS$ & " " & to$ ENDIF END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Relate(STRING arg$) LOCAL source$, to$, txt$, str$ LOCAL declared LOCAL thefile TYPE FILE* ' 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 OPEN g_HFILE$ FOR READING AS thefile WHILE NOT(ENDFILE(thefile)) DO READLN txt$ FROM thefile IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN declared = REGEX(txt$, "__b2c__" & source$ & "_type") IF ISTRUE(declared) THEN BREAK END IF WEND IF NOT(declared) THEN EPRINT NL$, "Syntax error: variable ", source$, " not declared in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF ' Assign relations FOR str$ IN to$ STEP "," WHILE NOT(ENDFILE(thefile)) DO READLN txt$ FROM thefile IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN declared = REGEX(txt$, "__b2c__" & CHOP$(str$) & "_type") IF ISTRUE(declared) THEN BREAK END IF WEND IF NOT(declared) THEN EPRINT NL$, "Syntax error: variable ", CHOP$(str$), " not declared in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF g_RELATE$[g_RELATE_CTR] = source$ & " " & CHOP$(str$) INCR g_RELATE_CTR NEXT CLOSE FILE thefile END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Data(STRING arg$) LOCAL in_string, pos, escaped, x, cctr, fctr ' 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 ' Start miniparser in_string = FALSE pos = 1 escaped = 0 FOR x = 1 TO LEN(arg$) SELECT MID$(arg$, x, 1) CASE "," IF ISFALSE(in_string) THEN IF INSTR(MID$(arg$, pos, x-pos), CHR$(34)) THEN WRITELN MID$(arg$, pos, x-pos), ", " TO STRINGARRAYFILE INCR cctr ELSE WRITELN MID$(arg$, pos, x-pos), ", " TO FLOATARRAYFILE INCR fctr END IF pos = x+1 escaped = FALSE END IF CASE CHR$(92) escaped = TRUE CASE CHR$(34) IF ISFALSE(escaped) THEN in_string = NOT(in_string) END IF escaped = FALSE DEFAULT escaped = FALSE END SELECT NEXT arg$ = MID$(arg$, pos) ' Write last element to file IF INSTR(arg$, CHR$(34)) THEN WRITELN arg$, ", " TO STRINGARRAYFILE INCR cctr ELSE WRITELN arg$, ", " TO FLOATARRAYFILE INCR fctr END IF WRITELN "__b2c__stringarray_ctr += ", cctr, ";" TO g_CFILE WRITELN "__b2c__floatarray_ctr += ", fctr, ";" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Redim(STRING arg$) LOCAL type$, var$, to$, mem$ LOCAL check ' 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)) ' See if we have a struct member IF INSTR(var$, ".") THEN mem$ = MID$(var$, INSTR(var$, ".")+1) ELSE mem$ = var$ END IF check = Search(g_HFILE$, " " & mem$ & ";") IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN check = Search(g_CFILE$, " " & mem$ & ";") ENDIF IF ISFALSE(check) 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 ' Get the type type$ = Check_Type$(g_HFILE$, mem$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, mem$) END IF ' Delete old data from strings if new size is smaller IF INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") THEN WRITELN "if(", to$, "<__b2c_array_", mem$, ") {for(__b2c__ctr=", to$, "+", g_OPTION_BASE, "; __b2c__ctr<__b2c_array_", mem$, "+", g_OPTION_BASE, "; __b2c__ctr++) {if(", var$, "[__b2c__ctr]!=NULL) free(", var$, "[__b2c__ctr]);} }" TO g_CFILE END IF ' Realloc type$ = CHOP$(LEFT$(type$, INSTR(type$, " ")-1)) WRITELN var$, " = (", type$, ")realloc(", var$, ", (", to$, "+", g_OPTION_BASE, ")*sizeof(", LEFT$(type$, LEN(type$)-1), "));" TO g_CFILE ' Re-initialize strings if new area is bigger IF INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") THEN WRITELN "if(", to$, ">__b2c_array_", mem$, ") {for(__b2c__ctr=__b2c_array_", mem$, "+", g_OPTION_BASE, "; __b2c__ctr<", to$, "+", g_OPTION_BASE, "; __b2c__ctr++) ", var$, "[__b2c__ctr] = calloc(1, sizeof(char));}" TO g_CFILE WRITELN "__b2c_array_", mem$, " = ", to$, ";" TO g_CFILE END IF END SUB '---------------------------------------------------------------------------------------------- SUB Handle_Swap(STRING arg$) LOCAL var$, to$, type$, tmp$ LOCAL check ' 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)) ' Determine type IF INSTR(var$, g_STRINGSIGN$) THEN type$ = "char *" ELSE type$ = Check_Type$(g_HFILE$, var$) IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, var$) END IF 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 type$ = MID$(type$, 1, INSTR(type$, " ")-1) END IF ' Get rid of array syntax IF INSTR(var$, "[") THEN tmp$ = LEFT$(var$, INSTR(var$, "[")-1) ELSE tmp$ = var$ ENDIF ' Declare temp variable IF LEN(g_FUNCNAME$) > 0 THEN check = Search(g_CFILE$, " __b2c__" & tmp$ & "_swap;") IF check < 0 THEN WRITELN type$, " __b2c__", tmp$, "_swap;" TO g_CFILE ENDIF ELSE check = Search(g_HFILE$, " __b2c__" & tmp$ & "_swap;") IF check < 0 THEN WRITELN type$, " __b2c__", tmp$, "_swap;" TO g_HFILE ENDIF ENDIF WRITELN "__b2c__", tmp$, "_swap = ", var$, "; ", var$, " = ", to$, "; ", to$, " = __b2c__", tmp$, "_swap;" TO g_CFILE 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); 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE END SUB '---------------------------------------------------------------------------------------------- ' ' Simple parser to tokenize line. ' ' Each line should begin with a statement. ' The rest of the line may contain functions, these are ' converted using C macros. ' '---------------------------------------------------------------------------------------------- SUB Parse_Line(STRING statement$) LOCAL inc$, copy_curfile$, total$, txt$, exp$, lft$, str$, newfeed$ LOCAL dim, i, found, copy_counter, to_parse, size LOCAL newfile TYPE FILE* SPLIT statement$ BY " " TO element$ SIZE dim IF dim > 0 THEN ' Check if enclosed IF/ELIF/ELSE needs to be closed IF g_IF_PARSE = 1 THEN IF element$[1] <> "ELIF" AND element$[1] <> "ELSE" THEN WRITELN "}" TO g_CFILE g_IF_PARSE = 0 END IF END IF ' In TRACE MODE show linenr and code IF g_TRACE = 1 AND NOT(INSTR(statement$, "FUNCTION ")) AND NOT(INSTR(statement$, "SUB ")) THEN WRITELN "if(__b2c__getch() == 27) exit(EXIT_SUCCESS); /* noparse */" TO g_CFILE txt$ = REPLACE$(statement$, CHR$(34), "'") IF INSTR(txt$, " FORMAT ") THEN txt$ = REPLACE$(txt$, "%", ":") END IF WRITELN "fprintf(stderr, \"", g_CURFILE$, " %d: ", txt$, "\\n\", ", g_COUNTER, "); /* noparse */" TO g_CFILE END IF ' See if we need to pass C code IF ISTRUE(g_USE_C) THEN IF LEFT$(statement$, 8) = "END USEC" OR element$[1] = "ENDUSEC" THEN g_USE_C = 0 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 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 "__b2c__assign=(char*)__b2c__strdup(strtok_r(NULL, ", g_LOOPSTEP$[g_LOOPCTR], ", &__b2c__forin_", g_LOOPVAR$[g_LOOPCTR], "_end)); if(", g_LOOPVAR$[g_LOOPCTR], " != NULL) free(", g_LOOPVAR$[g_LOOPCTR], "); ", g_LOOPVAR$[g_LOOPCTR], " = __b2c__assign; }" TO g_CFILE WRITELN "if(__b2c__forin_", g_LOOPVAR$[g_LOOPCTR], "!=NULL) { free(__b2c__forin_", g_LOOPVAR$[g_LOOPCTR], "); __b2c__forin_", g_LOOPVAR$[g_LOOPCTR], " = NULL; }" TO g_CFILE g_LOOPVAR$[g_LOOPCTR]="" g_LOOPSTEP$[g_LOOPCTR]="" ELSE WRITELN "}" TO g_CFILE END IF IF g_LOOPCTR > 0 THEN DECR g_LOOPCTR IF g_LOOPCTR > 0 THEN WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE END IF END IF CASE "IF" ' Check if THEN is available g_IF_PARSE = 0 IF ISFALSE(INSTRREV(statement$, " THEN")) THEN 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 CALL Tokenize(MID$(statement$, INSTRREV(statement$, " THEN") + 5)) g_IF_PARSE = 1 END IF ENDIF CASE "ELIF" ' Check if THEN is available g_IF_PARSE = 0 IF ISFALSE(INSTRREV(statement$, " THEN")) THEN 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))) WRITELN "} else if(", exp$, "){" TO g_CFILE IF LEN(CHOP$(MID$(statement$, INSTRREV(statement$, " THEN") + 5))) > 0 THEN CALL Tokenize(MID$(statement$, INSTRREV(statement$, " THEN") + 5)) g_IF_PARSE = 1 END IF END IF CASE "ELSE" ' Translate function to C function g_IF_PARSE = 0 WRITELN "} else {" TO g_CFILE IF LEN(CHOP$(MID$(statement$, INSTR(statement$, " ELSE") + 5))) > 0 THEN CALL Tokenize(MID$(statement$, INSTR(statement$, " ELSE") + 5)) g_IF_PARSE = 1 END IF CASE "ENDIF" WRITELN "}" TO g_CFILE CASE "FI" WRITELN "}" TO g_CFILE CASE "WHILE" INCR g_LOOPCTR Handle_While(MID$(statement$, INSTR(statement$, "WHILE") + 5)) CASE "WEND" WRITELN "}" TO g_CFILE IF g_LOOPCTR > 0 THEN DECR g_LOOPCTR IF g_LOOPCTR > 0 THEN WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE END IF END IF CASE "BREAK" ' Check argument IF dim > 1 AND VAL(MID$(statement$, INSTR(statement$, "BREAK") + 5)) NE 0 THEN WRITELN "__b2c__break_ctr = ", MID$(statement$, INSTR(statement$, "BREAK") + 5), "-1; __b2c__break_flag = 1;" TO g_CFILE END IF WRITELN "break;" TO g_CFILE CASE "CONTINUE" ' Check argument IF dim > 1 AND VAL(MID$(statement$, INSTR(statement$, "CONTINUE") + 8)) NE 0 THEN WRITELN "__b2c__break_ctr = ", MID$(statement$, INSTR(statement$, "CONTINUE") + 8), "-1; __b2c__break_flag = 2;" TO g_CFILE END IF IF VAL(MID$(statement$, INSTR(statement$, "CONTINUE") + 8)) > 1 THEN WRITELN "break;" TO g_CFILE ELSE WRITELN "continue;" TO g_CFILE END IF CASE "REPEAT" INCR g_LOOPCTR WRITELN "do{" TO g_CFILE CASE "UNTIL" ' Check argument IF dim EQ 1 THEN 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 THEN DECR g_LOOPCTR IF g_LOOPCTR > 0 THEN WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE END IF END IF END IF CASE "LET" Handle_Let(MID$(statement$, INSTR(statement$, "LET") + 3)) CASE "SYSTEM" ' Check argument IF dim EQ 1 THEN 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 EQ 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 SELECT element$[2] CASE "FILE" WRITELN "fclose(", element$[3], ");" TO g_CFILE CASE "DIRECTORY" WRITELN "closedir(", element$[3], ");" TO g_CFILE CASE "MEMORY" WRITELN element$[3], " = NULL;" TO g_CFILE CASE "NETWORK"; CASE "SERVER"; CASE "UDP"; CASE "DEVICE" WRITELN "close(", element$[3], ");" TO g_CFILE 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 EQ 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 EQ 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" IF dim > 1 THEN SELECT element$[2] CASE "IF" WRITELN "}" TO g_CFILE CASE "RECORD" IF LEN(g_FUNCNAME$) > 0 THEN WRITELN "};" TO g_CFILE WRITELN "struct ", g_RECORDNAME$, " ", g_RECORDVAR$, " = { 0 } ;" TO g_CFILE ELSE WRITELN "};" TO g_HFILE WRITELN "struct ", g_RECORDNAME$, " ", g_RECORDVAR$, " = { 0 } ;" TO g_HFILE 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$ = "" ' 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$ = "" DECR g_SELECTVAR_CTR END IF DEFAULT WRITELN "exit(", element$[2], ");" TO g_CFILE END SELECT ELSE WRITELN "exit(EXIT_SUCCESS);" TO g_CFILE END IF CASE "SUB" Handle_SubFunc(MID$(statement$, INSTR(statement$, "SUB") + 3)) CASE "ENDSUB" Handle_Endsub CASE "ENDWITH" g_WITHVAR$ = "" CASE "ENDSELECT" IF g_SELECTVAR_CTR = 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$ = "" DECR g_SELECTVAR_CTR END IF CASE "CALL" ' Check argument IF dim EQ 1 THEN EPRINT NL$, "Syntax error: empty CALL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE exp$ = MID$(statement$, INSTR(statement$, "CALL ") + 5) IF INSTR(statement$, " TO ") THEN IF INSTR(MID$(exp$, INSTR(exp$, " TO ") + 4), g_STRINGSIGN$) THEN IF INSTR(exp$, "(") THEN WRITELN "__b2c__assign=(char*)__b2c__strdup(", MID$(exp$, 1, INSTR(exp$, " TO ")-1), ");" TO g_CFILE ELSE WRITELN "__b2c__assign=(char*)__b2c__strdup(", MID$(exp$, 1, INSTR(exp$, " TO ")-1), "());" TO g_CFILE END IF WRITELN "if(__b2c__assign==NULL)__b2c__assign=calloc(1, sizeof(char)); if(", MID$(exp$, INSTR(exp$, " TO ")+4)," != NULL) free(", MID$(exp$, INSTR(exp$, " TO ")+4), "); ", MID$(exp$, INSTR(exp$, " TO ")+4), " = __b2c__assign;" TO g_CFILE ELSE WRITELN MID$(exp$, INSTR(exp$, " TO ")+4), "=" TO g_CFILE IF INSTR(exp$, "(") THEN WRITELN MID$(exp$, 1, INSTR(exp$, " TO ")-1), ";" TO g_CFILE ELSE WRITELN MID$(exp$, 1, INSTR(exp$, " TO ")-1), "();" TO g_CFILE END IF END IF ELSE IF INSTR(exp$, "(") THEN WRITELN exp$, ";" TO g_CFILE ELSE WRITELN exp$, "();" TO g_CFILE END IF END IF END IF CASE "FUNCTION" Handle_SubFunc(MID$(statement$, INSTR(statement$, "FUNCTION") + 8)) CASE "ENDFUNCTION" Handle_Endfunction CASE "RETURN" Handle_Return(MID$(statement$, INSTR(statement$, "RETURN") + 6)) CASE "IMPORT" Handle_Import(MID$(statement$, INSTR(statement$, "IMPORT") + 6)) CASE "DECLARE" Handle_Declare(MID$(statement$, INSTR(statement$, "DECLARE") + 7)) CASE "GLOBAL" Handle_Declare(MID$(statement$, INSTR(statement$, "GLOBAL") + 6)) CASE "LOCAL" Handle_Local(MID$(statement$, INSTR(statement$, "LOCAL") + 5)) CASE "DATA" Handle_Data(MID$(statement$, INSTR(statement$, "DATA") + 4)) CASE "RESTORE" IF dim EQ 1 THEN WRITELN "if(__b2c__floatarray_ptr > 0) __b2c__floatarray_ptr = 0;" TO g_CFILE WRITELN "if(__b2c__stringarray_ptr > 0) __b2c__stringarray_ptr = 0;" TO g_CFILE ELSE WRITELN "if(__b2c__floatarray_ptr > 0) __b2c__floatarray_ptr = __b2c__label_floatarray_", element$[2], ";" TO g_CFILE WRITELN "if(__b2c__stringarray_ptr > 0) __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 EQ 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 argument IF NOT(FILEEXISTS(inc$)) OR dim EQ 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 "\r\033[0J"; ' Check if the C Preprocessor needs to run IF ISTRUE(g_CPP) THEN IF ISTRUE(LEN(EXEC$("which cpp 2>/dev/null"))) THEN SYSTEM "cpp -P -w " & inc$ & " " & inc$ & ".cpp" newfeed$ = inc$ & ".cpp" g_TMP_FILES$ = g_TMP_FILES$ & " " & inc$ & ".cpp" 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$ ' Get rid of absolute path g_CURFILE$ = MID$(newfeed$, INSTRREV(newfeed$, "/") + 1) OPEN newfeed$ FOR READING AS newfile WHILE NOT(ENDFILE(newfile)) DO PRINT "\rConverting '", newfeed$, "'... ", g_COUNTER, "\033[0J"; 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 NOT(ENDFILE(newfile)) AND LEN(txt$) > 0 AND to_parse > 0 THEN IF RIGHT$(txt$, 2) = " \\" AND LEFT$(txt$, 3) != "REM" AND LEFT$(txt$, 1) != CHR$(39) THEN total$ = total$ & LEFT$(txt$, LEN(txt$)-2) ELSE WRITELN "/* noparse ", newfeed$, " BACON LINE ", g_COUNTER, " */" TO g_HFILE WRITELN "/* noparse ", newfeed$, " BACON LINE ", g_COUNTER, " */" TO g_CFILE total$ = CHOP$(total$ & txt$) IF LEFT$(total$, 3) != "REM" AND LEFT$(total$, 1) != CHR$(39) THEN CALL Tokenize(total$) END IF LET total$ = "" END IF ENDIF ' See if we need to stop parsing IF to_parse = 1 AND INSTR(txt$, "END") AND REGEX(txt$, "SUB|FUNCTION") THEN to_parse = 0 ' Increase line number INCR g_COUNTER WEND CLOSE FILE newfile ' Restore original counter g_COUNTER = copy_counter ' Restore original file g_CURFILE$ = copy_curfile$ END IF CASE "POKE" ' Check argument IF dim EQ 1 THEN EPRINT NL$, "Syntax error: empty POKE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE exp$ = MID$(statement$, INSTR(statement$, "POKE") + 4) WRITELN "if (!__b2c__trap){if(__b2c__memory__check((char*)", MID$(exp$, 1, INSTR(exp$, ",")-1), ")) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"POKE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE WRITELN "*(", g_OPTION_MEMTYPE$, "*)(", MID$(exp$, 1, INSTR(exp$, ",")-1), ") = ( ", g_OPTION_MEMTYPE$, ")(", MID$(exp$, INSTR(exp$, ",")+1), ");" TO g_CFILE END IF CASE "RESIZE" ' Check argument IF dim EQ 1 THEN 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$ = MID$(exp$, 1, INSTR(exp$, ",") - 1) str$ = MID$(exp$, INSTR(exp$, ",") + 1) WRITELN "if(!__b2c__trap) {if(__b2c__memory__check((void*)", lft$, ")) {ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"RESIZE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE WRITELN "switch(__b2c__memtype) {case 1: ", lft$, " = (long)realloc((void*)", lft$, ", sizeof(char)*(", str$, "+1)); break;" TO g_CFILE WRITELN "case 2: ", lft$, " = (long)realloc((void*)", lft$, ", sizeof(short)*(", str$, "+1)); break;" TO g_CFILE WRITELN "case 3: ", lft$, " = (long)realloc((void*)", lft$, ", sizeof(int)*(", str$, "+1)); break;" TO g_CFILE WRITELN "case 4: ", lft$, " = (long)realloc((void*)", lft$, ", sizeof(long)*(", str$, "+1)); break;" TO g_CFILE WRITELN "case 5: ", lft$, " = (long)realloc((void*)", lft$, ", sizeof(float)*(", str$, "+1)); break;" TO g_CFILE WRITELN "case 6: ", lft$, " = (long)realloc((void*)", lft$, ", sizeof(double)*(", str$, "+1)); break;" TO g_CFILE WRITELN "case 7: ", lft$, " = (long)realloc((void*)", lft$, ", sizeof(char*)*(", str$, "+1)); break;}" TO g_CFILE WRITELN "if(!__b2c__trap) {if((void*)", lft$, " == NULL) {ERROR=6; if(!__b2c__catch_set) RUNTIMEERROR(\"RESIZE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE END IF CASE "COPY" Handle_Copy(MID$(statement$, INSTR(statement$, "COPY") + 4)) CASE "DELETE" ' Check argument IF dim EQ 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE ELIF element$[2] = "RECURSIVE" THEN WRITELN "if (__b2c__rmrecursive(", MID$(statement$, INSTR(statement$, " RECURSIVE ") + 11), ") == -1){if(!__b2c__trap){ERROR = 20;if(!__b2c__catch_set) RUNTIMEERROR(\"DELETE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" 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 EQ 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE END IF CASE "CHANGEDIR" ' Check argument IF dim EQ 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE END IF CASE "FREE" ' Check argument IF dim EQ 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(element$[2], "\\(.*\\)") THEN exp$ = MID$(element$[2], INSTR(element$[2], " ")+1) IF INSTR(exp$, "(") THEN exp$ = LEFT$(exp$, INSTR(exp$, "(")-1) WRITELN "__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__location = __b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1), ";" TO g_CFILE IF INSTR(exp$, g_STRINGSIGN$) THEN WRITELN "if(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__location != NULL) {free(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__location->value);" TO g_CFILE WRITELN "__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__location->value = NULL;}" TO g_CFILE ELSE WRITELN "if(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__location != NULL) {__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__location->value = 0;}" TO g_CFILE ENDIF WRITELN "__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__del(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__location);" TO g_CFILE ELSE WRITELN "if(!__b2c__trap){if(__b2c__memory__check((char *)", element$[2], "))" TO g_CFILE WRITELN "{ERROR=1; if(!__b2c__catch_set) RUNTIMEERROR(\"FREE\", ", g_COUNTER, ", \"", g_CURFILE$, "\", ERROR); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} } free((void*)", element$[2], ");" TO g_CFILE END IF END IF CASE "GOTO" ' Check argument IF dim EQ 1 THEN 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 EQ 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); 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 END IF CASE "LABEL" ' Check argument IF dim EQ 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 WRITELN "int __b2c__label_floatarray_", element$[2], ";" TO g_HFILE WRITELN "__b2c__label_floatarray_", element$[2], " = __b2c__floatarray_ctr;" TO g_CFILE WRITELN "int __b2c__label_stringarray_", element$[2], ";" TO g_HFILE WRITELN "__b2c__label_stringarray_", element$[2], " = __b2c__stringarray_ctr;" TO g_CFILE END IF CASE "TRAP" ' Check argument IF dim EQ 1 THEN EPRINT NL$, "Syntax error: empty TRAP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE IF element$[2] = "SYSTEM" THEN WRITELN "/* Error catching is enabled */" TO g_CFILE WRITELN "__b2c__trap = 1;" TO g_CFILE WRITELN "signal(SIGILL, __b2c__catch_signal);" TO g_CFILE WRITELN "signal(SIGABRT, __b2c__catch_signal);" TO g_CFILE WRITELN "signal(SIGFPE, __b2c__catch_signal);" TO g_CFILE WRITELN "signal(SIGSEGV, __b2c__catch_signal);" TO g_CFILE ELIF element$[2] = "LOCAL" THEN WRITELN "/* Error catching is disabled */" TO g_CFILE WRITELN "__b2c__trap = 0;" TO g_CFILE WRITELN "signal(SIGILL, SIG_DFL);" TO g_CFILE WRITELN "signal(SIGABRT, SIG_DFL);" TO g_CFILE WRITELN "signal(SIGFPE, SIG_DFL);" TO g_CFILE WRITELN "signal(SIGSEGV, SIG_DFL);" TO g_CFILE ELSE 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 EQ 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] = "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 EQ 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 ' Translate to C typedef struct IF ISTRUE(LEN(g_FUNCNAME$)) THEN g_RECORDNAME$ = "RECORD_" & g_FUNCNAME$ & "_" & STR$(g_COUNTER) WRITELN "struct ", g_RECORDNAME$, "{" TO g_CFILE ELSE g_RECORDNAME$ = "RECORD_" & STR$(g_COUNTER) WRITELN "struct ", g_RECORDNAME$, "{" TO g_HFILE END IF g_RECORDVAR$ = element$[2] END IF CASE "WITH" ' Check argument IF dim EQ 1 THEN 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 EQ 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$ = "" END IF CASE "CASE" ' Check argument IF dim EQ 1 THEN EPRINT NL$, "Syntax error: empty CASE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE size = INSTR(g_SELECTVAR$[g_SELECTVAR_CTR], "(")-1 IF size < 0 THEN size = LEN(g_SELECTVAR$[g_SELECTVAR_CTR]) IF ISTRUE(g_IN_CASE[g_SELECTVAR_CTR]) THEN IF INSTR(MID$(g_SELECTVAR$[g_SELECTVAR_CTR], 1, size), g_STRINGSIGN$) THEN IF RIGHT$(statement$, 1) = ";" THEN exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4) g_CASE_FALL$ = "|| !__b2c__strcmp(" & g_SELECTVAR$[g_SELECTVAR_CTR] & ", " & LEFT$(exp$, LEN(exp$)-1) & ") " & g_CASE_FALL$ ELSE WRITELN "} else if (!__b2c__strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE g_CASE_FALL$ = "" END IF ELSE IF RIGHT$(statement$, 1) = ";" THEN exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4) g_CASE_FALL$ = "|| " & g_SELECTVAR$[g_SELECTVAR_CTR] & " == (" & LEFT$(exp$, LEN(exp$)-1) & ")" & g_CASE_FALL$ ELSE WRITELN "} else if (", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE g_CASE_FALL$ = "" END IF END IF ELSE IF INSTR(MID$(g_SELECTVAR$[g_SELECTVAR_CTR], 1, size), g_STRINGSIGN$) THEN IF RIGHT$(statement$, 1) = ";" THEN exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4) g_CASE_FALL$ = "|| !__b2c__strcmp(" & g_SELECTVAR$[g_SELECTVAR_CTR] & ", " & LEFT$(exp$, LEN(exp$)-1) & ") " & g_CASE_FALL$ ELSE WRITELN "if (!__b2c__strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", MID$(statement$, INSTR(statement$, "CASE") + 4),") ", g_CASE_FALL$, "){" TO g_CFILE g_IN_CASE[g_SELECTVAR_CTR] = 1 g_CASE_FALL$ = "" END IF ELSE IF RIGHT$(statement$, 1) = ";" THEN exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4) g_CASE_FALL$ = "|| " & g_SELECTVAR$[g_SELECTVAR_CTR] & " == (" & LEFT$(exp$, LEN(exp$)-1) & ")" & g_CASE_FALL$ ELSE WRITELN "if (", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE g_IN_CASE[g_SELECTVAR_CTR] = 1 g_CASE_FALL$ = "" END IF END IF END IF END IF CASE "DEFAULT" IF ISTRUE(g_IN_CASE[g_SELECTVAR_CTR]) THEN WRITELN "} else {" TO g_CFILE ELSE 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 EQ 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" WRITELN "kill(getpid(), SIGSTOP);" TO g_CFILE CASE "TRACE" ' Check argument IF dim EQ 1 THEN EPRINT NL$, "Syntax error: empty TRACE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE IF element$[2] = "ON" THEN g_TRACE = 1 ELIF element$[2] = "OFF" THEN g_TRACE =0 ENDIF CASE "OPTION" ' Check argument IF dim EQ 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 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] = "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] = "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 = 3 THEN IF REGEX(statement$, ".*short.*") THEN WRITELN "__b2c__memtype = 2;" TO g_CFILE g_OPTION_MEMTYPE$ = "short" ELIF REGEX(statement$, ".*int.*") THEN WRITELN "__b2c__memtype = 3;" TO g_CFILE g_OPTION_MEMTYPE$ = "int" ELIF REGEX(statement$, ".*long.*|.*NUMBER.*") THEN WRITELN "__b2c__memtype = 4;" TO g_CFILE g_OPTION_MEMTYPE$ = "long" ELIF REGEX(statement$, ".*float.*") THEN WRITELN "__b2c__memtype = 5;" TO g_CFILE g_OPTION_MEMTYPE$ = "float" ELIF REGEX(statement$, ".*double.*|.*FLOATING.*") THEN WRITELN "__b2c__memtype = 6;" TO g_CFILE g_OPTION_MEMTYPE$ = "double" ELIF REGEX(statement$, ".*void.*|.*char\\*.*|.*STRING.*") THEN WRITELN "__b2c__memtype = 7;" TO g_CFILE g_OPTION_MEMTYPE$ = "char*" ELIF REGEX(statement$, ".*char.*") THEN WRITELN "__b2c__memtype = 1;" TO g_CFILE g_OPTION_MEMTYPE$ = "char" ELSE EPRINT NL$, "Syntax error: invalid argument to OPTION MEMTYPE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF 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], "[0-1]|TRUE|FALSE") THEN WRITELN "#include " TO g_HFILE WRITELN "#include " 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); 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE 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 " 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 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 EQ 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$ ELSE g_IMPORTED$ = REPLACE$(exp$, ",", " ") & " " & g_IMPORTED$ END IF END IF CASE "INCR" ' Check argument IF dim EQ 1 THEN EPRINT NL$, "Syntax error: empty INCR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE ' Check if there is associative array assignment IF REGEX(statement$, ".*\\(.*\\).*") AND NOT(REGEX(statement$, ".*\\]$")) AND NOT(REGEX(statement$, ".*,.*\\(.*")) THEN IF REGEX(statement$, "\\).*,.*") THEN exp$ = CHOP$(MID$(statement$, INSTR(statement$, ",") + 1)) ELSE exp$ = "1" END IF statement$ = CHOP$(MID$(statement$, INSTR(statement$, " "))) IF REGEX(statement$, "\\).*,.*") THEN statement$ = LEFT$(statement$, INSTRREV(statement$, ",")-1) lft$ = LEFT$(statement$, INSTR(statement$, "(") - 1) str$ = MID$(statement$, INSTR(statement$, "(") + 1) WRITELN "__b2c__", lft$, "__location = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE WRITELN "__b2c__", lft$, "__location->value = ", statement$, " + (", exp$, ");" TO g_CFILE ' Check for relations Relate_Recurse(lft$, str$, statement$ & "+(" & exp$ & ")", -1) ELSE ' Walk through commas SPLIT CHOP$(MID$(statement$, INSTR(statement$, "INCR") + 4)) BY "," TO sym$ SIZE dim IF dim = 1 THEN exp$ = "1" ELSE exp$ = CHOP$(MID$(statement$, INSTR(statement$, ",") + 1)) END IF WRITELN sym$[1], " = ", sym$[1], " + (", exp$, ");" TO g_CFILE END IF END IF CASE "DECR" ' Check argument IF dim EQ 1 THEN EPRINT NL$, "Syntax error: empty DECR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE ' Check if there is associative array assignment IF REGEX(statement$, ".*\\(.*\\).*") AND NOT(REGEX(statement$, ".*\\]$")) AND NOT(REGEX(statement$, ".*,.*\\(.*")) THEN IF REGEX(statement$, "\\).*,.*") THEN exp$ = CHOP$(MID$(statement$, INSTR(statement$, ",") + 1)) ELSE exp$ = "1" END IF statement$ = CHOP$(MID$(statement$, INSTR(statement$, " "))) IF REGEX(statement$, "\\).*,.*") THEN statement$ = LEFT$(statement$, INSTRREV(statement$, ",")-1) lft$ = LEFT$(statement$, INSTR(statement$, "(") - 1) str$ = MID$(statement$, INSTR(statement$, "(") + 1) WRITELN "__b2c__", lft$, "__location = __b2c__", lft$, "__add(", str$, ";" TO g_CFILE WRITELN "__b2c__", lft$, "__location->value = ", statement$, " - (", exp$, ");" TO g_CFILE ' Check for relations Relate_Recurse(lft$, str$, statement$ & "-(" & exp$ & ")", -1) ELSE ' Walk through commas SPLIT CHOP$(MID$(statement$, INSTR(statement$, "DECR") + 4)) BY "," TO sym$ SIZE dim IF dim = 1 THEN exp$ = "1" ELSE exp$ = CHOP$(MID$(statement$, INSTR(statement$, ",") + 1)) END IF WRITELN sym$[1], " = ", sym$[1], " - (", exp$, ");" TO g_CFILE END IF END IF CASE "ALARM" ' Check argument IF dim EQ 1 THEN EPRINT NL$, "Syntax error: empty ALARM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE ' Walk through commas SPLIT CHOP$(MID$(statement$, INSTR(statement$, "ALARM") + 5)) BY "," TO sym$ SIZE dim IF dim = 2 THEN WRITELN "signal(SIGALRM, (void*)", sym$[1], ");" TO g_CFILE WRITELN "__b2c__alarm.it_value.tv_sec = (long)(", sym$[2], ")/1000; __b2c__alarm.it_value.tv_usec = ((", sym$[2], ")%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 ELSE EPRINT NL$, "Syntax error: missing argument in ALARM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 END IF END IF CASE "CURSOR" ' Check argument IF dim = 1 THEN EPRINT NL$, "Syntax error: empty CURSOR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE IF dim = 3 THEN exp$ = element$[3] ELSE exp$ = "1" END IF 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 EQ 1 THEN EPRINT NL$, "Syntax error: empty SCROLL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!" END 1 ELSE IF dim = 3 THEN exp$ = element$[3] ELSE exp$ = "1" END IF 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 EQ 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); 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); if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE 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 SPLIT g_LOCALSTRINGS$ BY " " TO sym$ SIZE dim FOR i = 1 TO dim IF LEN(sym$[i]) > 0 THEN WRITELN "if(", sym$[i], " != NULL) free(", sym$[i], ");" 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;" TO g_CFILE END IF CASE "PRAGMA" ' Check argument IF dim EQ 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] = "LDFLAGS" AND dim >= 3 THEN IF INSTR(element$[3], "config") THEN exp$ = EXTRACT$(MID$(statement$, INSTR(statement$, "LDFLAGS")+7), "`") g_LDFLAGS$ = g_LDFLAGS$ & " " & CHOP$(EXEC$(exp$)) ELSE FOR i = 3 TO dim g_LDFLAGS$ = g_LDFLAGS$ & " -l" & element$[i] NEXT END IF ELIF element$[2] = "INCLUDE" AND dim >= 3 THEN FOR i = 3 TO dim IF NOT(FILEEXISTS("/usr/include/" & element$[i])) THEN WRITELN "#include ", CHR$(34), element$[i], CHR$(34) TO g_HFILE ELSE WRITELN "#include <", element$[i], ">" TO g_HFILE ENDIF NEXT ELSE EPRINT NL$, "Syntax error: argument to PRAGMA at line ", g_COUNTER, " in file '", g_CURFILE$, "' not recognized!" END 1 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))) 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$) END SELECT END IF END IF END SUB '---------------------------------------------------------------------------------------------- SUB Tokenize (STRING current$) LOCAL i, is_string, is_escaped LOCAL token$, item1$, item2$, result$, element$ LOCAL j, in_str, in_spac, bracket, direct, inescaped, isquote ' If we have C code, skip tokenization IF ISTRUE(g_USE_C) THEN Parse_Line(current$) EXIT SUB END IF WHILE TRUE ' Initialize parser is_string = FALSE is_escaped = FALSE token$ = "" ' See if there are colons FOR i = 1 TO LEN(current$) IF MID$(current$, i, 5) = "INTL$" THEN IF ISFALSE(is_string) THEN token$ = token$ & "gettext" INCR i, 5 END IF ELIF MID$(current$, i, 5) = "NNTL$" THEN IF ISFALSE(is_string) THEN token$ = token$ & "ngettext" INCR i, 5 END IF END IF SELECT MID$(current$, i, 1) ' Separator CASE ":" IF ISFALSE(is_string) THEN token$ = token$ & CHR$(10) ELSE token$ = token$ & ":" END IF ' String symbol CASE "$" IF ISFALSE(is_string) OR REGEX(current$, "IMPORT.*FROM.*TYPE.*") THEN token$ = token$ & g_STRINGSIGN$ is_escaped = FALSE ELSE token$ = token$ & "$" END IF ' Escape symbol CASE CHR$(92) token$ = token$ & CHR$(92) is_escaped = NOT(is_escaped) ' Quote symbol CASE CHR$(34) token$ = token$ & CHR$(34) IF ISFALSE(is_escaped) THEN is_string = NOT(is_string) is_escaped = FALSE ' Ampersand symbol CASE CHR$(38) IF ISFALSE(is_string) 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 MID$(token$, LEN(token$)-j+1, 1) CASE ")" isquote = 0 INCR direct IF ISFALSE(in_str) THEN INCR bracket END IF CASE "(" isquote = 0 INCR direct IF ISFALSE(in_str) THEN DECR bracket IF bracket < 0 THEN BREAK ENDIF ENDIF CASE "=" isquote = 0 IF ISFALSE(in_str) THEN BREAK CASE "," isquote = 0 IF ISFALSE(in_str) AND ISFALSE(bracket) THEN BREAK ' Escape symbol CASE CHR$(92) IF isquote THEN in_str = 1 END IF isquote = 0 CASE CHR$(34) isquote = 1 INCR direct in_str = NOT(in_str) CASE CHR$(32) isquote = 0 IF ISFALSE(in_str) AND ISFALSE(bracket) THEN IF direct > 0 THEN INCR in_spac END IF ENDIF CASE ":" isquote = 0 IF ISFALSE(in_str) THEN BREAK END SELECT IF REGEX(MID$(token$, LEN(token$)-j+1, 1), "[A-Za-z]") THEN isquote = 0 INCR direct IF ISFALSE(in_str) AND ISFALSE(bracket) THEN IF in_spac > 0 THEN BREAK ENDIF END IF END IF item1$ = MID$(token$, LEN(token$)-j+1, 1) & item1$ NEXT IF INSTR(item1$, g_STRINGSIGN$) OR INSTR(item1$, CHR$(34)) 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 FOR j = i TO LEN(current$) SELECT MID$(current$, j, 1) CASE "(" INCR direct IF ISFALSE(in_str) THEN INCR bracket CASE ")" INCR direct IF ISFALSE(in_str) THEN DECR bracket IF bracket < 0 THEN BREAK ENDIF ENDIF CASE "," IF ISFALSE(in_str) AND ISFALSE(bracket) THEN BREAK CASE CHR$(38) IF ISFALSE(in_str) AND ISFALSE(bracket) THEN in_spac = 0 : direct = 0 END IF ' Escape symbol CASE CHR$(92) inescaped = NOT(inescaped) CASE CHR$(34) INCR direct IF NOT(inescaped) THEN in_str = NOT(in_str) inescaped = 0 CASE CHR$(32) IF ISFALSE(in_str) AND ISFALSE(bracket) THEN IF direct > 0 THEN INCR in_spac END IF ENDIF CASE ":" IF ISFALSE(in_str) THEN BREAK END SELECT IF REGEX(MID$(current$, j, 1), "[A-Za-z]") THEN INCR direct IF ISFALSE(in_str) AND ISFALSE(bracket) THEN IF in_spac > 0 THEN BREAK ENDIF END IF END IF IF MID$(current$, j, 1) = "$" THEN IF ISFALSE(in_str) OR REGEX(current$, "IMPORT.*FROM.*TYPE.*") THEN item2$ = item2$ & g_STRINGSIGN$ ELSE item2$ = item2$ & "$" ENDIF ELIF MID$(current$, j, 1) = "&" THEN IF ISFALSE(in_str) THEN item2$ = item2$ & "," ELSE item2$ = item2$ & "&" END IF ELSE item2$ = item2$ & MID$(current$, j, 1) END IF NEXT i = j-1 token$ = token$ & " CONCAT" & g_STRINGSIGN$ & "(" & item1$ & "," & item2$ & ") " 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$ OR NOT(INSTR(current$, "&")) THEN BREAK result$ = token$ current$ = token$ WEND ' Split into separate statements FOR element$ IN token$ STEP CHR$(10) ' Start parsing Parse_Line(CHOP$(element$)) NEXT END SUB '---------------------------------------------------------------------------------------------- FUNCTION Parse_Equation$(STRING current$) LOCAL i, j, is_string, is_escaped, is_equation, opctr LOCAL token$, term$, eq$, total$, type$, element$ 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, 5) = " AND " THEN IF ISFALSE(is_string) THEN token$ = token$ & CHR$(10) logop$[opctr] = " AND " INCR opctr : INCR i, 4 ELSE token$ = token$ & " " END IF ELIF MID$(current$, i, 4) = " OR " THEN IF ISFALSE(is_string) THEN token$ = token$ & CHR$(10) logop$[opctr] = " OR " INCR opctr : INCR i, 3 ELSE token$ = token$ & " " END IF ELIF MID$(current$, i, 1) = CHR$(92) THEN token$ = token$ & CHR$(92) is_escaped = NOT(is_escaped) ELIF MID$(current$, i, 1) = CHR$(34) THEN token$ = token$ & CHR$(34) IF ISFALSE(is_escaped) THEN is_string = NOT(is_string) is_escaped = FALSE ELSE token$ = token$ & MID$(current$, i, 1) is_escaped = FALSE END IF NEXT logop$[opctr] = "" opctr = 1 ' Start parsing FOR element$ IN token$ STEP CHR$(10) ' Initialize for this chunk eq$ = "!" token$ = "" is_equation = 0 is_string = 0 is_escaped = 0 ' Check if this is a string IF INSTR(element$, "(") THEN type$ = MID$(element$, 1, INSTR(element$, "(")) ELSE type$ = element$ END IF ' See if there are equal signs FOR i = 1 TO LEN(element$) 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 MID$(element$, i, 1) ' Separator CASE "=" IF ISFALSE(is_string) THEN IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN term$ = token$ token$ = "" ELIF NOT(is_equation) THEN token$ = token$ & "==" ELSE token$ = token$ & "=" is_equation = 0 END IF ELSE token$ = token$ & "=" END IF ' Negation CASE "!" IF ISFALSE(is_string) THEN IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN eq$ = "" ELIF NOT(is_equation) THEN token$ = token$ & "!=" INCR i ELSE token$ = token$ & "!" is_equation = 0 END IF ELSE token$ = token$ & "!" END IF ' Comparison symbols CASE "<" token$ = token$ & "<" is_equation = 1 CASE ">" token$ = token$ & ">" is_equation = 1 CASE "#" token$ = token$ & "#" is_equation = 1 ' Escape symbol CASE CHR$(92) token$ = token$ & CHR$(92) is_escaped = NOT(is_escaped) ' Quote symbol CASE CHR$(34) token$ = token$ & CHR$(34) IF ISFALSE(is_escaped) THEN is_string = NOT(is_string) is_escaped = FALSE DEFAULT token$ = token$ & MID$(element$, i, 1) is_escaped = FALSE END SELECT NEXT ' Construct string equation IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN token$ = "((__b2c__option_compare == 0) ? " & eq$ & "__b2c__strcmp(" & term$ & "," & token$ & ") : " & eq$ & "__b2c__strcasecmp(" & term$ & "," & token$ & "))" 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$ LOCAL length, mynet, size LOCAL baconfile TYPE FILE* CATCH GOTO network_error PRINT "Fetching file..."; OPEN LEFT$(name$, INSTR(name$, "/")-1) & ":80" FOR NETWORK AS mynet SEND "HEAD /" & MID$(name$, INSTR(name$, "/")+1) & " HTTP/1.1\r\nHost: " & LEFT$(name$, INSTR(name$, "/")-1) & "\r\n\r\n" TO mynet RECEIVE dat$ FROM mynet ' Get the filesize from the HTTP header IF NOT(INSTR(dat$, "Content-Length:")) THEN 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: " & LEFT$(name$, INSTR(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 END SUB '---------------------------------------------------------------------------------------------- ' ' Main program ' '---------------------------------------------------------------------------------------------- ' Default BACON settings LET g_MAX_DIGITS = 32 ' Maximum of internal buffers needed for string processing LET g_MAX_BUFFERS = 256 ' This is the size for static buffers like fgets, read etc. LET g_BUFFER_SIZE = 512 ' Maximum RETURN buffers LET g_MAX_RBUFFERS = 32 ' Defaults for parameters g_CCNAME$ = "cc" g_TEMPDIR$ = "." g_INCFILES$ = "" g_CCFLAGS$ = "" g_BINEXT$ = "" LET g_NO_COMPILE = 0 LET g_TMP_PRESERVE = 0 LET g_CPP = 0 LET g_XGETTEXT = 0 LET g_SAVE_CONFIG = 0 LET g_USE_C = 0 LET g_USE_H = 0 LET g_MAX_BACKLOG = 4 LET g_SHEBANG = FALSE g_INCLUDE_FILES$ = "" LET g_TRACE = 0 LET g_OPTION_BASE = 0 LET g_OPTION_SOCKET = 5 LET g_OPTION_MEMTYPE$ = "char" LET g_IF_PARSE = 0 ' Some global declarations g_CURFILE$ = "" g_FUNCNAME$ = "" g_FUNCTYPE$ = "" g_PROTOTYPE$ = "" g_TMP_FILES$ = "" g_LOCALSTRINGS$ = "" g_STRINGARRAYS$ = "" g_STRINGARGS$ = "" g_DYNAMICARRAYS$ = "" g_RECORDCACHE$ = "" LET g_LOOPCTR = 0 ' For...IN loops max 16 levels deep DECLARE g_LOOPVAR$[16] DECLARE g_LOOPSTEP$[16] g_ERRORTXT$ = "" g_COMMENT$="false" ' Always create a final label g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT" ' Records g_RECORDNAME$ = "" g_RECORDVAR$ = "" g_WITHVAR$ = "" g_RECORDEND_BODY$ = "" g_RECORDEND_HEADER$ = "" ' Socket defaults g_SOCKTYPE$ = "SOCK_STREAM" g_NETWORKTYPE$ = "TCP" g_MULTICAST_TTL = 1 g_SCTP_STREAMS = 1 ' Select/Case 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 ' Read any configfile values 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$ = CHOP$(MID$(line$, 7)) CASE "tempdir" g_TEMPDIR$ = CHOP$(MID$(line$, 8)) CASE "incfiles" g_INCFILES$ = CHOP$(MID$(line$, 9)) CASE "ldflags" g_LDFLAGS$ = CHOP$(MID$(line$, 8)) CASE "ccflags" g_CCFLAGS$ = CHOP$(MID$(line$, 8)) END SELECT WEND CLOSE FILE cfgfile ENDIF SPLIT CHOP$(ARGUMENT$) BY " " TO args$ SIZE amount IF amount < 2 THEN EPRINT "System error: no filename? Run with '-h' to see usage." END ENDIF i = 1 WHILE i <= amount DO SELECT LEFT$(args$[i], 2) ' Compiler option CASE "-c" IF LEN(args$[i]) > 2 THEN g_CCNAME$ = MID$(args$[i], 3) ELSE INCR i IF i <= amount THEN g_CCNAME$ = args$[i] END IF ' Include option CASE "-i" IF LEN(args$[i]) > 2 THEN args$[i] = MID$(args$[i], 3) ELSE INCR i END IF IF i <= amount THEN IF NOT(FILEEXISTS(args$[i])) AND NOT(FILEEXISTS("/usr/include/" & args$[i])) THEN EPRINT NL$, "System error: included C header file from -i option not found!" END 1 END IF IF LEN(args$[i]) > 0 THEN IF NOT(FILEEXISTS("/usr/include/" & args$[i])) THEN g_INCFILES$ = g_INCFILES$ & " " & args$[i] ELSE g_INCFILES$ = g_INCFILES$ & " <" & args$[i] & ">" END IF END IF END IF ' Library flags CASE "-l" IF LEN(args$[i]) > 2 THEN IF MID$(args$[i], 3, 1) = "-" THEN g_LDFLAGS$ = g_LDFLAGS$ & " " & MID$(args$[i], 3) ELSE g_LDFLAGS$ = g_LDFLAGS$ & " -l" & MID$(args$[i], 3) ENDIF ELSE INCR i IF i <= amount THEN IF LEFT$(args$[i], 1) = "-" THEN g_LDFLAGS$ = g_LDFLAGS$ & " " & args$[i] ELSE g_LDFLAGS$ = g_LDFLAGS$ & " -l" & args$[i] ENDIF END IF END IF ' Compiler flags CASE "-o" IF LEN(args$[i]) > 2 THEN g_CCFLAGS$ = g_CCFLAGS$ & " " & MID$(args$[i], 3) ELSE INCR i IF i <= amount THEN g_CCFLAGS$ = g_CCFLAGS$ & " " & args$[i] END IF ' Temporary directory CASE "-d" IF LEN(args$[i]) > 2 THEN args$[i] = MID$(args$[i], 3) ELSE INCR i END IF IF i <= amount THEN IF NOT(FILEEXISTS(args$[i])) THEN MAKEDIR args$[i] g_TEMPDIR$ = args$[i] END IF ' Help option CASE "-h"; CASE "-?"; CASE "--" PRINT NL$, "USAGE: bacon [options] program[.bac]" PRINT NL$, "OPTIONS:" PRINT NL$, " -c ", TAB$(1), "Compiler to use (default: ", g_CCNAME$, ")" PRINT " -l ", TAB$(1), "Pass libraries to linker" PRINT " -o ", TAB$(1), "Pass compiler options" PRINT " -i ", TAB$(1), "Add include file to C code" PRINT " -d ", TAB$(1), "Temporary directory (default: ", g_TEMPDIR$, ")" PRINT " -x ", TAB$(2), "Extract gettext strings" PRINT " -f ", TAB$(2), "Create Shared Object" PRINT " -n ", TAB$(2), "Do not compile, only convert" PRINT " -j ", TAB$(2), "Invoke C Preprocessor" PRINT " -p ", TAB$(2), "Preserve temporary files" PRINT " -b ", TAB$(2), "Execute from shebang" PRINT " -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 "-v" PRINT NL$, "BaCon version ", g_VERSION$, " - (c) Peter van Eerten - GPL v3.", NL$ END ' Preserve option CASE "-p" IF LEN(args$[i]) = 2 THEN g_TMP_PRESERVE = 1 ' Gettext option CASE "-x" IF LEN(args$[i]) = 2 THEN g_XGETTEXT = 1 ' No compile option CASE "-n" IF LEN(args$[i]) = 2 THEN g_NO_COMPILE = 1 ' Invoke C Preprocessor CASE "-j" IF LEN(args$[i]) = 2 THEN g_CPP = 1 ' Shared library CASE "-f" IF LEN(args$[i]) = 2 THEN g_CCFLAGS$ = g_CCFLAGS$ & " -shared -rdynamic" IF INSTR(OS$, "x86_64") THEN g_CCFLAGS$ = g_CCFLAGS$ & " -fPIC" g_BINEXT$ = ".so" END IF ' Use shebang CASE "-b" IF LEN(args$[i]) = 2 THEN g_SHEBANG = TRUE g_TEMPDIR$ = "/tmp" END IF ' Write config CASE "-w" IF LEN(args$[i]) = 2 THEN g_SAVE_CONFIG = 1 DEFAULT IF LEFT$(args$[i], 1) = "-" THEN ' Other flags are considered linker flags g_LDFLAGS$ = g_LDFLAGS$ & " " & args$[i] ELIF i > 1 THEN ' This is the sourcefile g_SOURCEFILE$ = g_SOURCEFILE$ & args$[i] & " " END IF END SELECT INCR i WEND ' See if configfile must be written IF g_SAVE_CONFIG = 1 THEN IF FILETYPE(GETENVIRON$("HOME") & "/.bacon") = 0 THEN MAKEDIR GETENVIRON$("HOME") & "/.bacon" 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 ", g_LDFLAGS$ TO cfgfile WRITELN "ccflags ", g_CCFLAGS$ TO cfgfile CLOSE FILE cfgfile ENDIF g_SOURCEFILE$ = CHOP$(g_SOURCEFILE$) 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 not found!" END ERROR END IF ' 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" ' 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 IF LEN(EXEC$("ls " & g_TEMPDIR$ & "/" & LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".bac")) & "*.* 2>/dev/null")) THEN INPUT "WARNING: temporary files found! Do you want to delete them (y/n)? ", answer$ IF answer$ = "y" THEN SYSTEM "rm -f " & g_TEMPDIR$ & "/" & LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".bac")) & "*.*" PRINT "Temporary files were deleted." ELSE PRINT "Exiting..." END 1 END IF END IF ' Create new sourcefile OPEN g_CFILE$ FOR WRITING AS g_CFILE ' Create basic C file WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO g_CFILE WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".h\"" TO g_CFILE WRITELN "int main(int argc, const char **argv){" TO g_CFILE ' See if we have the detector WRITELN "if(argc==2 && !strcmp(argv[1], \"-bacon\")){fprintf(stderr, \"Compiled with %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] = 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 "/* Rest of the program */" TO g_CFILE ' Create generic headerfile OPEN g_GENERIC$ FOR WRITING AS g_GENERIC ' Create basic H file, functions are converted using macros WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC IF INSTR(OS$, "BSD") THEN WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "static jmp_buf __b2c__jump;" TO g_GENERIC WRITELN "static int __b2c__trap = 0;" TO g_GENERIC WRITELN "static int __b2c__catch_set_backup, __b2c__catch_set = 0;" TO g_GENERIC WRITELN "static int ERROR = 0;" TO g_GENERIC WRITELN "static int __b2c__option_compare = 0;" TO g_GENERIC WRITELN "static int __b2c__option_memstream = 0;" TO g_GENERIC WRITELN "static int __b2c__option_startpoint = 0;" TO g_GENERIC WRITELN "static int __b2c__option_open = O_RDWR|O_NOCTTY|O_SYNC;" TO g_GENERIC WRITELN "static int __b2c__memtype = 1;" TO g_GENERIC WRITELN "static int __b2c__collapse = 0;" TO g_GENERIC WRITELN "int __b2c__break_ctr = 0;" TO g_GENERIC WRITELN "int __b2c__break_flag = 0;" TO g_GENERIC WRITELN "int RETVAL = 0;" TO g_GENERIC WRITELN "int REGLEN = 0;" TO g_GENERIC WRITELN "struct timeval __b2c__tm; time_t __b2c__elapsed_secs; int __b2c__elapsed_usecs;" TO g_GENERIC WRITELN "struct itimerval __b2c__alarm;" TO g_GENERIC WRITELN "char __b2c__chop_default[] = \"\\r\\n\\t \";" TO g_GENERIC WRITELN "char VERSION", g_STRINGSIGN$, "[] = \"", g_VERSION$, "\";" TO g_GENERIC ' Add user include files WRITELN "/* User include files */" TO g_GENERIC FOR tmpfiles$ IN g_INCFILES$ IF INSTR(tmpfiles$, "<") THEN WRITELN "#include ", tmpfiles$ TO g_GENERIC ELSE WRITELN "#include ", CHR$(34), tmpfiles$, CHR$(34) TO g_GENERIC ENDIF NEXT WRITELN "/* READ/DATA include files */" TO g_GENERIC WRITELN "int __b2c__stringarray_ptr = 0, __b2c__stringarray_ctr = 0;" TO g_GENERIC WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".string.h\"" TO g_GENERIC WRITELN "int __b2c__floatarray_ptr = 0, __b2c__floatarray_ctr = 0;" TO g_GENERIC WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".float.h\"" TO g_GENERIC WRITELN "int __b2c__ctr;" TO g_GENERIC WRITELN "/* Math functions */" TO g_GENERIC WRITELN "extern double round(double __b2c__x);" TO g_GENERIC WRITELN "extern long int lrint(double __b2c__x);" TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#define SQR(__b2c__x) sqrt((double)__b2c__x)" TO g_GENERIC WRITELN "#define POW(__b2c__x, __b2c__y) pow((double)__b2c__x, (double)__b2c__y)" TO g_GENERIC WRITELN "#define SIN(__b2c__x) sin((double)__b2c__x)" TO g_GENERIC WRITELN "#define COS(__b2c__x) cos((double)__b2c__x)" TO g_GENERIC WRITELN "#define TAN(__b2c__x) tan((double)__b2c__x)" TO g_GENERIC WRITELN "#define ASIN(__b2c__x) asin((double)__b2c__x)" TO g_GENERIC WRITELN "#define ACOS(__b2c__x) acos((double)__b2c__x)" TO g_GENERIC WRITELN "#define ATN(__b2c__x) atan((double)__b2c__x)" TO g_GENERIC WRITELN "#define LOG(__b2c__x) log((double)__b2c__x)" TO g_GENERIC WRITELN "#define EXP(__b2c__x) exp((double)__b2c__x)" TO g_GENERIC WRITELN "#define SGN(__b2c__x) ((__b2c__x) == 0 ? 0 : ((__b2c__x) < 0 ? -1 : 1))" TO g_GENERIC WRITELN "#define ROUND(__b2c__x) lrint((double)__b2c__x)" TO g_GENERIC WRITELN "#define INT(__b2c__x) lrint((double)__b2c__x)" TO g_GENERIC WRITELN "#define MOD(__b2c__x, __b2c__y) ((long)(__b2c__x) % (long)(__b2c__y))" TO g_GENERIC WRITELN "#define EVEN(__b2c__x) (((long)(__b2c__x) % 2 == 0) ? 1 : 0)" TO g_GENERIC WRITELN "#define ODD(__b2c__x) (((long)(__b2c__x) % 2 != 0) ? 1 : 0)" TO g_GENERIC WRITELN "#define FLOOR(__b2c__x) (long)floor(__b2c__x)" TO g_GENERIC WRITELN "#undef ABS" TO g_GENERIC WRITELN "#define ABS(__b2c__x) (((__b2c__x) < 0) ? -(__b2c__x) : (__b2c__x))" TO g_GENERIC WRITELN "#define RND random()" 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 RANDOM(__b2c__x) ((__b2c__x) != 0 ? random()/(MAXRANDOM/(__b2c__x)) : 0)" TO g_GENERIC WRITELN "/* Other functions */" TO g_GENERIC WRITELN "#define VAL(__b2c__x) ((__b2c__x) != NULL ? atof(__b2c__x) : 0)" TO g_GENERIC WRITELN "/* Unix functions */" TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#define SYSTEM(__b2c__x) do {if (__b2c__x != NULL) {RETVAL = system(__b2c__x); if(WIFEXITED(RETVAL)) RETVAL = WEXITSTATUS(RETVAL);} else RETVAL=0;} while(0)" TO g_GENERIC WRITELN "/* String functions */" TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "char __b2c__input__buffer[", g_BUFFER_SIZE, "];" TO g_GENERIC WRITELN "char* __b2c__sbuffer[", g_MAX_BUFFERS, "] = { NULL };" TO g_GENERIC WRITELN "long __b2c__sbuffer_length[", g_MAX_BUFFERS, "] = { 0 };" TO g_GENERIC WRITELN "int __b2c__sbuffer_ptr = 0;" TO g_GENERIC WRITELN "char* __b2c__rbuffer[", g_MAX_RBUFFERS, "] = { NULL };" TO g_GENERIC WRITELN "long __b2c__rbuffer_length[", g_MAX_RBUFFERS, "] = { 0 };" TO g_GENERIC WRITELN "int __b2c__rbuffer_ptr = 0;" TO g_GENERIC WRITELN "static jmp_buf __b2c__gosub_buffer[", g_MAX_RBUFFERS, "] = { 0 };" TO g_GENERIC WRITELN "int __b2c__gosub_buffer_ptr = -1;" TO g_GENERIC WRITELN "char **__b2c__deltree = { NULL }; int __b2c__del_ctr = 0;" TO g_GENERIC WRITELN "/* Temporary pointer to perform assignments */" TO g_GENERIC WRITELN "char *__b2c__assign = NULL;" TO g_GENERIC WRITELN "char *__b2c__split = NULL; char *__b2c__split_tmp = NULL;" TO g_GENERIC WRITELN "char *ERR", g_STRINGSIGN$, "(int);" TO g_GENERIC WRITELN "#define RUNTIMEERROR(__b2c__a, __b2c__x, __b2c__y, __b2c__z) do {fprintf(stderr, \"Runtime error: statement '%s' at line %d in '%s': %s\\n\", __b2c__a, __b2c__x, __b2c__y, ERR", g_STRINGSIGN$, "(__b2c__z)); exit(__b2c__z);} while(0)" TO g_GENERIC WRITELN "#define RUNTIMEFERR(__b2c__a, __b2c__x, __b2c__y, __b2c__z) do {fprintf(stderr, \"Runtime error: function '%s': %s\\n\", __b2c__y, ERR", g_STRINGSIGN$, "(__b2c__z)); exit(__b2c__z);} while(0)" TO g_GENERIC WRITELN "void *__rbuf_realloc(void *__b2c__ptr, size_t __b2c__size){if(__b2c__rbuffer_length[__b2c__rbuffer_ptr] < __b2c__size)" TO g_GENERIC WRITELN "{__b2c__rbuffer_length[__b2c__rbuffer_ptr] = (long)__b2c__size*4; return(realloc(__b2c__ptr, __b2c__size*4));} return(__b2c__ptr);}" TO g_GENERIC WRITELN "void *__sbuf_realloc(void *__b2c__ptr, size_t __b2c__size){if(__b2c__sbuffer_length[__b2c__sbuffer_ptr] < __b2c__size)" TO g_GENERIC WRITELN "{__b2c__sbuffer_length[__b2c__sbuffer_ptr] = (long)__b2c__size*4; return(realloc(__b2c__ptr, __b2c__size*4));} return(__b2c__ptr);}" TO g_GENERIC WRITELN "char *__b2c__strdup(const char *__b2c__s){if(__b2c__s == NULL) return(NULL); return(strdup(__b2c__s));}" TO g_GENERIC WRITELN "int __b2c__strcmp(const char *__b2c__s1, const char *__b2c__s2){if(__b2c__s1 == NULL && __b2c__s2 == NULL) return 0;" TO g_GENERIC WRITELN "if(__b2c__s1 == NULL)return(-1); if(__b2c__s2 == NULL)return(1); return(strcmp(__b2c__s1, __b2c__s2));}" TO g_GENERIC WRITELN "int __b2c__strcasecmp(const char *__b2c__s1, const char *__b2c__s2){if(__b2c__s1 == NULL && __b2c__s2 == NULL) return 0;" TO g_GENERIC WRITELN "if(__b2c__s1 == NULL)return(-1); if(__b2c__s2 == NULL)return(1); return(strcasecmp(__b2c__s1, __b2c__s2));}" TO g_GENERIC WRITELN "/* Functions for sort */" TO g_GENERIC WRITELN "int __b2c__sortnrd(const void *__b2c__a, const void *__b2c__b)" TO g_GENERIC 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_GENERIC WRITELN "int __b2c__sortnrd_down(const void *__b2c__a, const void *__b2c__b)" TO g_GENERIC 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_GENERIC WRITELN "int __b2c__sortnrf(const void *__b2c__a, const void *__b2c__b)" TO g_GENERIC 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_GENERIC WRITELN "int __b2c__sortnrf_down(const void *__b2c__a, const void *__b2c__b)" TO g_GENERIC 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_GENERIC WRITELN "int __b2c__sortnrl(const void *__b2c__a, const void *__b2c__b)" TO g_GENERIC 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_GENERIC WRITELN "int __b2c__sortnrl_down(const void *__b2c__a, const void *__b2c__b)" TO g_GENERIC 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_GENERIC WRITELN "int __b2c__sortnri(const void *__b2c__a, const void *__b2c__b)" TO g_GENERIC 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_GENERIC WRITELN "int __b2c__sortnri_down(const void *__b2c__a, const void *__b2c__b)" TO g_GENERIC 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_GENERIC WRITELN "int __b2c__sortstr(const void *__b2c__a, const void *__b2c__b)" TO g_GENERIC 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_GENERIC WRITELN "int __b2c__sortstr_down(const void *__b2c__a, const void *__b2c__b)" TO g_GENERIC 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_GENERIC WRITELN "/* Actual functions */" TO g_GENERIC WRITELN "int __b2c__remove(const char *__b2c__path, const struct stat *__b2c__sb, int __b2c__flag){" TO g_GENERIC WRITELN "__b2c__del_ctr++; __b2c__deltree = realloc(__b2c__deltree, __b2c__del_ctr*sizeof(char*)); __b2c__deltree[__b2c__del_ctr-1] = strdup(__b2c__path); return (0);}" TO g_GENERIC WRITELN "int __b2c__rmrecursive(char *__b2c__path){int __b2c__result = 0; __b2c__result = ftw(__b2c__path, __b2c__remove, FOPEN_MAX); qsort(&__b2c__deltree[0], __b2c__del_ctr, sizeof(char*), __b2c__sortstr);" TO g_GENERIC WRITELN "while(__b2c__del_ctr>0) {__b2c__del_ctr--; if(!__b2c__result) __b2c__result = remove(__b2c__deltree[__b2c__del_ctr]); free(__b2c__deltree[__b2c__del_ctr]);} free(__b2c__deltree); __b2c__deltree = NULL; return(__b2c__result);}" TO g_GENERIC WRITELN "char* __b2c__curdir(void){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "*sizeof(char));" TO g_GENERIC WRITELN "return (char*)(getcwd(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "));}" TO g_GENERIC WRITELN "#define CURDIR", g_STRINGSIGN$, " __b2c__curdir()" TO g_GENERIC WRITELN "char* __b2c__reverse(char *__b2c__src){long __b2c__i, __b2c__l; if (__b2c__src == NULL) return (\"\"); __b2c__l = strlen(__b2c__src); __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__l+2)*sizeof(char));" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__l+1);" TO g_GENERIC WRITELN "for(__b2c__i=0;__b2c__i<__b2c__l;__b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__src[__b2c__l-1-__b2c__i];}" TO g_GENERIC WRITELN "return(char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define REVERSE", g_STRINGSIGN$, "(__b2c__x) __b2c__reverse(__b2c__x)" TO g_GENERIC WRITELN "char* __b2c__str(double __b2c__d){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, "*sizeof(char));" TO g_GENERIC WRITELN "if(floor(__b2c__d) == __b2c__d) snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%ld\", (long)__b2c__d); else snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%g\", (double)__b2c__d); return(char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define STR", g_STRINGSIGN$, "(__b2c__x) __b2c__str(__b2c__x)" TO g_GENERIC WRITELN "char * __b2c__concat (char *__b2c__first, ...) { long __b2c__len, __b2c__new; char *__b2c__next; va_list __b2c__ap; __b2c__sbuffer_ptr++; if (__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr = 0;" TO g_GENERIC WRITELN "if (__b2c__first != NULL && (__b2c__len = strlen(__b2c__first)) > 0) {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__len * sizeof (char));" TO g_GENERIC WRITELN "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first, __b2c__len*sizeof(char)); } else { __b2c__len = 0; __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], sizeof (char));}" TO g_GENERIC WRITELN "va_start (__b2c__ap, __b2c__first); while ((__b2c__next = va_arg (__b2c__ap, char *)) != NULL) { __b2c__new = strlen (__b2c__next); __b2c__sbuffer[__b2c__sbuffer_ptr] =" TO g_GENERIC WRITELN "(char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len+__b2c__new + 1) * sizeof (char)); memcpy(__b2c__sbuffer[__b2c__sbuffer_ptr]+__b2c__len*sizeof(char), __b2c__next, __b2c__new*sizeof(char));" TO g_GENERIC WRITELN "__b2c__len += __b2c__new; } va_end (__b2c__ap); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\\0'; return (char *) (__b2c__sbuffer[__b2c__sbuffer_ptr]); }" TO g_GENERIC WRITELN "#define CONCAT", g_STRINGSIGN$, "(...) __b2c__concat(__VA_ARGS__, (char*)NULL)" TO g_GENERIC WRITELN "char* __b2c__left(char *__b2c__src, long __b2c__n){long __b2c__l; if(__b2c__src != NULL)__b2c__l = strlen(__b2c__src); if(__b2c__src == NULL || __b2c__n > __b2c__l || __b2c__n < 0) return(__b2c__src);" TO g_GENERIC WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__l+1)*sizeof(char));" TO g_GENERIC WRITELN "memcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src, __b2c__n*sizeof(char)); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__n] = '\\0';" TO g_GENERIC WRITELN "return (char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define LEFT", g_STRINGSIGN$, "(__b2c__x, __b2c__y) __b2c__left(__b2c__x, __b2c__y)" TO g_GENERIC WRITELN "char* __b2c__right(char *__b2c__src, long __b2c__n){long __b2c__l; if(__b2c__src != NULL)__b2c__l = strlen(__b2c__src); if(__b2c__src == NULL || __b2c__n > __b2c__l || __b2c__n < 0) return(__b2c__src);" TO g_GENERIC WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__l+1)*sizeof(char));" TO g_GENERIC WRITELN "memcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src + (__b2c__l - __b2c__n)*sizeof(char), __b2c__n*sizeof(char)); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__n] = '\\0';" TO g_GENERIC WRITELN "return (char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define RIGHT", g_STRINGSIGN$, "(__b2c__x, __b2c__y) __b2c__right(__b2c__x, __b2c__y)" TO g_GENERIC WRITELN "char* __b2c__mid(char *__b2c__src, ...){ va_list __b2c__ap; long __b2c__start, __b2c__len, __b2c__l; if(__b2c__src == NULL) return(\"\"); " TO g_GENERIC WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0; va_start(__b2c__ap, __b2c__src);" TO g_GENERIC WRITELN "__b2c__start = va_arg(__b2c__ap, long); if(__b2c__start < 1) return(__b2c__src); __b2c__l = strlen(__b2c__src); if(__b2c__start > __b2c__l) return(\"\"); __b2c__len = va_arg(__b2c__ap, long);" TO g_GENERIC WRITELN "if(__b2c__len < 0 || __b2c__start+__b2c__len > __b2c__l) __b2c__len = __b2c__l-__b2c__start+1; __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len+1)*sizeof(char));" TO g_GENERIC WRITELN "memcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+(__b2c__start-1)*sizeof(char), __b2c__len*sizeof(char)); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\\0'; va_end(__b2c__ap); return (char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define MID", g_STRINGSIGN$, "(__b2c__string, ...) __b2c__mid(__b2c__string, __VA_ARGS__, -1)" TO g_GENERIC WRITELN "long __b2c__instr(char *__b2c__first, ...){char *__b2c__tmp, *__b2c__res; int __b2c__pos; va_list __b2c__ap; if(__b2c__first == NULL) return (0); va_start(__b2c__ap, __b2c__first);" TO g_GENERIC WRITELN "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL) return (0);__b2c__pos = va_arg(__b2c__ap, int);" TO g_GENERIC WRITELN "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); __b2c__res = strstr(__b2c__first + __b2c__pos - 1, __b2c__tmp);" TO g_GENERIC WRITELN "if(__b2c__res == NULL) return (0); return (long)(__b2c__res - __b2c__first + 1);}" TO g_GENERIC WRITELN "#define INSTR(...) __b2c__instr(__VA_ARGS__, -1)" TO g_GENERIC WRITELN "long __b2c__instrrev (char *__b2c__first, ...){char *__b2c__tmp, *__b2c__res = NULL, *__b2c__found = NULL; long __b2c__pos, __b2c__l; va_list __b2c__ap;if (__b2c__first == NULL) return (0);" TO g_GENERIC WRITELN "va_start (__b2c__ap, __b2c__first); __b2c__tmp = va_arg (__b2c__ap, char *); if (__b2c__tmp == NULL) return (0); __b2c__pos = va_arg (__b2c__ap, int); if (__b2c__pos < 0) __b2c__pos = 0;" TO g_GENERIC WRITELN "va_end (__b2c__ap); __b2c__l = strlen(__b2c__first); __b2c__found = __b2c__first; do {__b2c__res = strstr (__b2c__found, __b2c__tmp); if(__b2c__res != NULL && __b2c__res <= __b2c__first + __b2c__l - __b2c__pos)" TO g_GENERIC WRITELN "{__b2c__found = __b2c__res + 1; continue;}if(__b2c__res > __b2c__first + __b2c__l - __b2c__pos) __b2c__res = NULL;} while (__b2c__res != NULL); if (__b2c__option_startpoint){if(__b2c__l - (__b2c__found - __b2c__first)+1 > __b2c__l) return 0;" TO g_GENERIC WRITELN "return (long)(__b2c__l - (__b2c__found - __b2c__first)+1);} return (long)(__b2c__found - __b2c__first);}" TO g_GENERIC WRITELN "#define INSTRREV(...) __b2c__instrrev(__VA_ARGS__, -1)" TO g_GENERIC WRITELN "char* __b2c__spc(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 32, __b2c__x); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__x] = '\\0'; return(char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define SPC", g_STRINGSIGN$, "(__b2c__x) ((__b2c__x) >= 0 ? __b2c__spc(__b2c__x) : \"\")" TO g_GENERIC WRITELN "char* __b2c__tab(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 9, __b2c__x); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__x] = '\\0'; return(char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define TAB", g_STRINGSIGN$, "(__b2c__x) ((__b2c__x) >= 0 ? __b2c__tab(__b2c__x) : \"\")" TO g_GENERIC WRITELN "char* __b2c__fill(unsigned long __b2c__x, unsigned char __b2c__y){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__y, __b2c__x); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__x] = '\\0'; return(char*)(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define FILL", g_STRINGSIGN$, "(__b2c__x, __b2c__y) ((__b2c__y) >= 0 && (__b2c__y) < 256 ? __b2c__fill(__b2c__x, __b2c__y) : \"\")" TO g_GENERIC WRITELN "char* __b2c__chop(char *__b2c__src, ...){char *__b2c__tmp, *__b2c__str; long __b2c__i, __b2c__l, __b2c__loc = 0; va_list __b2c__ap; if(__b2c__src == NULL || strlen(__b2c__src) == 0) return(__b2c__src);" TO g_GENERIC WRITELN "va_start (__b2c__ap, __b2c__src); __b2c__str = va_arg (__b2c__ap, char*); if(__b2c__str == 0) __b2c__str = (char*)__b2c__chop_default; else __b2c__loc = va_arg (__b2c__ap, int); va_end (__b2c__ap); __b2c__l = strlen(__b2c__str);" TO g_GENERIC WRITELN "if(__b2c__loc == 0 || __b2c__loc == 1) {while (*__b2c__src != '\\0') {for(__b2c__i = 0; __b2c__i < __b2c__l; __b2c__i++) {if (*__b2c__src == *(__b2c__str+__b2c__i)) {__b2c__src++; break; } }" TO g_GENERIC WRITELN "if(__b2c__i == __b2c__l) break;} if (*__b2c__src == '\\0') return(\"\");} __b2c__tmp = __b2c__src + strlen(__b2c__src) - 1;" TO g_GENERIC WRITELN "if(__b2c__loc == 0 || __b2c__loc == 2) {while (__b2c__tmp >= __b2c__src && *__b2c__tmp != '\\0') {for(__b2c__i = 0; __b2c__i < __b2c__l; __b2c__i++) {if (*__b2c__tmp == *(__b2c__str+__b2c__i))" TO g_GENERIC WRITELN "{__b2c__tmp--; break; } } if(__b2c__i == __b2c__l) break;} } __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_GENERIC WRITELN "for(__b2c__i = 0; __b2c__i <= __b2c__tmp - __b2c__src; __b2c__i++) __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__src[__b2c__i];" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i] = '\\0'; return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define CHOP", g_STRINGSIGN$, "(...) __b2c__chop(__VA_ARGS__, 0)" TO g_GENERIC WRITELN "char * __b2c__extract (int __b2c__ln, const char *__b2c__fl, ...) { int __b2c__i, __b2c__j, __b2c__flag, __b2c__reti, __b2c__ere, __b2c__pos = 0; char *__b2c__src, *__b2c__needle, *__b2c__tmp;" TO g_GENERIC WRITELN "regex_t __b2c__reg; char __b2c__buf[100]; regmatch_t __b2c__where[1]; va_list __b2c__ap; va_start (__b2c__ap, __b2c__fl); __b2c__src = va_arg (__b2c__ap, char *); __b2c__needle = va_arg (__b2c__ap, char *);" TO g_GENERIC WRITELN "__b2c__ere = va_arg (__b2c__ap, int); va_end (__b2c__ap); if (__b2c__src == NULL || __b2c__needle == NULL) return (char *) (__b2c__src); if (strlen (__b2c__src) == 0 || strlen (__b2c__needle) == 0)" TO g_GENERIC WRITELN "return (char *) (__b2c__src); __b2c__sbuffer_ptr++; if (__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr = 0; __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr]," TO g_GENERIC WRITELN "(strlen (__b2c__src) + 1) * sizeof (char)); if (__b2c__ere > 0) { if (__b2c__option_compare == 0) __b2c__reti = regcomp (&__b2c__reg, __b2c__needle, REG_EXTENDED); else __b2c__reti =" TO g_GENERIC WRITELN "regcomp (&__b2c__reg, __b2c__needle, REG_EXTENDED | REG_ICASE); if (!__b2c__trap && __b2c__reti) { ERROR = 27; regerror (__b2c__reti, &__b2c__reg, __b2c__buf, sizeof (__b2c__buf));" TO g_GENERIC WRITELN "fprintf (stderr, \"%s\\n\", __b2c__buf); RUNTIMEFERR (__b2c__ln, __b2c__fl, \"EXTRACT$\", ERROR); } while ((__b2c__reti = regexec (&__b2c__reg, __b2c__src, 1, __b2c__where, 0)) == 0) {" TO g_GENERIC WRITELN "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos * sizeof (char), __b2c__src, (size_t) __b2c__where[0].rm_so * sizeof (char)); __b2c__pos += __b2c__where[0].rm_so;" TO g_GENERIC WRITELN "__b2c__src += (long) __b2c__where[0].rm_eo; } regfree (&__b2c__reg); memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos * sizeof (char), __b2c__src, strlen (__b2c__src) * sizeof (char));" TO g_GENERIC WRITELN "__b2c__pos += strlen (__b2c__src); } else { while ((__b2c__tmp = strstr (__b2c__src, __b2c__needle)) != NULL) {" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__pos + (__b2c__tmp - __b2c__src) + 1) * sizeof (char));" TO g_GENERIC WRITELN "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos * sizeof (char), __b2c__src, (size_t) (__b2c__tmp - __b2c__src) * sizeof (char)); __b2c__pos += __b2c__tmp - __b2c__src;" TO g_GENERIC WRITELN "__b2c__src = __b2c__tmp+strlen(__b2c__needle)*sizeof(char); } __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__pos + strlen(__b2c__src) + 1) * sizeof (char));" TO g_GENERIC WRITELN "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos * sizeof (char), __b2c__src, strlen(__b2c__src) * sizeof (char)); __b2c__pos += strlen(__b2c__src); }" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__pos] = '\\0'; return (char *) (__b2c__sbuffer[__b2c__sbuffer_ptr]); }" TO g_GENERIC WRITELN "#define EXTRACT", g_STRINGSIGN$, "(...) __b2c__extract(__LINE__, __FILE__, __VA_ARGS__, -1)" TO g_GENERIC WRITELN "char * __b2c__replace (int __b2c__ln, const char *__b2c__fl, ...) { char *__b2c__tmp, *__b2c__haystack, *__b2c__needle, *__b2c__replace; long __b2c__rep, __b2c__hst, __b2c__ndl, __b2c__len = 0; regex_t __b2c__reg; int __b2c__reti, __b2c__flag; char __b2c__buf[100];" TO g_GENERIC WRITELN "regmatch_t __b2c__where[1]; va_list __b2c__ap; va_start (__b2c__ap, __b2c__fl); __b2c__haystack = va_arg (__b2c__ap, char*); __b2c__needle = va_arg (__b2c__ap, char*); __b2c__replace = va_arg (__b2c__ap, char*); __b2c__flag = va_arg (__b2c__ap, int); va_end (__b2c__ap);" TO g_GENERIC WRITELN "if(__b2c__haystack == NULL || __b2c__needle == NULL || __b2c__replace == NULL) return (char*)(__b2c__haystack); __b2c__ndl = strlen (__b2c__needle); if (strlen (__b2c__haystack) == 0 || __b2c__ndl == 0) return (char *) (__b2c__haystack);" TO g_GENERIC WRITELN "__b2c__sbuffer_ptr++; if (__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr = 0; __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], sizeof (char)); *__b2c__sbuffer[__b2c__sbuffer_ptr] = '\\0';" TO g_GENERIC WRITELN "__b2c__rep = strlen (__b2c__replace); if(__b2c__flag > 0) { if (__b2c__option_compare == 0) __b2c__reti = regcomp (&__b2c__reg, __b2c__needle, REG_EXTENDED); else __b2c__reti = regcomp (&__b2c__reg, __b2c__needle, REG_EXTENDED | REG_ICASE);" TO g_GENERIC WRITELN "if (!__b2c__trap && __b2c__reti) { ERROR = 27; regerror (__b2c__reti, &__b2c__reg, __b2c__buf, sizeof (__b2c__buf)); fprintf (stderr, \"%s\\n\", __b2c__buf); RUNTIMEFERR (__b2c__ln, __b2c__fl, \"REPLACE$\", ERROR); }" TO g_GENERIC WRITELN "while ((__b2c__reti = regexec (&__b2c__reg, __b2c__haystack, 1, __b2c__where, 0)) == 0) { __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len + __b2c__where[0].rm_so + __b2c__rep + 1) * sizeof (char));" TO g_GENERIC WRITELN "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len * sizeof (char), __b2c__haystack, (size_t) __b2c__where[0].rm_so * sizeof (char)); __b2c__len += __b2c__where[0].rm_so;" TO g_GENERIC WRITELN "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len * sizeof (char), __b2c__replace, __b2c__rep * sizeof (char)); __b2c__len += __b2c__rep; __b2c__haystack += (long) __b2c__where[0].rm_eo; } regfree (&__b2c__reg); }" TO g_GENERIC WRITELN "else {while ((__b2c__tmp = strstr (__b2c__haystack, __b2c__needle)) != NULL) {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len + (__b2c__tmp - __b2c__haystack) + __b2c__rep + 1) * sizeof (char));" TO g_GENERIC WRITELN "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len * sizeof (char), __b2c__haystack, (size_t) (__b2c__tmp - __b2c__haystack) * sizeof (char)); __b2c__len += __b2c__tmp - __b2c__haystack;" TO g_GENERIC WRITELN "memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len * sizeof (char), __b2c__replace, __b2c__rep * sizeof (char)); __b2c__len += __b2c__rep; __b2c__haystack = __b2c__tmp + __b2c__ndl; } } __b2c__hst = strlen (__b2c__haystack);" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len + __b2c__hst + 1) * sizeof (char)); memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len * sizeof (char), __b2c__haystack, __b2c__hst * sizeof (char));" TO g_GENERIC WRITELN "__b2c__len += __b2c__hst; __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\\0'; return (char *) (__b2c__sbuffer[__b2c__sbuffer_ptr]); }" TO g_GENERIC WRITELN "#define REPLACE", g_STRINGSIGN$, "(...) __b2c__replace(__LINE__, __FILE__, __VA_ARGS__, -1)" TO g_GENERIC WRITELN "#define LEN(__b2c__x) ((__b2c__x) != NULL ? strlen(__b2c__x) : 0)" TO g_GENERIC WRITELN "#define EQUAL(__b2c__x, __b2c__y) ((__b2c__x) != NULL && (__b2c__y) != NULL && __b2c__option_compare == 0 ? !strcmp(__b2c__x, __b2c__y) : ((__b2c__x) != NULL && (__b2c__y) != NULL && __b2c__option_compare == 1 ? !strcasecmp(__b2c__x, __b2c__y) : 0) )" TO g_GENERIC WRITELN "char* __b2c__getenv(char *__b2c__env){char* __b2c__tmp; __b2c__tmp = getenv(__b2c__env); if (__b2c__tmp == NULL)" TO g_GENERIC WRITELN "{return \"\";} return __b2c__tmp;}" TO g_GENERIC WRITELN "#define GETENVIRON", g_STRINGSIGN$, "(__b2c__x) ((__b2c__x) != NULL ? __b2c__getenv(__b2c__x) : \"null\")" TO g_GENERIC WRITELN "#define SETENVIRON(__b2c__x, __b2c__y) if((__b2c__x) != NULL && (__b2c__y) != NULL) setenv(__b2c__x, __b2c__y, 1)" TO g_GENERIC WRITELN "/* CHAR functions */" TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "char* __b2c__ucase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_GENERIC WRITELN "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=toupper(__b2c__s[__b2c__i]);}" TO g_GENERIC WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define UCASE", g_STRINGSIGN$, "(__b2c__x) ((__b2c__x) != NULL ? __b2c__ucase(__b2c__x) : \"null\")" TO g_GENERIC WRITELN "char* __b2c__lcase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_GENERIC WRITELN "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=tolower(__b2c__s[__b2c__i]);}" TO g_GENERIC WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define LCASE", g_STRINGSIGN$, "(__b2c__x) ((__b2c__x) != NULL ? __b2c__lcase(__b2c__x) : \"null\")" TO g_GENERIC WRITELN "/* I/O functions */" TO g_GENERIC WRITELN "FILE *__b2c__inFile; FILE *__b2c__outFile; int __b2c__Byte; struct dirent *__b2c__dir;" TO g_GENERIC WRITELN "char* __b2c__dec2hex(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ");" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, ");" TO g_GENERIC WRITELN "snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%X\", __b2c__i); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "long __b2c__hex2dec(int __b2c__ln, const char *__b2c__fl, char *__b2c__h){unsigned int __b2c__i; if(sscanf(__b2c__h, \"%X\", &__b2c__i) == EOF && !__b2c__trap){ERROR = 5;" TO g_GENERIC WRITELN "RUNTIMEFERR(__b2c__ln, __b2c__fl, \"DEC\", ERROR);} return(long)(__b2c__i);}" TO g_GENERIC WRITELN "unsigned char __b2c__char2asc(char *__b2c__c){return (unsigned char)*__b2c__c;}" TO g_GENERIC WRITELN "char* __b2c__asc2char(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char));" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, 2*sizeof(char)); snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], 2, \"%c\", __b2c__i);" TO g_GENERIC WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "/* Function FILEEXISTS contributed by Armando Rivera */ " TO g_GENERIC WRITELN "long __b2c__fileexists(const char *__b2c__x) {struct stat __b2c__buf; if (stat(__b2c__x, &__b2c__buf) != -1) return 1; return 0;}" TO g_GENERIC WRITELN "#define FILEEXISTS(__b2c__x) __b2c__fileexists(__b2c__x)" TO g_GENERIC WRITELN "long __b2c__filelen(int __b2c__ln, const char *__b2c__fl, const char *__b2c__x) {struct stat __b2c__buf; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"FILELEN\", ERROR);}" TO g_GENERIC WRITELN "if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0) return -1; else return(long)(__b2c__buf.st_size);}" TO g_GENERIC WRITELN "#define FILELEN(__b2c__x) __b2c__filelen(__LINE__, __FILE__, __b2c__x)" TO g_GENERIC WRITELN "long __b2c__filetime(int __b2c__ln, const char *__b2c__fl, const char *__b2c__x, int __b2c__y) {struct stat __b2c__buf; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"FILETIME\", ERROR);}" TO g_GENERIC WRITELN "if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0 || __b2c__y < 0 || __b2c__y > 2) return -1; switch(__b2c__y) {case 0: return(long)(__b2c__buf.st_atime); break;" TO g_GENERIC WRITELN "case 1: return(long)(__b2c__buf.st_mtime); break;} return(long)(__b2c__buf.st_ctime);}" TO g_GENERIC WRITELN "#define FILETIME(__b2c__x, __b2c__y) __b2c__filetime(__LINE__, __FILE__, __b2c__x, __b2c__y)" TO g_GENERIC WRITELN "long __b2c__filetype(int __b2c__ln, const char *__b2c__fl, const char *__b2c__x) {long __b2c_fs = 0; struct stat __b2c__buf; if(__b2c__x == NULL) return 0; if(lstat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap)" TO g_GENERIC WRITELN "{ERROR = 24; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"FILETYPE\", ERROR);}" TO g_GENERIC WRITELN "if (S_ISREG(__b2c__buf.st_mode)) __b2c_fs = 1; if (S_ISDIR(__b2c__buf.st_mode)) __b2c_fs = 2;" TO g_GENERIC WRITELN "if (S_ISCHR(__b2c__buf.st_mode)) __b2c_fs = 3; if (S_ISBLK(__b2c__buf.st_mode)) __b2c_fs = 4; if (S_ISFIFO(__b2c__buf.st_mode)) __b2c_fs = 5;" TO g_GENERIC WRITELN "if (S_ISLNK(__b2c__buf.st_mode)) __b2c_fs = 6; if (S_ISSOCK(__b2c__buf.st_mode)) __b2c_fs = 7; return __b2c_fs;}" TO g_GENERIC WRITELN "#define FILETYPE(__b2c__x) __b2c__filetype(__LINE__, __FILE__, __b2c__x)" TO g_GENERIC WRITELN "long __b2c__search(int __b2c__ln, const char *__b2c__fl, FILE* __b2c__x, char* __b2c__y){long __b2c__off, __b2c__pos; char* __b2c__ptr; size_t __b2c__tot;" TO g_GENERIC WRITELN "if(__b2c__x == NULL && !__b2c__trap){ERROR = 2; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"SEARCH\", ERROR);}" TO g_GENERIC WRITELN "if(__b2c__y == NULL && !__b2c__trap){ERROR = 25; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"SEARCH\", ERROR);}" TO g_GENERIC WRITELN "__b2c__pos = ftell(__b2c__x); __b2c__ptr = (char*)malloc((strlen(__b2c__y)+1)*sizeof(char)); __b2c__off = 0; do {" TO g_GENERIC WRITELN "fseek(__b2c__x, __b2c__off, SEEK_SET);memset(__b2c__ptr, 0, sizeof(char)*(strlen(__b2c__y)+1));" TO g_GENERIC WRITELN "__b2c__tot = fread(__b2c__ptr, sizeof(char), strlen(__b2c__y), __b2c__x);__b2c__off+=1;" TO g_GENERIC WRITELN "} while(!feof(__b2c__x) && strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y)));" TO g_GENERIC WRITELN "if(strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y))) __b2c__off = 0; fseek(__b2c__x, __b2c__pos, SEEK_SET); free(__b2c__ptr); return (--__b2c__off);}" TO g_GENERIC WRITELN "#define SEARCH(__b2c__x, __b2c__y) __b2c__search(__LINE__, __FILE__, __b2c__x, __b2c__y)" TO g_GENERIC WRITELN "char *__b2c__exec(int __b2c__ln, const char *__b2c__fl, char *__b2c__x, ...){int __b2c__r, __b2c__len, __b2c__i; int __b2c__wpipe[2], __b2c__rpipe[2]; char *__b2c__str, *__b2c__ans = NULL; va_list __b2c__ap;" TO g_GENERIC WRITELN "va_start(__b2c__ap, __b2c__x); __b2c__str = va_arg (__b2c__ap, char*); va_end(__b2c__ap); if (pipe (__b2c__rpipe) < 0 || pipe (__b2c__wpipe) < 0){if(!__b2c__trap) {ERROR=29; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"EXEC$\", ERROR);}}" TO g_GENERIC WRITELN "if ((__b2c__r = fork ()) < 0){if(!__b2c__trap) {ERROR=29; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"EXEC$\", ERROR);}} else if (__b2c__r == 0){" TO g_GENERIC WRITELN "close(__b2c__wpipe[1]);close (__b2c__rpipe[0]);dup2 (__b2c__wpipe[0], STDIN_FILENO);close (__b2c__wpipe[0]);dup2 (__b2c__rpipe[1], STDOUT_FILENO);close (__b2c__rpipe[1]); __b2c__r = system (__b2c__x); if(WIFEXITED(__b2c__r)) __b2c__i = WEXITSTATUS(__b2c__r); else __b2c__i=0; exit(__b2c__i);}" TO g_GENERIC WRITELN "else{close (__b2c__wpipe[0]);close (__b2c__rpipe[1]); __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0; __b2c__sbuffer[__b2c__sbuffer_ptr] = __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], sizeof (char));" TO g_GENERIC WRITELN "__b2c__ans = (char*)malloc(", g_BUFFER_SIZE, " *sizeof(char)); __b2c__len = 0;" TO g_GENERIC WRITELN "if(__b2c__str!=NULL) __b2c__i = write(__b2c__wpipe[1], __b2c__str, strlen(__b2c__str)+1); do{__b2c__i = read (__b2c__rpipe[0], __b2c__ans, ", g_BUFFER_SIZE, ");if (__b2c__i == -1 && !__b2c__trap){ERROR=30; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"EXEC$\", ERROR);}" TO g_GENERIC WRITELN "if (__b2c__i == 0)break; __b2c__sbuffer[__b2c__sbuffer_ptr] = __sbuf_realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (__b2c__len + __b2c__i + 1)*sizeof(char));" TO g_GENERIC WRITELN "if (__b2c__sbuffer[__b2c__sbuffer_ptr] == NULL && !__b2c__trap){ERROR=6; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"EXEC$\", ERROR);} memcpy(__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len*sizeof(char), __b2c__ans, __b2c__i*sizeof(char));" TO g_GENERIC WRITELN " __b2c__len += __b2c__i;} while (__b2c__i > 0); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\\0';close (__b2c__wpipe[1]);" TO g_GENERIC WRITELN "close (__b2c__rpipe[0]);free (__b2c__ans); wait(&RETVAL); RETVAL = WEXITSTATUS(RETVAL);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define EXEC", g_STRINGSIGN$, "(...) __b2c__exec(__LINE__, __FILE__, __VA_ARGS__, (char*)NULL)" TO g_GENERIC WRITELN "#define ENDFILE(__b2c__x) feof(__b2c__x)" TO g_GENERIC WRITELN "#define TELL(__b2c__x) ftell(__b2c__x)" TO g_GENERIC WRITELN "#define HEX", g_STRINGSIGN$, "(__b2c__x) __b2c__dec2hex(__b2c__x)" TO g_GENERIC WRITELN "#define DEC(__b2c__x) __b2c__hex2dec(__LINE__, __FILE__, __b2c__x)" TO g_GENERIC WRITELN "#define ASC(__b2c__x) __b2c__char2asc(__b2c__x)" TO g_GENERIC WRITELN "#define CHR", g_STRINGSIGN$, "(__b2c__x) __b2c__asc2char(__b2c__x)" TO g_GENERIC WRITELN "#define MEMTELL(__b2c__x) (long)__b2c__x" TO g_GENERIC WRITELN "/* Dynamic loading, errors */" TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "/* GETKEY */" TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "struct termios __b2c__tty;" TO g_GENERIC WRITELN "long __b2c__getch(){long __b2c__ch; struct termios __b2c__oldt, __b2c__newt; tcgetattr(STDIN_FILENO, &__b2c__oldt);" TO g_GENERIC WRITELN "__b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);" TO g_GENERIC WRITELN "__b2c__ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt); return __b2c__ch;} " TO g_GENERIC WRITELN "#define GETKEY __b2c__getch()" TO g_GENERIC WRITELN "long __b2c__getxy(int __b2c__type){char __b2c__asw[", g_BUFFER_SIZE, "]; struct termios __b2c__old, __b2c__new; int __b2c__len, __b2c__x, __b2c__y; ssize_t __b2c__tot;" TO g_GENERIC WRITELN "tcgetattr(STDIN_FILENO, &__b2c__old); __b2c__new = __b2c__old;__b2c__new.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__new);" TO g_GENERIC WRITELN "__b2c__tot = write(STDOUT_FILENO, \"\\033[6n\", strlen(\"\\033[6n\")); __b2c__len = read(STDIN_FILENO, __b2c__asw, ", g_BUFFER_SIZE, ");__b2c__asw[__b2c__len] = '\\0'; " TO g_GENERIC WRITELN "tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__old); sscanf(__b2c__asw, \"\\033[%d;%dR\", &__b2c__y, &__b2c__x); if (!__b2c__type) return(long)__b2c__x; return(long)__b2c__y;}" TO g_GENERIC WRITELN "#define GETX __b2c__getxy(0)" TO g_GENERIC WRITELN "#define GETY __b2c__getxy(1)" TO g_GENERIC WRITELN "long __b2c__screen(int __b2c__type){long __b2c__x; fprintf(stdout,\"\\033[s\"); fprintf(stdout,\"\\033[?25l\"); fprintf(stdout,\"\\033[999;999H\"); fflush(stdout);" TO g_GENERIC WRITELN "__b2c__x = __b2c__getxy(__b2c__type); fprintf(stdout,\"\\033[u\"); fprintf(stdout,\"\\033[?25h\"); fflush(stdout); return(__b2c__x); }" TO g_GENERIC WRITELN "#define COLUMNS __b2c__screen(0)" TO g_GENERIC WRITELN "#define ROWS __b2c__screen(1)" TO g_GENERIC WRITELN "/* Constants, logical stuff */" TO g_GENERIC WRITELN "#define PI 3.1415926536" TO g_GENERIC WRITELN "#define NOT(__b2c__x) (!(__b2c__x))" TO g_GENERIC WRITELN "#define AND &&" TO g_GENERIC WRITELN "#define OR ||" TO g_GENERIC WRITELN "#define IS ==" TO g_GENERIC WRITELN "#define NE !=" TO g_GENERIC WRITELN "#define ISNOT !=" TO g_GENERIC WRITELN "#define LT <" TO g_GENERIC WRITELN "#define GT >" TO g_GENERIC WRITELN "#define LE <=" TO g_GENERIC WRITELN "#define GE >=" TO g_GENERIC WRITELN "#define EQ ==" TO g_GENERIC WRITELN "#undef TRUE" TO g_GENERIC WRITELN "#define TRUE 1" TO g_GENERIC WRITELN "#undef FALSE" TO g_GENERIC WRITELN "#define FALSE 0" TO g_GENERIC WRITELN "#define NL", g_STRINGSIGN$, " \"\\n\"" TO g_GENERIC WRITELN "#define STRING char*" TO g_GENERIC WRITELN "#define NUMBER long" TO g_GENERIC WRITELN "#define FLOATING double" TO g_GENERIC WRITELN "#define ISTRUE(__b2c__x) ((__b2c__x) != 0)" TO g_GENERIC WRITELN "#define ISFALSE(__b2c__x) ((__b2c__x) == 0)" TO g_GENERIC WRITELN "#define SIZEOF(__b2c__x) sizeof(__b2c__x)" TO g_GENERIC WRITELN "/* Date and time */" TO g_GENERIC WRITELN "#include " TO g_GENERIC WRITELN "#define NOW (long)time(NULL)" TO g_GENERIC WRITELN "long __b2c__time(time_t __b2c__now, int __b2c__which){struct tm *__b2c__ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr],", g_MAX_DIGITS, ");" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, "); __b2c__ts = localtime(&__b2c__now); switch(__b2c__which) { case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%d\", __b2c__ts); break;" TO g_GENERIC WRITELN "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%m\", __b2c__ts); break; case 3: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%Y\", __b2c__ts); break;" TO g_GENERIC WRITELN "case 4: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%H\", __b2c__ts); break; case 5: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%M\", __b2c__ts); break;" TO g_GENERIC WRITELN "case 6: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%S\", __b2c__ts); break; case 7: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%W\", __b2c__ts); break;}" TO g_GENERIC WRITELN "return(atol(__b2c__sbuffer[__b2c__sbuffer_ptr]));}" TO g_GENERIC WRITELN "#define DAY(x) __b2c__time(x, 1)" TO g_GENERIC WRITELN "#define MONTH(x) __b2c__time(x, 2)" TO g_GENERIC WRITELN "#define YEAR(x) __b2c__time(x, 3)" TO g_GENERIC WRITELN "#define HOUR(x) __b2c__time(x, 4)" TO g_GENERIC WRITELN "#define MINUTE(x) __b2c__time(x, 5)" TO g_GENERIC WRITELN "#define SECOND(x) __b2c__time(x, 6)" TO g_GENERIC WRITELN "#define WEEK(x) __b2c__time(x, 7)" TO g_GENERIC WRITELN "char* __b2c__datename(time_t __b2c__now, int __b2c__which){struct tm *__b2c__ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ");" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, "); __b2c__ts = localtime(&__b2c__now); switch(__b2c__which){case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%A\", __b2c__ts); break;" TO g_GENERIC WRITELN "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%B\", __b2c__ts); break;} return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define WEEKDAY", g_STRINGSIGN$, "(x) __b2c__datename(x, 1)" TO g_GENERIC WRITELN "#define MONTH", g_STRINGSIGN$, "(x) __b2c__datename(x, 2)" TO g_GENERIC WRITELN "unsigned long __b2c__epoch(int __b2c__year, int __b2c__month, int __b2c__day, int __b2c__hour, int __b2c__minute, int __b2c__second){" TO g_GENERIC WRITELN "struct tm tm; time_t __b2c__t; tm.tm_year = __b2c__year - 1900; tm.tm_mon = __b2c__month - 1; tm.tm_mday = __b2c__day;" TO g_GENERIC WRITELN "tm.tm_hour = __b2c__hour; tm.tm_min = __b2c__minute; tm.tm_sec = __b2c__second;" TO g_GENERIC WRITELN "tm.tm_isdst = -1; __b2c__t = mktime(&tm); if (__b2c__t == -1) return (0); return(long) __b2c__t; }" TO g_GENERIC WRITELN "#define TIMEVALUE(x,y,z,a,b,c) __b2c__epoch(x,y,z,a,b,c)" TO g_GENERIC WRITELN "unsigned long __b2c__timer(){struct timeval __b2c__time; gettimeofday(&__b2c__time, NULL); if(difftime(__b2c__time.tv_sec, __b2c__elapsed_secs) < 1) return(unsigned long)((__b2c__time.tv_usec-__b2c__elapsed_usecs)/1000);" TO g_GENERIC WRITELN "else return(unsigned long)((difftime(__b2c__time.tv_sec, __b2c__elapsed_secs)-1)*1000+((1000000-__b2c__elapsed_usecs)+__b2c__time.tv_usec)/1000);}" TO g_GENERIC WRITELN "#define TIMER __b2c__timer()" TO g_GENERIC WRITELN "char* __b2c__os(int __b2c__ln, const char *__b2c__fl){struct utsname __b2c__buf; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, ");" TO g_GENERIC WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_BUFFER_SIZE, "); if(uname(&__b2c__buf) < 0 && !__b2c__trap) {ERROR = 26; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"OS$\", ERROR);}" TO g_GENERIC WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.sysname); strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], \" \");" TO g_GENERIC WRITELN "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.machine); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define OS", g_STRINGSIGN$, " __b2c__os(__LINE__, __FILE__)" TO g_GENERIC WRITELN "/* Signal trapping activated with TRAP */" TO g_GENERIC WRITELN "void __b2c__catch_signal(int __b2c__sig){" TO g_GENERIC WRITELN "switch (__b2c__sig) {case SIGABRT: fprintf(stderr, \"ERROR: signal ABORT received - internal error. Try to compile the program with TRAP LOCAL to find the cause.\\n\"); break;" TO g_GENERIC WRITELN "case SIGFPE: fprintf(stderr, \"ERROR: signal for FPE received - division by zero? Examine the calculations in the program.\\n\"); break;" TO g_GENERIC 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_GENERIC 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(__b2c__sig);}" TO g_GENERIC WRITELN "/* Peek and Poke */" TO g_GENERIC WRITELN "void __b2c__segv(int __b2c__sig){longjmp(__b2c__jump, 1);}" TO g_GENERIC WRITELN "int __b2c__memory__check(void* __b2c__x){volatile char __b2c__c; int __b2c__size, __b2c__i, __b2c__illegal = 0; switch(__b2c__memtype) {case 1: __b2c__size = sizeof(char); break;" TO g_GENERIC WRITELN "case 2: __b2c__size = sizeof(short); break; case 3: __b2c__size = sizeof(int); break; case 4: __b2c__size = sizeof(long); break; case 5: __b2c__size = sizeof(float); break;" TO g_GENERIC WRITELN "case 6: __b2c__size = sizeof(double); break; case 7: __b2c__size = sizeof(char*); break;} signal(SIGSEGV, __b2c__segv);" TO g_GENERIC WRITELN "if(!setjmp(__b2c__jump)) for(__b2c__i = 0; __b2c__i < __b2c__size; __b2c__i++) __b2c__c = *((char*)__b2c__x+__b2c__i); else __b2c__illegal = 1;" TO g_GENERIC WRITELN "if(__b2c__trap) signal(SIGSEGV, __b2c__catch_signal); else signal(SIGSEGV, SIG_DFL); return(__b2c__illegal);}" TO g_GENERIC WRITELN "#define MEMCHECK(__b2c__x) !(__b2c__memory__check((void*)__b2c__x))" TO g_GENERIC WRITELN "long __b2c__malloc(int __b2c__ln, const char *__b2c__fl, long __b2c__x) {void *__b2c__mem; if(__b2c__x==0) return(0); switch(__b2c__memtype) {case 1: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(char)); break;" TO g_GENERIC WRITELN "case 2: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(short)); break; case 3: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(int)); break;" TO g_GENERIC WRITELN "case 4: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(long)); break; case 5: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(float)); break;" TO g_GENERIC WRITELN "case 6: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(double)); break; case 7: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(char*)); break;}" TO g_GENERIC WRITELN "if(__b2c__mem == NULL && !__b2c__trap) {ERROR = 6; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"MEMORY\", ERROR);} return(long)__b2c__mem;}" TO g_GENERIC WRITELN "#define MEMORY(__b2c__x) __b2c__malloc(__LINE__, __FILE__, __b2c__x)" TO g_GENERIC WRITELN "char __b2c__peek(int __b2c__ln, const char *__b2c__fl, void* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check(__b2c__x)) {ERROR=1; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"PEEK\", ERROR);} }" TO g_GENERIC WRITELN "char __b2c__c = *(char*)(__b2c__x); return(__b2c__c);}" TO g_GENERIC WRITELN "short __b2c__peeks(int __b2c__ln, const char *__b2c__fl, void* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check(__b2c__x)) {ERROR=1; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"PEEK\", ERROR);} } " TO g_GENERIC WRITELN "short __b2c__s = *(short*)(__b2c__x); return(__b2c__s);}" TO g_GENERIC WRITELN "int __b2c__peeki(int __b2c__ln, const char *__b2c__fl, void* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check(__b2c__x)) {ERROR=1; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"PEEK\", ERROR);} }" TO g_GENERIC WRITELN "int __b2c__i = *(int*)(__b2c__x); return(__b2c__i);}" TO g_GENERIC WRITELN "long __b2c__peekl(int __b2c__ln, const char *__b2c__fl, void* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check(__b2c__x)) {ERROR=1; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"PEEK\", ERROR);} }" TO g_GENERIC WRITELN "long __b2c__l = *(long*)(__b2c__x); return(__b2c__l);}" TO g_GENERIC WRITELN "float __b2c__peekf(int __b2c__ln, const char *__b2c__fl, void* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check(__b2c__x)) {ERROR=1; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"PEEK\", ERROR);} }" TO g_GENERIC WRITELN "float __b2c__f = *(float*)(__b2c__x); return(__b2c__f);}" TO g_GENERIC WRITELN "double __b2c__peekd(int __b2c__ln, const char *__b2c__fl, void* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check(__b2c__x)) {ERROR=1; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"PEEK\", ERROR);} }" TO g_GENERIC WRITELN "double __b2c__d = *(double*)(__b2c__x); return(__b2c__d);}" TO g_GENERIC WRITELN "char* __b2c__peekv(int __b2c__ln, const char *__b2c__fl,void** __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check(__b2c__x)) {ERROR=1; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"PEEK\", ERROR);} }" TO g_GENERIC WRITELN "char* __b2c__c = *(char**)(__b2c__x); return(__b2c__c);}" TO g_GENERIC WRITELN "#define PEEK(__b2c__x) (__b2c__memtype==1 ? (char)__b2c__peek(__LINE__, __FILE__, (void*)__b2c__x) : (__b2c__memtype==2 ? (short)__b2c__peeks(__LINE__, __FILE__, (void*)__b2c__x) : (__b2c__memtype==3 ? (int)__b2c__peeki(__LINE__, __FILE__, (void*)__b2c__x) : \\" TO g_GENERIC WRITELN "(__b2c__memtype==4 ? (long)__b2c__peekl(__LINE__, __FILE__, (void*)__b2c__x) : ( __b2c__memtype==5 ? (float)__b2c__peekf(__LINE__, __FILE__, (void*)__b2c__x) : (__b2c__memtype==6 ? (double)__b2c__peekd(__LINE__, __FILE__, (void*)__b2c__x) : (char)__b2c__peek(__LINE__, __FILE__, (void**)__b2c__x) ))))))" TO g_GENERIC WRITELN "#define ADDRESS(__b2c__x) (long)(&__b2c__x)" TO g_GENERIC WRITELN "#define FP(__b2c__x) (void*)(&__b2c__x)" TO g_GENERIC WRITELN "/* Network variables and functions */" TO g_GENERIC WRITELN "struct timeval __b2c__to; struct hostent *__b2c__he; char *__b2c__host; char *__b2c__port; int __b2c__yes = 1; char __b2c__ttl = 1; struct sockaddr_in *__b2c__addr, *__b2c__from; struct ip_mreq __b2c__imreq;" TO g_GENERIC WRITELN "int __b2c__result; char __b2c__data_client[", g_BUFFER_SIZE, "] = { 0 }; char __b2c__data_server[", g_BUFFER_SIZE, "] = { 0 }; int __b2c__handle;" TO g_GENERIC WRITELN "long __b2c__netpeek(int __b2c__ln, const char *__b2c__fl, int __b2c__fd, int __b2c__usec){fd_set __b2c__rfds; struct timeval __b2c__tv; long __b2c__retval; struct termios __b2c__oldt, __b2c__newt;" TO g_GENERIC WRITELN "if(__b2c__fd == STDIN_FILENO){tcgetattr(STDIN_FILENO, &__b2c__oldt); __b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);}" TO g_GENERIC WRITELN "FD_ZERO(&__b2c__rfds); FD_SET(__b2c__fd, &__b2c__rfds);__b2c__tv.tv_usec = (__b2c__usec%1000)*1000; __b2c__tv.tv_sec = __b2c__usec/1000;" TO g_GENERIC WRITELN "__b2c__retval = select(__b2c__fd + 1, &__b2c__rfds, NULL, NULL, &__b2c__tv); if (__b2c__retval == -1 && !__b2c__trap) {ERROR = 16; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"WAIT\", ERROR);}" TO g_GENERIC WRITELN "if(__b2c__fd == STDIN_FILENO){if(__b2c__retval) if(read(__b2c__fd, &__b2c__retval, 1)==0) __b2c__retval=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt);} return(__b2c__retval);}" TO g_GENERIC WRITELN "#define WAIT(__b2c__x, __b2c__y) __b2c__netpeek(__LINE__, __FILE__, __b2c__x, __b2c__y)" TO g_GENERIC WRITELN "char* __b2c__nethost(int __b2c__ln, const char *__b2c__fl, char* __b2c__host) {int __b2c__y; int __b2c__flag = 0; struct in_addr __b2c__address; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "); memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_BUFFER_SIZE, ");" TO g_GENERIC WRITELN "for(__b2c__y=0; __b2c__y < strlen(__b2c__host); __b2c__y++) {if(isalpha(*(__b2c__host+__b2c__y))) {__b2c__flag = 1; break;}} if(__b2c__flag) __b2c__he = gethostbyname(__b2c__host); " TO g_GENERIC WRITELN "else {if(inet_aton(__b2c__host, &__b2c__address)) __b2c__he = gethostbyaddr((void*)&__b2c__address, sizeof(struct in_addr), AF_INET); } if (__b2c__he == NULL || __b2c__he->h_addr == NULL || __b2c__he->h_name == NULL)" TO g_GENERIC WRITELN "{if(!__b2c__trap){ERROR = 11; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"HOST$\", ERROR);} else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"Host not found\", ", g_BUFFER_SIZE ,"-1); } else {if(__b2c__flag) {__b2c__addr = calloc(1, sizeof(*__b2c__addr)); __b2c__addr->sin_addr = *((struct in_addr *)__b2c__he->h_addr);" TO g_GENERIC WRITELN "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], inet_ntoa(__b2c__addr->sin_addr), ", g_BUFFER_SIZE, "-1);free(__b2c__addr);} else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__he->h_name, ", g_BUFFER_SIZE, "-1);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define HOST", g_STRINGSIGN$, "(__b2c__x) __b2c__nethost(__LINE__, __FILE__, __b2c__x)" TO g_GENERIC IF INSTR(OS$, "OSF1") THEN line$ = "int" ELSE line$ = "unsigned int" ENDIF WRITELN "char* __b2c__getpeer(int __b2c__ln, const char *__b2c__fl, int __b2c__x){struct sockaddr_in *__b2c__peer; ", line$, " __b2c__len = sizeof(__b2c__peer); char __b2c__port[6]; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_GENERIC WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)__sbuf_realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "); memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_BUFFER_SIZE, ");" TO g_GENERIC WRITELN "__b2c__peer = calloc(1, sizeof(*__b2c__peer)); if(getpeername(__b2c__x, (struct sockaddr*)__b2c__peer, &__b2c__len) <0){if(!__b2c__trap){ERROR = 16; RUNTIMEFERR(__b2c__ln, __b2c__fl, \"GETPEER$\", ERROR);}" TO g_GENERIC WRITELN "else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"Peer not found\", ", g_BUFFER_SIZE, "-1);} else{strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], inet_ntoa(__b2c__peer->sin_addr), ", g_BUFFER_SIZE, "-7);" TO g_GENERIC WRITELN "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], \":\"); snprintf(__b2c__port, 6, \"%d\", ntohs(__b2c__peer->sin_port)); strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__port);}" TO g_GENERIC WRITELN "free(__b2c__peer); return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_GENERIC WRITELN "#define GETPEER", g_STRINGSIGN$, "(__b2c__x) __b2c__getpeer(__LINE__, __FILE__, __b2c__x)" TO g_GENERIC WRITELN "/* Regex */" TO g_GENERIC WRITELN "long __b2c__regex(int __b2c__ln, const char *__b2c__fl, char* __b2c__x, char* __b2c__y){regex_t __b2c__reg; int __b2c__reti; char __b2c__buf[100]; regmatch_t __b2c__where[1]; if(__b2c__option_compare == 0) __b2c__reti = regcomp(&__b2c__reg, __b2c__y, REG_EXTENDED);" TO g_GENERIC WRITELN "else __b2c__reti = regcomp(&__b2c__reg, __b2c__y, REG_EXTENDED|REG_ICASE); if(!__b2c__trap && __b2c__reti){ERROR=27; regerror(__b2c__reti, &__b2c__reg, __b2c__buf, sizeof(__b2c__buf)); fprintf(stderr, \"%s\\n\", __b2c__buf);" TO g_GENERIC WRITELN "RUNTIMEFERR(__b2c__ln, __b2c__fl, \"REGEX\", ERROR);} __b2c__reti = regexec(&__b2c__reg, __b2c__x, 1, __b2c__where, 0);" TO g_GENERIC WRITELN "regfree(&__b2c__reg); if( !__b2c__reti ) {REGLEN = __b2c__where[0].rm_eo - __b2c__where[0].rm_so; return (__b2c__where[0].rm_so+1);} else {REGLEN = 0; return (0);} }" TO g_GENERIC WRITELN "#define REGEX(__b2c__x, __b2c__y) __b2c__regex(__LINE__, __FILE__, __b2c__x, __b2c__y)" TO g_GENERIC WRITELN "/* Declare reserved variable 'ARGUMENT' */" TO g_GENERIC WRITELN "int __b2c__counter;" TO g_GENERIC WRITELN "int __b2c__arglen = 0;" TO g_GENERIC WRITELN "char *ARGUMENT", g_STRINGSIGN$, ";" TO g_GENERIC WRITELN "/* Initialize stack arrays and pointer */" TO g_GENERIC WRITELN "char **__b2c__stringstack = NULL; double *__b2c__doublestack = NULL;" TO g_GENERIC WRITELN "long *__b2c__longstack = NULL; int *__b2c__typestack = NULL;" TO g_GENERIC WRITELN "int __b2c__stackptr = 0;" TO g_GENERIC ' Makedir function WRITELN "int __b2c__makedir(char* __b2c__in){char *__b2c__i, *__b2c__dir; if(__b2c__in == NULL || strlen(__b2c__in)==0) return 0; if(*__b2c__in != '/'){__b2c__dir = calloc(strlen(__b2c__in)+3, sizeof (char));" TO g_GENERIC WRITELN "strncpy(__b2c__dir, \"./\", 2); __b2c__dir = strcat(__b2c__dir, __b2c__in);} else __b2c__dir = __b2c__strdup(__b2c__in); __b2c__i = __b2c__dir; do { __b2c__i++; while(*__b2c__i != '/' && *__b2c__i != '\\0') __b2c__i++;" TO g_GENERIC WRITELN "if(*__b2c__i == '/') {*__b2c__i = '\\0'; mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); *__b2c__i = '/';} else if (*__b2c__i == '\\0') mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);" TO g_GENERIC WRITELN "if(errno != EEXIST && errno != 0) {free(__b2c__dir); return errno;} } while (*__b2c__i != '\\0'); free(__b2c__dir); return 0;}" TO g_GENERIC ' Add error function WRITELN "/* Initialize error function */" TO g_GENERIC WRITELN "char *ERR", g_STRINGSIGN$, "(int __b2c__nr){static char __b2c__warn[", g_BUFFER_SIZE, "] = { 0 }; const char* __b2c__err;" TO g_GENERIC WRITELN "switch(__b2c__nr){" TO g_GENERIC WRITELN "case 0: strcpy(__b2c__warn,\"Success\"); break;" TO g_GENERIC WRITELN "case 1: strcpy(__b2c__warn,\"Trying to access illegal memory: \"); strncat(__b2c__warn,strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 2: strcpy(__b2c__warn,\"Error opening file: \"); strncat(__b2c__warn,strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 3: strcpy(__b2c__warn, \"Could not open library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, ", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 4: strcpy(__b2c__warn, \"Symbol not found in library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, ", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 5: strcpy(__b2c__warn, \"Wrong hexvalue: \"); strncat(__b2c__warn, strerror(errno), ", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 6: strcpy(__b2c__warn, \"Unable to claim memory.\"); break;" TO g_GENERIC WRITELN "case 7: strcpy(__b2c__warn, \"Unable to delete file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 8: strcpy(__b2c__warn, \"Could not open directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 9: strcpy(__b2c__warn, \"Unable to rename file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 10: strcpy(__b2c__warn, \"NETWORK argument should contain colon with port number\"); break;" TO g_GENERIC WRITELN "case 11: strcpy(__b2c__warn, \"Could not resolve hostname!\"); break;" TO g_GENERIC WRITELN "case 12: strcpy(__b2c__warn, \"Socket error: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 13: strcpy(__b2c__warn, \"Unable to open address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 14: strcpy(__b2c__warn, \"Error reading from socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 15: strcpy(__b2c__warn, \"Error sending to socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 16: strcpy(__b2c__warn, \"Error checking socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC 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_GENERIC WRITELN "case 18: strcpy(__b2c__warn, \"Unable to listen to socket address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 19: strcpy(__b2c__warn, \"Cannot accept incoming connection: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 20: strcpy(__b2c__warn, \"Unable to remove directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 21: strcpy(__b2c__warn, \"Unable to create directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 22: strcpy(__b2c__warn, \"Unable to change to directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 23: strcpy(__b2c__warn, \"GETENVIRON argument does not exist as environment variable\"); break;" TO g_GENERIC WRITELN "case 24: strcpy(__b2c__warn, \"Unable to stat file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 25: strcpy(__b2c__warn, \"Search contains illegal string\"); break;" TO g_GENERIC WRITELN "case 26: strcpy(__b2c__warn, \"Cannot return OS name: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 27: strcpy(__b2c__warn, \"Illegal regex expression\"); break;" TO g_GENERIC WRITELN "case 28: strcpy(__b2c__warn, \"Unable to create bidirectional pipes: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 29: strcpy(__b2c__warn, \"Unable to fork process: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 30: strcpy(__b2c__warn, \"Cannot read from pipe: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 31: strcpy(__b2c__warn, \"Gosub nesting too deep!\"); break;" TO g_GENERIC WRITELN "case 32: strcpy(__b2c__warn, \"Could not open device: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 33: strcpy(__b2c__warn, \"Error configuring serial port: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "case 34: strcpy(__b2c__warn, \"Error accessing device: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_GENERIC WRITELN "}; ERROR = 0; return(__b2c__warn);}" TO g_GENERIC WRITELN "#define COMPILED_BY_WHICH_BACON", g_STRINGSIGN$, " ", CHR$(34), "BaCon ", g_VERSION$, CHR$(34) TO g_GENERIC CLOSE FILE g_GENERIC ' Create new headerfile OPEN g_HFILE$ FOR WRITING AS g_HFILE WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO g_HFILE WRITELN "#include " & CHR$(34) & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".generic.h" & CHR$(34) TO g_HFILE ' Initialize the arrayfiles for DATA statement OPEN STRINGARRAYFILE$ FOR WRITING AS STRINGARRAYFILE WRITELN "char* __b2c__stringarray[] = {" TO STRINGARRAYFILE OPEN FLOATARRAYFILE$ FOR WRITING AS FLOATARRAYFILE WRITELN "double __b2c__floatarray[] = {" TO FLOATARRAYFILE ' There are no imported symbols yet LET g_IMPORTED$ = "" ' Check if the C Preprocessor needs to run IF ISTRUE(g_CPP) THEN IF ISTRUE(LEN(EXEC$("which cpp 2>/dev/null"))) THEN SYSTEM "cpp -P -w " & g_SOURCEFILE$ & " " & g_SOURCEFILE$ & ".cpp" FEED$ = g_SOURCEFILE$ & ".cpp" g_TMP_FILES$ = g_TMP_FILES$ & " " & g_SOURCEFILE$ & ".cpp" ELSE EPRINT "System error: the C Preprocessor 'cpp' not found on this system! Exiting..." END 1 END IF ELSE FEED$ = g_SOURCEFILE$ END IF LET g_CURFILE$ = MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) ' Initialize LET total$ = "" LET g_COUNTER = 1 ' Read source program OPEN FEED$ FOR READING AS g_SOURCEFILE WHILE NOT(ENDFILE(g_SOURCEFILE)) DO IF NOT(g_SHEBANG) THEN PRINT "\rConverting '", FEED$, "'... ", g_COUNTER, "\033[0J"; READLN line$ FROM g_SOURCEFILE ' Line is not empty? IF NOT(ENDFILE(g_SOURCEFILE)) AND LEN(line$) > 0 THEN IF 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 "/* noparse ", FEED$, " BACON LINE ", g_COUNTER, " */" TO g_HFILE WRITELN "/* noparse ", FEED$, " BACON LINE ", g_COUNTER, " */" TO g_CFILE Tokenize(total$) END IF LET total$ = "" END IF ENDIF INCR g_COUNTER WEND CLOSE FILE g_SOURCEFILE ' Check if enclosed IF/ELIF/ELSE needs to be closed IF g_IF_PARSE = 1 THEN WRITELN "}" TO g_CFILE ' Finalize main C-file WRITELN "__B2C__PROGRAM__EXIT:" TO g_CFILE WRITELN "return 0;" TO g_CFILE WRITELN "}" TO g_CFILE ' Finalize STRING ARRAY file for DATA WRITELN " \"\" };" TO STRINGARRAYFILE ' Finalize FLOAT ARRAY file for DATA WRITELN " 0.0};" TO FLOATARRAYFILE ' Include functions and subs FOR incfiles$ IN g_INCLUDE_FILES$ IF LEN(incfiles$) > 0 THEN WRITELN "#include \"", incfiles$, CHR$(34) TO g_HFILE NEXT ' Close all filehandles CLOSE FILE FLOATARRAYFILE CLOSE FILE STRINGARRAYFILE CLOSE FILE g_HFILE CLOSE FILE g_CFILE IF NOT(g_SHEBANG) THEN PRINT "\rConverting '", FEED$, "'... done.\033[0J" ' Start indentation IF ISTRUE(g_TMP_PRESERVE) THEN IF ISTRUE(LEN(EXEC$("which indent 2>/dev/null"))) THEN PRINT "Applying indentation... "; FOR tmpfiles$ IN g_TMP_FILES$ IF NOT(REGEX(tmpfiles$, ".*\\.cpp")) THEN IF ISTRUE(INSTR(OS$, "Darwin")) OR ISTRUE(INSTR(OS$, "BSD")) THEN RENAME tmpfiles$ TO tmpfiles$ & ".BAK" SYSTEM "indent " & tmpfiles$ & ".BAK " & tmpfiles$ DELETE FILE tmpfiles$ & ".BAK" ELSE SYSTEM "indent " & tmpfiles$ DELETE FILE tmpfiles$ & "~" END IF END IF NEXT i PRINT "done." ELSE PRINT "WARNING: 'indent' not found on this system!" PRINT "Generated source code cannot be beautified." END IF END IF ' Check if we need to run xgettext IF g_XGETTEXT THEN IF ISTRUE(LEN(EXEC$("which xgettext 2>/dev/null"))) THEN PRINT "Executing xgettext... "; SYSTEM "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 ' Start compilation IF ISFALSE(g_NO_COMPILE) THEN IF ISFALSE(LEN(EXEC$("which " & g_CCNAME$ & " 2>/dev/null"))) THEN PRINT "WARNING: '", g_CCNAME$, "' not found on this system!" PRINT "Generated source code cannot be compiled." END 0 END IF ' Make sure GCC uses English localization SETENVIRON "LANG", "C" IF NOT(g_SHEBANG) THEN PRINT "Compiling '", FEED$, "'... "; SYSTEM g_CCNAME$ & " " & g_CCFLAGS$ & " -o \"" & LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4) & g_BINEXT$ & "\" " & g_CFILE$ & " " & g_LDFLAGS$ & " > " & g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".log 2>&1" ELSE SYSTEM g_CCNAME$ & " " & g_CCFLAGS$ & " -o \"" & g_TEMPDIR$ & "/" & LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4) & g_BINEXT$ & "\" " & g_CFILE$ & " " & g_LDFLAGS$ & " > " & g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".log 2>&1" END IF ' Add temp file g_TMP_FILES$ = g_TMP_FILES$ & " " & g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".log" IF ISFALSE(FILELEN(g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".log")) THEN IF g_SHEBANG THEN SYSTEM g_TEMPDIR$ & "/" & LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4) ELSE PRINT "done." PRINT "Program '", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4), g_BINEXT$, "' ready." END IF ELSE ' Only print first error 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$, INSTR(g_ERROR$, "error:") + 6) g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTR(g_ERROR$, "error:") - 1) BREAK ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, "Error:")) AND REGEX(g_ERROR$, "[0-9]+") AND REGEX(g_ERROR$, "\\: Error\\:") THEN g_ERRORTXT$ = "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$, INSTR(g_ERROR$, "warning:") + 8) g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTR(g_ERROR$, "warning:") - 1) BREAK ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, ":")) AND REGEX(g_ERROR$, "[0-9]+\\:") THEN g_ERRORTXT$ = "Cause:" & NL$ & TAB$(1) & MID$(g_ERROR$, INSTRREV(g_ERROR$, ":") + 1) g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTRREV(g_ERROR$, ":") - 1) BREAK END IF WEND CLOSE FILE errlog ' Restore $-symbol if there is any g_ERRORTXT$ = REPLACE$(g_ERRORTXT$, g_STRINGSIGN$, "$") ' Get the file where the error is g_FILE$ = MID$(g_FILE_LINE$, 1, INSTR(g_FILE_LINE$, ":") - 1) ' Tru64Unix helper g_FILE$ = MID$(g_FILE$, 1, INSTR(g_FILE$, ",") - 1) ' Non-gcc or parse problem (file does not exist) IF ISFALSE(LEN(g_ERROR$)) OR ISTRUE(INSTR(g_CCFLAGS$, "Wall")) OR NOT(FILEEXISTS(g_FILE$)) THEN PRINT SYSTEM "cat " & g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".log" PRINT 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 ' Initiate error file name and error line in C code g_FEED$ = MID$(g_FILE_LINE$, 1, INSTR(g_FILE_LINE$, ":")-1) g_CURLINE$ = CONCAT$(STR$(g_LINE), " ") g_COUNTER = 1 OPEN g_FILE$ FOR READING AS errlog WHILE NOT(ENDFILE(errlog)) DO READLN line$ FROM errlog IF INSTR(line$, "BACON LINE") AND INSTR(line$, "noparse") THEN g_CURLINE$ = MID$(line$, INSTR(line$, "BACON LINE") + 10) g_FEED$ = MID$(line$, INSTR(line$, "noparse") + 7) g_FEED$ = CHOP$(MID$(g_FEED$, 1, INSTR(g_FEED$, " BACON LINE"))) END IF IF g_COUNTER IS g_LINE THEN COUNTER = 1 OPEN g_FEED$ FOR READING AS g_SOURCEFILE WHILE NOT(ENDFILE(g_SOURCEFILE)) DO READLN line$ FROM g_SOURCEFILE IF COUNTER IS VAL(MID$(g_CURLINE$, 1, INSTRREV(g_CURLINE$, " "))) THEN PRINT NL$, "Problem:", NL$, TAB$(1), " file '", g_FEED$, "' line ", COUNTER, ": ", CHOP$(line$) PRINT g_ERRORTXT$, NL$ BREAK END IF INCR COUNTER WEND CLOSE FILE g_SOURCEFILE BREAK END IF INCR g_COUNTER WEND CLOSE FILE errlog END IF ' Preserve temp files g_TMP_PRESERVE = 1 END IF END IF ' Cleanup IF ISFALSE(g_TMP_PRESERVE) THEN FOR tmpfiles$ IN g_TMP_FILES$ IF FILEEXISTS(tmpfiles$) THEN DELETE FILE tmpfiles$ ELSE PRINT NL$, "Warning: duplicate SUB or FUNCTION found! Temporary file ", tmpfiles$, " already deleted." END IF NEXT ELIF g_CPP = 1 THEN RENAME g_SOURCEFILE$ & ".cpp" TO g_TEMPDIR$ & "/" & MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1) & ".cpp" END IF